Repository navigation
Conversation
…w-loader flow-remove-types only erases type annotations, so on React Native 0.81+ flow-loader (and getJsTransformRules) emitted invalid JS for `component` / `hook` declarations, Flow enums and `match` expressions. Files using them now go through the project's React Native parser (hermes-parser or flow-parser) and @babel/plugin-transform-flow-strip-types; all other files still use flow-remove-types. Enums are lowered to flow-enums-runtime, resolved from the project or from react-native so it works with isolated installs. Source maps are emitted for lowered files. Also fix flow-loader crashing under webpack: getOptions() received the loader context as a schema. Part of callstack#1422
Flow `component` declarations with a `ref` are lowered to `forwardRef` on React 18 and pass `ref` as a prop on React 19. Pick the target from the project's `react` version instead of always assuming React 19. Part of callstack#1422
@react-native/babel-preset strips Flow enum declarations before its enum plugin runs, so references such as React Native's VirtualViewMode.cast() were undefined at runtime. Parse @flow sources with the shared parseReactNativeSource helper, which lowers enums to flow-enums-runtime and picks the component lowering target from the project's React version (hermesParserOverrides still take precedence). Related to callstack#1422
- detect multi-line `match (...)` in flow-loader's prefilter and cover the routing with unit tests - strip class fields of lowered files like flow-remove-types does: allow `declare` fields and honour `ignoreUninitializedFields` - require @babel/core only when a file needs lowering - cache flow-enums-runtime and React version lookups per project root - share the preset lookup and wrap its resolution errors - pin unused import preservation in a file that is not lowered Part of callstack#1422
🦋 Changeset detectedLatest commit: 1c62da2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@whydidoo is attempting to deploy a commit to the Callstack Team on Vercel. A member of the Team first needs to authorize it. |
| try { | ||
| if (needsFlowLowering(source)) { | ||
| const { code, map } = await lowerFlowSyntax(this, source, options); | ||
| callback(null, code, map as RawSourceMap | undefined); |
There was a problem hiding this comment.
When a file goes through the lowering path, this passes Babel's source map to the next loader as an object. babel-swc-loader (babelSwcLoader.ts:111) and babel-loader (babelLoader.ts:146) both run JSON.parse(sourceMap) on it, which throws SyntaxError: "[object Object]" is not valid JSON. So the new lowering breaks whenever flow-loader runs before one of the Babel loaders with source maps on, and source maps are on by default in dev.
How I reproduced it in apps/tester-app on this PR's head (rspack, babel-swc-loader config, iOS simulator):
- Added the flow-loader rule from the Flow support docs (
test: /\.jsx?$/,exclude: /node_modules/,options: { all: true }). - Added a
// @flowfile undersrc/that usescomponentsyntax and imported it fromApp.tsx. webpack-bundle --dev=truefails on that module, and so does the dev server. On the device the app shows a red box:Module build failed: SyntaxError: "[object Object]" is not valid JSON at Object.babelSwcLoader (babelSwcLoader.js:86:43).
With devtool: false it builds. I also got the same error with babel-loader in a standalone project. Without the parallel worker, the error happens before the loader's try, so it takes down the Node process instead of showing up as a module error.
This isn't a regression: on the base commit the same setup already failed, with Missing semicolon, because flow-remove-types leaves component in place. It does mean the fix doesn't take effect for anyone using flow-loader with a Babel loader. getJsTransformRules (builtin swc-loader) accepts the object and works fine.
I checked a one-line change in babelSwcLoader.ts that fixes it. The bundle builds and the component renders on the simulator:
const inputSourceMap: InputSourceMap = sourceMap
? typeof sourceMap === 'string'
? JSON.parse(sourceMap)
: sourceMap
: undefined;Could you do the same in babelLoader.ts? That also covers the existing pretty: true path, which already returns an object from generateMap(). Alternatively flow-loader could pass JSON.stringify(map), but accepting both seems more robust. A test that chains flow-loader into babel-swc-loader with devtool set would catch this.
|
Addin to that @dannyhw already said here: Some notes on the enum part: The cause is in babel.transformSync('// @flow\nenum Mode { A = 0 }\nexport const x = Mode.cast(0);', {
presets: ['@react-native/babel-preset'],
});
// → var x = exports.x = Mode.cast(0); (the enum is gone)It isn't Re.Pack-specific either: a Metro bundle of the same app never defines The fix only covers files that go through the hermes-parser path. Enum lowering lives in A simpler option to consider: add plugins: [
[
require.resolve('babel-plugin-transform-flow-enums', { paths: [presetDir] }),
{
getRuntime: (t) =>
t.callExpression(t.identifier('require'), [t.stringLiteral(flowEnumsRuntimePath)]),
},
],
],I checked that this produces Not a blocker. The current approach works in my tests, but this would be less code and would cover enums in every file. |
# Conflicts: # tests/integration/src/loaders/react-native-parser.test.ts
|
@dannyhw @CristiCeban thanks, both addressed:
|
Part of #1422 (v5 patch).
Summary
On RN 0.81+,
flow-loader(and sogetJsTransformRules) emitted invalid JS, becauseflow-remove-typesleaves Flowcomponent/hook/enum/matchin place. Separately,@react-native/babel-presetdrops Flow enums inbabel-loaderandbabel-swc-loader, so RN'sVirtualViewMode.cast()threw at runtime.flow-enums-runtime, resolved from the project orreact-native, so it works with pnpm.componentlowering follows the project's React version:forwardRefon 18,refas a prop on 19.flow-loadercrashing under webpack.Test plan
tests/integration, presets 0.87/0.88 × rspack/webpack: component, hook, enum, match, class fields, source maps, React 18/19, enums in both Babel loaders,getJsTransformRuleswith a pnpm Flow dependency.rspack-swcconfig in tester-app bundles real RN 0.86.3. It failed before this change onView.js.