Skip to content

Pass Metro's own @babel/runtime and its version to Babel presets via caller - #1957

Draft
robhogan wants to merge 1 commit into
mainfrom
pr1957
Draft

robhogan wants to merge 1 commit into
mainfrom
pr1957

Conversation

@robhogan

@robhogan robhogan commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up to 8388f71 (the default metro: scheme resolver), which maps metro:babel-runtime/<path> to metro-runtime's own @babel/runtime. This is the Metro half of pointing @babel/plugin-transform-runtime at it. The preset half is react/react-native#57974, and this is a no-op until a preset reads it.

When transformer.enableBabelRuntime is true (the default), Metro passes presets babelRuntimeModuleName: 'metro:babel-runtime' and the installed version of that @babel/runtime as Babel caller data, matching what @react-native/babel-preset reads. Caller data reaches a preset however it's configured, including via a project babel.config.js.

The version is read from the installed package rather than pinned, so it's added to the transform cache key. A string enableBabelRuntime (a version for the project's own @babel/runtime) keeps its meaning and passes neither value. It's now documented as deprecated, since a version describing the project's copy is meaningless once helpers come from Metro's.

Changelog:

 - **[Feature]**: When `transformer.enableBabelRuntime` is `true`, pass Metro's own `@babel/runtime` (`metro:babel-runtime`) and its installed version to Babel presets via caller data
 - **[Deprecated]**: String values of `transformer.enableBabelRuntime` (use `true`)

Test plan:
New integration test builds and runs a bundle through the full Metro + Babel pipeline, with a preset that reads the caller data as @react-native/babel-preset does. The fixture uses import * as, whose helper is only external from @babel/runtime 7.14.0, so it's imported rather than inlined only if the version reaches the preset. Verified with enableBabelRuntime both true and false.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 21, 2026
@robhogan
robhogan force-pushed the pr1957 branch 2 times, most recently from d9dcf8f to cb7a1fe Compare September 21, 2026 14:34
@robhogan robhogan changed the title Pass metro:babel-runtime to Babel presets as the runtime module name via caller Pass Metro's own @babel/runtime and its version to Babel presets via caller Sep 21, 2026
…caller

Summary:
Follow-up to 8388f71 (the default `metro:` scheme resolver), which maps `metro:babel-runtime/<path>` to metro-runtime's own `@babel/runtime` dependency. This diff is the Metro half of pointing `@babel/plugin-transform-runtime` at it.

When `transformer.enableBabelRuntime` is literally `true` (the default), the transform worker passes the Babel transformer `babelRuntimeModuleName: 'metro:babel-runtime'` and `babelRuntimeVersion` - the installed version of that `@babel/runtime`. `metro-babel-transformer` forwards them to presets as Babel caller data, as `babelRuntimeModuleName` and `enableBabelRuntime` respectively, matching what `@react-native/babel-preset` reads from react/react-native#57974. Caller data reaches a preset however it's configured - including via a project `babel.config.js`, where the preset's options come from the user.

The version is read from the installed `package.json` rather than pinned to metro-runtime's range floor, so output benefits from runtime updates without a manual sync. Because that makes transform output depend on it, the `package.json` is added to the transform worker's cache key when `enableBabelRuntime` is `true`.

A string `enableBabelRuntime` keeps its current meaning (a version for the project's own `@babel/runtime`) and passes neither value. It's now documented as deprecated in favour of `true`, since a version describing the project's copy is meaningless once helpers come from Metro's.

The lookup of metro-runtime's `@babel/runtime` moves from `metroSchemeResolver` into a shared `metro/private/lib/metroBabelRuntime`, so the resolver and the worker agree on the same copy.

This is a no-op until a preset reads it.

Changelog:
```
 - **[Feature]**: When `transformer.enableBabelRuntime` is `true`, pass Metro's own `@babel/runtime` (`metro:babel-runtime`) and its installed version to Babel presets via caller data
 - **[Deprecated]**: String values of `transformer.enableBabelRuntime` (use `true`)
```

Test plan:
New integration test (`integration_tests/__tests__/babel-runtime-test.js`) builds and executes a bundle through the full Metro + Babel pipeline with Metro's own `metro-babel-transformer`, and a fixture `babel.config.js` whose preset reads `@babel/runtime` configuration from caller data, as `@react-native/babel-preset` does. The fixture uses `import * as`, whose `interopRequireWildcard` helper is only available from `@babel/runtime` 7.14.0, so it's imported rather than inlined only if the installed version reaches the preset:
 - With `enableBabelRuntime: true`, the bundle imports `metro:babel-runtime/helpers/interopRequireWildcard`, which resolves to metro-runtime's own `@babel/runtime`, and executes correctly.
 - With `enableBabelRuntime: false`, the helper is inlined, and the bundle executes correctly.

```
yarn jest packages/metro/src/integration_tests packages/metro-transform-worker packages/metro-babel-transformer packages/metro/src/lib
yarn flow check
yarn build-ts-defs && yarn verify-api-snapshots
yarn typecheck-ts
```

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant