Skip to content

Commit 9ddd052

Browse files
authored
fix(Worklets): Bundle Mode accidentally toggling in Expo54 (#8335)
## Summary Expo 54 performs eager imports contrary to Metro which is lazy. This results in `workletRuntimeEntry.ts` file to be executed and for the `globalThis._WORKLETS_BUNDLE_MODE` flag to be set wrongfully to `true`. To handle both eager and lazy imports environments I decided to handle the setting of the flag's value in Worklets Babel Plugin. Worklets Babel Plugin makes it so the expression in `workletRuntimeEntry.ts`: ```ts globalThis._WORKLETS_BUNDLE_MODE = false ``` becomes ```ts globalThis._WORKLETS_BUNDLE_MODE = true ``` when Bundle Mode is enabled. ## Test plan I tested these changes with an Expo 54 app and they worked.
1 parent afaec37 commit 9ddd052

File tree

4 files changed

+110
-3
lines changed

4 files changed

+110
-3
lines changed

packages/react-native-worklets/plugin/index.js

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import type { NodePath } from '@babel/core';
2+
import { booleanLiteral, type ExpressionStatement } from '@babel/types';
3+
4+
import type { ReanimatedPluginPass } from './types';
5+
6+
/**
7+
* This function replaces the `false` value in
8+
*
9+
* `globalThis._WORKLETS_BUNDLE_MODE = false;`
10+
*
11+
* With `true` in the `workletRuntimeEntry` file when the `bundleMode` option is
12+
* enabled in the Babel plugin.
13+
*
14+
* This way Bundle Mode is not accidentally set up in eager import environments,
15+
*/
16+
export function toggleBundleMode(
17+
path: NodePath<ExpressionStatement>,
18+
state: ReanimatedPluginPass
19+
) {
20+
if (
21+
!state.opts.bundleMode ||
22+
!state.filename?.includes('workletRuntimeEntry')
23+
) {
24+
return;
25+
}
26+
27+
const expressionPath = path.get('expression');
28+
29+
if (!expressionPath.isAssignmentExpression()) {
30+
return;
31+
}
32+
33+
const left = expressionPath.get('left');
34+
35+
if (!left.isMemberExpression()) {
36+
return;
37+
}
38+
39+
const object = left.get('object');
40+
const property = left.get('property');
41+
42+
if (
43+
!object.isIdentifier() ||
44+
object.node.name !== 'globalThis' ||
45+
!property.isIdentifier() ||
46+
property.node.name !== '_WORKLETS_BUNDLE_MODE'
47+
) {
48+
return;
49+
}
50+
51+
const right = expressionPath.get('right');
52+
53+
right.replaceWith(booleanLiteral(true));
54+
}

packages/react-native-worklets/plugin/src/plugin.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { NodePath, PluginItem } from '@babel/core';
22
import type {
33
CallExpression,
44
ClassDeclaration,
5+
ExpressionStatement,
56
JSXAttribute,
67
ObjectExpression,
78
Program,
@@ -11,6 +12,7 @@ import {
1112
processCalleesAutoworkletizableCallbacks,
1213
processIfAutoworkletizableCallback,
1314
} from './autoworkletization';
15+
import { toggleBundleMode } from './bundleMode';
1416
import { processIfWorkletClass } from './class';
1517
import { processIfWorkletContextObject } from './contextObject';
1618
import { processIfWorkletFile } from './file';
@@ -85,6 +87,16 @@ module.exports = function WorkletsBabelPlugin(): PluginItem {
8587
});
8688
},
8789
},
90+
ExpressionStatement: {
91+
enter(
92+
path: NodePath<ExpressionStatement>,
93+
state: ReanimatedPluginPass
94+
) {
95+
runWithTaggedExceptions(() => {
96+
toggleBundleMode(path, state);
97+
});
98+
},
99+
},
88100
JSXAttribute: {
89101
enter(path: NodePath<JSXAttribute>, state: ReanimatedPluginPass) {
90102
runWithTaggedExceptions(() =>

packages/react-native-worklets/src/workletRuntimeEntry.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ import { WorkletsError } from './WorkletsError';
1818
* `_WORKLETS_BUNDLE_MODE` flag.
1919
*/
2020
export function bundleModeInit() {
21-
if (SHOULD_BE_USE_WEB) {
21+
// Worklets Babel Plugin replaces `false` with `true` here
22+
// when Bundle Mode is enabled.
23+
globalThis._WORKLETS_BUNDLE_MODE = false;
24+
25+
if (SHOULD_BE_USE_WEB || !globalThis._WORKLETS_BUNDLE_MODE) {
2226
return;
2327
}
2428

25-
globalThis._WORKLETS_BUNDLE_MODE = true;
26-
2729
const runtimeKind = globalThis.__RUNTIME_KIND;
2830
if (runtimeKind && runtimeKind !== RuntimeKind.ReactNative) {
2931
/**

0 commit comments

Comments
 (0)