Get uiRuntime directly from react-native-worklets#4276
Conversation
uiRuntime directly from react-native-worklets
There was a problem hiding this comment.
Pull request overview
This PR changes how RNGH finds the UI jsi::Runtime for installing UI-thread bindings, preferring the stable react-native-worklets API when available and falling back to the legacy Reanimated _WORKLET_RUNTIME approach.
Changes:
- Add a temporary JS global holder (
__RNGH_UI_WORKLET_RUNTIME_HOLDER) to pass the Worklets UI runtime holder to native during installation. - Update iOS/Android native installation to resolve the UI runtime via Worklets stable API first, then fall back to
_WORKLET_RUNTIME. - Add conditional platform build integration for RNWorklets (CocoaPods + Android Gradle/CMake) gated on Worklets version/API support.
Reviewed changes
Copilot reviewed 11 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/handlers/gestures/reanimatedWrapper.ts | Attempts to provide a Worklets UI runtime holder to native during UI bindings install. |
| packages/react-native-gesture-handler/src/global.d.ts | Declares the new temporary global holder type for TypeScript. |
| packages/react-native-gesture-handler/shared/runtime/RNGHRuntimeDecorator.h | Changes UI bindings install signature and adds tryFindUIRuntime. |
| packages/react-native-gesture-handler/shared/runtime/RNGHRuntimeDecorator.cpp | Splits “find UI runtime” from “install bindings” and preserves legacy lookup. |
| packages/react-native-gesture-handler/scripts/gesture_handler_utils.rb | Adds Worklets package/version detection for CocoaPods. |
| packages/react-native-gesture-handler/RNGestureHandler.podspec | Conditionally depends on RNWorklets (>= 0.8.0) when stable API is detected. |
| packages/react-native-gesture-handler/apple/RNGestureHandlerModule.mm | Uses Worklets stable API (when header available) to locate UI runtime before fallback. |
| packages/react-native-gesture-handler/android/src/main/jni/RNGestureHandlerModule.h | Renames native method to reflect installing UI runtime bindings. |
| packages/react-native-gesture-handler/android/src/main/jni/RNGestureHandlerModule.cpp | Uses Worklets stable API under RNGH_USE_WORKLETS, otherwise falls back to legacy lookup. |
| packages/react-native-gesture-handler/android/src/main/jni/CMakeLists.txt | Conditionally links react-native-worklets when enabled. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt | Updates the JNI method name used for installing bindings. |
| packages/react-native-gesture-handler/android/build.gradle | Adds version-gated enablement + dependency wiring for react-native-worklets. |
| apps/basic-example/ios/Podfile.lock | Updates example lockfile to include RNWorklets in pods set. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| jsi::Runtime *uiRuntime = nullptr; | ||
|
|
||
| #ifdef RNGH_USE_WORKLETS | ||
| std::shared_ptr<worklets::WorkletRuntime> uiWorkletRuntime; | ||
| const auto runtimeHolder = rnRuntime_->global().getProperty( | ||
| *rnRuntime_, "__RNGH_UI_WORKLET_RUNTIME_HOLDER"); | ||
|
|
||
| if (runtimeHolder.isObject()) { | ||
| uiWorkletRuntime = worklets::getWorkletRuntimeFromHolder( | ||
| *rnRuntime_, runtimeHolder.asObject(*rnRuntime_)); | ||
|
|
||
| if (uiWorkletRuntime) { | ||
| uiRuntime = &worklets::getJSIRuntimeFromWorkletRuntime(uiWorkletRuntime); | ||
| } | ||
| } | ||
| #endif |
There was a problem hiding this comment.
Why isn't this a part of RNGHRuntimeDecorator::tryFindUIRuntime?
| std::shared_ptr<worklets::WorkletRuntime> uiWorkletRuntime; | ||
| const auto runtimeHolder = _rnRuntime->global().getProperty(*_rnRuntime, "__RNGH_UI_WORKLET_RUNTIME_HOLDER"); | ||
|
|
||
| if (runtimeHolder.isObject()) { | ||
| uiWorkletRuntime = worklets::getWorkletRuntimeFromHolder(*_rnRuntime, runtimeHolder.asObject(*_rnRuntime)); | ||
|
|
||
| if (uiWorkletRuntime != nullptr) { | ||
| uiRuntime = &worklets::getJSIRuntimeFromWorkletRuntime(uiWorkletRuntime); | ||
| } | ||
| } | ||
| #endif |
| def packageJson = new JsonSlurper().parseText(new File(worklets.projectDir, "../package.json").text) | ||
| def version = packageJson.version as String | ||
|
|
||
| if (version.contains('-')) { | ||
| return false | ||
| } |
There was a problem hiding this comment.
Why is this needed?
Other lib checks don't have this, maybe it would be possible to fold it into getExternalLibVersion if necessary?
| if (uiRuntime == nullptr) { | ||
| uiRuntime = RNGHRuntimeDecorator::tryFindUIRuntime(*rnRuntime_); | ||
| } | ||
|
|
||
| if (uiRuntime == nullptr) { | ||
| return false; | ||
| } |
There was a problem hiding this comment.
This might be the one example when nesting these if reads easier
| bool RNGestureHandlerModule::installUIRuntimeBindings() { | ||
| jsi::Runtime *uiRuntime = nullptr; | ||
|
|
||
| #ifdef RNGH_USE_WORKLETS |
There was a problem hiding this comment.
#ifdef checks only if the value is defined, not if it's true - I guess there's no way that this will be defined, but not 1, right?
| | undefined; | ||
|
|
||
| // Temporary holder used to pass the Worklets UI runtime to native code. | ||
| // eslint-disable-next-line no-var |
There was a problem hiding this comment.
Maybe we should disable var rule for whole file?
Description
RNGH currently obtains the UI runtime through Reanimated’s private
_WORKLET_RUNTIMEglobal, which stores a rawjsi::Runtimepointer.This PR makes the public
react-native-workletsStable API the preferred way to obtain the UI runtime while preserving the existing Reanimated fallback.Runtime lookup
When compatible Worklets is available:
getUIRuntimeHolder().worklets/Compat/StableApi.h._setGestureStateSyncon the resulting UI runtime.RNGH no longer includes or accesses platform-specific Worklets implementation APIs such as
worklets/android/WorkletsModule.horworklets/apple/WorkletsModule.h.When Worklets is unavailable, too old, or holder retrieval fails, native code falls back to the existing
_WORKLET_RUNTIMEpointer provided by Reanimated.The JavaScript initialization handles the providers independently:
_WORKLET_RUNTIME.Optional dependency integration
react-native-workletsremains optional.Native Worklets integration is enabled only for stable versions
>= 0.8.0:RNWorklets (>= 0.8.0), and definesRNGH_USE_WORKLETS=1.StableApi.his included directly when the macro is enabled, so missing or incorrectly exported headers fail compilation instead of silently selecting the fallback.The shared runtime decorator was also split into:
_WORKLET_RUNTIMEpointer when needed.Test plan
Added Jest coverage and tested on Runtime Decoration example on iOS and Android.