worklets plugin: preserve JSX imports in bundle mode#9212
Conversation
a9f06c3 to
82991ed
Compare
tjzel
left a comment
There was a problem hiding this comment.
As we discussed briefly off-discord - I think there's no need to add a separate option for that. In Bundle Mode we should preserve JSX as long as it comes from modules allowed for imports.
Could you also add a runtime tests suite in /apps/common-app/src/apps/reanimated/examples/RuntimeTests/tests/plugin that checks if worklets with JSX work at runtime?
034c867 to
0470a3f
Compare
|
Hey @tjzel, i reworked the PR to just preserve JSX in general, without hiding it between an option. When testing in the example app i ran into this issue though: I made a "fix" for that here: This PR depends on the mentioned PR. |
|
I checked this against latest I made a test branch and applied only the JSX capture changes from this PR, without the generated JSX transform fix from #9610. The unit tests and typecheck pass, but bundling the Fabric example in bundle mode still fails with the same JSX dev transform error: So #9618 fixes the multiple-pass/autoworkletization case, but it does not seem to cover this specific JSX-in-generated-worklet-file case. So it seems like something like #9610 is still required unfortunately :/ |
332d63f to
1ecc161
Compare
| const transformedProg = transformFromAstSync(newProg, undefined, { | ||
| filename: state.file.opts.filename, | ||
| presets: ['@babel/preset-typescript'], | ||
| presets: ['@babel/preset-typescript', [reactPreset, reactPresetOptions]], |
There was a problem hiding this comment.
I looked into it and it turns out that the transformation that adds __self is added when entering the whole Program so when generating the worklet file we already have that in.
I think that instead of transforming it with react-preset to _jsx form maybe we should revert the work of that plugin, namely strip the __self and __source props to be closer to a real source file https://babeljs.io/docs/babel-preset-react#development.
A minimal plugin like this:
diff --git a/packages/react-native-worklets/plugin/src/closure.ts b/packages/react-native-worklets/plugin/src/closure.ts
index bac569c82d..34e998b910 100644
--- a/packages/react-native-worklets/plugin/src/closure.ts
+++ b/packages/react-native-worklets/plugin/src/closure.ts
@@ -32,7 +32,7 @@ export function getClosure(
typePath.skip();
},
ReferencedIdentifier(idPath) {
- if (idPath.isJSXIdentifier()) {
+ if (idPath.isJSXIdentifier() && !state.opts.bundleMode) {
return;
}
diff --git a/packages/react-native-worklets/plugin/src/generate.ts b/packages/react-native-worklets/plugin/src/generate.ts
index 32906d4244..87a54d9d26 100644
--- a/packages/react-native-worklets/plugin/src/generate.ts
+++ b/packages/react-native-worklets/plugin/src/generate.ts
@@ -4,6 +4,7 @@ import type {
FunctionExpression,
ImportDeclaration,
ImportSpecifier,
+ JSXAttribute,
} from '@babel/types';
import {
cloneNode,
@@ -72,7 +73,7 @@ export function generateWorkletFile(
const transformedProg = transformFromAstSync(newProg, undefined, {
filename: state.file.opts.filename,
presets: ['@babel/preset-typescript'],
- plugins: [state.autoworkletizationPlugin],
+ plugins: [state.autoworkletizationPlugin, stripJsxDevAttributesPlugin],
ast: false,
babelrc: false,
configFile: false,
@@ -85,3 +86,18 @@ export function generateWorkletFile(
writeFileSync(dedicatedFilePath, transformedProg);
}
+
+const stripJsxDevAttributesPlugin = {
+ name: 'worklets-strip-jsx-dev-attributes',
+ visitor: {
+ JSXAttribute(path: NodePath<JSXAttribute>) {
+ const name = path.node.name;
+ if (
+ name.type === 'JSXIdentifier' &&
+ (name.name === '__self' || name.name === '__source')
+ ) {
+ path.remove();
+ }
+ },
+ },
+};solved the issue for me with metro bundling. Could you see if it works for you too?
Summary
Caution
This PR depends on:
Without ^ this PR you'd get bundle time errors when trying to use JSX in the example app!
This adds support for importing JSX statements/imports in worklets bundle mode!
Test plan