New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow worklet referencing in plugin #5911
base: main
Are you sure you want to change the base?
Conversation
__tests__/plugin.test.ts
Outdated
describe('for runOnUI', () => { | ||
it('workletizes ArrowFunctionExpression inside runOnUI automatically', () => { | ||
const input = html`<script> | ||
runOnUI(() => { | ||
console.log('Hello from the UI thread!'); | ||
})(); | ||
</script>`; | ||
|
||
const { code } = runPlugin(input); | ||
expect(code).toHaveWorkletData(); | ||
expect(code).toMatchSnapshot(); | ||
}); | ||
|
||
it('workletizes unnamed FunctionExpression inside runOnUI automatically', () => { | ||
const input = html`<script> | ||
runOnUI(function () { | ||
console.log('Hello from the UI thread!'); | ||
})(); | ||
</script>`; | ||
|
||
const { code } = runPlugin(input); | ||
expect(code).toHaveWorkletData(); | ||
expect(code).toMatchSnapshot(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were duplicate tests of function hooks
suite.
plugin/src/autoworkletization.ts
Outdated
@@ -124,6 +125,9 @@ function processArguments( | |||
// workletizable argument doesn't always have to be specified | |||
return; | |||
} | |||
if (maybeWorklet.isReferencedIdentifier() && maybeWorklet.isIdentifier()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need this condition in such shape since JSX tags can be referenced identifiers but they're not identifiers.
…m/software-mansion/react-native-reanimated into @tjzel/plugin/worklet-referencing
runOnUI(function hello() { | ||
console.log('Hello from the UI thread!'); | ||
})(); | ||
const style = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use styleFactory
or styleWorklet
instead of just style
]); | ||
|
||
const functionHooks = new Set([ | ||
`useFrameCallback`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`useFrameCallback`, | |
'useFrameCallback', |
and so on
Why
Currently, when handling worklet callbacks, the user has either to mark a function directly with
worklet
directive or define the worklet as an inline argument.This pull request allows the user to define a worklet outside of a hook argument to get it autoworkletized. Keep in mind that it still has some boundaries:
?
operator). This however could be adjusted in the future.What
We are allowing the following constructions to be autoworkletized.
useAnimatedStyle
will be used as a example hook here, it will work with every bit of our API that facilitates autoworkletization.Function declarations
Function expressions
Arrow function expression
Object methods
This is a special case, used for example by
useAnimatedScrollHandler
.It doesn't matter if the method is actually an arrow function or function expression. Keep in mind that it actually has to be defined in place. As of now we don't support such deep cases as:
How
Changes implemented here are quite simple. The only thing we do is search the scope of a given context (that's usually a function) for a referenced identifier. For example:
The
styleFactory
identifier is referenced in theuseAnimatedStyle
call. We then search the scope of the function for a reference tostyleFactory
and look for variable declarations, variable assignments, and function declarations.If we find one of these, that can be autoworkletized, we do it. If there are multiple objects that can be autoworkletized, we pick the first one using the following rules:
Therefore in the following code:
Only the
function baz
will be autoworkletized. Keep in mind that this is just an edge-case scenario. Please don't ever write such code when using worklets!Scoping
We also support multiple scoping, for example:
Will work as expected. It follows the same rules as above. For now we don't support variable shadowing - expect undefined behavior there.
Notes
Currently we expect the worklet variable not to be reassigned after it's been used. For example, the following code will not work:
Because only the last assignment will be workletized. The first assignment will not be transformed and
useAnimatedStyle
will throw an error. This is desired behavior, since reassigning worklet variables is considered an anti-pattern right now.Test plan