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

In callInContext the function parameter is not a valid worklet and cannot be called between contexts or from/to JS from/to a context. #125

Open
Acetyld opened this issue Oct 11, 2023 · 15 comments

Comments

@Acetyld
Copy link

Acetyld commented Oct 11, 2023

While using:

function RealApp() {
  const fibonacci = (num: number): number => {
    'worklet';
    if (num <= 1) return 1;
    return fibonacci(num - 1) + fibonacci(num - 2);
  };

  const worklet = Worklets.createRunInContextFn(fibonacci);
  worklet(50).then(result => {
    console.log(`Fibonacci of 50 is ${result}`);
  });
}

I get:

In callInContext the function parameter is not a valid worklet and cannot be called between contexts or from/to JS from/to a context.

Running:

Expo: 49

Babel:
module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: [
      'nativewind/babel',
      'module:react-native-dotenv',
      'react-native-worklets-core/plugin',
      'react-native-reanimated/plugin',
      ['@babel/plugin-transform-flow-strip-types', { loose: true }],
      ['@babel/plugin-proposal-private-methods', { loose: true }],
    ],
  };
};

I did rebuild, prebuild, clean cache, clean pods, removed node modules reinstalled etc..

@mrousavy
Copy link
Member

Is this because of recursion? Does it work if you refactor your code to use simple for loops instead of recursively calling fibonacci?

@omermizr
Copy link

Same thing happening to me, with the simplest worklet possible - just immediately returning a string

@matis-dk
Copy link

matis-dk commented Oct 25, 2023

Happening to me as well. Running on Expo 49, and build with EAS.
When starting the Expo dev server:

 LOG  Loading react-native-worklets-core...
 LOG  Worklets loaded successfully

Is this package compatible with Expo ?

@chrfalch
Copy link
Collaborator

chrfalch commented Oct 25, 2023

The problem with the fibionacci example is that when the using recursion like you do - the function is not available as a worklet at the point of initialisation and will therefore be undefined in the context of the workletized fibionacci function. Reanimated gives the same error:

const fibonacci = (num: number): number => {
    "worklet";
    if (num <= 1) return 1;
    return fibonacci(num - 1) + fibonacci(num - 2);
};

runOnUI(fibonacci)(100);

Results in:

ERROR  ReanimatedError: undefined is not a function, js engine: reanimated

You can look at the transpiled code for the worklet to see that this is failing at the declaration level:

console.log("Closure:", fibonacci.__closure);

Results in:

closure: {"fibonacci": undefined}

Meaning that the worklet is not yet created when the plugin transforms its closure.

@mrousavy
Copy link
Member

Makes complete sense, recursion doesn't need to be supported imo.

@lgspacil
Copy link

lgspacil commented Dec 6, 2023

Any update on this? I am experiencing the same error. For example my code is:

const test = (num: number): number => {
    'worklet'
    return num * 2;
};

useEffect(() => {
    const run = async () => {
        try {
            const worklet = Worklets.createRunInContextFn(test);
            const result = await worklet(50);
            console.log(`result is ${result}`);
        } catch (e) {
            console.log(e);
        }
    };

    run();
}, []);

When I look at the logs I see:

Loading react-native-worklets-core...
Worklets loaded successfully
[Error: In callInContext the function parameter is not a valid worklet and cannot be called between contexts or from/to JS from/to a context.]

@nikhilyadavvvv
Copy link

const worklet = useWorklet(
'default',
() => {
'worklet';
console.log('hello from worklet!');
},
[],
);
useEffect(() => {
worklet();
}, []);

Even this doesn't work. How am i suppose to use this lib

@Acetyld
Copy link
Author

Acetyld commented Feb 27, 2024

I don't think this library is ment or at a point for public usage to easily run stuff on a seperate worker.

margelo is one of the goats of RN (imo :P) but don't know what his plans are for this library, i hope someday we have a library like https://github.com/joltup/react-native-threads or the old multi-tread from margelo so we can easily do extensive stuff on a seperate thread ;p

@mrousavy
Copy link
Member

I don't think this library is ment or at a point for public usage to easily run stuff on a seperate worker.

It is - but there is not a lot of real world cases for when you would use that- heavy lifting should be done on the native side, not on JS.

margelo is one of the goats of RN (imo :P)

Thank you! ❤️

but don't know what his plans are for this library, i hope someday we have a library like https://github.com/joltup/react-native-threads or the old multi-tread from margelo so we can easily do extensive stuff on a seperate thread ;p

Worklets is a new and improved version of my old multithreading library. Worklets can be used to run stuff on a separate Thread, and the example app here demonstrates how to do that.

VisionCamera V3 also uses this for Frame Processors, and this is being used in production by many apps.

@levepic
Copy link

levepic commented Feb 28, 2024

Im also upto using it in production but there is the memory leak issue (#137 , #129 ). Am I missing something? Is there a way to avoid that? Obviously I need to return some data to javascript (when a face is recognized etc) so somehow I need to call a JS function or set state from the worklet. Is there a way to do that without the memory leak bug? Without calling JS what would you use the worklet for if it cannot send any information the the js thread.

@ellora-virtue
Copy link

Similar to @lgspacil and @nikhilyadavvvv, I am trying to implement a very simple example from the usage doc and gettingError: In callInContext the function parameter is not a valid worklet and cannot be called between contexts or from/to JS from/to a context. in my console.

This happens after the logs Loading react-native-worklets-core... and Worklets loaded successfully.

I am using it in a React component, like so:

const worklet = useWorklet(
    'default',
    () => {
      'worklet';

      console.log('hello from worklet!');
    },
    [],
  );

 worklet();

@mrousavy are we missing something from this usage example?

@chrfalch
Copy link
Collaborator

chrfalch commented Mar 1, 2024

Did you install the plugin as described in the installation instructions? It is need so that the Javascript function is decorated with information necessary to make it runnable on another thread.

@ellora-virtue
Copy link

@chrfalch yes I did 🙂 provided you're talking about this step:

  1. Add the babel plugin to your babel.config.js:
module.exports = {
  plugins: [
    ["react-native-worklets-core/plugin"],
    // ...
  ],
  // ...
};

@ellora-virtue
Copy link

My issue above looks to have been caused by the fact that our repo was using an older version of react-native-reanimated (^2.14.1). Upgrading this to the latest version (^3.7.2) has fixed this for me - hope this helps someone else too!

@lgspacil
Copy link

@ellora-virtue Did you have a way to return a value from the worklet?

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

No branches or pull requests

9 participants