-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Get uiRuntime directly from react-native-worklets
#4276
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,10 +44,23 @@ endif() | |
|
|
||
| find_package(ReactAndroid REQUIRED CONFIG) | ||
| find_package(fbjni REQUIRED CONFIG) | ||
| if(${RNGH_USE_WORKLETS}) | ||
| find_package(react-native-worklets REQUIRED CONFIG) | ||
| target_compile_definitions(${PACKAGE_NAME} PRIVATE RNGH_USE_WORKLETS=1) | ||
| target_include_directories( | ||
| ${PACKAGE_NAME} | ||
| PRIVATE | ||
| "${REACT_NATIVE_DIR}/ReactCommon/jsiexecutor" | ||
| ) | ||
|
Comment on lines
+50
to
+54
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to do that? Maybe there's a target in react native that exposes these headers. |
||
| endif() | ||
|
|
||
| target_link_libraries( | ||
| ${PACKAGE_NAME} | ||
| ReactAndroid::reactnative | ||
| ReactAndroid::jsi | ||
| fbjni::fbjni | ||
| ) | ||
|
|
||
| if(${RNGH_USE_WORKLETS}) | ||
| target_link_libraries(${PACKAGE_NAME} react-native-worklets::worklets) | ||
| endif() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we have a single |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,13 @@ | |
|
|
||
| #import "RNGHRuntimeDecorator.h" | ||
|
|
||
| #if __has_include(<worklets/apple/WorkletsModule.h>) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you tried using different linking methods (static/dynamic)? |
||
| #import <worklets/apple/WorkletsModule.h> | ||
| #define RNGH_HAS_WORKLETS 1 | ||
| #else | ||
| #define RNGH_HAS_WORKLETS 0 | ||
| #endif | ||
|
|
||
| #import "RNGestureHandler.h" | ||
| #import "RNGestureHandlerDirection.h" | ||
| #import "RNGestureHandlerState.h" | ||
|
|
@@ -108,6 +115,26 @@ - (bool)decorateUIRuntime | |
| { | ||
| __weak RNGestureHandlerModule *weakSelf = self; | ||
|
|
||
| #if RNGH_HAS_WORKLETS | ||
| WorkletsModule *workletsModule = (WorkletsModule *)[self.moduleRegistry moduleForName:"WorkletsModule"]; | ||
| if (workletsModule != nil) { | ||
| auto workletsModuleProxy = [workletsModule getWorkletsModuleProxy]; | ||
| if (workletsModuleProxy != nullptr) { | ||
| auto uiWorkletRuntime = workletsModuleProxy->getUIWorkletRuntime(); | ||
| if (uiWorkletRuntime != nullptr) { | ||
| RNGHRuntimeDecorator::decorateUIRuntime( | ||
| uiWorkletRuntime->getJSIRuntime(), [weakSelf](int handlerTag, int state) { | ||
| RNGestureHandlerModule *strongSelf = weakSelf; | ||
| if (strongSelf != nil) { | ||
| [strongSelf setGestureState:state forHandler:handlerTag]; | ||
| } | ||
| }); | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| return RNGHRuntimeDecorator::installUIRuntimeBindings(*_rnRuntime, _moduleId, [weakSelf](int handlerTag, int state) { | ||
| RNGestureHandlerModule *strongSelf = weakSelf; | ||
| if (strongSelf != nil) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -89,25 +89,9 @@ void RNGHRuntimeDecorator::installRNRuntimeBindings( | |||||
| rnRuntime, "_RNGH_MODULE_ID", std::move(moduleIdValue)); | ||||||
| } | ||||||
|
|
||||||
| bool RNGHRuntimeDecorator::installUIRuntimeBindings( | ||||||
| jsi::Runtime &rnRuntime, | ||||||
| int moduleId, | ||||||
| void RNGHRuntimeDecorator::decorateUIRuntime( | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, now this is actually what installs the bindings.
Suggested change
|
||||||
| jsi::Runtime &uiRuntime, | ||||||
| std::function<void(int, int)> &&setGestureState) { | ||||||
| const auto runtimeHolder = | ||||||
| rnRuntime.global().getProperty(rnRuntime, "_WORKLET_RUNTIME"); | ||||||
|
|
||||||
| if (runtimeHolder.isUndefined()) { | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| const auto arrayBufferValue = | ||||||
| runtimeHolder.getObject(rnRuntime).getArrayBuffer(rnRuntime).data( | ||||||
| rnRuntime); | ||||||
| const auto uiRuntimeAddress = | ||||||
| reinterpret_cast<uintptr_t *>(&arrayBufferValue[0]); | ||||||
| jsi::Runtime &uiRuntime = | ||||||
| *reinterpret_cast<jsi::Runtime *>(*uiRuntimeAddress); | ||||||
|
|
||||||
| auto setGestureStateSync = jsi::Function::createFromHostFunction( | ||||||
| uiRuntime, | ||||||
| jsi::PropNameID::forAscii(uiRuntime, "_setGestureStateSync"), | ||||||
|
|
@@ -128,6 +112,28 @@ bool RNGHRuntimeDecorator::installUIRuntimeBindings( | |||||
|
|
||||||
| uiRuntime.global().setProperty( | ||||||
| uiRuntime, "_setGestureStateSync", std::move(setGestureStateSync)); | ||||||
| } | ||||||
|
|
||||||
| bool RNGHRuntimeDecorator::installUIRuntimeBindings( | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe rename it to something like
Suggested change
change it to return the runtime (or null), and then in the modules, do |
||||||
| jsi::Runtime &rnRuntime, | ||||||
| int moduleId, | ||||||
| std::function<void(int, int)> &&setGestureState) { | ||||||
| const auto runtimeHolder = | ||||||
| rnRuntime.global().getProperty(rnRuntime, "_WORKLET_RUNTIME"); | ||||||
|
|
||||||
| if (runtimeHolder.isUndefined()) { | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| const auto arrayBufferValue = | ||||||
| runtimeHolder.getObject(rnRuntime).getArrayBuffer(rnRuntime).data( | ||||||
| rnRuntime); | ||||||
| const auto uiRuntimeAddress = | ||||||
| reinterpret_cast<uintptr_t *>(&arrayBufferValue[0]); | ||||||
| jsi::Runtime &uiRuntime = | ||||||
| *reinterpret_cast<jsi::Runtime *>(*uiRuntimeAddress); | ||||||
|
|
||||||
| decorateUIRuntime(uiRuntime, std::move(setGestureState)); | ||||||
|
|
||||||
| auto moduleIdValue = jsi::Value(moduleId); | ||||||
| rnRuntime.global().setProperty( | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -32,6 +32,10 @@ export type ReanimatedHandler<THandlerData> = { | |||||
| context: ReanimatedContext<THandlerData>; | ||||||
| }; | ||||||
|
|
||||||
| type WorkletsModule = { | ||||||
| scheduleOnUI?: (worklet: () => void) => void; | ||||||
| }; | ||||||
|
|
||||||
| export type NativeEventsManager = new (component: { | ||||||
| props: Record<string, unknown>; | ||||||
| _componentRef: React.Ref<unknown>; | ||||||
|
|
@@ -82,12 +86,11 @@ let Reanimated: | |||||
| | undefined; | ||||||
|
|
||||||
| try { | ||||||
| Reanimated = require('react-native-reanimated'); | ||||||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires | ||||||
| const Worklets = require('react-native-worklets'); | ||||||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||||||
| const Worklets = require('react-native-worklets') as WorkletsModule; | ||||||
|
|
||||||
| // Make sure worklets are initialized before attempting to install UI runtime bindings | ||||||
| Worklets?.scheduleOnUI(() => { | ||||||
| Worklets.scheduleOnUI?.(() => { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| 'worklet'; | ||||||
| }); | ||||||
|
|
||||||
|
|
@@ -102,6 +105,12 @@ try { | |||||
| ); | ||||||
| } | ||||||
| }); | ||||||
| } catch (e) { | ||||||
| // When 'react-native-worklets' is not available we want to quietly continue | ||||||
| } | ||||||
|
|
||||||
| try { | ||||||
| Reanimated = require('react-native-reanimated'); | ||||||
| } catch (e) { | ||||||
| // When 'react-native-reanimated' is not available we want to quietly continue | ||||||
| // @ts-ignore TS demands the variable to be initialized | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also validate worklets' version, or does it work with each one published so far?
0.8.0 may be a good cutoff candidate since it introduces a stable api: software-mansion/react-native-reanimated#8996