-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Throw error when calling runOnUI
on the UI runtime
#4477
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
piaskowyk
approved these changes
May 19, 2023
tjzel
approved these changes
May 24, 2023
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.
👏
Merged
tomekzaw
added a commit
that referenced
this pull request
May 24, 2023
## Summary This PR fixes the following error which appeared after #4477. <img width="779" alt="error" src="https://github.com/software-mansion/react-native-reanimated/assets/20516055/4d5f7a2f-1f59-43ac-bce2-7ae8ed6bccf0"> ## Test plan Check if WebExample works.
fluiddot
pushed a commit
to wordpress-mobile/react-native-reanimated
that referenced
this pull request
Jun 5, 2023
…n#4477) ## Summary This PR adds a check that throws an error with a developer-friendly message when trying to call `runOnUI` function from a worklet which is already running on the UI runtime. ## Motivation It's difficult to decide what's the expected behavior of `runOnUI` in such case: * If the function should be scheduled for the current animation frame, use `queueMicrotask`. * If the function should be scheduled for the next animation frame, use `requestAnimationFrame`. * If the function should be executed immediately, simply call it synchronously. Note that neither `setTimeout` nor `setInterval` are implemented on the UI runtime. Also, `setImmediate` is not available as well as it's not a part of the standard. ## Implementation Currently, calling `runOnUI` on the UI thread throws an error "Tried to synchronously call..." because `runOnUI` is not marked as a worklet. Adding `'worklet';` directive causes "cannot add new property" error because `_runOnUIQueue` gets frozen while cloning the worklet to the UI runtime. This PR adds `_runOnUIQueue` to the whitelisted identifiers in Reanimated Babel plugin so it doesn't get captured into the closure, thus doesn't need to be cloned and frozen. ## Alternatives We could replace all occurrences of `_runOnUIQueue` with `global._runOnUIQueue` so that the queue isn't captured into worklet closure and thus doesn't get frozen. Another option would be simply to whitelist `runOnUI` function but it wouldn't work properly when aliased. ## Test plan <details> <summary>App.tsx</summary> ```tsx import { Button, StyleSheet, View } from 'react-native'; import React from 'react'; import { runOnUI } from 'react-native-reanimated'; export default function App() { const handlePress = () => { runOnUI(() => { 'worklet'; console.log(_WORKLET, 'Hello from the UI thread!'); runOnUI(() => { 'worklet'; console.log(_WORKLET, 'Hello from the UI thread again!'); })(); })(); }; return ( <View style={styles.container}> <Button title="Click me" onPress={handlePress} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, }); ``` </details> ```ts runOnUI(() => { 'worklet'; console.log(_WORKLET, 'Hello from the UI thread!'); runOnUI(() => { 'worklet'; console.log(_WORKLET, 'Hello from the UI thread again!'); })(); })(); ``` Your beautiful eyes should see the following error: <img width="503" alt="error" src="https://github.com/software-mansion/react-native-reanimated/assets/20516055/2a158606-7957-432d-9336-ab9ea8323402">
fluiddot
pushed a commit
to wordpress-mobile/react-native-reanimated
that referenced
this pull request
Jun 5, 2023
## Summary This PR fixes the following error which appeared after software-mansion#4477. <img width="779" alt="error" src="https://github.com/software-mansion/react-native-reanimated/assets/20516055/4d5f7a2f-1f59-43ac-bce2-7ae8ed6bccf0"> ## Test plan Check if WebExample works.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds a check that throws an error with a developer-friendly message when trying to call
runOnUI
function from a worklet which is already running on the UI runtime.Motivation
It's difficult to decide what's the expected behavior of
runOnUI
in such case:queueMicrotask
.requestAnimationFrame
.Note that neither
setTimeout
norsetInterval
are implemented on the UI runtime. Also,setImmediate
is not available as well as it's not a part of the standard.Implementation
Currently, calling
runOnUI
on the UI thread throws an error "Tried to synchronously call..." becauserunOnUI
is not marked as a worklet. Adding'worklet';
directive causes "cannot add new property" error because_runOnUIQueue
gets frozen while cloning the worklet to the UI runtime. This PR adds_runOnUIQueue
to the whitelisted identifiers in Reanimated Babel plugin so it doesn't get captured into the closure, thus doesn't need to be cloned and frozen.Alternatives
We could replace all occurrences of
_runOnUIQueue
withglobal._runOnUIQueue
so that the queue isn't captured into worklet closure and thus doesn't get frozen. Another option would be simply to whitelistrunOnUI
function but it wouldn't work properly when aliased.Test plan
App.tsx
Your beautiful eyes should see the following error: