react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

Calling `runOnJS` on a remote function marked as worklet throws "Attempted to extract from a HostObject that wasn't converted to a Shareable"

Open tomekzaw opened this issue 1 year ago • 10 comments

Description

The following error appears when trying to call runOnJS on a function which is also marked as worklet.

ReanimatedError: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable., js engine: reanimated
Zrzut ekranu 2023-11-30 o 17 37 36

Steps to reproduce

function RemoteFunctionWorkletDemo() {
  const someFunction = (x: number) => {
    'worklet'; // this is a worklet but we will call it as a remote function
    console.log(_WORKLET, x); // _WORKLET should be false
  };

  const someWorklet = (x: number) => {
    'worklet';
    console.log(_WORKLET, x); // _WORKLET should be true
    runOnJS(someFunction)(x);
  };

  const handlePress = () => {
    runOnUI(someWorklet)(Math.random());
  };

  return <Button onPress={handlePress} title="RemoteFunctionWorkletDemo" />;
}

Snack or a link to a repository

no

Reanimated version

3.6.0

React Native version

0.72.6

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

React Native

Architecture

Paper (Old Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

iPhone 15 Pro

Acknowledgements

Yes

tomekzaw avatar Nov 30 '23 16:11 tomekzaw

Workaround

Remove 'worklet'; directive.

 function RemoteFunctionWorkletDemo() {
   const someFunction = (x: number) => {
-    'worklet';
     console.log(_WORKLET, x); // _WORKLET should be false
   };

   const someWorklet = (x: number) => {
     'worklet';
     console.log(_WORKLET, x); // _WORKLET should be true
     runOnJS(someFunction)(x);
   };

   const handlePress = () => {
     runOnUI(someWorklet)(Math.random());
   };

   return <Button onPress={handlePress} title="RemoteFunctionWorkletDemo" />;
 }

Thanks @JDBoots for reporting this in https://github.com/software-mansion/react-native-reanimated/issues/5322#issuecomment-1833547242.

tomekzaw avatar Nov 30 '23 16:11 tomekzaw

Cant use workaround as it seems to be used like this in gesture handler and some other libs. Also cant really replicate it locally but users are crashing from it.

Here is my android stack trace if this helps:

Exception com.facebook.jni.CppException: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable.

Error: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable.
    at _scheduleOnJS (native)
    at anonymous (JavaScript:1:453)
    at anonymous (JavaScript:1:212)
    at anonymous (JavaScript:1:638)
    at handleAndFlushAnimationFrame (JavaScript:1:148)
  at com.swmansion.reanimated.nativeProxy.EventHandler.receiveEvent
  at com.swmansion.reanimated.nativeProxy.EventHandler.receiveEvent (EventHandler.java:25)
  at com.swmansion.gesturehandler.react.RNGestureHandlerStateChangeEvent.dispatch (RNGestureHandlerStateChangeEvent.kt:50)
  at com.swmansion.reanimated.NodesManager.handleEvent (NodesManager.java:327)
  at com.swmansion.reanimated.NodesManager.onEventDispatch (NodesManager.java:313)
  at com.facebook.react.uimanager.events.EventDispatcherImpl.dispatchEvent (EventDispatcherImpl.java:116)
  at com.swmansion.gesturehandler.ReactContextExtensionsKt.dispatchEvent (ReactContextExtensions.kt:9)
  at com.swmansion.gesturehandler.react.RNGestureHandlerModule.sendEventForDirectEvent (RNGestureHandlerModule.kt:605)
  at com.swmansion.gesturehandler.react.RNGestureHandlerModule.sendEventForReanimated (RNGestureHandlerModule.kt:591)
  at com.swmansion.gesturehandler.react.RNGestureHandlerModule.onStateChange (RNGestureHandlerModule.kt:543)
  at com.swmansion.gesturehandler.react.RNGestureHandlerModule.access$onStateChange (RNGestureHandlerModule.kt:49)
  at com.swmansion.gesturehandler.react.RNGestureHandlerModule$eventListener$1.onStateChange (RNGestureHandlerModule.kt:312)
  at com.swmansion.gesturehandler.core.GestureHandler.dispatchStateChange (GestureHandler.kt:84)
  at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.onHandlerStateChange (GestureHandlerOrchestrator.kt:133)
  at com.swmansion.gesturehandler.core.GestureHandler.moveToState (GestureHandler.kt:558)
  at com.swmansion.gesturehandler.core.GestureHandler.cancel (GestureHandler.kt:647)
  at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.cancelAll (GestureHandlerOrchestrator.kt:215)
  at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.onTouchEvent (GestureHandlerOrchestrator.kt:39)
  at com.swmansion.gesturehandler.react.RNGestureHandlerRootHelper.dispatchTouchEvent (RNGestureHandlerRootHelper.kt:101)
  at com.swmansion.gesturehandler.react.RNGestureHandlerRootView.dispatchTouchEvent (RNGestureHandlerRootView.kt:36)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3286)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2990)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3286)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2990)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3286)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2990)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3286)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2990)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3286)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2990)
  at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3286)
  at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:2990)
  at com.android.internal.policy.DecorView.superDispatchTouchEvent (DecorView.java:1116)
  at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent (PhoneWindow.java:1971)
  at android.app.Activity.dispatchTouchEvent (Activity.java:4388)
  at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent (WindowCallbackWrapper.java:70)
  at com.android.internal.policy.DecorView.dispatchTouchEvent (DecorView.java:1074)
  at android.view.View.dispatchPointerEvent (View.java:15803)
  at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent (ViewRootImpl.java:8153)
  at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:7877)
  at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:7213)
  at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:7270)
  at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:7236)
  at android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:7434)
  at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:7244)
  at android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:7491)
  at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:7217)
  at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:7270)
  at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:7236)
  at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:7244)
  at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:7217)
  at android.view.ViewRootImpl.deliverInputEvent (ViewRootImpl.java:10788)
  at android.view.ViewRootImpl.doProcessInputEvents (ViewRootImpl.java:10676)
  at android.view.ViewRootImpl.enqueueInputEvent (ViewRootImpl.java:10632)
  at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent (ViewRootImpl.java:10926)
  at android.view.InputEventReceiver.dispatchInputEvent (InputEventReceiver.java:285)
  at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents
  at android.view.InputEventReceiver.consumeBatchedInputEvents (InputEventReceiver.java:262)
  at android.view.ViewRootImpl.doConsumeBatchedInput (ViewRootImpl.java:10874)
  at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run (ViewRootImpl.java:11020)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1301)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1309)
  at android.view.Choreographer.doCallbacks (Choreographer.java:923)
  at android.view.Choreographer.doFrame (Choreographer.java:844)
  at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1283)
  at android.os.Handler.handleCallback (Handler.java:942)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.app.ActivityThread.main (ActivityThread.java:8762)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:604)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)

claudesortwell avatar Jan 03 '24 04:01 claudesortwell

@tomekzaw Do you want me to post this issue in Gesture handler? Also let me know if there is anything i can help with

claudesortwell avatar Jan 07 '24 22:01 claudesortwell

Hi @claudesortwell did you figure a workaround for Gesture handler?

kslbdev avatar Feb 07 '24 17:02 kslbdev

I am facing the same

Fatal Exception: com.facebook.jni.CppException: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable.

Error: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable.
    at _scheduleOnJS (native)
    at anonymous (JavaScript:1:438)
    at anonymous (JavaScript:1:212)
    at anonymous (JavaScript:1:629)
    at handleAndFlushAnimationFrame (JavaScript:1:148)
       at com.swmansion.reanimated.nativeProxy.EventHandler.receiveEvent(EventHandler.java)
       at com.swmansion.reanimated.nativeProxy.EventHandler.receiveEvent(EventHandler.java:25)
       at com.swmansion.gesturehandler.react.RNGestureHandlerStateChangeEvent.dispatch(RNGestureHandlerStateChangeEvent.kt:42)
       at com.swmansion.reanimated.NodesManager.handleEvent(NodesManager.java:327)
       at com.swmansion.reanimated.NodesManager.onEventDispatch(NodesManager.java:313)
       at com.facebook.react.uimanager.events.EventDispatcherImpl.dispatchEvent(EventDispatcherImpl.java:116)
       at com.swmansion.gesturehandler.ReactContextExtensionsKt.dispatchEvent(ReactContextExtensions.kt:9)
       at com.swmansion.gesturehandler.react.RNGestureHandlerModule.sendEventForDirectEvent(RNGestureHandlerModule.kt:638)
       at com.swmansion.gesturehandler.react.RNGestureHandlerModule.sendEventForReanimated(RNGestureHandlerModule.kt:624)
       at com.swmansion.gesturehandler.react.RNGestureHandlerModule.onStateChange(RNGestureHandlerModule.kt:576)
       at com.swmansion.gesturehandler.react.RNGestureHandlerModule.access$onStateChange(RNGestureHandlerModule.kt:38)
       at com.swmansion.gesturehandler.react.RNGestureHandlerModule$eventListener$1.onStateChange(RNGestureHandlerModule.kt:346)
       at com.swmansion.gesturehandler.core.GestureHandler.dispatchStateChange(GestureHandler.kt:84)
       at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.onHandlerStateChange(GestureHandlerOrchestrator.kt:155)
       at com.swmansion.gesturehandler.core.GestureHandler.moveToState(GestureHandler.kt:551)
       at com.swmansion.gesturehandler.core.GestureHandler.cancel(GestureHandler.kt:640)
       at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.cancelAll(GestureHandlerOrchestrator.kt:244)
       at com.swmansion.gesturehandler.core.GestureHandlerOrchestrator.onTouchEvent(GestureHandlerOrchestrator.kt:43)
       at com.swmansion.gesturehandler.react.RNGestureHandlerRootHelper.dispatchTouchEvent(RNGestureHandlerRootHelper.kt:97)
       at com.swmansion.gesturehandler.react.RNGestureHandlerRootView.dispatchTouchEvent(RNGestureHandlerRootView.kt:35)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3286)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2990)

The gesture is re-throwing the event and the reanimated is listening. I am not able to determine where this is happening

Do you know when this code is executed? @tomekzaw

link to code

 if (handler.actionType == GestureHandler.ACTION_TYPE_REANIMATED_WORKLET) {
        // Reanimated worklet
        val event = RNGestureHandlerEvent.obtain(handler, handlerFactory)
        sendEventForReanimated(event)
 }

ismaelsousa avatar Mar 12 '24 13:03 ismaelsousa

I am facing the same

Fatal Exception: com.facebook.jni.CppException: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable.

Error: Exception in HostFunction: [Reanimated] Attempted to extract from a HostObject that wasn't converted to a Shareable.
    at _scheduleOnJS (native)
    at anonymous (JavaScript:1:438)
    at anonymous (JavaScript:1:212)
    at anonymous (JavaScript:1:629)

Hi @claudesortwell, @kslbdev, and @tomekzaw, you are right @tomekzaw

in my case was an inline declaration of a function to run in the runOnJS

workletContext {
    runOnJS(() => onGestureCancel?.())();
}
stack trace of an app using react native and drawer library

For me was happening in the implementation of the react-native-drawer-layout while using the useAnimatedGestureHandler

For the fix just need to create the function in the JSContext

Check the official fix for this: https://github.com/react-navigation/react-navigation/commit/3cfb3e63949f0aa6f4b14db02161dd88fd10cb12?diff=unified&w=1

ismaelsousa avatar Mar 13 '24 18:03 ismaelsousa

@ismaelsousa Thanks a lot for your investigation, fixing this bug at source and letting us know here! You're a hero!

tomekzaw avatar Mar 13 '24 21:03 tomekzaw

I get this error every time I try to use runOnJS in useAnimatedReaction or in a callback function of reanimated. Is there a way to "de-workletise" these or another workaround? I'm on 3.12.0.

huschu avatar Jun 18 '24 10:06 huschu