Skip to content
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

Schedule worklets via runOnJS #4622

Merged
merged 6 commits into from
Jul 20, 2023
Merged

Schedule worklets via runOnJS #4622

merged 6 commits into from
Jul 20, 2023

Conversation

tomekzaw
Copy link
Member

@tomekzaw tomekzaw commented Jun 24, 2023

Summary

Currently, it's impossible to pass functions directly to runOnJS:

runOnUI(() => {
   console.log(_WORKLET, 'Hello from UI thread');
  runOnJS(() => {
    console.log(_WORKLET, 'Hello from JS thread');
  })();
})();

The above example will fail with the following error:

Zrzut ekranu 2023-06-24 o 21 25 47

The workaround is to define the function in outer scope so that it gets cloned via closure as a remote function:

const hello = () => {
  console.log(_WORKLET, 'Hello from JS thread');
};

runOnUI(() => {
  console.log(_WORKLET, 'Hello from UI thread');
  runOnJS(hello)();
})();

This is sufficient for most of the cases since you can always parametrize the behavior of the function by passing the additional arguments. However, our library users deserve better experience, so this PR adds support for passing worklets directly to runOnJS function:

runOnUI(() => {
   console.log(_WORKLET, 'Hello from UI thread');
  runOnJS(() => {
    'worklet';
    console.log(_WORKLET, 'Hello from JS thread');
  })();
})();

Test plan

This change requires the following PR:

You will also need to enable the flag in Example/babel.config.js:

 module.exports = {
   presets: ['module:metro-react-native-babel-preset'],
-  plugins: ['../plugin'],
+  plugins: [['../plugin', {processNestedWorklets: true}]],
 };
App.tsx
import {Button, StyleSheet, View} from 'react-native';
import {runOnJS, runOnUI} from 'react-native-reanimated';

import React from 'react';

export default function App() {
  const handlePress = () => {
    runOnUI(() => {
      console.log(_WORKLET, 'Hello from UI thread');
      runOnJS(() => {
        'worklet';
        console.log(_WORKLET, 'Hello from JS thread');
      })();
    })();
  };

  return (
    <View style={styles.container}>
      <Button onPress={handlePress} title="Click me" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

if (fun.__workletHash) {
// if `fun` is a worklet, we schedule a call of a remote function `runWorkletOnJS`
// and pass the worklet as a first argument followed by original arguments
return (...args) => runOnJS(runWorkletOnJS<A, R>)(fun, ...args);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tjzel Thanks for the hint with <A, R> here! :swiniok:

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

                                                                                
                #&%#((((/            ...            ,/(((                       
                 ##%%%(///((,(((((((((((((((((((#(((///#.                       
                 ((#####(/##((((((((///////(((((((((/(#(.                       
                 //(((%##%######((((//////////(((((((#(/.                       
                  .%##%%%%%####((((##(///////(((#((###(#                        
                     %%%%%%##%%&@@%(##(((((/(((##(&&%%                          
                     .&%%%#((###((((###((((((((///////*        .                
                      #%###(((((((((########/////////((((     .                 
                  ,#,  ###(((((((((######%#/((##(//(((##((    .                 
                 ###*. .##((((((########%%/((@&%(/((((&&#(   .  *               
               /##%%%*,. ,### #########%%(((&&&%///(((&&%(/*. .*                
              #&%%%%%%(*,..,,.*######%%%%#//&&&//////((&&//..*.                 
                %%%%&%#((/*,/,.*%%%%%%%%&&%(/////////(((###,,                   
                %%%%%&%#(/((((*,...*#%%%&&&&&&#(((/((((***/*/.#,. .#            
               ,%%%%%&&&%%########((((((((&%####%%%%%#(((((((((////*%           
               (%%%%%%&&&&&&&&&%%%%%%%####%&%%###%%%%%%#((((((((((((.           
                  &%%%%&&&&&&&&&&&&&&&&%%%%%%%%%%%%&(  (%#((((((##*             
                   &%%&&&&&&&&&&&&&&&&&&&&&&&&&&&%&      %####%,                
                    &&&&&&&&&&&&&&&&&&&&&&&&&&&&%(        /#                    
                        %&&&&&&&&&&&&&&&&&&&&#                                  
                          &%&&&&&&&&&&&&&&%&                                    
                                &%%%%&                                          
                                                                                

@tomekzaw tomekzaw requested a review from piaskowyk July 3, 2023 08:27
@tomekzaw tomekzaw marked this pull request as ready for review July 3, 2023 08:27
@tomekzaw tomekzaw added this pull request to the merge queue Jul 20, 2023
Merged via the queue into main with commit 8778192 Jul 20, 2023
@tomekzaw tomekzaw deleted the @tomekzaw/run-worklet-on-js branch July 20, 2023 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants