Skip to content

Commit a4cef53

Browse files
authored
fix(Worklets): re-workletizing in bundle mode (#8428)
## Summary __This change applies only to the Bundle Mode__ Prevent bundle mode re-workletizing already workletized files, i.e.: ```js // file.js function callback() { scheduleOnUI(callback); } ``` Produces: ```js // file.out.js const callback = require("react-native-worklets/__generatedWorklets/16394205897371.js").default({ scheduleOnUI }); ``` and ```js // react-native-worklets/__generatedWorklets/16394205897371.js export default (function callback_fileJs1Factory({ scheduleOnUI }) { const callback = function () { scheduleOnUI(callback); }; callback.__closure = { scheduleOnUI }; callback.__workletHash = 16394205897371; return callback; }); ``` and then erroneously transforms it into ```js // react-native-worklets/__generatedWorklets/16394205897371.out.js export default (function callback_fileJs1Factory({ scheduleOnUI }) { const callback = require("react-native-worklets/__generatedWorklets/12241415968957.js").default({ scheduleOnUI, callback }); callback.__closure = { scheduleOnUI }; callback.__workletHash = 16394205897371; return callback; }); ``` and creates ```js // react-native-worklets/__generatedWorklets/12241415968957.js export default (function callback_fileJs1Factory({ scheduleOnUI }) { const callback = function () { scheduleOnUI(callback); }; callback.__closure = { scheduleOnUI }; callback.__workletHash = 16394205897371; return callback; }); ``` With these changes the transformation of `react-native-worklets/__generatedWorklets/16394205897371.js` is idempotent. ## Test plan Trust me bro 👍
1 parent 60a9212 commit a4cef53

File tree

4 files changed

+65
-28
lines changed

4 files changed

+65
-28
lines changed

packages/react-native-worklets/plugin/babel.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = {
88
[
99
workletsPlugin,
1010
{
11-
// bundleMode true,
11+
// bundleMode: true,
1212
},
1313
],
1414
],

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

Lines changed: 23 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ function processArgs(
128128
const maybeWorklet = findWorklet(
129129
arg,
130130
acceptWorkletizableFunction,
131-
acceptObject
131+
acceptObject,
132+
state
132133
);
133134
// @ts-expect-error There's no need to workletize
134135
// inside an already workletized function.
@@ -146,7 +147,8 @@ function processArgs(
146147
function findWorklet(
147148
arg: NodePath,
148149
acceptWorkletizableFunction: boolean,
149-
acceptObject: boolean
150+
acceptObject: boolean,
151+
state: ReanimatedPluginPass
150152
): NodePath<WorkletizableFunction> | NodePath<WorkletizableObject> | undefined {
151153
if (acceptWorkletizableFunction && isWorkletizableFunctionPath(arg)) {
152154
return arg;
@@ -158,7 +160,8 @@ function findWorklet(
158160
return findReferencedWorklet(
159161
arg,
160162
acceptWorkletizableFunction,
161-
acceptObject
163+
acceptObject,
164+
state
162165
);
163166
}
164167
return undefined;

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

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import type { NodePath } from '@babel/core';
22
import type { Binding } from '@babel/traverse';
33
import type { AssignmentExpression, Identifier } from '@babel/types';
4+
import { isIdentifier, isMemberExpression } from '@babel/types';
45

5-
import type { WorkletizableFunction, WorkletizableObject } from './types';
6+
import type {
7+
ReanimatedPluginPass,
8+
WorkletizableFunction,
9+
WorkletizableObject,
10+
} from './types';
611
import {
712
isWorkletizableFunctionPath,
813
isWorkletizableObjectPath,
@@ -11,7 +16,8 @@ import {
1116
export function findReferencedWorklet(
1217
workletIdentifier: NodePath<Identifier>,
1318
acceptWorkletizableFunction: boolean,
14-
acceptObject: boolean
19+
acceptObject: boolean,
20+
state: ReanimatedPluginPass
1521
): NodePath<WorkletizableFunction> | NodePath<WorkletizableObject> | undefined {
1622
const workletName = workletIdentifier.node.name;
1723
const scope = workletIdentifier.scope;
@@ -21,6 +27,10 @@ export function findReferencedWorklet(
2127
return undefined;
2228
}
2329

30+
if (state.opts.bundleMode && bindingIsWorklet(workletBinding)) {
31+
return undefined;
32+
}
33+
2434
if (
2535
acceptWorkletizableFunction &&
2636
workletBinding.path.isFunctionDeclaration()
@@ -33,20 +43,23 @@ export function findReferencedWorklet(
3343
return findReferencedWorkletFromVariableDeclarator(
3444
workletBinding,
3545
acceptWorkletizableFunction,
36-
acceptObject
46+
acceptObject,
47+
state
3748
);
3849
}
3950
return findReferencedWorkletFromAssignmentExpression(
4051
workletBinding,
4152
acceptWorkletizableFunction,
42-
acceptObject
53+
acceptObject,
54+
state
4355
);
4456
}
4557

4658
function findReferencedWorkletFromVariableDeclarator(
4759
workletBinding: Binding,
4860
acceptWorkletizableFunction: boolean,
49-
acceptObject: boolean
61+
acceptObject: boolean,
62+
state: ReanimatedPluginPass
5063
): NodePath<WorkletizableFunction> | NodePath<WorkletizableObject> | undefined {
5164
const workletDeclaration = workletBinding.path;
5265
if (!workletDeclaration.isVariableDeclarator()) {
@@ -64,7 +77,8 @@ function findReferencedWorkletFromVariableDeclarator(
6477
return findReferencedWorklet(
6578
worklet,
6679
acceptWorkletizableFunction,
67-
acceptObject
80+
acceptObject,
81+
state
6882
);
6983
}
7084
return undefined;
@@ -73,7 +87,8 @@ function findReferencedWorkletFromVariableDeclarator(
7387
function findReferencedWorkletFromAssignmentExpression(
7488
workletBinding: Binding,
7589
acceptWorkletizableFunction: boolean,
76-
acceptObject: boolean
90+
acceptObject: boolean,
91+
state: ReanimatedPluginPass
7792
): NodePath<WorkletizableFunction> | NodePath<WorkletizableObject> | undefined {
7893
const workletDeclaration = workletBinding.constantViolations
7994
.reverse()
@@ -108,8 +123,20 @@ function findReferencedWorkletFromAssignmentExpression(
108123
return findReferencedWorklet(
109124
workletDefinition,
110125
acceptWorkletizableFunction,
111-
acceptObject
126+
acceptObject,
127+
state
112128
);
113129
}
114130
return undefined;
115131
}
132+
133+
function bindingIsWorklet(binding: Binding) {
134+
return binding.referencePaths.some(
135+
(refPath) =>
136+
!Array.isArray(refPath.container) &&
137+
isMemberExpression(refPath.container) &&
138+
refPath.container.object === refPath.node &&
139+
isIdentifier(refPath.container.property) &&
140+
refPath.container.property.name === '__workletHash'
141+
);
142+
}

0 commit comments

Comments
 (0)