Skip to content

Commit 2dc5e3a

Browse files
robhoganfacebook-github-bot
authored andcommitted
Inline Platform within RN’s Babel preset
Summary: Adds a React Native-owned Babel plugin that inlines `Platform.OS` and `Platform.select(...)`, from `react-native/babel-preset` at the front of the preset's plugin list (importantly, before the preset lowers ES modules to CommonJS). Metro already inlines `Platform`, but its matcher (`metro-transform-plugins`' `inline-plugin` via `createInlinePlatformChecks`) runs *after* ESM has been lowered to CommonJS. By then a genuine `import {Platform} from 'react-native'` has become `_reactNative.Platform.OS` and the specifier proving the value came from React Native is gone. Metro compensates by matching on the local identifier spelling - so `Platform.OS` inlines whether or not `Platform` is actually React Native's, and a genuine deep or RN-relative import may be missed entirely. `Platform` inlining is in any case much more of an RN concern than a Metro one - it has to be aware of RN APIs and module names, and even the module’s path. This plugin recognises: - `import {Platform} from 'react-native'` (including aliased imports) - `import * as RN from 'react-native'`, uses of `RN.Platform` - `import P from 'react-native/Libraries/Utilities/Platform'` - the equivalent `require` forms, plus destructuring and immutable aliases - RN's internal relative imports, e.g. `../../Utilities/Platform` …and deliberately does *not* recognise anything it cannot prove - a bare `Platform.OS` global, `React.Platform.OS`, or a same-named import from another package. Metro's late matcher is left fully enabled and remains responsible for those historical forms, so this change is purely additive: it inlines genuine imports Metro was missing, and changes nothing Metro already handled. Metro’s plugin will be deprecated and removed in future. Notable details: - Relative RN imports are resolved lexically, with no filesystem access and no platform-extension resolution — the identity we need is the extension-less module `<rn-root>/Libraries/Utilities/Platform`, and Metro picks `Platform.ios.js` / `Platform.android.js` later. The RN package root is identified by directory name, which covers `node_modules/react-native`, `packages/react-native` and pnpm layouts alike, and rejects `react-native-web` and friends (who would be expected to adjust the paths in their forks) - Imports are left in place. Removing them would change dependency collection, so it is handled separately. - A no-platform build (`null`, or the empty string that RN's Jest preprocessor passes) is a no-op — inlining `Platform.OS` to `""` would be wrong. - The plugin source is added to the preset's `getCacheKey` so edits invalidate Metro's transform cache. Changelog: [General][Changed] - Inline `Platform.OS` and `Platform.select(...)` for React Native `Platform` imports during the Babel preset, covering some cases that were previously left un-inlined. Differential Revision: D114647943
1 parent 3f3425e commit 2dc5e3a

5 files changed

Lines changed: 1261 additions & 0 deletions

File tree

0 commit comments

Comments
 (0)