diff --git a/packages/react-native-babel-preset/src/configs/main.js b/packages/react-native-babel-preset/src/configs/main.js index d4fc7e10378b..06e3d14e8575 100644 --- a/packages/react-native-babel-preset/src/configs/main.js +++ b/packages/react-native-babel-preset/src/configs/main.js @@ -39,12 +39,21 @@ function isFirstParty(fileName) { ); } +// Called by Babel whenever caller information changes between transform calls +// for a given config. If the return value changes, Babel re-evaluates +// getPreset, which is otherwise cached based on `options`. This must be pure, +// and should be cheap. +function getTransformProfile(caller) { + return caller?.unstable_transformProfile ?? 'default'; +} + // use `this.foo = bar` instead of `this.defineProperty('foo', ...)` const loose = true; -const getPreset = (src, options) => { +const getPreset = (src, options, babel) => { const transformProfile = - (options && options.unstable_transformProfile) || 'default'; + options?.unstable_transformProfile ?? babel?.caller(getTransformProfile); + const isHermesStable = transformProfile === 'hermes-stable'; const isHermesCanary = transformProfile === 'hermes-canary'; const isHermes = isHermesStable || isHermesCanary; @@ -252,14 +261,14 @@ const getPreset = (src, options) => { }; }; -module.exports = options => { +module.exports = (options, babel) => { if (options.withDevTools == null) { const env = process.env.BABEL_ENV || process.env.NODE_ENV; if (!env || env === 'development') { - return getPreset(null, {...options, dev: true}); + return getPreset(null, {...options, dev: true}, babel); } } - return getPreset(null, options); + return getPreset(null, options, babel); }; module.exports.getPreset = getPreset; diff --git a/packages/react-native-babel-preset/src/index.js b/packages/react-native-babel-preset/src/index.js index d2b5fc987213..e785c9759386 100644 --- a/packages/react-native-babel-preset/src/index.js +++ b/packages/react-native-babel-preset/src/index.js @@ -14,7 +14,7 @@ const {version: packageVersion} = require('../package.json'); const main = require('./configs/main'); module.exports = function (babel, options) { - return main(options); + return main(options, babel); }; let cacheKey; diff --git a/packages/react-native-babel-transformer/src/index.js b/packages/react-native-babel-transformer/src/index.js index d5e541c370a8..358d62f175be 100644 --- a/packages/react-native-babel-transformer/src/index.js +++ b/packages/react-native-babel-transformer/src/index.js @@ -193,7 +193,14 @@ const transform /*: BabelTransformer['transform'] */ = ({ // ES modules require sourceType='module' but OSS may not always want that sourceType: 'unambiguous', ...buildBabelConfig(filename, options, plugins), - caller: {name: 'metro', bundler: 'metro', platform: options.platform}, + caller: { + // Varies Babel's config cache - presets will be re-initialized + // if they use caller information. + name: 'metro', + bundler: 'metro', + platform: options.platform, + unstable_transformProfile: options.unstable_transformProfile, + }, ast: true, // NOTE(EvanBacon): We split the parse/transform steps up to accommodate