react-native-worklets-core icon indicating copy to clipboard operation
react-native-worklets-core copied to clipboard

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

Open Acetyld opened this issue 2 years ago • 15 comments

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..

Acetyld avatar Oct 11 '23 17:10 Acetyld

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

mrousavy avatar Oct 18 '23 09:10 mrousavy

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

omermizr avatar Oct 19 '23 16:10 omermizr

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 ?

matis-dk avatar Oct 25 '23 10:10 matis-dk

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.

chrfalch avatar Oct 25 '23 17:10 chrfalch

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

mrousavy avatar Oct 31 '23 13:10 mrousavy

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.]

lgspacil avatar Dec 06 '23 23:12 lgspacil

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

nikhilyadavvvv avatar Feb 27 '24 14:02 nikhilyadavvvv

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

Acetyld avatar Feb 27 '24 14:02 Acetyld

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.

mrousavy avatar Feb 28 '24 11:02 mrousavy

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.

levepic avatar Feb 28 '24 11:02 levepic

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?

ellora-virtue avatar Feb 29 '24 22:02 ellora-virtue

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.

chrfalch avatar Mar 01 '24 07:03 chrfalch

@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 avatar Mar 03 '24 19:03 ellora-virtue

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!

ellora-virtue avatar Mar 04 '24 19:03 ellora-virtue

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

lgspacil avatar Mar 10 '24 05:03 lgspacil