Repository navigation
Conversation
The worker's input Babel plugin writes function maps to `metadata`, so this removes the deprecated fallback to a `functionMap` returned by the transformer. A custom transformer that doesn't apply the `plugins` it's given loses function names in stack traces. Changelog: ``` - **[Breaking]**: Babel transformers can no longer return a `functionMap`. Apply the `plugins` passed by Metro, which write it to `metadata` ``` Test plan: Existing tests. React Native's transformer doesn't return one, and `@expo/metro-config` has its own worker.
Metro review: Looks goodRisk: low · Commit: This removes the deprecated No findings. Verified
Not run: No benchmark: the change removes one nullish fallback per Babel transform, with no plausible cost effect. Windows wasn't run: no path or platform behavior changes. The full Jest suite wasn't run, only the changed packages and the function map consumers listed. Ecosystem checks cover the latest versions of the three packages named, not older releases or other transformers. A first download command using a shell variable was denied by the permission policy, so Automated review by Claude. Advisory only: it never approves or blocks, and a maintainer makes the call. |
Summary: Publish Metro 0.88.0 from `main`. This is a draft until we choose the cut. These breaking PRs are still open, and can land first or wait for the next minor: - #2186 (`globalPrefix` for all module system globals) - #2158 (`/symbolicate` stops reading `req.rawBody`) - #2157 (remove `functionMap` from the Babel transformer result) - #1990 (keep the file extension in async bundle paths, approved and held for 0.88) - #1985 and #2156 (drafts, decoded source maps) Approved non-breaking PRs that could also make it: #2185, #2040, #2034 and #2150 (which turns a missing watch folder into an immediate startup error, rather than a 240s hang). I'll rebase this and extend the notes as they land. Changelog: [Internal] Test plan: ``` node scripts/updateVersion.js 0.88.0 sl diff --stat ``` Only the 17 `packages/*/package.json` manifests change, and every `0.87.3` reference is replaced. Notable breakage in third parties, for the notes or a heads-up before React Native adopts this: - `@rnx-kit/metro-config` 2.2.6 adds `path.dirname(resolver.emptyModulePath)` as a watch folder when there are none, which is now `metro:runtime/modules`, so the dev server never serves a bundle for a single-package app. - `@tamagui/metro-plugin` 3.x refuses `metro-resolver` outside 0.84-0.87, and then imports the removed `metro-resolver/private/createDefaultContext`. - `@rnx-kit/metro-resolver-symlinks` calls the removed `context.redirectModulePath`. End to end (AI-driven), with the packed tarballs against 0.87.3 from npm, in a React Native 0.89.0-rc.0 template app with a few popular dependencies: dev and release bundles, source maps and assets for iOS and Android are byte-identical, except where #2174 changes resolution. `rxjs/operators` now resolves to the same ESM build as `rxjs`, dropping 190 duplicate modules, and `require('nanoid/non-secure')` gets nanoid's CJS build. Release builds reach the first screen on a Galaxy A16 and the iOS simulator (built before #2184 landed, which leaves the prelude and module system byte-identical). The dev server passes the same checks on both, with and without Watchman (edits, added and deleted files, HMR, `/symbolicate`, assets and lazy `import()`), and Fast Refresh works on the simulator. Draft release notes (from the 14 commits in v0.87.3...main - internal-only changes omitted): ``` - **[Breaking]**: Resolver: Read `"exports"` from the package root, and apply `"browser"` redirections to the file it resolves to, by default. Set `resolver.unstable_resolveExportsFromPackageRoot` and `resolver.unstable_applyBrowserSpecAfterExports` to `false` for the previous behavior (#2174 by @robhogan) - **[Breaking]**: Default `transformer.asyncRequireModulePath` and `resolver.emptyModulePath` to `metro:runtime/...`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest`, and code that reads either option as a file path must resolve it instead (#2180 by @robhogan) - **[Breaking]**: Resolve the module system via `metro:runtime/polyfills/require`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest` (#2184 by @robhogan) - **[Breaking]**: Remove the deprecated `redirectModulePath` from `ResolutionContext`. A custom resolver should drop any call to it and delegate to `context.resolveRequest` or `resolve`, which already apply `"browser"` redirections and return `{type: 'empty'}` for `false` (#2181 by @robhogan) - **[Breaking]**: Remove the deprecated `doesFileExist` from `ResolutionContext`, and the `DoesFileExist` type from `metro-resolver` (use `fileSystemLookup`) (#2181 by @robhogan) - **[Breaking]**: `ResolutionContext.isESMImport` is required (#2182 by @robhogan) - **[Breaking]**: Source and JSON files containing the reserved string `_$$_METRO_`, including in comments and string literals, now fail to transform (#2155 by @robhogan) - **[Breaking]**: Remove the deprecated, always-`true` `hot` option from `getTransformOptions` (#2159 by @robhogan) - **[Feature]**: Custom serializers receive the reserved string as `options.reservedString` (#2155 by @robhogan) - **[Fix]**: Fall back to file-based resolution, instead of throwing a `TypeError`, when a package's `"exports"` field is not a string, array or object (#2187 by @kwy404) - **[Fix]**: Fix relative symlinks on a different Windows drive than the project root (#2161 by @ramya-2196) - **[Performance]**: ~5-10% faster resolution (#2181 by @robhogan) > NOTE: Experimental features are not covered by semver and can change at any time. - **[Experimental]**: Remove `unstable_incrementalResolution` from `ResolutionContext`, and `metro-resolver/private/createDefaultContext` (#2181 by @robhogan) **Full Changelog**: v0.87.3...v0.88.0 ```
Summary: Publish Metro 0.88.0 from `main`. This is a draft until we choose the cut. These breaking PRs are still open, and can land first or wait for the next minor: - #2158 (`/symbolicate` stops reading `req.rawBody`) - #2157 (remove `functionMap` from the Babel transformer result) - #1990 (keep the file extension in async bundle paths, approved and held for 0.88) - #1985 and #2156 (drafts, decoded source maps) Approved non-breaking PRs that could also make it: #2185, #2040, #2034 and #2150 (which turns a missing watch folder into an immediate startup error, rather than a 240s hang). I'll rebase this and extend the notes as they land. Changelog: [Internal] Test plan: ``` node scripts/updateVersion.js 0.88.0 sl diff --stat ``` Only the 17 `packages/*/package.json` manifests change, and every `0.87.3` reference is replaced. Notable breakage in third parties, for the notes or a heads-up before React Native adopts this: - `@rnx-kit/metro-config` 2.2.6 adds `path.dirname(resolver.emptyModulePath)` as a watch folder when there are none, which is now `metro:runtime/modules`, so the dev server never serves a bundle for a single-package app. - `@tamagui/metro-plugin` 3.x refuses `metro-resolver` outside 0.84-0.87, and then imports the removed `metro-resolver/private/createDefaultContext`. - `@rnx-kit/metro-resolver-symlinks` calls the removed `context.redirectModulePath`. End to end (AI-driven), with the packed tarballs against 0.87.3 from npm, in a React Native 0.89.0-rc.0 template app with a few popular dependencies: dev and release bundles, source maps and assets for iOS and Android are byte-identical, except where #2174 changes resolution. `rxjs/operators` now resolves to the same ESM build as `rxjs`, dropping 190 duplicate modules, and `require('nanoid/non-secure')` gets nanoid's CJS build. With #2186, only the module system and `asyncRequire` differ besides those. Release builds reach the first screen on a Galaxy A16 and the iOS simulator. The dev server passes the same checks on both, with and without Watchman (edits, added and deleted files, HMR, `/symbolicate`, assets and lazy `import()`), and Fast Refresh works on the simulator. Draft release notes (from the 15 commits in v0.87.3...main - internal-only changes omitted): ``` - **[Breaking]**: Resolver: Read `"exports"` from the package root, and apply `"browser"` redirections to the file it resolves to, by default. Set `resolver.unstable_resolveExportsFromPackageRoot` and `resolver.unstable_applyBrowserSpecAfterExports` to `false` for the previous behavior (#2174 by @robhogan) - **[Breaking]**: Default `transformer.asyncRequireModulePath` and `resolver.emptyModulePath` to `metro:runtime/...`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest`, and code that reads either option as a file path must resolve it instead (#2180 by @robhogan) - **[Breaking]**: Resolve the module system via `metro:runtime/polyfills/require`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest` (#2184 by @robhogan) - **[Breaking]**: `transformer.globalPrefix` now also prefixes `__r`, `__c`, `__registerSegment` and `__accept`, and the default run statement. Code that calls these by name must apply the prefix (#2186 by @robhogan) - **[Breaking]**: Remove the deprecated `redirectModulePath` from `ResolutionContext`. A custom resolver should drop any call to it and delegate to `context.resolveRequest` or `resolve`, which already apply `"browser"` redirections and return `{type: 'empty'}` for `false` (#2181 by @robhogan) - **[Breaking]**: Remove the deprecated `doesFileExist` from `ResolutionContext`, and the `DoesFileExist` type from `metro-resolver` (use `fileSystemLookup`) (#2181 by @robhogan) - **[Breaking]**: `ResolutionContext.isESMImport` is required (#2182 by @robhogan) - **[Breaking]**: Source and JSON files containing the reserved string `_$$_METRO_`, including in comments and string literals, now fail to transform (#2155 by @robhogan) - **[Breaking]**: Remove the deprecated, always-`true` `hot` option from `getTransformOptions` (#2159 by @robhogan) - **[Feature]**: Custom serializers receive the reserved string as `options.reservedString` (#2155 by @robhogan) - **[Fix]**: Fall back to file-based resolution, instead of throwing a `TypeError`, when a package's `"exports"` field is not a string, array or object (#2187 by @kwy404) - **[Fix]**: Fix relative symlinks on a different Windows drive than the project root (#2161 by @ramya-2196) - **[Performance]**: ~5-10% faster resolution (#2181 by @robhogan) > NOTE: Experimental features are not covered by semver and can change at any time. - **[Experimental]**: Remove `unstable_incrementalResolution` from `ResolutionContext`, and `metro-resolver/private/createDefaultContext` (#2181 by @robhogan) **Full Changelog**: v0.87.3...v0.88.0 ```
Summary: Publish Metro 0.88.0 from `main`. Changelog: [Internal] Test plan: ``` node scripts/updateVersion.js 0.88.0 sl diff --stat ``` Only the 17 `packages/*/package.json` manifests change, and every `0.87.3` reference is replaced. Flow, ESLint, Prettier, TypeScript, API snapshots, Markdown lint and Jest pass on this commit. Notable breakage in third parties, for the notes or a heads-up before React Native adopts this: - `@rnx-kit/metro-config` 2.2.6 adds `path.dirname(resolver.emptyModulePath)` as a watch folder when there are none, which is now `metro:runtime/modules`, so the dev server never serves a bundle for a single-package app. - `@tamagui/metro-plugin` 3.x refuses `metro-resolver` outside 0.84-0.87, and then imports the removed `metro-resolver/private/createDefaultContext`. - `@rnx-kit/metro-resolver-symlinks` calls the removed `context.redirectModulePath`. End to end (AI-driven), with the packed tarballs against 0.87.3 from npm, in a React Native 0.89.0-rc.0 template app with a few popular dependencies: dev and release bundles, source maps and assets for iOS and Android are byte-identical, except where #2174 changes resolution. `rxjs/operators` now resolves to the same ESM build as `rxjs`, dropping 190 duplicate modules, and `require('nanoid/non-secure')` gets nanoid's CJS build. With #2186, only the module system and `asyncRequire` differ besides those. Release builds reach the first screen on a Galaxy A16 and the iOS simulator. The dev server passes the same checks on both, with and without Watchman (edits, added and deleted files, HMR, `/symbolicate`, assets and lazy `import()`), and Fast Refresh works on the simulator. The end-to-end checks above were on 9de42bbed3b2, before #2170, #2157, #2158 and #1990 landed. I'm re-running them now and will update this. Draft release notes (from the 19 commits in v0.87.3...main - internal-only changes omitted): ``` - **[Breaking]**: Resolver: Read `"exports"` from the package root, and apply `"browser"` redirections to the file it resolves to, by default. Set `resolver.unstable_resolveExportsFromPackageRoot` and `resolver.unstable_applyBrowserSpecAfterExports` to `false` for the previous behavior (#2174 by @robhogan) - **[Breaking]**: Default `transformer.asyncRequireModulePath` and `resolver.emptyModulePath` to `metro:runtime/...`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest`, and code that reads either option as a file path must resolve it instead (#2180 by @robhogan) - **[Breaking]**: Resolve the module system via `metro:runtime/polyfills/require`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest` (#2184 by @robhogan) - **[Breaking]**: `transformer.globalPrefix` now also prefixes `__r`, `__c`, `__registerSegment` and `__accept`, and the default run statement. Code that calls these by name must apply the prefix (#2186 by @robhogan) - **[Breaking]**: Remove the deprecated `redirectModulePath` from `ResolutionContext`. A custom resolver should drop any call to it and delegate to `context.resolveRequest` or `resolve`, which already apply `"browser"` redirections and return `{type: 'empty'}` for `false` (#2181 by @robhogan) - **[Breaking]**: Remove the deprecated `doesFileExist` from `ResolutionContext`, and the `DoesFileExist` type from `metro-resolver` (use `fileSystemLookup`) (#2181 by @robhogan) - **[Breaking]**: `ResolutionContext.isESMImport` is required (#2182 by @robhogan) - **[Breaking]**: Async bundle and HMR module URLs keep the module's file extension (`foo.js.bundle`) and carry the bundle's `platform`, fixing lazy loading and HMR source maps for files whose extension isn't in `sourceExts` (e.g. `.cjs`, `.mjs`) or that share a name with a sibling (e.g. `foo.json` next to `foo.js`). Old URLs still work (#1990 by @dasjideepak) - **[Breaking]**: Babel transformers can no longer return a `functionMap`. Apply the `plugins` passed by Metro and return the resulting Babel `metadata` to keep function names in stack traces (#2157 by @robhogan) - **[Breaking]**: `/symbolicate` no longer reads `req.rawBody`, and fails if a middleware has already read the request body (#2158 by @robhogan) - **[Breaking]**: Remove the `bundle_transform_progressed_throttled` event from `TerminalReportableEvent`. `TerminalReporter` subclasses should handle `bundle_transform_progressed`, which their `_log` now receives for every progress update (#2170 by @vzaidman) - **[Breaking]**: Source and JSON files containing the reserved string `_$$_METRO_`, including in comments and string literals, now fail to transform (#2155 by @robhogan) - **[Breaking]**: Remove the deprecated, always-`true` `hot` option from `getTransformOptions` (#2159 by @robhogan) - **[Feature]**: Custom serializers receive the reserved string as `options.reservedString` (#2155 by @robhogan) - **[Fix]**: Don't print the terminal status in the middle of bursts of output written outside of it, and don't wait for a pending status update before exiting (#2170 by @vzaidman) - **[Fix]**: Fall back to file-based resolution, instead of throwing a `TypeError`, when a package's `"exports"` field is not a string, array or object (#2187 by @kwy404) - **[Fix]**: Fix relative symlinks on a different Windows drive than the project root (#2161 by @ramya-2196) - **[Performance]**: ~5-10% faster resolution (#2181 by @robhogan) > NOTE: Experimental features are not covered by semver and can change at any time. - **[Experimental]**: Remove `unstable_incrementalResolution` from `ResolutionContext`, and `metro-resolver/private/createDefaultContext` (#2181 by @robhogan) **Full Changelog**: v0.87.3...v0.88.0 ```
Summary: Publish Metro 0.88.0 from `main`. Changelog: [Internal] Test plan: ``` node scripts/updateVersion.js 0.88.0 sl diff --stat ``` Only the 17 `packages/*/package.json` manifests change, and every `0.87.3` reference is replaced. Flow, ESLint, Prettier, TypeScript, API snapshots, Markdown lint and Jest pass on this commit. Notable breakage in third parties, for the notes or a heads-up before React Native adopts this: - `@rnx-kit/metro-config` 2.2.6 adds `path.dirname(resolver.emptyModulePath)` as a watch folder when there are none, which is now `metro:runtime/modules`, so the dev server never serves a bundle for a single-package app. - `@tamagui/metro-plugin` 3.x refuses `metro-resolver` outside 0.84-0.87, and then imports the removed `metro-resolver/private/createDefaultContext`. - `@rnx-kit/metro-resolver-symlinks` calls the removed `context.redirectModulePath`. End to end (AI-driven), with the packed tarballs against 0.87.3 from npm, in a React Native 0.89.0-rc.0 template app with a few popular dependencies: dev and release bundles, source maps and assets for iOS and Android are byte-identical, except where #2174 changes resolution. `rxjs/operators` now resolves to the same ESM build as `rxjs`, dropping 190 duplicate modules, and `require('nanoid/non-secure')` gets nanoid's CJS build. With #2186, only the module system and `asyncRequire` differ besides those. Release builds reach the first screen on a Galaxy A16 and the iOS simulator. The dev server passes the same checks on both, with and without Watchman (edits, added and deleted files, HMR, `/symbolicate`, assets and lazy `import()`), and Fast Refresh works on the simulator. The end-to-end checks above were on 9de42bbed3b2, before #2170, #2157, #2158 and #1990 landed. I'm re-running them now and will update this. Draft release notes (from the 19 commits in v0.87.3...main - internal-only changes omitted): ``` - **[Breaking]**: Resolver: Read `"exports"` from the package root, and apply `"browser"` redirections to the file it resolves to, by default. Set `resolver.unstable_resolveExportsFromPackageRoot` and `resolver.unstable_applyBrowserSpecAfterExports` to `false` for the previous behavior (#2174 by @robhogan) - **[Breaking]**: Default `transformer.asyncRequireModulePath` and `resolver.emptyModulePath` to `metro:runtime/...`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest`, and code that reads either option as a file path must resolve it instead (#2180 by @robhogan) - **[Breaking]**: Resolve the module system via `metro:runtime/polyfills/require`. A custom `resolver.resolveRequest` must delegate `metro:` specifiers it doesn't handle to `context.resolveRequest` (#2184 by @robhogan) - **[Breaking]**: `transformer.globalPrefix` now also prefixes `__r`, `__c`, `__registerSegment` and `__accept`, and the default run statement. Code that calls these by name must apply the prefix (#2186 by @robhogan) - **[Breaking]**: Remove the deprecated `redirectModulePath` from `ResolutionContext`. A custom resolver should drop any call to it and delegate to `context.resolveRequest` or `resolve`, which already apply `"browser"` redirections and return `{type: 'empty'}` for `false` (#2181 by @robhogan) - **[Breaking]**: Remove the deprecated `doesFileExist` from `ResolutionContext`, and the `DoesFileExist` type from `metro-resolver` (use `fileSystemLookup`) (#2181 by @robhogan) - **[Breaking]**: `ResolutionContext.isESMImport` is required (#2182 by @robhogan) - **[Breaking]**: Async bundle and HMR module URLs keep the module's file extension (`foo.js.bundle`) and carry the bundle's `platform`, fixing lazy loading and HMR source maps for files whose extension isn't in `sourceExts` (e.g. `.cjs`, `.mjs`) or that share a name with a sibling (e.g. `foo.json` next to `foo.js`). Old URLs still work (#1990 by @dasjideepak) - **[Breaking]**: Babel transformers can no longer return a `functionMap`. Apply the `plugins` passed by Metro and return the resulting Babel `metadata` to keep function names in stack traces (#2157 by @robhogan) - **[Breaking]**: `/symbolicate` no longer reads `req.rawBody`, and fails if a middleware has already read the request body (#2158 by @robhogan) - **[Breaking]**: Remove the `bundle_transform_progressed_throttled` event from `TerminalReportableEvent`. `TerminalReporter` subclasses should handle `bundle_transform_progressed`, which their `_log` now receives for every progress update (#2170 by @vzaidman) - **[Breaking]**: Source and JSON files containing the reserved string `_$$_METRO_`, including in comments and string literals, now fail to transform (#2155 by @robhogan) - **[Breaking]**: Remove the deprecated, always-`true` `hot` option from `getTransformOptions` (#2159 by @robhogan) - **[Feature]**: Custom serializers receive the reserved string as `options.reservedString` (#2155 by @robhogan) - **[Fix]**: Don't print the terminal status in the middle of bursts of output written outside of it, and don't wait for a pending status update before exiting (#2170 by @vzaidman) - **[Fix]**: Fall back to file-based resolution, instead of throwing a `TypeError`, when a package's `"exports"` field is not a string, array or object (#2187 by @kwy404) - **[Fix]**: Fix relative symlinks on a different Windows drive than the project root (#2161 by @ramya-2196) - **[Performance]**: ~5-10% faster resolution (#2181 by @robhogan) > NOTE: Experimental features are not covered by semver and can change at any time. - **[Experimental]**: Remove `unstable_incrementalResolution` from `ResolutionContext`, and `metro-resolver/private/createDefaultContext` (#2181 by @robhogan) **Full Changelog**: v0.87.3...v0.88.0 ```
The worker's input Babel plugin writes function maps to
metadata, so this removes the deprecated fallback to afunctionMapreturned by the transformer. A custom transformer that doesn't apply thepluginsit's given loses function names in stack traces.Changelog:
Test plan:
Existing tests. React Native's transformer doesn't return one, and
@expo/metro-confighas its own worker.