From 6af6d2e667acefd9800f3a8eda2dc0baa2e7891c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Kapu=C5=9Bciak?= <39658211+kacperkapusciak@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:29:29 +0100 Subject: [PATCH 01/36] docs: worklets on the Web are just JavaScript functions (#6737) This PR explains the worklet behaviour on the Web and separates the [Worklets guide](https://docs.swmansion.com/react-native-reanimated/docs/guides/worklets) into easier to reference and scan sections. --------- Co-authored-by: Tomek Zawadzki --- .../docs-reanimated/docs/guides/worklets.mdx | 70 ++++++++++++------- .../docs/threading/runOnUI.mdx | 2 + 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/packages/docs-reanimated/docs/guides/worklets.mdx b/packages/docs-reanimated/docs/guides/worklets.mdx index a1a6ba2393d..e91645af9f7 100644 --- a/packages/docs-reanimated/docs/guides/worklets.mdx +++ b/packages/docs-reanimated/docs/guides/worklets.mdx @@ -8,6 +8,8 @@ sidebar_position: 1 Worklets are short-running JavaScript functions that can run on the [UI thread](/docs/fundamentals/glossary#ui-thread). Reanimated uses worklets to calculate view styles and react to events on the UI thread. +## Defining worklets + You can create your own worklets using the `'worklet';` directive at the top of a function. ```javascript @@ -17,6 +19,8 @@ function myWorklet() { } ``` +## Workletization + The [Reanimated Babel Plugin](https://github.com/software-mansion/react-native-reanimated/blob/main/packages/react-native-reanimated/plugin/README-dev.md#basics) looks for functions marked with the `'worklet'` directive and converts them into serializable objects. We call this process [workletization](/docs/fundamentals/glossary#to-workletize). These objects can then be copied and run over on the UI thread. Most of the time when working with Reanimated and [Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/) the code is automatically workletized and run on the UI thread by default. @@ -32,7 +36,7 @@ function App() { } ``` -Functions marked with `'worklet';` aren't [hoisted](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting). Besides affecting hoisting, the `'worklet';` directive has no effect on the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread). +## Running worklets on the UI thread You can use [`runOnUI`](/docs/threading/runOnUI) to manually schedule worklet execution on the UI thread: @@ -60,6 +64,41 @@ function onPress() { } ``` +## Running functions from worklets + +You can run functions on the JS thread from the UI thread with [`runOnJS`](/docs/threading/runOnJS). Most frequently used to call functions that aren't marked with a `'worklet';` directive (i.e. most third-party libraries) or to update the React state. + +```javascript +import { router } from 'expo-router'; +import { Gesture } from 'react-native-gesture-handler'; + +function App() { + const tap = Gesture.Tap().onEnd(() => { + // i'm a worklet too! + // highlight-next-line + runOnJS(router.back)(); + }); +} +``` + +Functions passed to `runOnJS` must be defined in the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread) scope, i.e. in the component body or the global scope. This code won't work because `myFunction` is defined in the `withTiming` callback, which is only executed in the [UI thread](/docs/fundamentals/glossary#ui-thread): + +```javascript +function App() { + const tap = Gesture.Tap().onEnd(() => { + // myFunction is defined on the UI thread 🚨 + const myFunction = () => {}; + runOnJS(myFunction)(); // 💥 + }); +} +``` + +## Hoisting + +Functions marked with `'worklet';` aren't [hoisted](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting). Besides affecting hoisting, the `'worklet';` directive has no effect on the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread). + +## Capturing closure + Worklets are [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). They can access variables declared outside of their own scope. Only variables referenced in the worklet body will be captured inside the worklet scope. ```javascript @@ -94,6 +133,8 @@ function myWorklet() { } ``` +## Passing data to worklets + Worklets can return data within the same thread. ```javascript @@ -128,32 +169,13 @@ function App() { } ``` -You can run functions on the JS thread from the UI thread with [`runOnJS`](/docs/threading/runOnJS). Most frequently used to call functions that aren't marked with a `'worklet';` directive (i.e. most third-party libraries) or to update the React state. +## Using worklets on the Web -```javascript -import { router } from 'expo-router'; -import { Gesture } from 'react-native-gesture-handler'; +There's no separate UI thread available on the Web. Because of that, when Reanimated runs in the browser, worklets are resolved to plain JavaScript functions. -function App() { - const tap = Gesture.Tap().onEnd(() => { - // i'm a worklet too! - // highlight-next-line - runOnJS(router.back)(); - }); -} -``` +However, the `'worklet';` directive is still necessary on the Web, because Reanimated relies on the Babel plugin to capture dependencies inside worklet functions. -Functions passed to `runOnJS` must be defined in the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread) scope, i.e. in the component body or the global scope. This code won't work because `myFunction` is defined in the `withTiming` callback, which is only executed in the [UI thread](/docs/fundamentals/glossary#ui-thread): - -```javascript -function App() { - const tap = Gesture.Tap().onEnd(() => { - // myFunction is defined on the UI thread 🚨 - const myFunction = () => {}; - runOnJS(myFunction)(); // 💥 - }); -} -``` +## Other worklet runtimes Worklets can run in other runtimes than the one provided by Reanimated. For example [VisionCamera](https://github.com/mrousavy/react-native-vision-camera) and [LiveMarkdown](https://github.com/Expensify/react-native-live-markdown) create their own worklet runtimes. diff --git a/packages/docs-reanimated/docs/threading/runOnUI.mdx b/packages/docs-reanimated/docs/threading/runOnUI.mdx index 63e73debc39..96a4452d18b 100644 --- a/packages/docs-reanimated/docs/threading/runOnUI.mdx +++ b/packages/docs-reanimated/docs/threading/runOnUI.mdx @@ -71,6 +71,8 @@ import RunOnUISrc from '!!raw-loader!@site/src/examples/RunOnUI'; - Make sure not to execute `runOnUI` on the UI thread as this will result in an error. +- In browsers there's no separate UI thread available. Because of that, on the Web, `runOnUI` behaves similarly to `requestAnimationFrame`. It creates a function that, when called, will be scheduled to run with given arguments on next animation frame. + ## Platform compatibility From 79ea845b2e1b95d023660776679d3d8000ed699c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:46:20 +0100 Subject: [PATCH 02/36] chore(Worklets): SingleInstanceChecker (#6694) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Moving `SingleInstanceChecker` to Worklets and applying it there. ## Test plan 🚀 --- .../cpp/reanimated/NativeModules/NativeReanimatedModule.h | 7 ++++--- .../cpp/worklets/NativeModules/NativeWorkletsModule.h | 4 ++++ .../{reanimated => worklets}/Tools/SingleInstanceChecker.h | 7 ++++--- .../apple/reanimated/apple/REAModule.mm | 2 +- .../apple/worklets/apple/WorkletsModule.mm | 4 ++++ 5 files changed, 17 insertions(+), 7 deletions(-) rename packages/react-native-reanimated/Common/cpp/{reanimated => worklets}/Tools/SingleInstanceChecker.h (95%) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h index 41af8f2e0d9..55530e1a8d0 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h @@ -4,7 +4,6 @@ #include #include #include -#include #ifdef RCT_NEW_ARCH_ENABLED #include @@ -16,6 +15,7 @@ #include #include #include +#include #include #ifdef RCT_NEW_ARCH_ENABLED @@ -243,8 +243,9 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec { const KeyboardEventUnsubscribeFunction unsubscribeFromKeyboardEventsFunction_; #ifndef NDEBUG - SingleInstanceChecker singleInstanceChecker_; -#endif + worklets::SingleInstanceChecker + singleInstanceChecker_; +#endif // NDEBUG }; } // namespace reanimated diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h index 15e8d7a271a..08c23a8813e 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h @@ -2,6 +2,7 @@ #include #include +#include #include namespace worklets { @@ -18,6 +19,9 @@ class NativeWorkletsModule : public NativeWorkletsModuleSpec { private: const std::string valueUnpackerCode_; +#ifndef NDEBUG + SingleInstanceChecker singleInstanceChecker_; +#endif // NDEBUG }; } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/Tools/SingleInstanceChecker.h b/packages/react-native-reanimated/Common/cpp/worklets/Tools/SingleInstanceChecker.h similarity index 95% rename from packages/react-native-reanimated/Common/cpp/reanimated/Tools/SingleInstanceChecker.h rename to packages/react-native-reanimated/Common/cpp/worklets/Tools/SingleInstanceChecker.h index 2a183e87004..3be7ce80fec 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/Tools/SingleInstanceChecker.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/Tools/SingleInstanceChecker.h @@ -5,14 +5,15 @@ #include #include +#include #include #include #ifdef ANDROID #include -#endif +#endif // ANDROID -namespace reanimated { +namespace worklets { // This is a class that counts how many instances of a different class there // are. It is meant only to be used with classes that should only have one @@ -66,6 +67,6 @@ SingleInstanceChecker::~SingleInstanceChecker() { instanceCount_--; } -} // namespace reanimated +} // namespace worklets #endif // NDEBUG diff --git a/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm b/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm index 625c5c6e5a4..8ba308ce79f 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm @@ -14,13 +14,13 @@ #endif // RCT_NEW_ARCH_ENABLED #import -#import #import #import #import #import #import +#import #import #import #import diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm index 78b1759f5c9..3872f949ef2 100644 --- a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm +++ b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm @@ -1,6 +1,7 @@ #import #import #import +#import using worklets::NativeWorkletsModule; using worklets::RNRuntimeWorkletDecorator; @@ -16,6 +17,9 @@ - (void)_tryAndHandleError:(dispatch_block_t)block; @implementation WorkletsModule { std::shared_ptr nativeWorkletsModule_; +#ifndef NDEBUG + worklets::SingleInstanceChecker singleInstanceChecker_; +#endif // NDEBUG } - (std::shared_ptr)getNativeWorkletsModule From 8c110b500db757ce8d0f6606c79466b0587ac3e2 Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Fri, 22 Nov 2024 10:39:53 +0100 Subject: [PATCH 03/36] Update ReanimatedPackage to supported stable API (#6730) ## Summary Replace the deprecated `TurboReactPackage` with the newer `BaseReactPackage` to improve compatibility with future React Native releases. Note that this change requires at least react-native@0.74+, but this should not be an issue as, according to the compatibility table, Reanimated@3.17.0 only supports versions 0.74 and above. Similar change has been introduced in the SVG package https://github.com/software-mansion/react-native-svg/pull/2541 ## Test plan CI should pass --- .../main/java/com/swmansion/reanimated/ReanimatedPackage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedPackage.java b/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedPackage.java index 8f32f0e6ec5..b3eae298949 100644 --- a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedPackage.java +++ b/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedPackage.java @@ -4,10 +4,10 @@ import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START; import androidx.annotation.NonNull; +import com.facebook.react.BaseReactPackage; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactPackage; -import com.facebook.react.TurboReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMarker; @@ -36,7 +36,7 @@ ReanimatedModule.class, ReanimatedUIManager.class, }) -public class ReanimatedPackage extends TurboReactPackage implements ReactPackage { +public class ReanimatedPackage extends BaseReactPackage implements ReactPackage { @Override public NativeModule getModule( @NonNull String name, @NonNull ReactApplicationContext reactContext) { From 1d52db335ffc5b757a77b0704d46606293d1e19a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:43:43 +0100 Subject: [PATCH 04/36] chore(deps): bump cross-spawn from 6.0.5 to 6.0.6 (#6729) Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 6.0.5 to 6.0.6.
Changelog

Sourced from cross-spawn's changelog.

6.0.6 (2024-11-18)

Bug Fixes

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cross-spawn&package-manager=npm_and_yarn&previous-version=6.0.5&new-version=6.0.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/software-mansion/react-native-reanimated/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b4873e7d2ab..7736167a103 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9086,15 +9086,15 @@ __metadata: linkType: hard "cross-spawn@npm:^6.0.0, cross-spawn@npm:^6.0.5": - version: 6.0.5 - resolution: "cross-spawn@npm:6.0.5" + version: 6.0.6 + resolution: "cross-spawn@npm:6.0.6" dependencies: nice-try: "npm:^1.0.4" path-key: "npm:^2.0.1" semver: "npm:^5.5.0" shebang-command: "npm:^1.2.0" which: "npm:^1.2.9" - checksum: 10/f07e643b4875f26adffcd7f13bc68d9dff20cf395f8ed6f43a23f3ee24fc3a80a870a32b246fd074e514c8fd7da5f978ac6a7668346eec57aa87bac89c1ed3a1 + checksum: 10/7abf6137b23293103a22bfeaf320f2d63faae70d97ddb4b58597237501d2efdd84cdc69a30246977e0c5f68216593894d41a7f122915dd4edf448db14c74171b languageName: node linkType: hard From 3e391681659ccb4d55b88a9ca499fc66f792b0bb Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 22 Nov 2024 12:54:31 +0000 Subject: [PATCH 05/36] Replace findNodeHandle with reading _componentViewTag (#6720) ## Summary Partially addresses https://github.com/software-mansion/react-native-reanimated/issues/6719. This is better because it doesn't enter the traversal codepath inside React. The `findNodeHandle` calculation inside the `Animated.View` itself is not so bad because it's short circuited inside for native refs (at least with `View`). Whereas passing a class instance like here always triggers the slower path in React. Regardless, it's already computed so why compute again? ## Test plan I've added console logs in our app to verify whether `animatedComponent._componentViewTag === findNodeHandle(animatedComponent)` and it always turned out true in the cases I hit. Not sure if there any cases where those could be different. Co-authored-by: Krzysztof Piaskowy --- .../src/createAnimatedComponent/JSPropsUpdater.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts b/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts index 59bc5a75a87..f0bd87da036 100644 --- a/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts +++ b/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts @@ -1,6 +1,5 @@ 'use strict'; import { NativeEventEmitter, Platform } from 'react-native'; -import { findNodeHandle } from '../platformFunctions/findNodeHandle'; import type { NativeModule } from 'react-native'; import { shouldBeUseWeb } from '../PlatformChecker'; import type { StyleProps } from '../commonTypes'; @@ -39,7 +38,7 @@ class JSPropsUpdaterPaper implements IJSPropsUpdater { > & IAnimatedComponentInternal ) { - const viewTag = findNodeHandle(animatedComponent); + const viewTag = animatedComponent._componentViewTag; JSPropsUpdaterPaper._tagToComponentMapping.set(viewTag, animatedComponent); if (JSPropsUpdaterPaper._tagToComponentMapping.size === 1) { const listener = (data: ListenerData) => { @@ -61,7 +60,7 @@ class JSPropsUpdaterPaper implements IJSPropsUpdater { > & IAnimatedComponentInternal ) { - const viewTag = findNodeHandle(animatedComponent); + const viewTag = animatedComponent._componentViewTag; JSPropsUpdaterPaper._tagToComponentMapping.delete(viewTag); if (JSPropsUpdaterPaper._tagToComponentMapping.size === 0) { this._reanimatedEventEmitter.removeAllListeners( @@ -101,7 +100,7 @@ class JSPropsUpdaterFabric implements IJSPropsUpdater { if (!JSPropsUpdaterFabric.isInitialized) { return; } - const viewTag = findNodeHandle(animatedComponent); + const viewTag = animatedComponent._componentViewTag; JSPropsUpdaterFabric._tagToComponentMapping.set(viewTag, animatedComponent); } @@ -114,7 +113,7 @@ class JSPropsUpdaterFabric implements IJSPropsUpdater { if (!JSPropsUpdaterFabric.isInitialized) { return; } - const viewTag = findNodeHandle(animatedComponent); + const viewTag = animatedComponent._componentViewTag; JSPropsUpdaterFabric._tagToComponentMapping.delete(viewTag); } } From f54fb3c2bf8cda6b7fd34440c3318d434cd5ecee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:54:47 +0100 Subject: [PATCH 06/36] refactor(Worklets): Move shareable creation to Worklets (#6576) ## Summary Moving `makeShareableClone` function from `NativeReanimatedModule` to `NativeWorkletsModule`. ## Test plan CI --- .../NativeModules/NativeReanimatedModule.cpp | 9 -- .../NativeModules/NativeReanimatedModule.h | 6 -- .../NativeReanimatedModuleSpec.cpp | 82 ++++++++----------- .../NativeReanimatedModuleSpec.h | 7 -- .../NativeModules/NativeWorkletsModule.cpp | 13 +++ .../NativeModules/NativeWorkletsModule.h | 6 ++ .../NativeWorkletsModuleSpec.cpp | 20 ++++- .../NativeModules/NativeWorkletsModuleSpec.h | 7 ++ .../src/ReanimatedModule/NativeReanimated.ts | 12 --- .../js-reanimated/JSReanimated.ts | 6 -- .../ReanimatedModule/reanimatedModuleProxy.ts | 6 -- .../src/commonTypes.ts | 65 ++------------- .../react-native-reanimated/src/shareables.ts | 6 +- .../src/worklets/WorkletsModule/JSWorklets.ts | 11 ++- .../worklets/WorkletsModule/NativeWorklets.ts | 12 +++ .../WorkletsModule/workletsModuleProxy.ts | 10 ++- 16 files changed, 119 insertions(+), 159 deletions(-) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp index 404ca6b6493..b1f430a89cd 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp @@ -253,15 +253,6 @@ jsi::Value NativeReanimatedModule::scheduleOnRuntime( return jsi::Value::undefined(); } -jsi::Value NativeReanimatedModule::makeShareableClone( - jsi::Runtime &rt, - const jsi::Value &value, - const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource) { - return reanimated::makeShareableClone( - rt, value, shouldRetainRemote, nativeStateSource); -} - jsi::Value NativeReanimatedModule::registerEventHandler( jsi::Runtime &rt, const jsi::Value &worklet, diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h index 55530e1a8d0..29bfecc7a63 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h @@ -44,12 +44,6 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec { ~NativeReanimatedModule(); - jsi::Value makeShareableClone( - jsi::Runtime &rt, - const jsi::Value &value, - const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource) override; - void scheduleOnUI(jsi::Runtime &rt, const jsi::Value &worklet) override; jsi::Value executeOnUIRuntimeSync(jsi::Runtime &rt, const jsi::Value &worklet) override; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.cpp index 1a48dc46ad0..036f201a88d 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.cpp @@ -2,25 +2,14 @@ #include -#define SPEC_PREFIX(FN_NAME) __hostFunction_NativeReanimatedModuleSpec_##FN_NAME +#define REANIMATED_SPEC_PREFIX(FN_NAME) \ + __hostFunction_NativeReanimatedModuleSpec_##FN_NAME namespace reanimated { -// SharedValue - -static jsi::Value SPEC_PREFIX(makeShareableClone)( - jsi::Runtime &rt, - TurboModule &turboModule, - const jsi::Value *args, - size_t) { - return static_cast(&turboModule) - ->makeShareableClone( - rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); -} - // scheduler -static jsi::Value SPEC_PREFIX(scheduleOnUI)( +static jsi::Value REANIMATED_SPEC_PREFIX(scheduleOnUI)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -30,7 +19,7 @@ static jsi::Value SPEC_PREFIX(scheduleOnUI)( return jsi::Value::undefined(); } -static jsi::Value SPEC_PREFIX(executeOnUIRuntimeSync)( +static jsi::Value REANIMATED_SPEC_PREFIX(executeOnUIRuntimeSync)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -39,7 +28,7 @@ static jsi::Value SPEC_PREFIX(executeOnUIRuntimeSync)( ->executeOnUIRuntimeSync(rt, std::move(args[0])); } -static jsi::Value SPEC_PREFIX(createWorkletRuntime)( +static jsi::Value REANIMATED_SPEC_PREFIX(createWorkletRuntime)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -48,7 +37,7 @@ static jsi::Value SPEC_PREFIX(createWorkletRuntime)( ->createWorkletRuntime(rt, std::move(args[0]), std::move(args[1])); } -static jsi::Value SPEC_PREFIX(scheduleOnRuntime)( +static jsi::Value REANIMATED_SPEC_PREFIX(scheduleOnRuntime)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -57,7 +46,7 @@ static jsi::Value SPEC_PREFIX(scheduleOnRuntime)( ->scheduleOnRuntime(rt, std::move(args[0]), std::move(args[1])); } -static jsi::Value SPEC_PREFIX(registerEventHandler)( +static jsi::Value REANIMATED_SPEC_PREFIX(registerEventHandler)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -67,7 +56,7 @@ static jsi::Value SPEC_PREFIX(registerEventHandler)( rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); } -static jsi::Value SPEC_PREFIX(unregisterEventHandler)( +static jsi::Value REANIMATED_SPEC_PREFIX(unregisterEventHandler)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -77,7 +66,7 @@ static jsi::Value SPEC_PREFIX(unregisterEventHandler)( return jsi::Value::undefined(); } -static jsi::Value SPEC_PREFIX(getViewProp)( +static jsi::Value REANIMATED_SPEC_PREFIX(getViewProp)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -88,7 +77,7 @@ static jsi::Value SPEC_PREFIX(getViewProp)( return jsi::Value::undefined(); } -static jsi::Value SPEC_PREFIX(enableLayoutAnimations)( +static jsi::Value REANIMATED_SPEC_PREFIX(enableLayoutAnimations)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -98,7 +87,7 @@ static jsi::Value SPEC_PREFIX(enableLayoutAnimations)( return jsi::Value::undefined(); } -static jsi::Value SPEC_PREFIX(registerSensor)( +static jsi::Value REANIMATED_SPEC_PREFIX(registerSensor)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -112,7 +101,7 @@ static jsi::Value SPEC_PREFIX(registerSensor)( std::move(args[3])); } -static jsi::Value SPEC_PREFIX(unregisterSensor)( +static jsi::Value REANIMATED_SPEC_PREFIX(unregisterSensor)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -122,7 +111,7 @@ static jsi::Value SPEC_PREFIX(unregisterSensor)( return jsi::Value::undefined(); } -static jsi::Value SPEC_PREFIX(configureProps)( +static jsi::Value REANIMATED_SPEC_PREFIX(configureProps)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -132,7 +121,7 @@ static jsi::Value SPEC_PREFIX(configureProps)( return jsi::Value::undefined(); } -static jsi::Value SPEC_PREFIX(subscribeForKeyboardEvents)( +static jsi::Value REANIMATED_SPEC_PREFIX(subscribeForKeyboardEvents)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -142,7 +131,7 @@ static jsi::Value SPEC_PREFIX(subscribeForKeyboardEvents)( rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); } -static jsi::Value SPEC_PREFIX(unsubscribeFromKeyboardEvents)( +static jsi::Value REANIMATED_SPEC_PREFIX(unsubscribeFromKeyboardEvents)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -152,7 +141,7 @@ static jsi::Value SPEC_PREFIX(unsubscribeFromKeyboardEvents)( return jsi::Value::undefined(); } -static jsi::Value SPEC_PREFIX(configureLayoutAnimationBatch)( +static jsi::Value REANIMATED_SPEC_PREFIX(configureLayoutAnimationBatch)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -161,7 +150,7 @@ static jsi::Value SPEC_PREFIX(configureLayoutAnimationBatch)( ->configureLayoutAnimationBatch(rt, std::move(args[0])); } -static jsi::Value SPEC_PREFIX(setShouldAnimateExiting)( +static jsi::Value REANIMATED_SPEC_PREFIX(setShouldAnimateExiting)( jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value *args, @@ -174,37 +163,38 @@ static jsi::Value SPEC_PREFIX(setShouldAnimateExiting)( NativeReanimatedModuleSpec::NativeReanimatedModuleSpec( const std::shared_ptr &jsInvoker) : TurboModule("NativeReanimated", jsInvoker) { - methodMap_["makeShareableClone"] = - MethodMetadata{2, SPEC_PREFIX(makeShareableClone)}; - - methodMap_["scheduleOnUI"] = MethodMetadata{1, SPEC_PREFIX(scheduleOnUI)}; + methodMap_["scheduleOnUI"] = + MethodMetadata{1, REANIMATED_SPEC_PREFIX(scheduleOnUI)}; methodMap_["executeOnUIRuntimeSync"] = - MethodMetadata{1, SPEC_PREFIX(executeOnUIRuntimeSync)}; + MethodMetadata{1, REANIMATED_SPEC_PREFIX(executeOnUIRuntimeSync)}; methodMap_["createWorkletRuntime"] = - MethodMetadata{2, SPEC_PREFIX(createWorkletRuntime)}; + MethodMetadata{2, REANIMATED_SPEC_PREFIX(createWorkletRuntime)}; methodMap_["scheduleOnRuntime"] = - MethodMetadata{2, SPEC_PREFIX(scheduleOnRuntime)}; + MethodMetadata{2, REANIMATED_SPEC_PREFIX(scheduleOnRuntime)}; methodMap_["registerEventHandler"] = - MethodMetadata{3, SPEC_PREFIX(registerEventHandler)}; + MethodMetadata{3, REANIMATED_SPEC_PREFIX(registerEventHandler)}; methodMap_["unregisterEventHandler"] = - MethodMetadata{1, SPEC_PREFIX(unregisterEventHandler)}; + MethodMetadata{1, REANIMATED_SPEC_PREFIX(unregisterEventHandler)}; - methodMap_["getViewProp"] = MethodMetadata{3, SPEC_PREFIX(getViewProp)}; + methodMap_["getViewProp"] = + MethodMetadata{3, REANIMATED_SPEC_PREFIX(getViewProp)}; methodMap_["enableLayoutAnimations"] = - MethodMetadata{2, SPEC_PREFIX(enableLayoutAnimations)}; - methodMap_["registerSensor"] = MethodMetadata{4, SPEC_PREFIX(registerSensor)}; + MethodMetadata{2, REANIMATED_SPEC_PREFIX(enableLayoutAnimations)}; + methodMap_["registerSensor"] = + MethodMetadata{4, REANIMATED_SPEC_PREFIX(registerSensor)}; methodMap_["unregisterSensor"] = - MethodMetadata{1, SPEC_PREFIX(unregisterSensor)}; - methodMap_["configureProps"] = MethodMetadata{2, SPEC_PREFIX(configureProps)}; + MethodMetadata{1, REANIMATED_SPEC_PREFIX(unregisterSensor)}; + methodMap_["configureProps"] = + MethodMetadata{2, REANIMATED_SPEC_PREFIX(configureProps)}; methodMap_["subscribeForKeyboardEvents"] = - MethodMetadata{2, SPEC_PREFIX(subscribeForKeyboardEvents)}; + MethodMetadata{2, REANIMATED_SPEC_PREFIX(subscribeForKeyboardEvents)}; methodMap_["unsubscribeFromKeyboardEvents"] = - MethodMetadata{1, SPEC_PREFIX(unsubscribeFromKeyboardEvents)}; + MethodMetadata{1, REANIMATED_SPEC_PREFIX(unsubscribeFromKeyboardEvents)}; methodMap_["configureLayoutAnimationBatch"] = - MethodMetadata{1, SPEC_PREFIX(configureLayoutAnimationBatch)}; + MethodMetadata{1, REANIMATED_SPEC_PREFIX(configureLayoutAnimationBatch)}; methodMap_["setShouldAnimateExitingForTag"] = - MethodMetadata{2, SPEC_PREFIX(setShouldAnimateExiting)}; + MethodMetadata{2, REANIMATED_SPEC_PREFIX(setShouldAnimateExiting)}; } } // namespace reanimated diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.h index 89a6c20e91a..a9a85ad1a6c 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.h @@ -18,13 +18,6 @@ class JSI_EXPORT NativeReanimatedModuleSpec : public TurboModule { const std::shared_ptr &jsInvoker); public: - // SharedValue - virtual jsi::Value makeShareableClone( - jsi::Runtime &rt, - const jsi::Value &value, - const jsi::Value &shouldRetainRemote, - const jsi::Value &nativeStateSource) = 0; - // Scheduling virtual void scheduleOnUI(jsi::Runtime &rt, const jsi::Value &worklet) = 0; virtual jsi::Value executeOnUIRuntimeSync( diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp index 1a776bf8812..80270752948 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp @@ -6,6 +6,7 @@ #endif // RCT_NEW_ARCH_ENABLED #include +#include #ifdef __ANDROID__ #include @@ -22,4 +23,16 @@ NativeWorkletsModule::NativeWorkletsModule(const std::string &valueUnpackerCode) valueUnpackerCode_(valueUnpackerCode) {} NativeWorkletsModule::~NativeWorkletsModule() {} + +jsi::Value NativeWorkletsModule::makeShareableClone( + jsi::Runtime &rt, + const jsi::Value &value, + const jsi::Value &shouldRetainRemote, + const jsi::Value &nativeStateSource) { + // TODO: It might be a good idea to rename one of these methods to avoid + // confusion. + return worklets::makeShareableClone( + rt, value, shouldRetainRemote, nativeStateSource); +} + } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h index 08c23a8813e..5912056fb16 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h @@ -13,6 +13,12 @@ class NativeWorkletsModule : public NativeWorkletsModuleSpec { ~NativeWorkletsModule(); + jsi::Value makeShareableClone( + jsi::Runtime &rt, + const jsi::Value &value, + const jsi::Value &shouldRetainRemote, + const jsi::Value &nativeStateSource) override; + [[nodiscard]] inline std::string getValueUnpackerCode() const { return valueUnpackerCode_; } diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp index d8828c7fc31..95f05ac8036 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp @@ -1,9 +1,27 @@ #include +#include + +#define WORKLETS_SPEC_PREFIX(FN_NAME) \ + __hostFunction_NativeWorkletsModuleSpec_##FN_NAME + namespace worklets { +static jsi::Value WORKLETS_SPEC_PREFIX(makeShareableClone)( + jsi::Runtime &rt, + TurboModule &turboModule, + const jsi::Value *args, + size_t) { + return static_cast(&turboModule) + ->makeShareableClone( + rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); +} + NativeWorkletsModuleSpec::NativeWorkletsModuleSpec( const std::shared_ptr jsInvoker) - : TurboModule("NativeWorklets", jsInvoker) {} + : TurboModule("NativeWorklets", jsInvoker) { + methodMap_["makeShareableClone"] = + MethodMetadata{2, WORKLETS_SPEC_PREFIX(makeShareableClone)}; +} } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h index 5b813ceaf0e..1c1d622e17c 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h @@ -13,6 +13,13 @@ class JSI_EXPORT NativeWorkletsModuleSpec : public TurboModule { protected: explicit NativeWorkletsModuleSpec( const std::shared_ptr jsInvoker); + + public: + virtual jsi::Value makeShareableClone( + jsi::Runtime &rt, + const jsi::Value &value, + const jsi::Value &shouldRetainRemote, + const jsi::Value &nativeStateSource) = 0; }; } // namespace worklets diff --git a/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts b/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts index 51e084c9d79..364a1126da4 100644 --- a/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts +++ b/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts @@ -64,18 +64,6 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti this.#reanimatedModuleProxy = global.__reanimatedModuleProxy; } - makeShareableClone( - value: T, - shouldPersistRemote: boolean, - nativeStateSource?: object - ) { - return this.#reanimatedModuleProxy.makeShareableClone( - value, - shouldPersistRemote, - nativeStateSource - ); - } - scheduleOnUI(shareable: ShareableRef) { return this.#reanimatedModuleProxy.scheduleOnUI(shareable); } diff --git a/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts b/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts index 05c04c97e74..f54963b6171 100644 --- a/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts +++ b/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts @@ -42,12 +42,6 @@ class JSReanimated implements IReanimatedModule { sensors = new Map(); platform?: Platform = undefined; - makeShareableClone(): ShareableRef { - throw new ReanimatedError( - 'makeShareableClone should never be called in JSReanimated.' - ); - } - scheduleOnUI(worklet: ShareableRef) { // @ts-ignore web implementation has still not been updated after the rewrite, this will be addressed once the web implementation updates are ready requestAnimationFrameImpl(worklet); diff --git a/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts b/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts index 70fc5c7f0c2..cff70e423a7 100644 --- a/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts +++ b/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts @@ -11,12 +11,6 @@ import type { WorkletRuntime } from '../runtimes'; /** Type of `__reanimatedModuleProxy` injected with JSI. */ export interface ReanimatedModuleProxy { - makeShareableClone( - value: T, - shouldPersistRemote: boolean, - nativeStateSource?: object - ): ShareableRef; - scheduleOnUI(shareable: ShareableRef): void; executeOnUIRuntimeSync(shareable: ShareableRef): R; diff --git a/packages/react-native-reanimated/src/commonTypes.ts b/packages/react-native-reanimated/src/commonTypes.ts index 5b3f2fd1f08..f50717436d8 100644 --- a/packages/react-native-reanimated/src/commonTypes.ts +++ b/packages/react-native-reanimated/src/commonTypes.ts @@ -5,74 +5,19 @@ import type { TransformsStyle, ImageStyle, } from 'react-native'; -import type { WorkletRuntime } from './runtimes'; +import type { WorkletsModuleProxy } from './worklets'; +import type { ReanimatedModuleProxy } from './ReanimatedModule'; -export interface IWorkletsModule {} - -export interface IReanimatedModule { - registerSensor( - sensorType: number, - interval: number, - iosReferenceFrame: number, - handler: ShareableRef<(data: Value3D | ValueRotation) => void> - ): number; - - unregisterSensor(sensorId: number): void; - - registerEventHandler( - eventHandler: ShareableRef, - eventName: string, - emitterReactTag: number - ): number; - - unregisterEventHandler(id: number): void; +export interface IWorkletsModule extends WorkletsModuleProxy {} +export interface IReanimatedModule + extends Omit { getViewProp( viewTag: number, propName: string, component: React.Component | undefined, callback?: (result: TValue) => void ): Promise; - - configureLayoutAnimationBatch( - layoutAnimationsBatch: LayoutAnimationBatchItem[] - ): void; - - setShouldAnimateExitingForTag(viewTag: number, shouldAnimate: boolean): void; - - enableLayoutAnimations(flag: boolean): void; - - configureProps(uiProps: string[], nativeProps: string[]): void; - - subscribeForKeyboardEvents( - handler: ShareableRef, - isStatusBarTranslucent: boolean, - isNavigationBarTranslucent: boolean - ): number; - - unsubscribeFromKeyboardEvents(listenerId: number): void; - - makeShareableClone( - value: TValue, - shouldPersistRemote: boolean, - nativeStateSource?: object - ): ShareableRef; - - scheduleOnUI(shareable: ShareableRef): void; - - executeOnUIRuntimeSync( - shareable: ShareableRef - ): TResult; - - createWorkletRuntime( - name: string, - initializer: ShareableRef<() => void> - ): WorkletRuntime; - - scheduleOnRuntime( - workletRuntime: WorkletRuntime, - shareableWorklet: ShareableRef - ): void; } export type LayoutAnimationsOptions = diff --git a/packages/react-native-reanimated/src/shareables.ts b/packages/react-native-reanimated/src/shareables.ts index 0565272e30c..23070fe7de9 100644 --- a/packages/react-native-reanimated/src/shareables.ts +++ b/packages/react-native-reanimated/src/shareables.ts @@ -13,7 +13,7 @@ import { shareableMappingFlag, } from './shareableMappingCache'; import { logger } from './logger'; -import { ReanimatedModule } from './ReanimatedModule'; +import { WorkletsModule } from './worklets'; // for web/chrome debugger/jest environments this file provides a stub implementation // where no shareable references are used. Instead, the objects themselves are used @@ -273,7 +273,7 @@ Offending code was: \`${getWorkletCode(value)}\``); shareableMappingCache.set(value, inaccessibleObject); return inaccessibleObject; } - const adapted = ReanimatedModule.makeShareableClone( + const adapted = WorkletsModule.makeShareableClone( toAdapt, shouldPersistRemote, value @@ -283,7 +283,7 @@ Offending code was: \`${getWorkletCode(value)}\``); return adapted; } } - return ReanimatedModule.makeShareableClone( + return WorkletsModule.makeShareableClone( value, shouldPersistRemote, undefined diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts index 95b0978d214..2cc7cfa714c 100644 --- a/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts +++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts @@ -1,9 +1,16 @@ 'use strict'; -import type { IWorkletsModule } from '../../commonTypes'; +import type { IWorkletsModule, ShareableRef } from '../../commonTypes'; +import { ReanimatedError } from '../../errors'; export function createJSWorkletsModule(): IWorkletsModule { return new JSWorklets(); } -class JSWorklets implements IWorkletsModule {} +class JSWorklets implements IWorkletsModule { + makeShareableClone(): ShareableRef { + throw new ReanimatedError( + 'makeShareableClone should never be called in JSWorklets.' + ); + } +} diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts index 2dbd69df4ab..e305d6f164d 100644 --- a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts +++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts @@ -25,4 +25,16 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti } this.#workletsModuleProxy = global.__workletsModuleProxy; } + + makeShareableClone( + value: T, + shouldPersistRemote: boolean, + nativeStateSource?: object + ) { + return this.#workletsModuleProxy.makeShareableClone( + value, + shouldPersistRemote, + nativeStateSource + ); + } } diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts index 00ae1391e31..537e5556502 100644 --- a/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts +++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts @@ -1,4 +1,12 @@ 'use strict'; +import type { ShareableRef } from '../../commonTypes'; + /** Type of `__workletsModuleProxy` injected with JSI. */ -export interface WorkletsModuleProxy {} +export interface WorkletsModuleProxy { + makeShareableClone( + value: TValue, + shouldPersistRemote: boolean, + nativeStateSource?: object + ): ShareableRef; +} From 16cd933c1f418868b709a0bd4e152b6c3a0124ec Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski <61011609+sumo-slonik@users.noreply.github.com> Date: Fri, 22 Nov 2024 16:58:30 +0100 Subject: [PATCH 07/36] Fix bug in useSharedValueMock (#6742) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary The API for sharedValue has changed from using .value to get() and set() methods. As a result, the mock that previously returned an object with a single value property no longer works in the tests. ## Test plan This is a PR for the mocks, so it's not necessary for it. --------- Co-authored-by: Tomasz Żelawski --- packages/react-native-reanimated/src/mock.ts | 32 +++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/react-native-reanimated/src/mock.ts b/packages/react-native-reanimated/src/mock.ts index 65288ac6d64..3d8e3f8a67c 100644 --- a/packages/react-native-reanimated/src/mock.ts +++ b/packages/react-native-reanimated/src/mock.ts @@ -50,7 +50,37 @@ const hook = { ): EventHandlerProcessed => NOOP, // useHandler: ADD ME IF NEEDED useWorkletCallback: ID, - useSharedValue: (init: Value) => ({ value: init }), + useSharedValue: (init: Value) => { + const value = { value: init }; + return new Proxy(value, { + get(target, prop) { + if (prop === 'value') { + return target.value; + } + if (prop === 'get') { + return () => target.value; + } + if (prop === 'set') { + return (newValue: Value | ((currentValue: Value) => Value)) => { + if (typeof newValue === 'function') { + target.value = (newValue as (currentValue: Value) => Value)( + target.value + ); + } else { + target.value = newValue; + } + }; + } + }, + set(target, prop: string, newValue) { + if (prop === 'value') { + target.value = newValue; + return true; + } + return false; + }, + }); + }, // useReducedMotion: ADD ME IF NEEDED useAnimatedStyle: IMMEDIATE_CALLBACK_INVOCATION, useAnimatedGestureHandler: NOOP_FACTORY, From 65b520c8103cb72c8dcd8ff157cc0e7f9c30dfbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ma=C5=82ecki?= Date: Fri, 22 Nov 2024 17:59:12 +0100 Subject: [PATCH 08/36] chore: migrate npx react-native init (#6628) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Migrating deprecated `npx react-native init` command to `npx @react-native-community/cli init` as mentioned [here](https://github.com/software-mansion/react-native-reanimated/pull/6533#pullrequestreview-2321459011) --------- Co-authored-by: Tomasz Żelawski --- .../V8-reanimated-build-check-nightly.yml | 18 +++++----- .github/workflows/example-ios-build-check.yml | 2 +- .../expo-devclient-build-check-nightly.yml | 2 +- ...repo-app-reanimated-build-check-action.yml | 10 +++--- ...nightly-reanimated-build-check-nightly.yml | 20 ++++++----- ...reanimated-compatibility-check-nightly.yml | 17 +++++++--- ...amework-reanimated-build-check-nightly.yml | 33 ++++++++++++++----- ...ted-app-reanimated-build-check-nightly.yml | 14 +++++--- 8 files changed, 76 insertions(+), 40 deletions(-) diff --git a/.github/workflows/V8-reanimated-build-check-nightly.yml b/.github/workflows/V8-reanimated-build-check-nightly.yml index b79a507fb79..ba053a94a1b 100644 --- a/.github/workflows/V8-reanimated-build-check-nightly.yml +++ b/.github/workflows/V8-reanimated-build-check-nightly.yml @@ -33,17 +33,19 @@ jobs: java-version: '17' - name: Setup Yarn - # Sometimes `npx react-native init` fails due to dependency mismatches or other - # rather vague errors. This is a workaround for that. + # Sometimes `npx @react-native-community/cli init` fails at random. + # Pre-installing it with Yarn seems to improve stability. run: corepack enable && yarn init - - name: Install React Native - run: yarn add react-native + - name: Install React Native CLI + run: yarn add @react-native-community/cli - name: Create app - run: | - yarn react-native init ${{ env.APP_NAME }} --version ${{env.LATEST_SUPPORTED_RN_VERSION_IN_V8}} --skip-install --pm yarn --skip-install --install-pods false --skip-git-init - - name: Setup Yarn Modern + run: yarn rnc-cli init ${{ env.APP_NAME }} --version ${{env.LATEST_SUPPORTED_RN_VERSION_IN_V8}} --skip-install --pm yarn --install-pods false --skip-git-init + - name: Setup Yarn Modern in app working-directory: ${{ env.APP_NAME }} - run: touch yarn.lock && yarn set version berry && yarn config set nodeLinker node-modules + run: | + touch yarn.lock + yarn set version berry + yarn config set nodeLinker node-modules - name: Install dependencies working-directory: ${{ env.APP_NAME }} run: yarn install diff --git a/.github/workflows/example-ios-build-check.yml b/.github/workflows/example-ios-build-check.yml index b3cb44c11b7..5b1b6a3cacc 100644 --- a/.github/workflows/example-ios-build-check.yml +++ b/.github/workflows/example-ios-build-check.yml @@ -58,4 +58,4 @@ jobs: - name: Build app working-directory: ${{ matrix.working-directory }} - run: npx react-native run-ios --no-packager + run: yarn react-native run-ios --no-packager diff --git a/.github/workflows/expo-devclient-build-check-nightly.yml b/.github/workflows/expo-devclient-build-check-nightly.yml index 56a7f08aa9b..8f4a7773e88 100644 --- a/.github/workflows/expo-devclient-build-check-nightly.yml +++ b/.github/workflows/expo-devclient-build-check-nightly.yml @@ -66,7 +66,7 @@ jobs: - name: Build app (iOS) working-directory: ${{ env.APP_NAME }} if: ${{ matrix.platform == 'iOS' }} - run: npx react-native run-ios --simulator='iPhone 14' --terminal='Terminal' + run: yarn react-native run-ios --terminal='Terminal' - name: Build app (Android) working-directory: ${{ env.APP_NAME }}/android if: ${{ matrix.platform == 'Android' }} diff --git a/.github/workflows/monorepo-app-reanimated-build-check-action.yml b/.github/workflows/monorepo-app-reanimated-build-check-action.yml index f9262ddd4f3..729ef3503f7 100644 --- a/.github/workflows/monorepo-app-reanimated-build-check-action.yml +++ b/.github/workflows/monorepo-app-reanimated-build-check-action.yml @@ -35,15 +35,17 @@ jobs: # TODO: Put Monorepo template into a separate repo/package run: echo '{"name":"rnos-monorepo-tester","version":"1.0.0","license":"MIT","private":true,"workspaces":{"packages":["RootApp","packages/PackageApp", "AppA", "AppB"],"nohoist":["**/react","**/react-dom","**/react-native","**/react-native/**","**/react-native-codegen","**/react-native-dev-menu"]}}' > package.json - name: Install dependencies + working-directory: monorepo run: yarn install + - name: Install React Native CLI + working-directory: monorepo + run: yarn add -W @react-native-community/cli - name: Create RootApp working-directory: monorepo - # TODO: Revise if we want to hardcode 0.73 here. - run: npx react-native@0.73 init RootApp --skip-install --version 0.73 + run: yarn rnc-cli init RootApp --skip-install --pm yarn --install-pods false --skip-git-init - name: Create PackageApp working-directory: monorepo/packages - # TODO: Revise if we want to hardcode 0.73 here. - run: npx react-native@0.73 init PackageApp --skip-install --version 0.73 + run: yarn rnc-cli init PackageApp --skip-install --pm yarn --install-pods false --skip-git-init - name: Install dependencies for RootApp working-directory: monorepo/RootApp diff --git a/.github/workflows/react-native-nightly-reanimated-build-check-nightly.yml b/.github/workflows/react-native-nightly-reanimated-build-check-nightly.yml index 2491f8177cd..53739f28a2b 100644 --- a/.github/workflows/react-native-nightly-reanimated-build-check-nightly.yml +++ b/.github/workflows/react-native-nightly-reanimated-build-check-nightly.yml @@ -27,8 +27,8 @@ jobs: cancel-in-progress: true steps: - name: Setup Yarn - # Sometimes `npx react-native init` fails due to dependency mismatches or other - # rather vague errors. This is a workaround for that. + # Sometimes `npx @react-native-community/cli init` fails at random. + # Pre-installing it with Yarn seems to improve stability. run: corepack enable && yarn init - name: Set up JDK 18 if: ${{ matrix.platform == 'Android' }} @@ -41,14 +41,16 @@ jobs: if npm view react-native dist-tags | grep -q 'next:' ; then echo "REACT_NATIVE_TAG=next" >> $GITHUB_ENV fi - - name: Install React Native - run: yarn add react-native@${{ env.REACT_NATIVE_TAG }} + - name: Install React Native CLI + run: yarn add @react-native-community/cli - name: Create app - run: | - yarn react-native init ${{ env.APP_NAME }} --version ${{ env.REACT_NATIVE_TAG }} --pm yarn --skip-install --install-pods false --skip-git-init - - name: Setup Yarn Modern + run: yarn rnc-cli init ${{ env.APP_NAME }} --version ${{ env.REACT_NATIVE_TAG }} --pm yarn --skip-install --install-pods false --skip-git-init + - name: Setup Yarn Modern in app working-directory: ${{ env.APP_NAME }} - run: touch yarn.lock && yarn set version berry + run: | + touch yarn.lock + yarn set version berry + yarn config set nodeLinker node-modules - name: Install Reanimated working-directory: ${{ env.APP_NAME }} run: yarn add "react-native-reanimated@https://github.com/software-mansion/react-native-reanimated.git#workspace=react-native-reanimated&commit=${{ github.sha }}" @@ -67,7 +69,7 @@ jobs: - name: Build app (iOS) if: ${{ matrix.platform == 'iOS' }} working-directory: ${{ env.APP_NAME }} - run: yarn react-native run-ios --simulator='iPhone 14' + run: yarn react-native run-ios --terminal='Terminal' - name: Build app (Android) if: ${{ matrix.platform == 'Android' }} working-directory: ${{ env.APP_NAME }}/android diff --git a/.github/workflows/reanimated-compatibility-check-nightly.yml b/.github/workflows/reanimated-compatibility-check-nightly.yml index 8bde71c666e..308152632ae 100644 --- a/.github/workflows/reanimated-compatibility-check-nightly.yml +++ b/.github/workflows/reanimated-compatibility-check-nightly.yml @@ -44,13 +44,22 @@ jobs: uses: actions/setup-node@v3 with: node-version: 18 + - name: + Setup Yarn + # Sometimes `npx @react-native-community/cli init` fails at random. + # Pre-installing it with Yarn seems to improve stability. + run: corepack enable && yarn init + - name: Install React Native CLI + run: yarn add @react-native-community/cli - name: Create app - run: | - npx react-native@latest init ${{env.APP_NAME}} --version ${{ matrix.react-native.version }} --skip-install --pm yarn --skip-install --install-pods 0 --skip-git-init - - name: Setup Yarn Modern + run: yarn rnc-cli init ${{env.APP_NAME}} --version ${{ matrix.react-native.version }} --skip-install --pm yarn --install-pods 0 --skip-git-init + - name: Setup Yarn Modern in app # For convenience, sometimes there are vague issues with RN CLI and Yarn Legacy on the runner. working-directory: ${{ env.APP_NAME }} - run: corepack enable && yarn set version berry + run: | + touch yarn.lock + yarn set version berry + yarn config set nodeLinker node-modules - name: Install Reanimated working-directory: ${{ env.APP_NAME }} run: yarn add "react-native-reanimated@https://github.com/software-mansion/react-native-reanimated.git#workspace=react-native-reanimated&commit=${{ github.sha }}" diff --git a/.github/workflows/static-framework-reanimated-build-check-nightly.yml b/.github/workflows/static-framework-reanimated-build-check-nightly.yml index b7cff8b68ed..b29edb45149 100644 --- a/.github/workflows/static-framework-reanimated-build-check-nightly.yml +++ b/.github/workflows/static-framework-reanimated-build-check-nightly.yml @@ -21,20 +21,37 @@ jobs: concurrency: group: ios-static-framework-${{ matrix.react-native-architecture }}-${{ github.ref }} cancel-in-progress: true + env: + APP_NAME: app steps: - - name: Create React Native app - run: npx react-native init app + - name: Setup Yarn + # Sometimes `npx @react-native-community/cli init` fails at random. + # Pre-installing it with Yarn seems to improve stability. + run: corepack enable && yarn init + - name: Install React Native + run: yarn add @react-native-community/cli + - name: Create app + run: yarn rnc-cli init ${{ env.APP_NAME }} --skip-install --pm yarn --install-pods false --skip-git-init + - name: Setup Yarn Modern in app + working-directory: ${{ env.APP_NAME }} + run: | + touch yarn.lock + yarn set version berry + yarn config set nodeLinker node-modules + - name: Install dependencies + working-directory: ${{ env.APP_NAME }} + run: yarn install - name: Install Reanimated - working-directory: app + working-directory: ${{ env.APP_NAME }} run: yarn add "react-native-reanimated@https://github.com/software-mansion/react-native-reanimated.git#workspace=react-native-reanimated&commit=${{ github.sha }}" - name: Install Paper Pods if: ${{ matrix.react-native-architecture == 'Paper' }} - working-directory: app/ios + working-directory: ${{env.APP_NAME}}/ios run: export USE_FRAMEWORKS=static NO_FLIPPER=1 && bundle install && bundle exec pod install - name: Install Fabric Pods if: ${{ matrix.react-native-architecture == 'Fabric' }} - working-directory: app/ios - run: export USE_FRAMEWORKS=static NO_FLIPPER=1 RCT_NEW_ARCH_ENABLED=1 && bundle install && bundle exec pod install + working-directory: ${{env.APP_NAME}}/ios + run: export USE_FRAMEWORKS=static NO_FLIPPER=1 RCT_NEW_ARCH_ENABLED=1 && bundle install && bundle exec pod update - name: Build app - working-directory: app - run: npx react-native run-ios --no-packager + working-directory: ${{env.APP_NAME}}/ios + run: xcodebuild -workspace ${{env.APP_NAME}}.xcworkspace -scheme ${{env.APP_NAME}} -configuration Debug -destination 'generic/platform=iOS Simulator' build | xcpretty diff --git a/.github/workflows/windows-hosted-app-reanimated-build-check-nightly.yml b/.github/workflows/windows-hosted-app-reanimated-build-check-nightly.yml index dc188fe19b4..cdee2b230b2 100644 --- a/.github/workflows/windows-hosted-app-reanimated-build-check-nightly.yml +++ b/.github/workflows/windows-hosted-app-reanimated-build-check-nightly.yml @@ -25,17 +25,21 @@ jobs: with: distribution: 'zulu' java-version: '17' - - name: Setup Yarn - # Sometimes `npx react-native init` fails due to dependency mismatches or other - # rather vague errors. This is a workaround for that. + - name: + Setup Yarn + # Sometimes `npx @react-native-community/cli init` fails at random. + # Pre-installing it with Yarn seems to improve stability. run: corepack enable && yarn init --yes - name: Install React Native run: yarn add @react-native-community/cli - name: Create app run: yarn rnc-cli init ${{ env.APP_NAME }} --pm yarn --skip-install --install-pods false --skip-git-init - - name: Setup Yarn Modern + - name: Setup Yarn Modern in app working-directory: ${{ env.APP_NAME }} - run: touch yarn.lock && yarn set version berry + run: | + touch yarn.lock + yarn set version berry + yarn config set nodeLinker node-modules - name: Install dependencies working-directory: ${{ env.APP_NAME }} run: yarn From 3212ae4f22d82fb855d7b8f9dc48a18f3a868595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Mon, 25 Nov 2024 15:56:53 +0100 Subject: [PATCH 09/36] refactor(Worklets): Move `messageQueue` to Worklets (#6577) ## Summary Moving `MessageQueueThread` to Worklets. It still has the name `REAMessageThread` or similar in some places. This will be addressed in the following PR. ## Test plan - [x] iOS 0.76 paper/fabric - [x] android 0.76 paper/fabric CI does the rest. --- .../NativeModules/NativeReanimatedModule.cpp | 6 ++---- .../NativeModules/NativeReanimatedModule.h | 2 -- .../NativeModules/NativeWorkletsModule.cpp | 7 +++++-- .../NativeModules/NativeWorkletsModule.h | 11 ++++++++++- .../main/cpp/reanimated/android/NativeProxy.cpp | 17 ++++------------- .../main/cpp/reanimated/android/NativeProxy.h | 9 ++------- .../cpp/worklets/android/WorkletsModule.cpp | 14 +++++++++----- .../main/cpp/worklets/android/WorkletsModule.h | 6 ++++-- .../com/swmansion/worklets/WorkletsModule.java | 10 ++++++++-- .../com/swmansion/reanimated/NativeProxy.java | 7 ------- .../com/swmansion/reanimated/NativeProxy.java | 7 ------- .../com/swmansion/reanimated/NativeProxy.java | 8 ++------ .../com/swmansion/reanimated/NativeProxy.java | 8 ++------ .../reanimated/apple/native/NativeProxy.mm | 13 ++----------- .../native/PlatformDepMethodsHolderImpl.mm | 2 +- .../apple}/REAMessageThread.h | 0 .../apple}/REAMessageThread.mm | 8 ++++---- .../apple/worklets/apple/WorkletsModule.mm | 6 +++++- 18 files changed, 60 insertions(+), 81 deletions(-) rename packages/react-native-reanimated/apple/{reanimated/apple/native => worklets/apple}/REAMessageThread.h (100%) rename packages/react-native-reanimated/apple/{reanimated/apple/native => worklets/apple}/REAMessageThread.mm (82%) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp index b1f430a89cd..3e81bdee99e 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp @@ -55,7 +55,6 @@ NativeReanimatedModule::NativeReanimatedModule( const std::shared_ptr &nativeWorkletsModule, jsi::Runtime &rnRuntime, const std::shared_ptr &jsScheduler, - const std::shared_ptr &jsQueue, const std::shared_ptr &uiScheduler, const PlatformDepMethodsHolder &platformDepMethodsHolder, const bool isBridgeless, @@ -64,14 +63,13 @@ NativeReanimatedModule::NativeReanimatedModule( isBridgeless ? nullptr : jsScheduler->getJSCallInvoker()), isBridgeless_(isBridgeless), isReducedMotion_(isReducedMotion), - jsQueue_(jsQueue), nativeWorkletsModule_(nativeWorkletsModule), jsScheduler_(jsScheduler), uiScheduler_(uiScheduler), valueUnpackerCode_(nativeWorkletsModule->getValueUnpackerCode()), uiWorkletRuntime_(std::make_shared( rnRuntime, - jsQueue, + nativeWorkletsModule->getJSQueue(), jsScheduler_, "Reanimated UI runtime", true /* supportsLocking */, @@ -233,7 +231,7 @@ jsi::Value NativeReanimatedModule::createWorkletRuntime( const jsi::Value &initializer) { auto workletRuntime = std::make_shared( rt, - jsQueue_, + nativeWorkletsModule_->getJSQueue(), jsScheduler_, name.asString(rt).utf8(rt), false /* supportsLocking */, diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h index 29bfecc7a63..ba5e8deee29 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h @@ -36,7 +36,6 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec { const std::shared_ptr &nativeWorkletsModule, jsi::Runtime &rnRuntime, const std::shared_ptr &jsScheduler, - const std::shared_ptr &jsQueue, const std::shared_ptr &uiScheduler, const PlatformDepMethodsHolder &platformDepMethodsHolder, const bool isBridgeless, @@ -194,7 +193,6 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec { const bool isBridgeless_; const bool isReducedMotion_; - const std::shared_ptr jsQueue_; const std::shared_ptr nativeWorkletsModule_; const std::shared_ptr jsScheduler_; const std::shared_ptr uiScheduler_; diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp index 80270752948..5189d0aa561 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp @@ -18,9 +18,12 @@ using namespace facebook; namespace worklets { -NativeWorkletsModule::NativeWorkletsModule(const std::string &valueUnpackerCode) +NativeWorkletsModule::NativeWorkletsModule( + const std::string &valueUnpackerCode, + const std::shared_ptr &jsQueue) : NativeWorkletsModuleSpec(nullptr), - valueUnpackerCode_(valueUnpackerCode) {} + valueUnpackerCode_(valueUnpackerCode), + jsQueue_(jsQueue) {} NativeWorkletsModule::~NativeWorkletsModule() {} diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h index 5912056fb16..13eb581337c 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h @@ -3,13 +3,17 @@ #include #include #include +#include +#include #include namespace worklets { class NativeWorkletsModule : public NativeWorkletsModuleSpec { public: - explicit NativeWorkletsModule(const std::string &valueUnpackerCode); + explicit NativeWorkletsModule( + const std::string &valueUnpackerCode, + const std::shared_ptr &jsQueue); ~NativeWorkletsModule(); @@ -23,8 +27,13 @@ class NativeWorkletsModule : public NativeWorkletsModuleSpec { return valueUnpackerCode_; } + [[nodiscard]] inline std::shared_ptr getJSQueue() const { + return jsQueue_; + } + private: const std::string valueUnpackerCode_; + const std::shared_ptr jsQueue_; #ifndef NDEBUG SingleInstanceChecker singleInstanceChecker_; #endif // NDEBUG diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp index 42b1f21ce14..61fd25338fc 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp +++ b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include @@ -33,8 +32,7 @@ NativeProxy::NativeProxy( jsi::Runtime *rnRuntime, const std::shared_ptr &jsCallInvoker, const std::shared_ptr &uiScheduler, - jni::global_ref layoutAnimations, - jni::alias_ref messageQueueThread + jni::global_ref layoutAnimations #ifdef RCT_NEW_ARCH_ENABLED , jni::alias_ref @@ -47,7 +45,6 @@ NativeProxy::NativeProxy( nativeWorkletsModule, *rnRuntime, std::make_shared(*rnRuntime, jsCallInvoker), - std::make_shared(messageQueueThread), uiScheduler, getPlatformDependentMethods(), /* isBridgeless */ false, @@ -66,7 +63,6 @@ NativeProxy::NativeProxy( RuntimeExecutor runtimeExecutor, const std::shared_ptr &uiScheduler, jni::global_ref layoutAnimations, - jni::alias_ref messageQueueThread, jni::alias_ref fabricUIManager) : javaPart_(jni::make_global(jThis)), @@ -75,7 +71,6 @@ NativeProxy::NativeProxy( nativeWorkletsModule, *rnRuntime, std::make_shared(*rnRuntime, runtimeExecutor), - std::make_shared(messageQueueThread), uiScheduler, getPlatformDependentMethods(), /* isBridgeless */ true, @@ -119,8 +114,7 @@ jni::local_ref NativeProxy::initHybrid( jni::alias_ref jsCallInvokerHolder, jni::alias_ref androidUiScheduler, - jni::alias_ref layoutAnimations, - jni::alias_ref messageQueueThread + jni::alias_ref layoutAnimations #ifdef RCT_NEW_ARCH_ENABLED , jni::alias_ref @@ -137,10 +131,9 @@ jni::local_ref NativeProxy::initHybrid( (jsi::Runtime *)jsContext, jsCallInvoker, uiScheduler, - make_global(layoutAnimations), - messageQueueThread + make_global(layoutAnimations) #ifdef RCT_NEW_ARCH_ENABLED - , + , fabricUIManager #endif ); @@ -154,7 +147,6 @@ jni::local_ref NativeProxy::initHybridBridgeless( jni::alias_ref runtimeExecutorHolder, jni::alias_ref androidUiScheduler, jni::alias_ref layoutAnimations, - jni::alias_ref messageQueueThread, jni::alias_ref fabricUIManager) { auto uiScheduler = androidUiScheduler->cthis()->getUIScheduler(); @@ -168,7 +160,6 @@ jni::local_ref NativeProxy::initHybridBridgeless( runtimeExecutor, uiScheduler, make_global(layoutAnimations), - messageQueueThread, fabricUIManager); } #endif // RCT_NEW_ARCH_ENABLED diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h index 1f2ac757987..ea250729644 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h +++ b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -155,8 +154,7 @@ class NativeProxy : public jni::HybridClass { jni::alias_ref jsCallInvokerHolder, jni::alias_ref androidUiScheduler, - jni::alias_ref layoutAnimations, - jni::alias_ref messageQueueThread + jni::alias_ref layoutAnimations #ifdef RCT_NEW_ARCH_ENABLED , jni::alias_ref @@ -172,7 +170,6 @@ class NativeProxy : public jni::HybridClass { jni::alias_ref runtimeExecutorHolder, jni::alias_ref androidUiScheduler, jni::alias_ref layoutAnimations, - jni::alias_ref messageQueueThread, jni::alias_ref fabricUIManager); #endif // RCT_NEW_ARCH_ENABLED @@ -282,8 +279,7 @@ class NativeProxy : public jni::HybridClass { jsi::Runtime *rnRuntime, const std::shared_ptr &jsCallInvoker, const std::shared_ptr &uiScheduler, - jni::global_ref layoutAnimations, - jni::alias_ref messageQueueThread + jni::global_ref layoutAnimations #ifdef RCT_NEW_ARCH_ENABLED , jni::alias_ref @@ -299,7 +295,6 @@ class NativeProxy : public jni::HybridClass { RuntimeExecutor runtimeExecutor, const std::shared_ptr &uiScheduler, jni::global_ref layoutAnimations, - jni::alias_ref messageQueueThread, jni::alias_ref fabricUIManager); diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp index 6be7b73349d..833c5a36cbf 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp +++ b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp @@ -20,19 +20,23 @@ using namespace react; WorkletsModule::WorkletsModule( jni::alias_ref jThis, jsi::Runtime *rnRuntime, - const std::string &valueUnpackerCode) + const std::string &valueUnpackerCode, + jni::alias_ref messageQueueThread) : javaPart_(jni::make_global(jThis)), rnRuntime_(rnRuntime), - nativeWorkletsModule_( - std::make_shared(valueUnpackerCode)) { + nativeWorkletsModule_(std::make_shared( + valueUnpackerCode, + std::make_shared(messageQueueThread))) { RNRuntimeWorkletDecorator::decorate(*rnRuntime_, nativeWorkletsModule_); } jni::local_ref WorkletsModule::initHybrid( jni::alias_ref jThis, jlong jsContext, - const std::string &valueUnpackerCode) { - return makeCxxInstance(jThis, (jsi::Runtime *)jsContext, valueUnpackerCode); + const std::string &valueUnpackerCode, + jni::alias_ref messageQueueThread) { + return makeCxxInstance( + jThis, (jsi::Runtime *)jsContext, valueUnpackerCode, messageQueueThread); } void WorkletsModule::registerNatives() { diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h index 349853b1edb..e367780de3c 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h +++ b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h @@ -31,7 +31,8 @@ class WorkletsModule : public jni::HybridClass { static jni::local_ref initHybrid( jni::alias_ref jThis, jlong jsContext, - const std::string &valueUnpackerCode); + const std::string &valueUnpackerCode, + jni::alias_ref messageQueueThread); static void registerNatives(); @@ -48,7 +49,8 @@ class WorkletsModule : public jni::HybridClass { explicit WorkletsModule( jni::alias_ref jThis, jsi::Runtime *rnRuntime, - const std::string &valueUnpackerCode); + const std::string &valueUnpackerCode, + jni::alias_ref messageQueueThread); }; } // namespace worklets diff --git a/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java index 2da67792f66..31c74a6e560 100644 --- a/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java +++ b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java @@ -5,10 +5,12 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.common.annotations.FrameworkAPI; import com.facebook.react.module.annotations.ReactModule; import com.facebook.soloader.SoLoader; import com.swmansion.reanimated.NativeWorkletsModuleSpec; +import com.swmansion.reanimated.ReanimatedMessageQueueThread; import java.util.Objects; @ReactModule(name = WorkletsModule.NAME) @@ -28,11 +30,15 @@ protected HybridData getHybridData() { return mHybridData; } + private final ReanimatedMessageQueueThread mMessageQueueThread = + new ReanimatedMessageQueueThread(); + /** * @noinspection JavaJniMissingFunction */ @OptIn(markerClass = FrameworkAPI.class) - private native HybridData initHybrid(long jsContext, String valueUnpackerCode); + private native HybridData initHybrid( + long jsContext, String valueUnpackerCode, MessageQueueThread messageQueueThread); public WorkletsModule(ReactApplicationContext reactContext) { super(reactContext); @@ -44,7 +50,7 @@ public boolean installTurboModule(String valueUnpackerCode) { var context = getReactApplicationContext(); var jsContext = Objects.requireNonNull(context.getJavaScriptContextHolder()).get(); - mHybridData = initHybrid(jsContext, valueUnpackerCode); + mHybridData = initHybrid(jsContext, valueUnpackerCode, mMessageQueueThread); return true; } diff --git a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/74/com/swmansion/reanimated/NativeProxy.java b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/74/com/swmansion/reanimated/NativeProxy.java index 1f732ab91f1..5cd43091f22 100644 --- a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/74/com/swmansion/reanimated/NativeProxy.java +++ b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/74/com/swmansion/reanimated/NativeProxy.java @@ -5,7 +5,6 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.RuntimeExecutor; -import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.common.annotations.FrameworkAPI; import com.facebook.react.fabric.FabricUIManager; import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; @@ -33,8 +32,6 @@ public class NativeProxy extends NativeProxyCommon { LayoutAnimations LayoutAnimations = new LayoutAnimations(context); - ReanimatedMessageQueueThread messageQueueThread = new ReanimatedMessageQueueThread(); - if (context.isBridgeless()) { RuntimeExecutor runtimeExecutor = context.getRuntimeExecutor(); mHybridData = @@ -44,7 +41,6 @@ public class NativeProxy extends NativeProxyCommon { runtimeExecutor, mAndroidUIScheduler, LayoutAnimations, - messageQueueThread, fabricUIManager); } else { CallInvokerHolderImpl callInvokerHolder = @@ -56,7 +52,6 @@ public class NativeProxy extends NativeProxyCommon { callInvokerHolder, mAndroidUIScheduler, LayoutAnimations, - messageQueueThread, fabricUIManager); } prepareLayoutAnimations(LayoutAnimations); @@ -72,7 +67,6 @@ private native HybridData initHybrid( CallInvokerHolderImpl jsCallInvokerHolder, AndroidUIScheduler androidUIScheduler, LayoutAnimations LayoutAnimations, - MessageQueueThread messageQueueThread, FabricUIManager fabricUIManager); private native HybridData initHybridBridgeless( @@ -81,7 +75,6 @@ private native HybridData initHybridBridgeless( RuntimeExecutor runtimeExecutor, AndroidUIScheduler androidUIScheduler, LayoutAnimations LayoutAnimations, - MessageQueueThread messageQueueThread, FabricUIManager fabricUIManager); public native boolean isAnyHandlerWaitingForEvent(String eventName, int emitterReactTag); diff --git a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/latest/com/swmansion/reanimated/NativeProxy.java b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/latest/com/swmansion/reanimated/NativeProxy.java index ddfb00aceb5..16f95043f78 100644 --- a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/latest/com/swmansion/reanimated/NativeProxy.java +++ b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyFabric/latest/com/swmansion/reanimated/NativeProxy.java @@ -5,7 +5,6 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.RuntimeExecutor; -import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.common.annotations.FrameworkAPI; import com.facebook.react.fabric.FabricUIManager; import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; @@ -33,8 +32,6 @@ public class NativeProxy extends NativeProxyCommon { LayoutAnimations LayoutAnimations = new LayoutAnimations(context); - ReanimatedMessageQueueThread messageQueueThread = new ReanimatedMessageQueueThread(); - if (context.isBridgeless()) { RuntimeExecutor runtimeExecutor = context.getCatalystInstance().getRuntimeExecutor(); mHybridData = @@ -44,7 +41,6 @@ public class NativeProxy extends NativeProxyCommon { runtimeExecutor, mAndroidUIScheduler, LayoutAnimations, - messageQueueThread, fabricUIManager); } else { CallInvokerHolderImpl callInvokerHolder = @@ -56,7 +52,6 @@ public class NativeProxy extends NativeProxyCommon { callInvokerHolder, mAndroidUIScheduler, LayoutAnimations, - messageQueueThread, fabricUIManager); } prepareLayoutAnimations(LayoutAnimations); @@ -72,7 +67,6 @@ private native HybridData initHybrid( CallInvokerHolderImpl jsCallInvokerHolder, AndroidUIScheduler androidUIScheduler, LayoutAnimations LayoutAnimations, - MessageQueueThread messageQueueThread, FabricUIManager fabricUIManager); private native HybridData initHybridBridgeless( @@ -81,7 +75,6 @@ private native HybridData initHybridBridgeless( RuntimeExecutor runtimeExecutor, AndroidUIScheduler androidUIScheduler, LayoutAnimations LayoutAnimations, - MessageQueueThread messageQueueThread, FabricUIManager fabricUIManager); public native boolean isAnyHandlerWaitingForEvent(String eventName, int emitterReactTag); diff --git a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/74/com/swmansion/reanimated/NativeProxy.java b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/74/com/swmansion/reanimated/NativeProxy.java index 9078f5486c6..418ff7fc890 100644 --- a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/74/com/swmansion/reanimated/NativeProxy.java +++ b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/74/com/swmansion/reanimated/NativeProxy.java @@ -6,7 +6,6 @@ import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.common.annotations.FrameworkAPI; import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; import com.swmansion.reanimated.layoutReanimation.LayoutAnimations; @@ -28,15 +27,13 @@ public NativeProxy(ReactApplicationContext context, WorkletsModule workletsModul CallInvokerHolderImpl holder = (CallInvokerHolderImpl) context.getCatalystInstance().getJSCallInvokerHolder(); LayoutAnimations LayoutAnimations = new LayoutAnimations(context); - ReanimatedMessageQueueThread messageQueueThread = new ReanimatedMessageQueueThread(); mHybridData = initHybrid( workletsModule, Objects.requireNonNull(context.getJavaScriptContextHolder()).get(), holder, mAndroidUIScheduler, - LayoutAnimations, - messageQueueThread); + LayoutAnimations); prepareLayoutAnimations(LayoutAnimations); installJSIBindings(); if (BuildConfig.DEBUG) { @@ -50,8 +47,7 @@ private native HybridData initHybrid( long jsContext, CallInvokerHolderImpl jsCallInvokerHolder, AndroidUIScheduler androidUIScheduler, - LayoutAnimations LayoutAnimations, - MessageQueueThread messageQueueThread); + LayoutAnimations LayoutAnimations); public native boolean isAnyHandlerWaitingForEvent(String eventName, int emitterReactTag); diff --git a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/latest/com/swmansion/reanimated/NativeProxy.java b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/latest/com/swmansion/reanimated/NativeProxy.java index f4bfa2c555c..09068804bb3 100644 --- a/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/latest/com/swmansion/reanimated/NativeProxy.java +++ b/packages/react-native-reanimated/android/src/reactNativeVersionPatch/NativeProxyPaper/latest/com/swmansion/reanimated/NativeProxy.java @@ -6,7 +6,6 @@ import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.queue.MessageQueueThread; import com.facebook.react.common.annotations.FrameworkAPI; import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; import com.swmansion.reanimated.layoutReanimation.LayoutAnimations; @@ -27,15 +26,13 @@ public NativeProxy(ReactApplicationContext context, WorkletsModule workletsModul super(context); CallInvokerHolderImpl holder = (CallInvokerHolderImpl) context.getJSCallInvokerHolder(); LayoutAnimations LayoutAnimations = new LayoutAnimations(context); - ReanimatedMessageQueueThread messageQueueThread = new ReanimatedMessageQueueThread(); mHybridData = initHybrid( workletsModule, Objects.requireNonNull(context.getJavaScriptContextHolder()).get(), holder, mAndroidUIScheduler, - LayoutAnimations, - messageQueueThread); + LayoutAnimations); prepareLayoutAnimations(LayoutAnimations); installJSIBindings(); if (BuildConfig.DEBUG) { @@ -49,8 +46,7 @@ private native HybridData initHybrid( long jsContext, CallInvokerHolderImpl jsCallInvokerHolder, AndroidUIScheduler androidUIScheduler, - LayoutAnimations LayoutAnimations, - MessageQueueThread messageQueueThread); + LayoutAnimations LayoutAnimations); public native boolean isAnyHandlerWaitingForEvent(String eventName, int emitterReactTag); diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm index b960c6c642b..eba24c8a15c 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm @@ -14,7 +14,7 @@ #import #import #import -#import + #import #ifndef NDEBUG @@ -22,6 +22,7 @@ #endif #import +#import #ifdef RCT_NEW_ARCH_ENABLED #import @@ -65,10 +66,6 @@ static inline bool getIsReducedMotion() jsi::Runtime &rnRuntime = *reinterpret_cast(reaModule.bridge.runtime); - auto jsQueue = std::make_shared([NSRunLoop currentRunLoop], ^(NSError *error) { - throw error; - }); - PlatformDepMethodsHolder platformDepMethodsHolder = makePlatformDepMethodsHolder(bridge, nodesManager, reaModule); std::shared_ptr uiScheduler = std::make_shared(); @@ -81,7 +78,6 @@ static inline bool getIsReducedMotion() nativeWorkletsModule, rnRuntime, jsScheduler, - jsQueue, uiScheduler, platformDepMethodsHolder, isBridgeless, @@ -110,10 +106,6 @@ static inline bool getIsReducedMotion() { auto nodesManager = reaModule.nodesManager; - auto jsQueue = std::make_shared([NSRunLoop currentRunLoop], ^(NSError *error) { - throw error; - }); - PlatformDepMethodsHolder platformDepMethodsHolder = makePlatformDepMethodsHolderBridgeless(moduleRegistry, nodesManager, reaModule); @@ -126,7 +118,6 @@ static inline bool getIsReducedMotion() nativeWorkletsModule, runtime, jsScheduler, - jsQueue, uiScheduler, platformDepMethodsHolder, isBridgeless, diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm b/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm index c1a6789aaab..4f2f3ac611b 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm @@ -12,7 +12,6 @@ #import #import #import -#import #import #ifndef NDEBUG @@ -20,6 +19,7 @@ #endif #import +#import #ifdef RCT_NEW_ARCH_ENABLED #import diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/REAMessageThread.h b/packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.h similarity index 100% rename from packages/react-native-reanimated/apple/reanimated/apple/native/REAMessageThread.h rename to packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.h diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/REAMessageThread.mm b/packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.mm similarity index 82% rename from packages/react-native-reanimated/apple/reanimated/apple/native/REAMessageThread.mm rename to packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.mm index be19a904ef4..0df1e2f1794 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/REAMessageThread.mm +++ b/packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.mm @@ -1,4 +1,4 @@ -#import +#import #import #import @@ -12,9 +12,9 @@ // Essentially the same as RCTMessageThread, but with public fields. struct REAMessageThreadPublic { - // I don't know why we need three vtables (if you know then feel free to - // explain it instead of this message), but this is what makes the casts in - // quitSynchronous() work correctly. + // I don't know why we need three vtables (if you know then feel free to#import + // explain it instead of this message), but this is what makes the casts + // in quitSynchronous() work correctly. void *vtable1; void *vtable2; void *vtable3; diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm index 3872f949ef2..622539ee20f 100644 --- a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm +++ b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm @@ -1,5 +1,6 @@ #import #import +#import #import #import @@ -35,7 +36,10 @@ @implementation WorkletsModule { { auto *bridge = self.bridge; auto &rnRuntime = *(jsi::Runtime *)bridge.runtime; - nativeWorkletsModule_ = std::make_shared(std::string([valueUnpackerCode UTF8String])); + auto jsQueue = std::make_shared([NSRunLoop currentRunLoop], ^(NSError *error) { + throw error; + }); + nativeWorkletsModule_ = std::make_shared(std::string([valueUnpackerCode UTF8String]), jsQueue); RNRuntimeWorkletDecorator::decorate(rnRuntime, nativeWorkletsModule_); return @YES; From b28dc07a6073ae2032519b31155853aab6fccf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:44:44 +0100 Subject: [PATCH 10/36] fix: restore `classic` runtime for @babel/preset-react (#6760) ## Summary Fixes https://github.com/software-mansion/react-native-reanimated/issues/6665 Applying the change I made to `react-native-builder-bob`: - https://github.com/callstack/react-native-builder-bob/pull/695 It restores `classic` runtime for the `@babel/react-native` preset used for generating ESModule code. The behavior was changed when we bumped builder-bob: - https://github.com/software-mansion/react-native-reanimated/pull/6485 ## Test plan I ran the `diff` for the version of `lib` without `jsxRuntime: classic` and with it - the differences are only in regards to `_jsx` usage. You can read more here: - https://github.com/software-mansion/react-native-reanimated/issues/6665 --- packages/react-native-reanimated/package.json | 5 +++-- yarn.lock | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/react-native-reanimated/package.json b/packages/react-native-reanimated/package.json index 50d8d9e89c6..e36e120959e 100644 --- a/packages/react-native-reanimated/package.json +++ b/packages/react-native-reanimated/package.json @@ -143,7 +143,7 @@ "prettier": "^3.3.3", "react": "18.3.1", "react-native": "^0.76.1", - "react-native-builder-bob": "0.30.2", + "react-native-builder-bob": "0.33.1", "react-native-gesture-handler": "2.20.2", "react-native-web": "0.19.11", "react-test-renderer": "18.2.0", @@ -158,7 +158,8 @@ [ "module", { - "esm": true + "esm": true, + "jsxRuntime": "classic" } ], "typescript" diff --git a/yarn.lock b/yarn.lock index 7736167a103..a87a4799e54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17688,9 +17688,9 @@ __metadata: languageName: node linkType: hard -"react-native-builder-bob@npm:0.30.2": - version: 0.30.2 - resolution: "react-native-builder-bob@npm:0.30.2" +"react-native-builder-bob@npm:0.33.1": + version: 0.33.1 + resolution: "react-native-builder-bob@npm:0.33.1" dependencies: "@babel/core": "npm:^7.25.2" "@babel/plugin-transform-strict-mode": "npm:^7.24.7" @@ -17716,7 +17716,7 @@ __metadata: yargs: "npm:^17.5.1" bin: bob: bin/bob - checksum: 10/0a6f2321ce7ba4aa08a40e5d599c94fe4705afc7d67ac9d4e2400603dd91cfa6646afdc02697ff683dca3b2654b1701bab4114c3548f4dfa0c9327a74a8a8a48 + checksum: 10/c4aaefdc1f82a88ce66c5b448ed851213ca614c777a775cb0772ab80e75852761b915d715ed6f58f99670b1b2fba6435e1d9c03445b9ba8eb44befeb77f5b532 languageName: node linkType: hard @@ -17877,7 +17877,7 @@ __metadata: prettier: "npm:^3.3.3" react: "npm:18.3.1" react-native: "npm:^0.76.1" - react-native-builder-bob: "npm:0.30.2" + react-native-builder-bob: "npm:0.33.1" react-native-gesture-handler: "npm:2.20.2" react-native-web: "npm:0.19.11" react-test-renderer: "npm:18.2.0" From 3a1622d6687232912007d42ccc8e6152f76a9072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Tue, 26 Nov 2024 09:48:49 +0100 Subject: [PATCH 11/36] Make `makeShareableCloneRecursive` more readable (#5724) ## Summary Refactoring `makeShareableCloneRecursive` so it would be actually readable now. The behavior of the function (and it's flow) shouldn't change. ## Test plan - [x] Runtime tests --- .../src/ReanimatedModule/NativeReanimated.ts | 3 +- .../js-reanimated/JSReanimated.ts | 3 +- .../ReanimatedModule/reanimatedModuleProxy.ts | 3 +- .../react-native-reanimated/src/Sensor.ts | 3 +- .../src/commonTypes.ts | 14 +- packages/react-native-reanimated/src/core.ts | 11 +- .../react-native-reanimated/src/shareables.ts | 467 +++++++++++------- 7 files changed, 330 insertions(+), 174 deletions(-) diff --git a/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts b/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts index 364a1126da4..3ff0ef98727 100644 --- a/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts +++ b/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts @@ -6,6 +6,7 @@ import type { LayoutAnimationBatchItem, IReanimatedModule, IWorkletsModule, + WorkletFunction, } from '../commonTypes'; import { checkCppVersion } from '../platform-specific/checkCppVersion'; import { jsVersion } from '../platform-specific/jsVersion'; @@ -165,7 +166,7 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti } subscribeForKeyboardEvents( - handler: ShareableRef, + handler: ShareableRef, isStatusBarTranslucent: boolean, isNavigationBarTranslucent: boolean ) { diff --git a/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts b/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts index f54963b6171..e4fa3b8a008 100644 --- a/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts +++ b/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts @@ -12,6 +12,7 @@ import type { ShareableRef, Value3D, ValueRotation, + WorkletFunction, } from '../../commonTypes'; import type { WebSensor } from './WebSensor'; import { mockedRequestAnimationFrame } from '../../mockedRequestAnimationFrame'; @@ -210,7 +211,7 @@ class JSReanimated implements IReanimatedModule { } } - subscribeForKeyboardEvents(_: ShareableRef): number { + subscribeForKeyboardEvents(_: ShareableRef): number { if (isWeb()) { logger.warn('useAnimatedKeyboard is not available on web yet.'); } else if (isJest()) { diff --git a/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts b/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts index cff70e423a7..5d334fb9897 100644 --- a/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts +++ b/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts @@ -6,6 +6,7 @@ import type { Value3D, ValueRotation, LayoutAnimationBatchItem, + WorkletFunction, } from '../commonTypes'; import type { WorkletRuntime } from '../runtimes'; @@ -53,7 +54,7 @@ export interface ReanimatedModuleProxy { configureProps(uiProps: string[], nativeProps: string[]): void; subscribeForKeyboardEvents( - handler: ShareableRef, + handler: ShareableRef, isStatusBarTranslucent: boolean, isNavigationBarTranslucent: boolean ): number; diff --git a/packages/react-native-reanimated/src/Sensor.ts b/packages/react-native-reanimated/src/Sensor.ts index af0c1d2f552..64dc9dd6e92 100644 --- a/packages/react-native-reanimated/src/Sensor.ts +++ b/packages/react-native-reanimated/src/Sensor.ts @@ -6,6 +6,7 @@ import type { Value3D, ValueRotation, ShareableRef, + WorkletFunction, } from './commonTypes'; import { SensorType } from './commonTypes'; import { makeMutable } from './mutables'; @@ -56,7 +57,7 @@ export default class Sensor { sensorType, config.interval === 'auto' ? -1 : config.interval, config.iosReferenceFrame, - eventHandler + eventHandler as ShareableRef ); return this.sensorId !== -1; } diff --git a/packages/react-native-reanimated/src/commonTypes.ts b/packages/react-native-reanimated/src/commonTypes.ts index f50717436d8..725436df1d8 100644 --- a/packages/react-native-reanimated/src/commonTypes.ts +++ b/packages/react-native-reanimated/src/commonTypes.ts @@ -327,10 +327,22 @@ interface WorkletBaseDev extends WorkletBaseCommon { __stackDetails?: WorkletStackDetails; } +export type WorkletFunctionDev< + Args extends unknown[] = unknown[], + ReturnValue = unknown, +> = ((...args: Args) => ReturnValue) & WorkletBaseDev; + +type WorkletFunctionRelease< + Args extends unknown[] = unknown[], + ReturnValue = unknown, +> = ((...args: Args) => ReturnValue) & WorkletBaseRelease; + export type WorkletFunction< Args extends unknown[] = unknown[], ReturnValue = unknown, -> = ((...args: Args) => ReturnValue) & (WorkletBaseRelease | WorkletBaseDev); +> = + | WorkletFunctionDev + | WorkletFunctionRelease; /** * This function allows you to determine if a given function is a worklet. It diff --git a/packages/react-native-reanimated/src/core.ts b/packages/react-native-reanimated/src/core.ts index dbe92773120..c913d948c45 100644 --- a/packages/react-native-reanimated/src/core.ts +++ b/packages/react-native-reanimated/src/core.ts @@ -9,6 +9,7 @@ import type { SharedValue, Value3D, ValueRotation, + WorkletFunction, } from './commonTypes'; import { makeShareableCloneRecursive } from './shareables'; import { initializeUIRuntime } from './initializers'; @@ -85,7 +86,9 @@ export function registerEventHandler( global.__frameTimestamp = undefined; } return ReanimatedModule.registerEventHandler( - makeShareableCloneRecursive(handleAndFlushAnimationFrame), + makeShareableCloneRecursive( + handleAndFlushAnimationFrame as WorkletFunction + ), eventName, emitterReactTag ); @@ -110,7 +113,9 @@ export function subscribeForKeyboardEvents( global.__frameTimestamp = undefined; } return ReanimatedModule.subscribeForKeyboardEvents( - makeShareableCloneRecursive(handleAndFlushAnimationFrame), + makeShareableCloneRecursive( + handleAndFlushAnimationFrame as WorkletFunction + ), options.isStatusBarTranslucentAndroid ?? false, options.isNavigationBarTranslucentAndroid ?? false ); @@ -132,7 +137,7 @@ export function registerSensor( return sensorContainer.registerSensor( sensorType, config, - makeShareableCloneRecursive(eventHandler) + makeShareableCloneRecursive(eventHandler as WorkletFunction) ); } diff --git a/packages/react-native-reanimated/src/shareables.ts b/packages/react-native-reanimated/src/shareables.ts index 23070fe7de9..ca99961133e 100644 --- a/packages/react-native-reanimated/src/shareables.ts +++ b/packages/react-native-reanimated/src/shareables.ts @@ -4,6 +4,7 @@ import type { ShareableRef, FlatShareableRef, WorkletFunction, + WorkletFunctionDev, } from './commonTypes'; import { shouldBeUseWeb } from './PlatformChecker'; import { ReanimatedError, registerWorkletStackDetails } from './errors'; @@ -32,10 +33,19 @@ function isHostObject(value: NonNullable) { return MAGIC_KEY in value; } -function isPlainJSObject(object: object) { +function isPlainJSObject(object: object): object is Record { return Object.getPrototypeOf(object) === Object.prototype; } +function getFromCache(value: object) { + const cached = shareableMappingCache.get(value); + if (cached === shareableMappingFlag) { + // This means that `value` was already a clone and we should return it as is. + return value; + } + return cached; +} + // The below object is used as a replacement for objects that cannot be transferred // as shareable values. In makeShareableCloneRecursive we detect if an object is of // a plain Object.prototype and only allow such objects to be transferred. This lets @@ -100,14 +110,72 @@ const DETECT_CYCLIC_OBJECT_DEPTH_THRESHOLD = 30; // We use it to check if later on the function reenters with the same object let processedObjectAtThresholdDepth: unknown; -export function makeShareableCloneRecursive( - value: any, +function makeShareableCloneRecursiveWeb(value: T): ShareableRef { + return value as ShareableRef; +} + +function makeShareableCloneRecursiveNative( + value: T, shouldPersistRemote = false, depth = 0 ): ShareableRef { - if (SHOULD_BE_USE_WEB) { - return value; + detectCyclicObject(value, depth); + + const isObject = typeof value === 'object'; + const isFunction = typeof value === 'function'; + + if ((!isObject && !isFunction) || value === null) { + return clonePrimitive(value, shouldPersistRemote); + } + + const cached = getFromCache(value); + if (cached !== undefined) { + return cached as ShareableRef; + } + + if (Array.isArray(value)) { + return cloneArray(value, shouldPersistRemote, depth); + } + if (isFunction && !isWorkletFunction(value)) { + return cloneRemoteFunction(value, shouldPersistRemote); } + if (isHostObject(value)) { + return cloneHostObject(value, shouldPersistRemote); + } + if (isPlainJSObject(value) && value.__workletContextObjectFactory) { + return cloneContextObject(value); + } + if ((isPlainJSObject(value) || isFunction) && isWorkletFunction(value)) { + return cloneWorklet(value, shouldPersistRemote, depth); + } + if (isPlainJSObject(value) || isFunction) { + return clonePlainJSObject(value, shouldPersistRemote, depth); + } + if (value instanceof RegExp) { + return cloneRegExp(value); + } + if (value instanceof Error) { + return cloneError(value); + } + if (value instanceof ArrayBuffer) { + return cloneArrayBuffer(value, shouldPersistRemote); + } + if (ArrayBuffer.isView(value)) { + // typed array (e.g. Int32Array, Uint8ClampedArray) or DataView + return cloneArrayBufferView(value); + } + return inaccessibleObject(value); +} + +interface MakeShareableClone { + (value: T, shouldPersistRemote?: boolean, depth?: number): ShareableRef; +} + +export const makeShareableCloneRecursive: MakeShareableClone = SHOULD_BE_USE_WEB + ? makeShareableCloneRecursiveWeb + : makeShareableCloneRecursiveNative; + +function detectCyclicObject(value: unknown, depth: number) { if (depth >= DETECT_CYCLIC_OBJECT_DEPTH_THRESHOLD) { // if we reach certain recursion depth we suspect that we are dealing with a cyclic object. // this type of objects are not supported and cannot be transferred as shareable, so we @@ -124,176 +192,243 @@ export function makeShareableCloneRecursive( } else { processedObjectAtThresholdDepth = undefined; } - // This one actually may be worth to be moved to c++, we also need similar logic to run on the UI thread - const type = typeof value; - const isTypeObject = type === 'object'; - const isTypeFunction = type === 'function'; - if ((isTypeObject || isTypeFunction) && value !== null) { - const cached = shareableMappingCache.get(value); - if (cached === shareableMappingFlag) { - return value; - } else if (cached !== undefined) { - return cached as ShareableRef; - } else { - let toAdapt: any; - if (Array.isArray(value)) { - toAdapt = value.map((element) => - makeShareableCloneRecursive(element, shouldPersistRemote, depth + 1) - ); - freezeObjectIfDev(value); - } else if (isTypeFunction && !isWorkletFunction(value)) { - // this is a remote function - toAdapt = value; - freezeObjectIfDev(value); - } else if (isHostObject(value)) { - // for host objects we pass the reference to the object as shareable and - // then recreate new host object wrapping the same instance on the UI thread. - // there is no point of iterating over keys as we do for regular objects. - toAdapt = value; - } else if ( - isPlainJSObject(value) && - value.__workletContextObjectFactory - ) { - const workletContextObjectFactory = value.__workletContextObjectFactory; - const handle = makeShareableCloneRecursive({ - __init: () => { - 'worklet'; - return workletContextObjectFactory(); - }, - }); - shareableMappingCache.set(value, handle); - return handle as ShareableRef; - } else if (isPlainJSObject(value) || isTypeFunction) { - toAdapt = {}; - if (isWorkletFunction(value)) { - if (__DEV__) { - const babelVersion = value.__initData.version; - if (babelVersion !== undefined && babelVersion !== jsVersion) { - throw new ReanimatedError(`Mismatch between JavaScript code version and Reanimated Babel plugin version (${jsVersion} vs. ${babelVersion}). +} + +function clonePrimitive( + value: T, + shouldPersistRemote: boolean +): ShareableRef { + return WorkletsModule.makeShareableClone(value, shouldPersistRemote); +} + +function cloneArray( + value: T, + shouldPersistRemote: boolean, + depth: number +): ShareableRef { + const clonedElements = value.map((element) => + makeShareableCloneRecursive(element, shouldPersistRemote, depth + 1) + ); + const clone = WorkletsModule.makeShareableClone( + clonedElements, + shouldPersistRemote + ) as ShareableRef; + shareableMappingCache.set(value, clone); + shareableMappingCache.set(clone); + + freezeObjectInDev(value); + return clone; +} + +function cloneRemoteFunction( + value: T, + shouldPersistRemote: boolean +): ShareableRef { + const clone = WorkletsModule.makeShareableClone(value, shouldPersistRemote); + shareableMappingCache.set(value, clone); + shareableMappingCache.set(clone); + + freezeObjectInDev(value); + return clone; +} + +function cloneHostObject( + value: T, + shouldPersistRemote: boolean +): ShareableRef { + // for host objects we pass the reference to the object as shareable and + // then recreate new host object wrapping the same instance on the UI thread. + // there is no point of iterating over keys as we do for regular objects. + const clone = WorkletsModule.makeShareableClone(value, shouldPersistRemote); + shareableMappingCache.set(value, clone); + shareableMappingCache.set(clone); + + return clone; +} + +function cloneWorklet( + value: T, + shouldPersistRemote: boolean, + depth: number +): ShareableRef { + if (__DEV__) { + const babelVersion = (value as WorkletFunctionDev).__initData.version; + if (babelVersion !== undefined && babelVersion !== jsVersion) { + throw new ReanimatedError(`[Reanimated] Mismatch between JavaScript code version and Reanimated Babel plugin version (${jsVersion} vs. ${babelVersion}). See \`https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting#mismatch-between-javascript-code-version-and-reanimated-babel-plugin-version\` for more details. Offending code was: \`${getWorkletCode(value)}\``); - } - registerWorkletStackDetails( - value.__workletHash, - value.__stackDetails! - ); - } - if (value.__stackDetails) { - // `Error` type of value cannot be copied to the UI thread, so we - // remove it after we handled it in dev mode or delete it to ignore it in production mode. - // Not removing this would cause an infinite loop in production mode and it just - // seems more elegant to handle it this way. - delete value.__stackDetails; - } - // to save on transferring static __initData field of worklet structure - // we request shareable value to persist its UI counterpart. This means - // that the __initData field that contains long strings representing the - // worklet code, source map, and location, will always be - // serialized/deserialized once. - toAdapt.__initData = makeShareableCloneRecursive( - value.__initData, - true, - depth + 1 - ); - } - - for (const [key, element] of Object.entries(value)) { - if (key === '__initData' && toAdapt.__initData !== undefined) { - continue; - } - toAdapt[key] = makeShareableCloneRecursive( - element, - shouldPersistRemote, - depth + 1 - ); - } - freezeObjectIfDev(value); - } else if (value instanceof RegExp) { - const pattern = value.source; - const flags = value.flags; - const handle = makeShareableCloneRecursive({ - __init: () => { - 'worklet'; - return new RegExp(pattern, flags); - }, - }); - shareableMappingCache.set(value, handle); - return handle as ShareableRef; - } else if (value instanceof Error) { - const { name, message, stack } = value; - const handle = makeShareableCloneRecursive({ - __init: () => { - 'worklet'; - // eslint-disable-next-line reanimated/use-reanimated-error - const error = new Error(); - error.name = name; - error.message = message; - error.stack = stack; - return error; - }, - }); - shareableMappingCache.set(value, handle); - return handle as ShareableRef; - } else if (value instanceof ArrayBuffer) { - toAdapt = value; - } else if (ArrayBuffer.isView(value)) { - // typed array (e.g. Int32Array, Uint8ClampedArray) or DataView - const buffer = value.buffer; - const typeName = value.constructor.name; - const handle = makeShareableCloneRecursive({ - __init: () => { - 'worklet'; - if (!VALID_ARRAY_VIEWS_NAMES.includes(typeName)) { - throw new ReanimatedError( - `Invalid array view name \`${typeName}\`.` - ); - } - const constructor = global[typeName as keyof typeof global]; - if (constructor === undefined) { - throw new ReanimatedError( - `Constructor for \`${typeName}\` not found.` - ); - } - return new constructor(buffer); - }, - }); - shareableMappingCache.set(value, handle); - return handle as ShareableRef; - } else { - // This is reached for object types that are not of plain Object.prototype. - // We don't support such objects from being transferred as shareables to - // the UI runtime and hence we replace them with "inaccessible object" - // which is implemented as a Proxy object that throws on any attempt - // of accessing its fields. We argue that such objects can sometimes leak - // as attributes of objects being captured by worklets but should never - // be used on the UI runtime regardless. If they are being accessed, the user - // will get an appropriate error message. - const inaccessibleObject = - makeShareableCloneRecursive(INACCESSIBLE_OBJECT); - shareableMappingCache.set(value, inaccessibleObject); - return inaccessibleObject; - } - const adapted = WorkletsModule.makeShareableClone( - toAdapt, - shouldPersistRemote, - value - ); - shareableMappingCache.set(value, adapted); - shareableMappingCache.set(adapted); - return adapted; } + registerWorkletStackDetails( + value.__workletHash, + (value as WorkletFunctionDev).__stackDetails! + ); + } + if ((value as WorkletFunctionDev).__stackDetails) { + // `Error` type of value cannot be copied to the UI thread, so we + // remove it after we handled it in dev mode or delete it to ignore it in production mode. + // Not removing this would cause an infinite loop in production mode and it just + // seems more elegant to handle it this way. + delete (value as WorkletFunctionDev).__stackDetails; } - return WorkletsModule.makeShareableClone( - value, - shouldPersistRemote, - undefined + // to save on transferring static __initData field of worklet structure + // we request shareable value to persist its UI counterpart. This means + // that the __initData field that contains long strings represeting the + // worklet code, source map, and location, will always be + // serialized/deserialized once. + const clonedProps: Record = {}; + clonedProps.__initData = makeShareableCloneRecursive( + value.__initData, + true, + depth + 1 ); + + for (const [key, element] of Object.entries(value)) { + if (key === '__initData' && clonedProps.__initData !== undefined) { + continue; + } + clonedProps[key] = makeShareableCloneRecursive( + element, + shouldPersistRemote, + depth + 1 + ); + } + const clone = WorkletsModule.makeShareableClone( + clonedProps, + shouldPersistRemote + ) as ShareableRef; + shareableMappingCache.set(value, clone); + shareableMappingCache.set(clone); + + freezeObjectInDev(value); + return clone; +} + +function cloneContextObject(value: T): ShareableRef { + const workletContextObjectFactory = (value as Record) + .__workletContextObjectFactory as () => T; + const handle = makeShareableCloneRecursive({ + __init: () => { + 'worklet'; + return workletContextObjectFactory(); + }, + }); + shareableMappingCache.set(value, handle); + return handle as ShareableRef; +} + +function clonePlainJSObject( + value: T, + shouldPersistRemote: boolean, + depth: number +): ShareableRef { + const clonedProps: Record = {}; + for (const [key, element] of Object.entries(value)) { + if (key === '__initData' && clonedProps.__initData !== undefined) { + continue; + } + clonedProps[key] = makeShareableCloneRecursive( + element, + shouldPersistRemote, + depth + 1 + ); + } + const clone = WorkletsModule.makeShareableClone( + clonedProps, + shouldPersistRemote + ) as ShareableRef; + shareableMappingCache.set(value, clone); + shareableMappingCache.set(clone); + + freezeObjectInDev(value); + return clone; +} + +function cloneRegExp(value: T): ShareableRef { + const pattern = value.source; + const flags = value.flags; + const handle = makeShareableCloneRecursive({ + __init: () => { + 'worklet'; + return new RegExp(pattern, flags); + }, + }) as unknown as ShareableRef; + shareableMappingCache.set(value, handle); + + return handle; +} + +function cloneError(value: T): ShareableRef { + const { name, message, stack } = value; + const handle = makeShareableCloneRecursive({ + __init: () => { + 'worklet'; + // eslint-disable-next-line reanimated/use-reanimated-error + const error = new Error(); + error.name = name; + error.message = message; + error.stack = stack; + return error; + }, + }); + shareableMappingCache.set(value, handle); + return handle as unknown as ShareableRef; +} + +function cloneArrayBuffer( + value: T, + shouldPersistRemote: boolean +): ShareableRef { + const clone = WorkletsModule.makeShareableClone(value, shouldPersistRemote); + shareableMappingCache.set(value, clone); + shareableMappingCache.set(clone); + + return clone; +} + +function cloneArrayBufferView( + value: T +): ShareableRef { + const buffer = value.buffer; + const typeName = value.constructor.name; + const handle = makeShareableCloneRecursive({ + __init: () => { + 'worklet'; + if (!VALID_ARRAY_VIEWS_NAMES.includes(typeName)) { + throw new ReanimatedError( + `[Reanimated] Invalid array view name \`${typeName}\`.` + ); + } + const constructor = global[typeName as keyof typeof global]; + if (constructor === undefined) { + throw new ReanimatedError( + `[Reanimated] Constructor for \`${typeName}\` not found.` + ); + } + return new constructor(buffer); + }, + }) as unknown as ShareableRef; + shareableMappingCache.set(value, handle); + + return handle; +} + +function inaccessibleObject(value: T): ShareableRef { + // This is reached for object types that are not of plain Object.prototype. + // We don't support such objects from being transferred as shareables to + // the UI runtime and hence we replace them with "inaccessible object" + // which is implemented as a Proxy object that throws on any attempt + // of accessing its fields. We argue that such objects can sometimes leak + // as attributes of objects being captured by worklets but should never + // be used on the UI runtime regardless. If they are being accessed, the user + // will get an appropriate error message. + const clone = makeShareableCloneRecursive(INACCESSIBLE_OBJECT as T); + shareableMappingCache.set(value, clone); + return clone; } const WORKLET_CODE_THRESHOLD = 255; function getWorkletCode(value: WorkletFunction) { - // @ts-ignore this is fine const code = value?.__initData?.code; if (!code) { return 'unknown'; @@ -329,7 +464,7 @@ function isRemoteFunction(value: { * the UI thread. If the user really wants some objects to be mutable they * should use shared values instead. */ -function freezeObjectIfDev(value: T) { +function freezeObjectInDev(value: T) { if (!__DEV__) { return; } From 95d7de6cf360658c509c38eaf974cfcd1f380cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:48:15 +0100 Subject: [PATCH 12/36] refactor: rename MessageQueueThread (#6750) ## Summary ## Test plan --- .../WorkletsMessageQueueThread.java} | 4 ++-- .../WorkletsMessageQueueThreadBase.java} | 6 +++--- .../java/com/swmansion/worklets/WorkletsModule.java | 4 +--- .../apple/reanimated/apple/native/NativeProxy.mm | 2 +- .../apple/native/PlatformDepMethodsHolderImpl.mm | 2 +- .../{REAMessageThread.h => WorkletsMessageThread.h} | 2 +- .../{REAMessageThread.mm => WorkletsMessageThread.mm} | 10 +++++----- .../apple/worklets/apple/WorkletsModule.mm | 4 ++-- 8 files changed, 16 insertions(+), 18 deletions(-) rename packages/react-native-reanimated/android/src/main/java/com/swmansion/{reanimated/ReanimatedMessageQueueThread.java => worklets/WorkletsMessageQueueThread.java} (69%) rename packages/react-native-reanimated/android/src/main/java/com/swmansion/{reanimated/ReanimatedMessageQueueThreadBase.java => worklets/WorkletsMessageQueueThreadBase.java} (93%) rename packages/react-native-reanimated/apple/worklets/apple/{REAMessageThread.h => WorkletsMessageThread.h} (87%) rename packages/react-native-reanimated/apple/worklets/apple/{REAMessageThread.mm => WorkletsMessageThread.mm} (72%) diff --git a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedMessageQueueThread.java b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThread.java similarity index 69% rename from packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedMessageQueueThread.java rename to packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThread.java index e6a4cd1c37b..b1ccdf8b59d 100644 --- a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedMessageQueueThread.java +++ b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThread.java @@ -1,9 +1,9 @@ -package com.swmansion.reanimated; +package com.swmansion.worklets; import com.facebook.proguard.annotations.DoNotStrip; @DoNotStrip -public class ReanimatedMessageQueueThread extends ReanimatedMessageQueueThreadBase { +public class WorkletsMessageQueueThread extends WorkletsMessageQueueThreadBase { @Override public boolean runOnQueue(Runnable runnable) { return messageQueueThread.runOnQueue(runnable); diff --git a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedMessageQueueThreadBase.java b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java similarity index 93% rename from packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedMessageQueueThreadBase.java rename to packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java index ca7733d0cbc..ade92c5b8b2 100644 --- a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedMessageQueueThreadBase.java +++ b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java @@ -1,4 +1,4 @@ -package com.swmansion.reanimated; +package com.swmansion.worklets; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.queue.MessageQueueThread; @@ -14,10 +14,10 @@ // The only method that has changed is `quitSynchronous()` (see comment above // function implementation for details). @DoNotStrip -public abstract class ReanimatedMessageQueueThreadBase implements MessageQueueThread { +public abstract class WorkletsMessageQueueThreadBase implements MessageQueueThread { protected final MessageQueueThreadImpl messageQueueThread; - public ReanimatedMessageQueueThreadBase() { + public WorkletsMessageQueueThreadBase() { messageQueueThread = MessageQueueThreadImpl.create( MessageQueueThreadSpec.mainThreadSpec(), diff --git a/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java index 31c74a6e560..62ca7713cdc 100644 --- a/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java +++ b/packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java @@ -10,7 +10,6 @@ import com.facebook.react.module.annotations.ReactModule; import com.facebook.soloader.SoLoader; import com.swmansion.reanimated.NativeWorkletsModuleSpec; -import com.swmansion.reanimated.ReanimatedMessageQueueThread; import java.util.Objects; @ReactModule(name = WorkletsModule.NAME) @@ -30,8 +29,7 @@ protected HybridData getHybridData() { return mHybridData; } - private final ReanimatedMessageQueueThread mMessageQueueThread = - new ReanimatedMessageQueueThread(); + private final WorkletsMessageQueueThread mMessageQueueThread = new WorkletsMessageQueueThread(); /** * @noinspection JavaJniMissingFunction diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm index eba24c8a15c..d99b0e97c99 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm @@ -22,7 +22,7 @@ #endif #import -#import +#import #ifdef RCT_NEW_ARCH_ENABLED #import diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm b/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm index 4f2f3ac611b..65f5584a4c8 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm @@ -19,7 +19,7 @@ #endif #import -#import +#import #ifdef RCT_NEW_ARCH_ENABLED #import diff --git a/packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.h b/packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.h similarity index 87% rename from packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.h rename to packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.h index 16f47378a33..2ac8055a090 100644 --- a/packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.h +++ b/packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.h @@ -10,7 +10,7 @@ namespace facebook { namespace react { -class REAMessageThread : public RCTMessageThread { +class WorkletsMessageThread : public RCTMessageThread { public: using RCTMessageThread::RCTMessageThread; virtual void quitSynchronous() override; diff --git a/packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.mm b/packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.mm similarity index 72% rename from packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.mm rename to packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.mm index 0df1e2f1794..b5e46a10e56 100644 --- a/packages/react-native-reanimated/apple/worklets/apple/REAMessageThread.mm +++ b/packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.mm @@ -1,4 +1,4 @@ -#import +#import #import #import @@ -11,9 +11,9 @@ namespace react { // Essentially the same as RCTMessageThread, but with public fields. -struct REAMessageThreadPublic { +struct WorkletsMessageThreadPublic { // I don't know why we need three vtables (if you know then feel free to#import - // explain it instead of this message), but this is what makes the casts + // explain it instead of this message), but this is what makes the casts // in quitSynchronous() work correctly. void *vtable1; void *vtable2; @@ -27,10 +27,10 @@ // is an assertion for that in the destructor of RCTMessageThread, but we have // to override quitSynchronous() as it would quit the main looper and freeze // the app. -void REAMessageThread::quitSynchronous() +void WorkletsMessageThread::quitSynchronous() { RCTMessageThread *rctThread = static_cast(this); - REAMessageThreadPublic *rctThreadPublic = reinterpret_cast(rctThread); + WorkletsMessageThreadPublic *rctThreadPublic = reinterpret_cast(rctThread); rctThreadPublic->m_shutdown = true; } diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm index 622539ee20f..77f502ed825 100644 --- a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm +++ b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm @@ -1,6 +1,6 @@ #import #import -#import +#import #import #import @@ -36,7 +36,7 @@ @implementation WorkletsModule { { auto *bridge = self.bridge; auto &rnRuntime = *(jsi::Runtime *)bridge.runtime; - auto jsQueue = std::make_shared([NSRunLoop currentRunLoop], ^(NSError *error) { + auto jsQueue = std::make_shared([NSRunLoop currentRunLoop], ^(NSError *error) { throw error; }); nativeWorkletsModule_ = std::make_shared(std::string([valueUnpackerCode UTF8String]), jsQueue); From 26decdc6ca7f8eec4568b6f626f33a6d465fce2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20B=C5=82oniarz?= <56109050+bartlomiejbloniarz@users.noreply.github.com> Date: Tue, 26 Nov 2024 15:15:15 +0100 Subject: [PATCH 13/36] Restore `nativeStateSource` in `makeShareableCloneRecursive` (#6763) ## Summary This PR restores the `nativeStateSource` argument in `makeShareableCloneRecursive` calls, that got lost in #5724 ## Test plan --- .../react-native-reanimated/src/shareables.ts | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/react-native-reanimated/src/shareables.ts b/packages/react-native-reanimated/src/shareables.ts index ca99961133e..0bce648a35a 100644 --- a/packages/react-native-reanimated/src/shareables.ts +++ b/packages/react-native-reanimated/src/shareables.ts @@ -211,7 +211,8 @@ function cloneArray( ); const clone = WorkletsModule.makeShareableClone( clonedElements, - shouldPersistRemote + shouldPersistRemote, + value ) as ShareableRef; shareableMappingCache.set(value, clone); shareableMappingCache.set(clone); @@ -224,7 +225,11 @@ function cloneRemoteFunction( value: T, shouldPersistRemote: boolean ): ShareableRef { - const clone = WorkletsModule.makeShareableClone(value, shouldPersistRemote); + const clone = WorkletsModule.makeShareableClone( + value, + shouldPersistRemote, + value + ); shareableMappingCache.set(value, clone); shareableMappingCache.set(clone); @@ -239,7 +244,11 @@ function cloneHostObject( // for host objects we pass the reference to the object as shareable and // then recreate new host object wrapping the same instance on the UI thread. // there is no point of iterating over keys as we do for regular objects. - const clone = WorkletsModule.makeShareableClone(value, shouldPersistRemote); + const clone = WorkletsModule.makeShareableClone( + value, + shouldPersistRemote, + value + ); shareableMappingCache.set(value, clone); shareableMappingCache.set(clone); @@ -294,7 +303,8 @@ Offending code was: \`${getWorkletCode(value)}\``); } const clone = WorkletsModule.makeShareableClone( clonedProps, - shouldPersistRemote + shouldPersistRemote, + value ) as ShareableRef; shareableMappingCache.set(value, clone); shareableMappingCache.set(clone); @@ -334,7 +344,8 @@ function clonePlainJSObject( } const clone = WorkletsModule.makeShareableClone( clonedProps, - shouldPersistRemote + shouldPersistRemote, + value ) as ShareableRef; shareableMappingCache.set(value, clone); shareableMappingCache.set(clone); @@ -378,7 +389,11 @@ function cloneArrayBuffer( value: T, shouldPersistRemote: boolean ): ShareableRef { - const clone = WorkletsModule.makeShareableClone(value, shouldPersistRemote); + const clone = WorkletsModule.makeShareableClone( + value, + shouldPersistRemote, + value + ); shareableMappingCache.set(value, clone); shareableMappingCache.set(clone); From f47d4d1a6c7f7deb7a8ff77dafb196dac2f6c9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:42:27 +0100 Subject: [PATCH 14/36] refactor: rename cpp NativeReanimatedModule to ReanimatedModuleProxy (#6766) ## Summary `NativeReanimatedModule` is the name of the ObjC/Java modules generated from `REAModule` and `ReanimatedModule`. It's confusing that we name some Cpp object the same way. With this change Cpp `NativeReanimatedModule` becomes `ReanimatedModuleProxy`, the same name we use to refer to it from JavaScript. ## Test plan CI --- .../LayoutAnimationsProxy.cpp | 2 +- .../LayoutAnimations/LayoutAnimationsProxy.h | 2 +- ...edModule.cpp => ReanimatedModuleProxy.cpp} | 78 +++++++++--------- ...imatedModule.h => ReanimatedModuleProxy.h} | 11 ++- ...Spec.cpp => ReanimatedModuleProxySpec.cpp} | 36 ++++----- ...duleSpec.h => ReanimatedModuleProxySpec.h} | 4 +- .../RuntimeDecorators/RNRuntimeDecorator.cpp | 12 +-- .../RuntimeDecorators/RNRuntimeDecorator.h | 4 +- .../cpp/reanimated/android/NativeProxy.cpp | 81 +++++++++---------- .../main/cpp/reanimated/android/NativeProxy.h | 4 +- .../apple/reanimated/apple/REAModule.mm | 27 +++---- .../apple/reanimated/apple/REANodesManager.mm | 2 +- .../reanimated/apple/native/NativeProxy.h | 10 +-- .../reanimated/apple/native/NativeProxy.mm | 76 ++++++++--------- .../native/PlatformDepMethodsHolderImpl.h | 2 +- 15 files changed, 174 insertions(+), 177 deletions(-) rename packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/{NativeReanimatedModule.cpp => ReanimatedModuleProxy.cpp} (93%) rename packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/{NativeReanimatedModule.h => ReanimatedModuleProxy.h} (96%) rename packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/{NativeReanimatedModuleSpec.cpp => ReanimatedModuleProxySpec.cpp} (83%) rename packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/{NativeReanimatedModuleSpec.h => ReanimatedModuleProxySpec.h} (96%) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp index 0aeda945bb4..f55b383bdc8 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp @@ -1,7 +1,7 @@ #ifdef RCT_NEW_ARCH_ENABLED #include -#include +#include #include #include diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h index 8fd9a89d7fa..a37f43a414a 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h @@ -19,7 +19,7 @@ namespace reanimated { -class NativeReanimatedModule; +class ReanimatedModuleProxy; using namespace facebook; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp similarity index 93% rename from packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp rename to packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp index 3e81bdee99e..02b4f6a5495 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -51,7 +51,7 @@ using namespace facebook; namespace reanimated { -NativeReanimatedModule::NativeReanimatedModule( +ReanimatedModuleProxy::ReanimatedModuleProxy( const std::shared_ptr &nativeWorkletsModule, jsi::Runtime &rnRuntime, const std::shared_ptr &jsScheduler, @@ -59,7 +59,7 @@ NativeReanimatedModule::NativeReanimatedModule( const PlatformDepMethodsHolder &platformDepMethodsHolder, const bool isBridgeless, const bool isReducedMotion) - : NativeReanimatedModuleSpec( + : ReanimatedModuleProxySpec( isBridgeless ? nullptr : jsScheduler->getJSCallInvoker()), isBridgeless_(isBridgeless), isReducedMotion_(isReducedMotion), @@ -101,7 +101,7 @@ NativeReanimatedModule::NativeReanimatedModule( commonInit(platformDepMethodsHolder); } -void NativeReanimatedModule::commonInit( +void ReanimatedModuleProxy::commonInit( const PlatformDepMethodsHolder &platformDepMethodsHolder) { auto requestAnimationFrame = [this](jsi::Runtime &rt, const jsi::Value &callback) { @@ -193,7 +193,7 @@ void NativeReanimatedModule::commonInit( platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction); } -NativeReanimatedModule::~NativeReanimatedModule() { +ReanimatedModuleProxy::~ReanimatedModuleProxy() { // event handler registry and frame callbacks store some JSI values from UI // runtime, so they have to go away before we tear down the runtime eventHandlerRegistry_.reset(); @@ -201,7 +201,7 @@ NativeReanimatedModule::~NativeReanimatedModule() { uiWorkletRuntime_.reset(); } -void NativeReanimatedModule::scheduleOnUI( +void ReanimatedModuleProxy::scheduleOnUI( jsi::Runtime &rt, const jsi::Value &worklet) { auto shareableWorklet = extractShareableOrThrow( @@ -219,13 +219,13 @@ void NativeReanimatedModule::scheduleOnUI( }); } -jsi::Value NativeReanimatedModule::executeOnUIRuntimeSync( +jsi::Value ReanimatedModuleProxy::executeOnUIRuntimeSync( jsi::Runtime &rt, const jsi::Value &worklet) { return uiWorkletRuntime_->executeSync(rt, worklet); } -jsi::Value NativeReanimatedModule::createWorkletRuntime( +jsi::Value ReanimatedModuleProxy::createWorkletRuntime( jsi::Runtime &rt, const jsi::Value &name, const jsi::Value &initializer) { @@ -243,7 +243,7 @@ jsi::Value NativeReanimatedModule::createWorkletRuntime( return jsi::Object::createFromHostObject(rt, workletRuntime); } -jsi::Value NativeReanimatedModule::scheduleOnRuntime( +jsi::Value ReanimatedModuleProxy::scheduleOnRuntime( jsi::Runtime &rt, const jsi::Value &workletRuntimeValue, const jsi::Value &shareableWorkletValue) { @@ -251,7 +251,7 @@ jsi::Value NativeReanimatedModule::scheduleOnRuntime( return jsi::Value::undefined(); } -jsi::Value NativeReanimatedModule::registerEventHandler( +jsi::Value ReanimatedModuleProxy::registerEventHandler( jsi::Runtime &rt, const jsi::Value &worklet, const jsi::Value &eventName, @@ -273,7 +273,7 @@ jsi::Value NativeReanimatedModule::registerEventHandler( return jsi::Value(static_cast(newRegistrationId)); } -void NativeReanimatedModule::unregisterEventHandler( +void ReanimatedModuleProxy::unregisterEventHandler( jsi::Runtime &, const jsi::Value ®istrationId) { uint64_t id = registrationId.asNumber(); @@ -297,7 +297,7 @@ static inline std::string intColorToHex(const int val) { return hexColor; } -std::string NativeReanimatedModule::obtainPropFromShadowNode( +std::string ReanimatedModuleProxy::obtainPropFromShadowNode( jsi::Runtime &rt, const std::string &propName, const ShadowNode::Shared &shadowNode) { @@ -340,7 +340,7 @@ std::string NativeReanimatedModule::obtainPropFromShadowNode( "` with function `getViewProp` is not supported")); } -jsi::Value NativeReanimatedModule::getViewProp( +jsi::Value ReanimatedModuleProxy::getViewProp( jsi::Runtime &rnRuntime, const jsi::Value &shadowNodeWrapper, const jsi::Value &propName, @@ -365,7 +365,7 @@ jsi::Value NativeReanimatedModule::getViewProp( #else -jsi::Value NativeReanimatedModule::getViewProp( +jsi::Value ReanimatedModuleProxy::getViewProp( jsi::Runtime &rnRuntime, const jsi::Value &viewTag, const jsi::Value &propName, @@ -398,14 +398,14 @@ jsi::Value NativeReanimatedModule::getViewProp( #endif -jsi::Value NativeReanimatedModule::enableLayoutAnimations( +jsi::Value ReanimatedModuleProxy::enableLayoutAnimations( jsi::Runtime &, const jsi::Value &config) { FeaturesConfig::setLayoutAnimationEnabled(config.getBool()); return jsi::Value::undefined(); } -jsi::Value NativeReanimatedModule::configureProps( +jsi::Value ReanimatedModuleProxy::configureProps( jsi::Runtime &rt, const jsi::Value &uiProps, const jsi::Value &nativeProps) { @@ -428,7 +428,7 @@ jsi::Value NativeReanimatedModule::configureProps( return jsi::Value::undefined(); } -jsi::Value NativeReanimatedModule::configureLayoutAnimationBatch( +jsi::Value ReanimatedModuleProxy::configureLayoutAnimationBatch( jsi::Runtime &rt, const jsi::Value &layoutAnimationsBatch) { auto array = layoutAnimationsBatch.asObject(rt).asArray(rt); @@ -464,7 +464,7 @@ jsi::Value NativeReanimatedModule::configureLayoutAnimationBatch( return jsi::Value::undefined(); } -void NativeReanimatedModule::setShouldAnimateExiting( +void ReanimatedModuleProxy::setShouldAnimateExiting( jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &shouldAnimate) { @@ -472,21 +472,21 @@ void NativeReanimatedModule::setShouldAnimateExiting( viewTag.asNumber(), shouldAnimate.getBool()); } -bool NativeReanimatedModule::isAnyHandlerWaitingForEvent( +bool ReanimatedModuleProxy::isAnyHandlerWaitingForEvent( const std::string &eventName, const int emitterReactTag) { return eventHandlerRegistry_->isAnyHandlerWaitingForEvent( eventName, emitterReactTag); } -void NativeReanimatedModule::requestAnimationFrame( +void ReanimatedModuleProxy::requestAnimationFrame( jsi::Runtime &rt, const jsi::Value &callback) { frameCallbacks_.push_back(std::make_shared(rt, callback)); maybeRequestRender(); } -void NativeReanimatedModule::maybeRequestRender() { +void ReanimatedModuleProxy::maybeRequestRender() { if (!renderRequested_) { renderRequested_ = true; jsi::Runtime &uiRuntime = uiWorkletRuntime_->getJSIRuntime(); @@ -494,7 +494,7 @@ void NativeReanimatedModule::maybeRequestRender() { } } -void NativeReanimatedModule::onRender(double timestampMs) { +void ReanimatedModuleProxy::onRender(double timestampMs) { auto callbacks = std::move(frameCallbacks_); frameCallbacks_.clear(); jsi::Runtime &uiRuntime = uiWorkletRuntime_->getJSIRuntime(); @@ -504,7 +504,7 @@ void NativeReanimatedModule::onRender(double timestampMs) { } } -jsi::Value NativeReanimatedModule::registerSensor( +jsi::Value ReanimatedModuleProxy::registerSensor( jsi::Runtime &rt, const jsi::Value &sensorType, const jsi::Value &interval, @@ -519,18 +519,18 @@ jsi::Value NativeReanimatedModule::registerSensor( sensorDataHandler); } -void NativeReanimatedModule::unregisterSensor( +void ReanimatedModuleProxy::unregisterSensor( jsi::Runtime &, const jsi::Value &sensorId) { animatedSensorModule_.unregisterSensor(sensorId); } -void NativeReanimatedModule::cleanupSensors() { +void ReanimatedModuleProxy::cleanupSensors() { animatedSensorModule_.unregisterAllSensors(); } #ifdef RCT_NEW_ARCH_ENABLED -bool NativeReanimatedModule::isThereAnyLayoutProp( +bool ReanimatedModuleProxy::isThereAnyLayoutProp( jsi::Runtime &rt, const jsi::Object &props) { const jsi::Array propNames = props.getPropertyNames(rt); @@ -546,7 +546,7 @@ bool NativeReanimatedModule::isThereAnyLayoutProp( return false; } -jsi::Value NativeReanimatedModule::filterNonAnimatableProps( +jsi::Value ReanimatedModuleProxy::filterNonAnimatableProps( jsi::Runtime &rt, const jsi::Value &props) { jsi::Object nonAnimatableProps(rt); @@ -570,7 +570,7 @@ jsi::Value NativeReanimatedModule::filterNonAnimatableProps( } #endif // RCT_NEW_ARCH_ENABLED -bool NativeReanimatedModule::handleEvent( +bool ReanimatedModuleProxy::handleEvent( const std::string &eventName, const int emitterReactTag, const jsi::Value &payload, @@ -584,7 +584,7 @@ bool NativeReanimatedModule::handleEvent( } #ifdef RCT_NEW_ARCH_ENABLED -bool NativeReanimatedModule::handleRawEvent( +bool ReanimatedModuleProxy::handleRawEvent( const RawEvent &rawEvent, double currentTime) { const EventTarget *eventTarget = rawEvent.eventTarget.get(); @@ -615,7 +615,7 @@ bool NativeReanimatedModule::handleRawEvent( return res; } -void NativeReanimatedModule::updateProps( +void ReanimatedModuleProxy::updateProps( jsi::Runtime &rt, const jsi::Value &operations) { auto array = operations.asObject(rt).asArray(rt); @@ -630,7 +630,7 @@ void NativeReanimatedModule::updateProps( } } -void NativeReanimatedModule::performOperations() { +void ReanimatedModuleProxy::performOperations() { if (operationsInBatch_.empty() && tagsToRemove_.empty()) { // nothing to do return; @@ -755,7 +755,7 @@ void NativeReanimatedModule::performOperations() { } } -void NativeReanimatedModule::removeFromPropsRegistry( +void ReanimatedModuleProxy::removeFromPropsRegistry( jsi::Runtime &rt, const jsi::Value &viewTags) { auto array = viewTags.asObject(rt).asArray(rt); @@ -764,7 +764,7 @@ void NativeReanimatedModule::removeFromPropsRegistry( } } -void NativeReanimatedModule::dispatchCommand( +void ReanimatedModuleProxy::dispatchCommand( jsi::Runtime &rt, const jsi::Value &shadowNodeValue, const jsi::Value &commandNameValue, @@ -775,7 +775,7 @@ void NativeReanimatedModule::dispatchCommand( uiManager_->dispatchCommand(shadowNode, commandName, args); } -jsi::String NativeReanimatedModule::obtainProp( +jsi::String ReanimatedModuleProxy::obtainProp( jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper, const jsi::Value &propName) { @@ -787,7 +787,7 @@ jsi::String NativeReanimatedModule::obtainProp( return jsi::String::createFromUtf8(rt, resultStr); } -jsi::Value NativeReanimatedModule::measure( +jsi::Value ReanimatedModuleProxy::measure( jsi::Runtime &rt, const jsi::Value &shadowNodeValue) { // based on implementation from UIManagerBinding.cpp @@ -831,7 +831,7 @@ jsi::Value NativeReanimatedModule::measure( return result; } -void NativeReanimatedModule::initializeFabric( +void ReanimatedModuleProxy::initializeFabric( const std::shared_ptr &uiManager) { uiManager_ = uiManager; @@ -843,7 +843,7 @@ void NativeReanimatedModule::initializeFabric( propsRegistry_, uiManager_, layoutAnimationsProxy_); } -void NativeReanimatedModule::initializeLayoutAnimationsProxy() { +void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() { uiManager_->setAnimationDelegate(nullptr); auto scheduler = reinterpret_cast(uiManager_->getDelegate()); auto componentDescriptorRegistry = @@ -864,7 +864,7 @@ void NativeReanimatedModule::initializeLayoutAnimationsProxy() { #endif // RCT_NEW_ARCH_ENABLED -jsi::Value NativeReanimatedModule::subscribeForKeyboardEvents( +jsi::Value ReanimatedModuleProxy::subscribeForKeyboardEvents( jsi::Runtime &rt, const jsi::Value &handlerWorklet, const jsi::Value &isStatusBarTranslucent, @@ -884,7 +884,7 @@ jsi::Value NativeReanimatedModule::subscribeForKeyboardEvents( isNavigationBarTranslucent.getBool()); } -void NativeReanimatedModule::unsubscribeFromKeyboardEvents( +void ReanimatedModuleProxy::unsubscribeFromKeyboardEvents( jsi::Runtime &, const jsi::Value &listenerId) { unsubscribeFromKeyboardEventsFunction_(listenerId.asNumber()); diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h similarity index 96% rename from packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h rename to packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h index ba5e8deee29..518e5bc7411 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModule.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h @@ -2,7 +2,7 @@ #include #include -#include +#include #include #ifdef RCT_NEW_ARCH_ENABLED @@ -30,9 +30,9 @@ namespace reanimated { -class NativeReanimatedModule : public NativeReanimatedModuleSpec { +class ReanimatedModuleProxy : public ReanimatedModuleProxySpec { public: - NativeReanimatedModule( + ReanimatedModuleProxy( const std::shared_ptr &nativeWorkletsModule, jsi::Runtime &rnRuntime, const std::shared_ptr &jsScheduler, @@ -41,7 +41,7 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec { const bool isBridgeless, const bool isReducedMotion); - ~NativeReanimatedModule(); + ~ReanimatedModuleProxy(); void scheduleOnUI(jsi::Runtime &rt, const jsi::Value &worklet) override; jsi::Value executeOnUIRuntimeSync(jsi::Runtime &rt, const jsi::Value &worklet) @@ -235,8 +235,7 @@ class NativeReanimatedModule : public NativeReanimatedModuleSpec { const KeyboardEventUnsubscribeFunction unsubscribeFromKeyboardEventsFunction_; #ifndef NDEBUG - worklets::SingleInstanceChecker - singleInstanceChecker_; + worklets::SingleInstanceChecker singleInstanceChecker_; #endif // NDEBUG }; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp similarity index 83% rename from packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.cpp rename to packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp index 036f201a88d..d797483bcf1 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp @@ -1,9 +1,9 @@ -#include +#include #include #define REANIMATED_SPEC_PREFIX(FN_NAME) \ - __hostFunction_NativeReanimatedModuleSpec_##FN_NAME + __hostFunction_ReanimatedModuleProxySpec_##FN_NAME namespace reanimated { @@ -14,7 +14,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(scheduleOnUI)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->scheduleOnUI(rt, std::move(args[0])); return jsi::Value::undefined(); } @@ -24,7 +24,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(executeOnUIRuntimeSync)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->executeOnUIRuntimeSync(rt, std::move(args[0])); } @@ -33,7 +33,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(createWorkletRuntime)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->createWorkletRuntime(rt, std::move(args[0]), std::move(args[1])); } @@ -42,7 +42,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(scheduleOnRuntime)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->scheduleOnRuntime(rt, std::move(args[0]), std::move(args[1])); } @@ -51,7 +51,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(registerEventHandler)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->registerEventHandler( rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); } @@ -61,7 +61,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(unregisterEventHandler)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->unregisterEventHandler(rt, std::move(args[0])); return jsi::Value::undefined(); } @@ -71,7 +71,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(getViewProp)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->getViewProp( rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); return jsi::Value::undefined(); @@ -82,7 +82,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(enableLayoutAnimations)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->enableLayoutAnimations(rt, std::move(args[0])); return jsi::Value::undefined(); } @@ -92,7 +92,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(registerSensor)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->registerSensor( rt, std::move(args[0]), @@ -106,7 +106,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(unregisterSensor)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->unregisterSensor(rt, std::move(args[0])); return jsi::Value::undefined(); } @@ -116,7 +116,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(configureProps)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->configureProps(rt, std::move(args[0]), std::move(args[1])); return jsi::Value::undefined(); } @@ -126,7 +126,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(subscribeForKeyboardEvents)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->subscribeForKeyboardEvents( rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); } @@ -136,7 +136,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(unsubscribeFromKeyboardEvents)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->unsubscribeFromKeyboardEvents(rt, std::move(args[0])); return jsi::Value::undefined(); } @@ -146,7 +146,7 @@ static jsi::Value REANIMATED_SPEC_PREFIX(configureLayoutAnimationBatch)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->configureLayoutAnimationBatch(rt, std::move(args[0])); } @@ -155,12 +155,12 @@ static jsi::Value REANIMATED_SPEC_PREFIX(setShouldAnimateExiting)( TurboModule &turboModule, const jsi::Value *args, size_t) { - static_cast(&turboModule) + static_cast(&turboModule) ->setShouldAnimateExiting(rt, std::move(args[0]), std::move(args[1])); return jsi::Value::undefined(); } -NativeReanimatedModuleSpec::NativeReanimatedModuleSpec( +ReanimatedModuleProxySpec::ReanimatedModuleProxySpec( const std::shared_ptr &jsInvoker) : TurboModule("NativeReanimated", jsInvoker) { methodMap_["scheduleOnUI"] = diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h similarity index 96% rename from packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.h rename to packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h index a9a85ad1a6c..3f82813abff 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/NativeReanimatedModuleSpec.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h @@ -12,9 +12,9 @@ using namespace react; namespace reanimated { -class JSI_EXPORT NativeReanimatedModuleSpec : public TurboModule { +class JSI_EXPORT ReanimatedModuleProxySpec : public TurboModule { protected: - explicit NativeReanimatedModuleSpec( + explicit ReanimatedModuleProxySpec( const std::shared_ptr &jsInvoker); public: diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp index 660145a40f7..5bf60c154a8 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp @@ -5,10 +5,10 @@ namespace reanimated { void RNRuntimeDecorator::decorate( jsi::Runtime &rnRuntime, - const std::shared_ptr &nativeReanimatedModule) { + const std::shared_ptr &reanimatedModuleProxy) { rnRuntime.global().setProperty(rnRuntime, "_WORKLET", false); - jsi::Runtime &uiRuntime = nativeReanimatedModule->getUIRuntime(); + jsi::Runtime &uiRuntime = reanimatedModuleProxy->getUIRuntime(); auto workletRuntimeValue = rnRuntime.global() .getPropertyAsObject(rnRuntime, "ArrayBuffer") @@ -29,22 +29,22 @@ void RNRuntimeDecorator::decorate( rnRuntime.global().setProperty(rnRuntime, "_IS_FABRIC", isFabric); rnRuntime.global().setProperty( - rnRuntime, "_IS_BRIDGELESS", nativeReanimatedModule->isBridgeless()); + rnRuntime, "_IS_BRIDGELESS", reanimatedModuleProxy->isBridgeless()); #ifndef NDEBUG - checkJSVersion(rnRuntime, nativeReanimatedModule->getJSLogger()); + checkJSVersion(rnRuntime, reanimatedModuleProxy->getJSLogger()); #endif // NDEBUG injectReanimatedCppVersion(rnRuntime); rnRuntime.global().setProperty( rnRuntime, "_REANIMATED_IS_REDUCED_MOTION", - nativeReanimatedModule->isReducedMotion()); + reanimatedModuleProxy->isReducedMotion()); rnRuntime.global().setProperty( rnRuntime, "__reanimatedModuleProxy", - jsi::Object::createFromHostObject(rnRuntime, nativeReanimatedModule)); + jsi::Object::createFromHostObject(rnRuntime, reanimatedModuleProxy)); } } // namespace reanimated diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.h b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.h index ff18f2c2dc6..ac568a678b2 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include @@ -14,7 +14,7 @@ class RNRuntimeDecorator { public: static void decorate( jsi::Runtime &rnRuntime, - const std::shared_ptr &nativeReanimatedModule); + const std::shared_ptr &reanimatedModuleProxy); }; } // namespace reanimated diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp index 61fd25338fc..f88eba94b6e 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp +++ b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp @@ -41,7 +41,7 @@ NativeProxy::NativeProxy( ) : javaPart_(jni::make_global(jThis)), rnRuntime_(rnRuntime), - nativeReanimatedModule_(std::make_shared( + reanimatedModuleProxy_(std::make_shared( nativeWorkletsModule, *rnRuntime, std::make_shared(*rnRuntime, jsCallInvoker), @@ -67,7 +67,7 @@ NativeProxy::NativeProxy( fabricUIManager) : javaPart_(jni::make_global(jThis)), rnRuntime_(rnRuntime), - nativeReanimatedModule_(std::make_shared( + reanimatedModuleProxy_(std::make_shared( nativeWorkletsModule, *rnRuntime, std::make_shared(*rnRuntime, runtimeExecutor), @@ -84,12 +84,12 @@ void NativeProxy::commonInit( &fabricUIManager) { const auto &uiManager = fabricUIManager->getBinding()->getScheduler()->getUIManager(); - nativeReanimatedModule_->initializeFabric(uiManager); + reanimatedModuleProxy_->initializeFabric(uiManager); // removed temporarily, event listener mechanism needs to be fixed on RN side // eventListener_ = std::make_shared( - // [nativeReanimatedModule, + // [reanimatedModuleProxy, // getAnimationTimestamp](const RawEvent &rawEvent) { - // return nativeReanimatedModule->handleRawEvent( + // return reanimatedModuleProxy->handleRawEvent( // rawEvent, getAnimationTimestamp()); // }); // reactScheduler_ = binding->getScheduler(); @@ -104,7 +104,7 @@ NativeProxy::~NativeProxy() { // cleanup all animated sensors here, since NativeProxy // has already been destroyed when AnimatedSensorModule's // destructor is ran - nativeReanimatedModule_->cleanupSensors(); + reanimatedModuleProxy_->cleanupSensors(); } jni::local_ref NativeProxy::initHybrid( @@ -206,7 +206,7 @@ void NativeProxy::injectCppVersion() { void NativeProxy::installJSIBindings() { jsi::Runtime &rnRuntime = *rnRuntime_; WorkletRuntimeCollector::install(rnRuntime); - RNRuntimeDecorator::decorate(rnRuntime, nativeReanimatedModule_); + RNRuntimeDecorator::decorate(rnRuntime, reanimatedModuleProxy_); #ifndef NDEBUG checkJavaVersion(rnRuntime); injectCppVersion(); @@ -219,13 +219,13 @@ void NativeProxy::installJSIBindings() { bool NativeProxy::isAnyHandlerWaitingForEvent( const std::string &eventName, const int emitterReactTag) { - return nativeReanimatedModule_->isAnyHandlerWaitingForEvent( + return reanimatedModuleProxy_->isAnyHandlerWaitingForEvent( eventName, emitterReactTag); } void NativeProxy::performOperations() { #ifdef RCT_NEW_ARCH_ENABLED - nativeReanimatedModule_->performOperations(); + reanimatedModuleProxy_->performOperations(); #endif } @@ -462,7 +462,7 @@ void NativeProxy::handleEvent( return; } - jsi::Runtime &rt = nativeReanimatedModule_->getUIRuntime(); + jsi::Runtime &rt = reanimatedModuleProxy_->getUIRuntime(); jsi::Value payload; try { payload = jsi::Value::createFromJsonUtf8( @@ -472,7 +472,7 @@ void NativeProxy::handleEvent( return; } - nativeReanimatedModule_->handleEvent( + reanimatedModuleProxy_->handleEvent( eventName->toString(), emitterReactTag, payload, getAnimationTimestamp()); } @@ -558,14 +558,14 @@ PlatformDepMethodsHolder NativeProxy::getPlatformDependentMethods() { } void NativeProxy::setupLayoutAnimations() { - auto weakNativeReanimatedModule = - std::weak_ptr(nativeReanimatedModule_); + auto weakReanimatedModuleProxy = + std::weak_ptr(reanimatedModuleProxy_); layoutAnimations_->cthis()->setAnimationStartingBlock( - [weakNativeReanimatedModule]( + [weakReanimatedModuleProxy]( int tag, int type, alias_ref> values) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - jsi::Runtime &rt = nativeReanimatedModule->getUIRuntime(); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + jsi::Runtime &rt = reanimatedModuleProxy->getUIRuntime(); jsi::Object yogaValues(rt); for (const auto &entry : *values) { try { @@ -586,25 +586,24 @@ void NativeProxy::setupLayoutAnimations() { "[Reanimated] Failed to convert value to number."); } } - nativeReanimatedModule->layoutAnimationsManager() - .startLayoutAnimation( - rt, tag, static_cast(type), yogaValues); + reanimatedModuleProxy->layoutAnimationsManager().startLayoutAnimation( + rt, tag, static_cast(type), yogaValues); } }); layoutAnimations_->cthis()->setHasAnimationBlock( - [weakNativeReanimatedModule](int tag, int type) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - return nativeReanimatedModule->layoutAnimationsManager() + [weakReanimatedModuleProxy](int tag, int type) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + return reanimatedModuleProxy->layoutAnimationsManager() .hasLayoutAnimation(tag, static_cast(type)); } return false; }); layoutAnimations_->cthis()->setShouldAnimateExitingBlock( - [weakNativeReanimatedModule](int tag, bool shouldAnimate) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - return nativeReanimatedModule->layoutAnimationsManager() + [weakReanimatedModuleProxy](int tag, bool shouldAnimate) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + return reanimatedModuleProxy->layoutAnimationsManager() .shouldAnimateExiting(tag, shouldAnimate); } return false; @@ -612,35 +611,35 @@ void NativeProxy::setupLayoutAnimations() { #ifndef NDEBUG layoutAnimations_->cthis()->setCheckDuplicateSharedTag( - [weakNativeReanimatedModule](int viewTag, int screenTag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - nativeReanimatedModule->layoutAnimationsManager() + [weakReanimatedModuleProxy](int viewTag, int screenTag) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + reanimatedModuleProxy->layoutAnimationsManager() .checkDuplicateSharedTag(viewTag, screenTag); } }); #endif layoutAnimations_->cthis()->setClearAnimationConfigBlock( - [weakNativeReanimatedModule](int tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - nativeReanimatedModule->layoutAnimationsManager() + [weakReanimatedModuleProxy](int tag) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + reanimatedModuleProxy->layoutAnimationsManager() .clearLayoutAnimationConfig(tag); } }); layoutAnimations_->cthis()->setCancelAnimationForTag( - [weakNativeReanimatedModule](int tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - jsi::Runtime &rt = nativeReanimatedModule->getUIRuntime(); - nativeReanimatedModule->layoutAnimationsManager() + [weakReanimatedModuleProxy](int tag) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + jsi::Runtime &rt = reanimatedModuleProxy->getUIRuntime(); + reanimatedModuleProxy->layoutAnimationsManager() .cancelLayoutAnimation(rt, tag); } }); layoutAnimations_->cthis()->setFindPrecedingViewTagForTransition( - [weakNativeReanimatedModule](int tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - return nativeReanimatedModule->layoutAnimationsManager() + [weakReanimatedModuleProxy](int tag) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + return reanimatedModuleProxy->layoutAnimationsManager() .findPrecedingViewTagForTransition(tag); } else { return -1; @@ -648,9 +647,9 @@ void NativeProxy::setupLayoutAnimations() { }); layoutAnimations_->cthis()->setGetSharedGroupBlock( - [weakNativeReanimatedModule](int tag) -> std::vector { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - return nativeReanimatedModule->layoutAnimationsManager() + [weakReanimatedModuleProxy](int tag) -> std::vector { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + return reanimatedModuleProxy->layoutAnimationsManager() .getSharedGroup(tag); } else { return {}; diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h index ea250729644..9f312063b8b 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h +++ b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -181,7 +181,7 @@ class NativeProxy : public jni::HybridClass { friend HybridBase; jni::global_ref javaPart_; jsi::Runtime *rnRuntime_; - std::shared_ptr nativeReanimatedModule_; + std::shared_ptr reanimatedModuleProxy_; jni::global_ref layoutAnimations_; #ifndef NDEBUG void checkJavaVersion(jsi::Runtime &); diff --git a/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm b/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm index 8ba308ce79f..5ee5b74c4f7 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm @@ -50,7 +50,7 @@ - (void)_tryAndHandleError:(dispatch_block_t)block; @implementation REAModule { #ifdef RCT_NEW_ARCH_ENABLED __weak RCTSurfacePresenter *_surfacePresenter; - std::weak_ptr weakNativeReanimatedModule_; + std::weak_ptr weakReanimatedModuleProxy_; #else NSMutableArray *_operations; #endif // RCT_NEW_ARCH_ENABLED @@ -104,8 +104,8 @@ - (void)injectDependencies:(jsi::Runtime &)runtime { const auto &uiManager = [self getUIManager]; react_native_assert(uiManager.get() != nil); - if (auto nativeReanimatedModule = weakNativeReanimatedModule_.lock()) { - nativeReanimatedModule->initializeFabric(uiManager); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy_.lock()) { + reanimatedModuleProxy->initializeFabric(uiManager); } } @@ -142,16 +142,16 @@ - (void)attachReactEventListener if (strongSelf == nil) { return; } - if (auto nativeReanimatedModule = strongSelf->weakNativeReanimatedModule_.lock()) { + if (auto reanimatedModuleProxy = strongSelf->weakReanimatedModuleProxy_.lock()) { auto eventListener = - std::make_shared([nativeReanimatedModule](const RawEvent &rawEvent) { + std::make_shared([reanimatedModuleProxy](const RawEvent &rawEvent) { if (!RCTIsMainQueue()) { // event listener called on the JS thread, let's ignore this event // as we cannot safely access worklet runtime here // and also we don't care about topLayout events return false; } - return nativeReanimatedModule->handleRawEvent(rawEvent, CACurrentMediaTime() * 1000); + return reanimatedModuleProxy->handleRawEvent(rawEvent, CACurrentMediaTime() * 1000); }); [scheduler addEventListener:eventListener]; } @@ -291,10 +291,10 @@ - (void)sendEventWithName:(NSString *)eventName body:(id)body callbackBlock(runtime); }]; }); - auto nativeReanimatedModule = reanimated::createReanimatedModuleBridgeless( + auto reanimatedModuleProxy = reanimated::createReanimatedModuleBridgeless( self, _moduleRegistry, rnRuntime, workletsModule, executorFunction); [self attachReactEventListener]; - [self commonInit:nativeReanimatedModule withRnRuntime:rnRuntime]; + [self commonInit:reanimatedModuleProxy withRnRuntime:rnRuntime]; #else [NSException raise:@"Missing bridge" format:@"[Reanimated] Failed to obtain the bridge."]; #endif // RCT_NEW_ARCH_ENABLED @@ -304,11 +304,11 @@ - (void)sendEventWithName:(NSString *)eventName body:(id)body : nullptr; if (jsiRuntime) { - auto nativeReanimatedModule = + auto reanimatedModuleProxy = reanimated::createReanimatedModule(self, self.bridge, self.bridge.jsCallInvoker, workletsModule); jsi::Runtime &rnRuntime = *jsiRuntime; - [self commonInit:nativeReanimatedModule withRnRuntime:rnRuntime]; + [self commonInit:reanimatedModuleProxy withRnRuntime:rnRuntime]; } } return @YES; @@ -322,13 +322,12 @@ - (void)sendEventWithName:(NSString *)eventName body:(id)body } #endif // RCT_NEW_ARCH_ENABLED -- (void)commonInit:(std::shared_ptr)nativeReanimatedModule - withRnRuntime:(jsi::Runtime &)rnRuntime +- (void)commonInit:(std::shared_ptr)reanimatedModuleProxy withRnRuntime:(jsi::Runtime &)rnRuntime { WorkletRuntimeCollector::install(rnRuntime); - RNRuntimeDecorator::decorate(rnRuntime, nativeReanimatedModule); + RNRuntimeDecorator::decorate(rnRuntime, reanimatedModuleProxy); #ifdef RCT_NEW_ARCH_ENABLED - weakNativeReanimatedModule_ = nativeReanimatedModule; + weakReanimatedModuleProxy_ = reanimatedModuleProxy; if (self->_surfacePresenter != nil) { // reload, uiManager is null right now, we need to wait for `installReanimatedAfterReload` [self injectDependencies:rnRuntime]; diff --git a/packages/react-native-reanimated/apple/reanimated/apple/REANodesManager.mm b/packages/react-native-reanimated/apple/reanimated/apple/REANodesManager.mm index ec86d086b92..eb0a70c50ac 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/REANodesManager.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/REANodesManager.mm @@ -313,7 +313,7 @@ - (void)onAnimationFrame:(READisplayLink *)displayLink - (void)performOperations { #ifdef RCT_NEW_ARCH_ENABLED - _performOperations(); // calls NativeReanimatedModule::performOperations + _performOperations(); // calls ReanimatedModuleProxy::performOperations _wantRunUpdates = NO; #else if (_operationsInBatch.count != 0) { diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.h b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.h index 7e68aa16cd6..c6e14ef2b30 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.h +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.h @@ -1,7 +1,7 @@ #if __cplusplus #import -#import +#import #import #import #import @@ -14,14 +14,14 @@ namespace reanimated { static inline bool getIsReducedMotion(); -std::shared_ptr createReanimatedModule( +std::shared_ptr createReanimatedModule( REAModule *reaModule, RCTBridge *bridge, const std::shared_ptr &jsInvoker, WorkletsModule *workletsModule); #ifdef RCT_NEW_ARCH_ENABLED -std::shared_ptr +std::shared_ptr createReanimatedModuleBridgeless( REAModule *reaModule, RCTModuleRegistry *moduleRegistry, @@ -32,13 +32,13 @@ createReanimatedModuleBridgeless( void commonInit( REAModule *reaModule, - std::shared_ptr nativeReanimatedModule); + std::shared_ptr reanimatedModuleProxy); #ifdef RCT_NEW_ARCH_ENABLED // nothing #else // RCT_NEW_ARCH_ENABLED void setupLayoutAnimationCallbacks( - std::shared_ptr nativeReanimatedModule, + std::shared_ptr reanimatedModuleProxy, REAAnimationsManager *animationsManager); #endif // RCT_NEW_ARCH_ENABLED diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm index d99b0e97c99..1ed3429b2c9 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm @@ -1,5 +1,5 @@ #import -#import +#import #import #import #import @@ -56,7 +56,7 @@ static inline bool getIsReducedMotion() #endif // __has_include() } -std::shared_ptr createReanimatedModule( +std::shared_ptr createReanimatedModule( REAModule *reaModule, RCTBridge *bridge, const std::shared_ptr &jsInvoker, @@ -74,7 +74,7 @@ static inline bool getIsReducedMotion() const auto nativeWorkletsModule = [workletsModule getNativeWorkletsModule]; - auto nativeReanimatedModule = std::make_shared( + auto reanimatedModuleProxy = std::make_shared( nativeWorkletsModule, rnRuntime, jsScheduler, @@ -83,21 +83,21 @@ static inline bool getIsReducedMotion() isBridgeless, getIsReducedMotion()); - commonInit(reaModule, nativeReanimatedModule); + commonInit(reaModule, reanimatedModuleProxy); // Layout Animation callbacks setup #ifdef RCT_NEW_ARCH_ENABLED // nothing #else REAAnimationsManager *animationsManager = reaModule.animationsManager; - setupLayoutAnimationCallbacks(nativeReanimatedModule, animationsManager); + setupLayoutAnimationCallbacks(reanimatedModuleProxy, animationsManager); #endif // RCT_NEW_ARCH_ENABLED - return nativeReanimatedModule; + return reanimatedModuleProxy; } #ifdef RCT_NEW_ARCH_ENABLED -std::shared_ptr createReanimatedModuleBridgeless( +std::shared_ptr createReanimatedModuleBridgeless( REAModule *reaModule, RCTModuleRegistry *moduleRegistry, jsi::Runtime &runtime, @@ -114,7 +114,7 @@ static inline bool getIsReducedMotion() auto jsScheduler = std::make_shared(runtime, runtimeExecutor); constexpr auto isBridgeless = true; - auto nativeReanimatedModule = std::make_shared( + auto reanimatedModuleProxy = std::make_shared( nativeWorkletsModule, runtime, jsScheduler, @@ -123,30 +123,30 @@ static inline bool getIsReducedMotion() isBridgeless, getIsReducedMotion()); - commonInit(reaModule, nativeReanimatedModule); + commonInit(reaModule, reanimatedModuleProxy); - return nativeReanimatedModule; + return reanimatedModuleProxy; } #endif // RCT_NEW_ARCH_ENABLED -void commonInit(REAModule *reaModule, std::shared_ptr nativeReanimatedModule) +void commonInit(REAModule *reaModule, std::shared_ptr reanimatedModuleProxy) { [reaModule.nodesManager registerEventHandler:^(id event) { // handles RCTEvents from RNGestureHandler std::string eventName = [event.eventName UTF8String]; int emitterReactTag = [event.viewTag intValue]; id eventData = [event arguments][2]; - jsi::Runtime &uiRuntime = nativeReanimatedModule->getUIRuntime(); + jsi::Runtime &uiRuntime = reanimatedModuleProxy->getUIRuntime(); jsi::Value payload = convertObjCObjectToJSIValue(uiRuntime, eventData); double currentTime = CACurrentMediaTime() * 1000; - nativeReanimatedModule->handleEvent(eventName, emitterReactTag, payload, currentTime); + reanimatedModuleProxy->handleEvent(eventName, emitterReactTag, payload, currentTime); }]; #ifdef RCT_NEW_ARCH_ENABLED - std::weak_ptr weakNativeReanimatedModule = nativeReanimatedModule; // to avoid retain cycle + std::weak_ptr weakReanimatedModuleProxy = reanimatedModuleProxy; // to avoid retain cycle [reaModule.nodesManager registerPerformOperations:^() { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - nativeReanimatedModule->performOperations(); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + reanimatedModuleProxy->performOperations(); } }]; #endif // RCT_NEW_ARCH_ENABLED @@ -156,14 +156,14 @@ void commonInit(REAModule *reaModule, std::shared_ptr na // nothing #else // RCT_NEW_ARCH_ENABLED void setupLayoutAnimationCallbacks( - std::shared_ptr nativeReanimatedModule, + std::shared_ptr reanimatedModuleProxy, REAAnimationsManager *animationsManager) { - std::weak_ptr weakNativeReanimatedModule = nativeReanimatedModule; // to avoid retain cycle + std::weak_ptr weakReanimatedModuleProxy = reanimatedModuleProxy; // to avoid retain cycle [animationsManager setAnimationStartingBlock:^(NSNumber *_Nonnull tag, LayoutAnimationType type, NSDictionary *_Nonnull values) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - jsi::Runtime &rt = nativeReanimatedModule->getUIRuntime(); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + jsi::Runtime &rt = reanimatedModuleProxy->getUIRuntime(); jsi::Object yogaValues(rt); for (NSString *key in values.allKeys) { NSObject *value = values[key]; @@ -178,59 +178,59 @@ void setupLayoutAnimationCallbacks( yogaValues.setProperty(rt, [key UTF8String], [(NSNumber *)value doubleValue]); } } - nativeReanimatedModule->layoutAnimationsManager().startLayoutAnimation(rt, [tag intValue], type, yogaValues); + reanimatedModuleProxy->layoutAnimationsManager().startLayoutAnimation(rt, [tag intValue], type, yogaValues); } }]; [animationsManager setHasAnimationBlock:^(NSNumber *_Nonnull tag, LayoutAnimationType type) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { bool hasLayoutAnimation = - nativeReanimatedModule->layoutAnimationsManager().hasLayoutAnimation([tag intValue], type); + reanimatedModuleProxy->layoutAnimationsManager().hasLayoutAnimation([tag intValue], type); return hasLayoutAnimation ? YES : NO; } return NO; }]; [animationsManager setShouldAnimateExitingBlock:^(NSNumber *_Nonnull tag, BOOL shouldAnimate) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { bool shouldAnimateExiting = - nativeReanimatedModule->layoutAnimationsManager().shouldAnimateExiting([tag intValue], shouldAnimate); + reanimatedModuleProxy->layoutAnimationsManager().shouldAnimateExiting([tag intValue], shouldAnimate); return shouldAnimateExiting ? YES : NO; } return NO; }]; [animationsManager setAnimationRemovingBlock:^(NSNumber *_Nonnull tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - nativeReanimatedModule->layoutAnimationsManager().clearLayoutAnimationConfig([tag intValue]); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + reanimatedModuleProxy->layoutAnimationsManager().clearLayoutAnimationConfig([tag intValue]); } }]; [animationsManager setSharedTransitionRemovingBlock:^(NSNumber *_Nonnull tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - nativeReanimatedModule->layoutAnimationsManager().clearSharedTransitionConfig([tag intValue]); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + reanimatedModuleProxy->layoutAnimationsManager().clearSharedTransitionConfig([tag intValue]); } }]; [animationsManager setCancelAnimationBlock:^(NSNumber *_Nonnull tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - jsi::Runtime &rt = nativeReanimatedModule->getUIRuntime(); - nativeReanimatedModule->layoutAnimationsManager().cancelLayoutAnimation(rt, [tag intValue]); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + jsi::Runtime &rt = reanimatedModuleProxy->getUIRuntime(); + reanimatedModuleProxy->layoutAnimationsManager().cancelLayoutAnimation(rt, [tag intValue]); } }]; [animationsManager setFindPrecedingViewTagForTransitionBlock:^NSNumber *_Nullable(NSNumber *_Nonnull tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { int resultTag = - nativeReanimatedModule->layoutAnimationsManager().findPrecedingViewTagForTransition([tag intValue]); + reanimatedModuleProxy->layoutAnimationsManager().findPrecedingViewTagForTransition([tag intValue]); return resultTag == -1 ? nil : @(resultTag); } return nil; }]; [animationsManager setGetSharedGroupBlock:^NSArray *_Nullable(NSNumber *_Nonnull tag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { - const auto &results = nativeReanimatedModule->layoutAnimationsManager().getSharedGroup([tag intValue]); + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { + const auto &results = reanimatedModuleProxy->layoutAnimationsManager().getSharedGroup([tag intValue]); NSMutableArray *convertedResult = [NSMutableArray new]; for (const int tag : results) { [convertedResult addObject:@(tag)]; @@ -241,11 +241,11 @@ void setupLayoutAnimationCallbacks( }]; #ifndef NDEBUG [animationsManager setCheckDuplicateSharedTagBlock:^(REAUIView *view, NSNumber *_Nonnull viewTag) { - if (auto nativeReanimatedModule = weakNativeReanimatedModule.lock()) { + if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) { REAUIView *screen = [REAScreensHelper getScreenForView:(REAUIView *)view]; auto screenTag = [screen.reactTag intValue]; // Here we check if there are duplicate tags (we don't use return bool value currently) - nativeReanimatedModule->layoutAnimationsManager().checkDuplicateSharedTag([viewTag intValue], screenTag); + reanimatedModuleProxy->layoutAnimationsManager().checkDuplicateSharedTag([viewTag intValue], screenTag); } }]; #endif // NDEBUG diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.h b/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.h index be566d82d4d..89c937dd8fa 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.h +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.h @@ -5,7 +5,7 @@ #import #import #import -#import +#import #import #import From 394f2c20df5b707bf1109a7ddc3459000a6e8102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Wed, 27 Nov 2024 17:48:41 +0100 Subject: [PATCH 15/36] refactor: rename cpp NativeWorkletsModule to WorkletsModuleProxy (#6767) ## Summary Analogous to: - #6766 `NativeWorkletsModule` is the name of the ObjC/Java modules generated from `WorkletsModule`. It's confusing that we name some Cpp object the same way. With this change Cpp `NativeWorkletsModule` becomes `WorkletsModuleProxy`, the same name we use to refer to it from JavaScript. ## Test plan CI --- .../NativeModules/ReanimatedModuleProxy.cpp | 10 +++++----- .../NativeModules/ReanimatedModuleProxy.h | 12 ++++++------ ...kletsModule.cpp => WorkletsModuleProxy.cpp} | 10 +++++----- ...eWorkletsModule.h => WorkletsModuleProxy.h} | 10 +++++----- ...uleSpec.cpp => WorkletsModuleProxySpec.cpp} | 8 ++++---- ...sModuleSpec.h => WorkletsModuleProxySpec.h} | 4 ++-- .../RNRuntimeWorkletDecorator.cpp | 4 ++-- .../WorkletRuntime/RNRuntimeWorkletDecorator.h | 4 ++-- .../cpp/reanimated/android/NativeProxy.cpp | 18 ++++++++---------- .../main/cpp/reanimated/android/NativeProxy.h | 4 ++-- .../cpp/worklets/android/WorkletsModule.cpp | 4 ++-- .../main/cpp/worklets/android/WorkletsModule.h | 8 ++++---- .../reanimated/apple/native/NativeProxy.mm | 8 ++++---- .../apple/worklets/apple/WorkletsModule.h | 4 ++-- .../apple/worklets/apple/WorkletsModule.mm | 12 ++++++------ 15 files changed, 59 insertions(+), 61 deletions(-) rename packages/react-native-reanimated/Common/cpp/worklets/NativeModules/{NativeWorkletsModule.cpp => WorkletsModuleProxy.cpp} (78%) rename packages/react-native-reanimated/Common/cpp/worklets/NativeModules/{NativeWorkletsModule.h => WorkletsModuleProxy.h} (77%) rename packages/react-native-reanimated/Common/cpp/worklets/NativeModules/{NativeWorkletsModuleSpec.cpp => WorkletsModuleProxySpec.cpp} (71%) rename packages/react-native-reanimated/Common/cpp/worklets/NativeModules/{NativeWorkletsModuleSpec.h => WorkletsModuleProxySpec.h} (82%) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp index 02b4f6a5495..12b4b22fe8b 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp @@ -52,7 +52,7 @@ using namespace facebook; namespace reanimated { ReanimatedModuleProxy::ReanimatedModuleProxy( - const std::shared_ptr &nativeWorkletsModule, + const std::shared_ptr &workletsModuleProxy, jsi::Runtime &rnRuntime, const std::shared_ptr &jsScheduler, const std::shared_ptr &uiScheduler, @@ -63,13 +63,13 @@ ReanimatedModuleProxy::ReanimatedModuleProxy( isBridgeless ? nullptr : jsScheduler->getJSCallInvoker()), isBridgeless_(isBridgeless), isReducedMotion_(isReducedMotion), - nativeWorkletsModule_(nativeWorkletsModule), + workletsModuleProxy_(workletsModuleProxy), jsScheduler_(jsScheduler), uiScheduler_(uiScheduler), - valueUnpackerCode_(nativeWorkletsModule->getValueUnpackerCode()), + valueUnpackerCode_(workletsModuleProxy->getValueUnpackerCode()), uiWorkletRuntime_(std::make_shared( rnRuntime, - nativeWorkletsModule->getJSQueue(), + workletsModuleProxy->getJSQueue(), jsScheduler_, "Reanimated UI runtime", true /* supportsLocking */, @@ -231,7 +231,7 @@ jsi::Value ReanimatedModuleProxy::createWorkletRuntime( const jsi::Value &initializer) { auto workletRuntime = std::make_shared( rt, - nativeWorkletsModule_->getJSQueue(), + workletsModuleProxy_->getJSQueue(), jsScheduler_, name.asString(rt).utf8(rt), false /* supportsLocking */, diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h index 518e5bc7411..f56a5c8c739 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h @@ -12,7 +12,7 @@ #include #endif // RCT_NEW_ARCH_ENABLED -#include +#include #include #include #include @@ -33,7 +33,7 @@ namespace reanimated { class ReanimatedModuleProxy : public ReanimatedModuleProxySpec { public: ReanimatedModuleProxy( - const std::shared_ptr &nativeWorkletsModule, + const std::shared_ptr &workletsModuleProxy, jsi::Runtime &rnRuntime, const std::shared_ptr &jsScheduler, const std::shared_ptr &uiScheduler, @@ -174,9 +174,9 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec { return isReducedMotion_; } - [[nodiscard]] inline std::shared_ptr - getNativeWorkletsModule() const { - return nativeWorkletsModule_; + [[nodiscard]] inline std::shared_ptr + getWorkletsModuleProxy() const { + return workletsModuleProxy_; } private: @@ -193,7 +193,7 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec { const bool isBridgeless_; const bool isReducedMotion_; - const std::shared_ptr nativeWorkletsModule_; + const std::shared_ptr workletsModuleProxy_; const std::shared_ptr jsScheduler_; const std::shared_ptr uiScheduler_; const std::string valueUnpackerCode_; diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp similarity index 78% rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp rename to packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp index 5189d0aa561..c439dc2e6a8 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp @@ -5,7 +5,7 @@ #include #endif // RCT_NEW_ARCH_ENABLED -#include +#include #include #ifdef __ANDROID__ @@ -18,16 +18,16 @@ using namespace facebook; namespace worklets { -NativeWorkletsModule::NativeWorkletsModule( +WorkletsModuleProxy::WorkletsModuleProxy( const std::string &valueUnpackerCode, const std::shared_ptr &jsQueue) - : NativeWorkletsModuleSpec(nullptr), + : WorkletsModuleProxySpec(nullptr), valueUnpackerCode_(valueUnpackerCode), jsQueue_(jsQueue) {} -NativeWorkletsModule::~NativeWorkletsModule() {} +WorkletsModuleProxy::~WorkletsModuleProxy() {} -jsi::Value NativeWorkletsModule::makeShareableClone( +jsi::Value WorkletsModuleProxy::makeShareableClone( jsi::Runtime &rt, const jsi::Value &value, const jsi::Value &shouldRetainRemote, diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h similarity index 77% rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h rename to packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h index 13eb581337c..e9fedb04e22 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModule.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -9,13 +9,13 @@ namespace worklets { -class NativeWorkletsModule : public NativeWorkletsModuleSpec { +class WorkletsModuleProxy : public WorkletsModuleProxySpec { public: - explicit NativeWorkletsModule( + explicit WorkletsModuleProxy( const std::string &valueUnpackerCode, const std::shared_ptr &jsQueue); - ~NativeWorkletsModule(); + ~WorkletsModuleProxy(); jsi::Value makeShareableClone( jsi::Runtime &rt, @@ -35,7 +35,7 @@ class NativeWorkletsModule : public NativeWorkletsModuleSpec { const std::string valueUnpackerCode_; const std::shared_ptr jsQueue_; #ifndef NDEBUG - SingleInstanceChecker singleInstanceChecker_; + SingleInstanceChecker singleInstanceChecker_; #endif // NDEBUG }; diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp similarity index 71% rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp rename to packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp index 95f05ac8036..624c42ee224 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp @@ -1,9 +1,9 @@ -#include +#include #include #define WORKLETS_SPEC_PREFIX(FN_NAME) \ - __hostFunction_NativeWorkletsModuleSpec_##FN_NAME + __hostFunction_WorkletsModuleProxySpec_##FN_NAME namespace worklets { @@ -12,12 +12,12 @@ static jsi::Value WORKLETS_SPEC_PREFIX(makeShareableClone)( TurboModule &turboModule, const jsi::Value *args, size_t) { - return static_cast(&turboModule) + return static_cast(&turboModule) ->makeShareableClone( rt, std::move(args[0]), std::move(args[1]), std::move(args[2])); } -NativeWorkletsModuleSpec::NativeWorkletsModuleSpec( +WorkletsModuleProxySpec::WorkletsModuleProxySpec( const std::shared_ptr jsInvoker) : TurboModule("NativeWorklets", jsInvoker) { methodMap_["makeShareableClone"] = diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h similarity index 82% rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h rename to packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h index 1c1d622e17c..c79a86b908f 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/NativeWorkletsModuleSpec.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h @@ -9,9 +9,9 @@ using namespace react; namespace worklets { -class JSI_EXPORT NativeWorkletsModuleSpec : public TurboModule { +class JSI_EXPORT WorkletsModuleProxySpec : public TurboModule { protected: - explicit NativeWorkletsModuleSpec( + explicit WorkletsModuleProxySpec( const std::shared_ptr jsInvoker); public: diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp index 37565314534..8575570f72b 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp @@ -4,11 +4,11 @@ namespace worklets { void RNRuntimeWorkletDecorator::decorate( jsi::Runtime &rnRuntime, - const std::shared_ptr &nativeWorkletsModule) { + const std::shared_ptr &workletsModuleProxy) { rnRuntime.global().setProperty( rnRuntime, "__workletsModuleProxy", - jsi::Object::createFromHostObject(rnRuntime, nativeWorkletsModule)); + jsi::Object::createFromHostObject(rnRuntime, workletsModuleProxy)); } } // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h index 9884e71091a..41cf12b5598 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include using namespace facebook; @@ -13,7 +13,7 @@ class RNRuntimeWorkletDecorator { public: static void decorate( jsi::Runtime &rnRuntime, - const std::shared_ptr &nativeWorkletsModule); + const std::shared_ptr &workletsModuleProxy); }; } // namespace worklets diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp index f88eba94b6e..01e2b1aaefa 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp +++ b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp @@ -28,7 +28,7 @@ using namespace react; NativeProxy::NativeProxy( jni::alias_ref jThis, - const std::shared_ptr &nativeWorkletsModule, + const std::shared_ptr &workletsModuleProxy, jsi::Runtime *rnRuntime, const std::shared_ptr &jsCallInvoker, const std::shared_ptr &uiScheduler, @@ -42,7 +42,7 @@ NativeProxy::NativeProxy( : javaPart_(jni::make_global(jThis)), rnRuntime_(rnRuntime), reanimatedModuleProxy_(std::make_shared( - nativeWorkletsModule, + workletsModuleProxy, *rnRuntime, std::make_shared(*rnRuntime, jsCallInvoker), uiScheduler, @@ -58,7 +58,7 @@ NativeProxy::NativeProxy( #ifdef RCT_NEW_ARCH_ENABLED NativeProxy::NativeProxy( jni::alias_ref jThis, - const std::shared_ptr &nativeWorkletsModule, + const std::shared_ptr &workletsModuleProxy, jsi::Runtime *rnRuntime, RuntimeExecutor runtimeExecutor, const std::shared_ptr &uiScheduler, @@ -68,7 +68,7 @@ NativeProxy::NativeProxy( : javaPart_(jni::make_global(jThis)), rnRuntime_(rnRuntime), reanimatedModuleProxy_(std::make_shared( - nativeWorkletsModule, + workletsModuleProxy, *rnRuntime, std::make_shared(*rnRuntime, runtimeExecutor), uiScheduler, @@ -123,11 +123,10 @@ jni::local_ref NativeProxy::initHybrid( ) { auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker(); auto uiScheduler = androidUiScheduler->cthis()->getUIScheduler(); - auto nativeWorkletsModule = - jWorkletsModule->cthis()->getNativeWorkletsModule(); + auto workletsModuleProxy = jWorkletsModule->cthis()->getWorkletsModuleProxy(); return makeCxxInstance( jThis, - nativeWorkletsModule, + workletsModuleProxy, (jsi::Runtime *)jsContext, jsCallInvoker, uiScheduler, @@ -151,11 +150,10 @@ jni::local_ref NativeProxy::initHybridBridgeless( fabricUIManager) { auto uiScheduler = androidUiScheduler->cthis()->getUIScheduler(); auto runtimeExecutor = runtimeExecutorHolder->cthis()->get(); - auto nativeWorkletsModule = - jWorkletsModule->cthis()->getNativeWorkletsModule(); + auto workletsModuleProxy = jWorkletsModule->cthis()->getWorkletsModuleProxy(); return makeCxxInstance( jThis, - nativeWorkletsModule, + workletsModuleProxy, (jsi::Runtime *)jsContext, runtimeExecutor, uiScheduler, diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h index 9f312063b8b..175570e10e1 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h +++ b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h @@ -275,7 +275,7 @@ class NativeProxy : public jni::HybridClass { explicit NativeProxy( jni::alias_ref jThis, - const std::shared_ptr &nativeWorkletsModule, + const std::shared_ptr &workletsModuleProxy, jsi::Runtime *rnRuntime, const std::shared_ptr &jsCallInvoker, const std::shared_ptr &uiScheduler, @@ -290,7 +290,7 @@ class NativeProxy : public jni::HybridClass { #ifdef RCT_NEW_ARCH_ENABLED explicit NativeProxy( jni::alias_ref jThis, - const std::shared_ptr &nativeWorkletsModule, + const std::shared_ptr &workletsModuleProxy, jsi::Runtime *rnRuntime, RuntimeExecutor runtimeExecutor, const std::shared_ptr &uiScheduler, diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp index 833c5a36cbf..ff2b0401e6f 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp +++ b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp @@ -24,10 +24,10 @@ WorkletsModule::WorkletsModule( jni::alias_ref messageQueueThread) : javaPart_(jni::make_global(jThis)), rnRuntime_(rnRuntime), - nativeWorkletsModule_(std::make_shared( + workletsModuleProxy_(std::make_shared( valueUnpackerCode, std::make_shared(messageQueueThread))) { - RNRuntimeWorkletDecorator::decorate(*rnRuntime_, nativeWorkletsModule_); + RNRuntimeWorkletDecorator::decorate(*rnRuntime_, workletsModuleProxy_); } jni::local_ref WorkletsModule::initHybrid( diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h index e367780de3c..4a771925164 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h +++ b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -36,15 +36,15 @@ class WorkletsModule : public jni::HybridClass { static void registerNatives(); - inline std::shared_ptr getNativeWorkletsModule() { - return nativeWorkletsModule_; + inline std::shared_ptr getWorkletsModuleProxy() { + return workletsModuleProxy_; } private: friend HybridBase; jni::global_ref javaPart_; jsi::Runtime *rnRuntime_; - std::shared_ptr nativeWorkletsModule_; + std::shared_ptr workletsModuleProxy_; explicit WorkletsModule( jni::alias_ref jThis, diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm index 1ed3429b2c9..81ad96fd0a0 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm @@ -72,10 +72,10 @@ static inline bool getIsReducedMotion() std::shared_ptr jsScheduler = std::make_shared(rnRuntime, jsInvoker); constexpr auto isBridgeless = false; - const auto nativeWorkletsModule = [workletsModule getNativeWorkletsModule]; + const auto workletsModuleProxy = [workletsModule getWorkletsModuleProxy]; auto reanimatedModuleProxy = std::make_shared( - nativeWorkletsModule, + workletsModuleProxy, rnRuntime, jsScheduler, uiScheduler, @@ -109,13 +109,13 @@ static inline bool getIsReducedMotion() PlatformDepMethodsHolder platformDepMethodsHolder = makePlatformDepMethodsHolderBridgeless(moduleRegistry, nodesManager, reaModule); - const auto nativeWorkletsModule = [workletsModule getNativeWorkletsModule]; + const auto workletsModuleProxy = [workletsModule getWorkletsModuleProxy]; auto uiScheduler = std::make_shared(); auto jsScheduler = std::make_shared(runtime, runtimeExecutor); constexpr auto isBridgeless = true; auto reanimatedModuleProxy = std::make_shared( - nativeWorkletsModule, + workletsModuleProxy, runtime, jsScheduler, uiScheduler, diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.h b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.h index 25b96da8b9b..5a3b01a10dd 100644 --- a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.h +++ b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.h @@ -1,9 +1,9 @@ #import #import -#import +#import @interface WorkletsModule : RCTEventEmitter -- (std::shared_ptr)getNativeWorkletsModule; +- (std::shared_ptr)getWorkletsModuleProxy; @end diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm index 77f502ed825..64cb9069439 100644 --- a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm +++ b/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm @@ -4,8 +4,8 @@ #import #import -using worklets::NativeWorkletsModule; using worklets::RNRuntimeWorkletDecorator; +using worklets::WorkletsModuleProxy; @interface RCTBridge (JSIRuntime) - (void *)runtime; @@ -17,15 +17,15 @@ - (void)_tryAndHandleError:(dispatch_block_t)block; @end @implementation WorkletsModule { - std::shared_ptr nativeWorkletsModule_; + std::shared_ptr workletsModuleProxy_; #ifndef NDEBUG worklets::SingleInstanceChecker singleInstanceChecker_; #endif // NDEBUG } -- (std::shared_ptr)getNativeWorkletsModule +- (std::shared_ptr)getWorkletsModuleProxy { - return nativeWorkletsModule_; + return workletsModuleProxy_; } @synthesize moduleRegistry = _moduleRegistry; @@ -39,8 +39,8 @@ @implementation WorkletsModule { auto jsQueue = std::make_shared([NSRunLoop currentRunLoop], ^(NSError *error) { throw error; }); - nativeWorkletsModule_ = std::make_shared(std::string([valueUnpackerCode UTF8String]), jsQueue); - RNRuntimeWorkletDecorator::decorate(rnRuntime, nativeWorkletsModule_); + workletsModuleProxy_ = std::make_shared(std::string([valueUnpackerCode UTF8String]), jsQueue); + RNRuntimeWorkletDecorator::decorate(rnRuntime, workletsModuleProxy_); return @YES; } From 556edafbb4a27e9a252040b3fb28ced2c0949500 Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Tue, 3 Dec 2024 10:30:08 +0100 Subject: [PATCH 16/36] Clear `operationsInBatch_` before terminating UI runtime (#6779) ## Summary This PR fixes the following crash that happens during a reload due to `jsi::Value` outliving the UI runtime. The offending `jsi::Value` comes from `operationsInBatch_` inside `ReanimatedModuleProxy` (formerly `NativeReanimatedModule`. In `~ReanimatedModuleProxy` we manually clear data structures containing `jsi::Value` prior to resetting `uiWorkletRuntime_` which effectively terminates the runtimes. It looks like we forgot about `operationsInBatch_`. Screenshot 2024-12-02 at 13 00 08 ## Test plan 1. Launch FabricExample app 2. Reload the app several times 3. Repeat steps 1 and 2 several times --- .../cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp index 12b4b22fe8b..2be3ac637e8 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp @@ -198,6 +198,9 @@ ReanimatedModuleProxy::~ReanimatedModuleProxy() { // runtime, so they have to go away before we tear down the runtime eventHandlerRegistry_.reset(); frameCallbacks_.clear(); +#ifdef RCT_NEW_ARCH_ENABLED + operationsInBatch_.clear(); +#endif // RCT_NEW_ARCH_ENABLED uiWorkletRuntime_.reset(); } From a566fbc0bf794b2597e7fc7cbb3242818f778178 Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Tue, 3 Dec 2024 11:11:41 +0100 Subject: [PATCH 17/36] Assert that `workletsModuleProxy` is found (#6780) ## Summary The following crash happened to me during an app reload. The top stack frame points to `getValueUnpackerCode` but the actual offender is inside `createReanimatedModuleBridgeless` where `workletsModuleProxy` returned from `[workletsModule getWorkletsModuleProxy]` is `nullptr`. Screenshot 2024-12-02 at 12 59 30 ## Test plan --- .../apple/reanimated/apple/native/NativeProxy.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm index 81ad96fd0a0..3a632f7c3d0 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm @@ -110,6 +110,7 @@ static inline bool getIsReducedMotion() makePlatformDepMethodsHolderBridgeless(moduleRegistry, nodesManager, reaModule); const auto workletsModuleProxy = [workletsModule getWorkletsModuleProxy]; + assert(workletsModuleProxy != nullptr); auto uiScheduler = std::make_shared(); auto jsScheduler = std::make_shared(runtime, runtimeExecutor); constexpr auto isBridgeless = true; From 64053b97ac27942b15b6e0b06b208cd4f084d387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:59:15 +0100 Subject: [PATCH 18/36] chore: rephrase render shared value read warning (#6785) ## Summary Turns out it can be understood that you should be using `get` in render instead of `.value`. ## Test plan --- packages/react-native-reanimated/src/mutables.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-native-reanimated/src/mutables.ts b/packages/react-native-reanimated/src/mutables.ts index 4a05b56b103..a0aac328df3 100644 --- a/packages/react-native-reanimated/src/mutables.ts +++ b/packages/react-native-reanimated/src/mutables.ts @@ -18,7 +18,7 @@ function shouldWarnAboutAccessDuringRender() { function checkInvalidReadDuringRender() { if (shouldWarnAboutAccessDuringRender()) { logger.warn( - 'Reading from `value` during component render. Please ensure that you do not access the `value` property or use `get` method of a shared value while React is rendering a component.', + "Reading from `value` during component render. Please ensure that you don't access the `value` property nor use `get` method of a shared value while React is rendering a component.", { strict: true } ); } @@ -27,7 +27,7 @@ function checkInvalidReadDuringRender() { function checkInvalidWriteDuringRender() { if (shouldWarnAboutAccessDuringRender()) { logger.warn( - 'Writing to `value` during component render. Please ensure that you do not access the `value` property or use `set` method of a shared value while React is rendering a component.', + "Writing to `value` during component render. Please ensure that you don't access the `value` property nor use `set` method of a shared value while React is rendering a component.", { strict: true } ); } From d381387518adff8f617f0db8fff9de187baa83dc Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Wed, 4 Dec 2024 11:09:40 +0100 Subject: [PATCH 19/36] Refactor findNodeHandler (#6736) ## Summary This PR addresses the issue reported at [https://github.com/software-mansion/react-native-reanimated/issues/6719](https://github.com/software-mansion/react-native-reanimated/issues/6719) and aims to: - **Unify the method used to obtain the view tag**, as there are currently several approaches. - **Avoid passing a class component to the findNodeHandler**. Instead, we'll pass a ref to the component, similar to what Expo implemented here: [https://github.com/expo/expo/pull/33016](https://github.com/expo/expo/pull/33016). - **Limit unnecessary invocations of findNodeHandler** to no more than one call per render. - **Remove the invocation of findHostInstance from Paper renderer** on the New Architecture. **Additional Remarks:** - When a class component is passed to `createAnimatedComponent`, it will still fall back to the slow path where we can get a native ref. - In `NativeEventManager`, we need to call findNodeHandler again after every render to ensure that the children of `` haven't changed their native tags. - `LayoutAnimationConfig` still uses findNodeHandler. It requires a complete refactor of their functionality to eliminate its use, and I plan to handle this in another PR. - `findHostInstance_DEPRECATED` always follows the slow path even for native refs, which is why I've implemented our own version of `findHostInstance` to optimize the happy path. Fixes https://github.com/software-mansion/react-native-reanimated/issues/6719 Related PRs: - https://github.com/software-mansion/react-native-reanimated/pull/6030 - https://github.com/software-mansion/react-native-reanimated/pull/5960 - https://github.com/software-mansion/react-native-reanimated/pull/4445 - https://github.com/expo/expo/pull/33016 ## Test plan - [x] check Paper - [x] check Fabric - [x] check Web --- .../createAnimatedComponent/JSPropsUpdater.ts | 8 +- .../NativeEventsManager.ts | 57 +++++++-- .../createAnimatedComponent/commonTypes.ts | 12 +- .../createAnimatedComponent.tsx | 111 +++++++++--------- .../src/fabricUtils.ts | 24 ++-- .../src/platform-specific/RNRenderer.ts | 4 - .../src/platform-specific/RNRenderer.web.ts | 4 - .../src/platform-specific/findHostInstance.ts | 77 ++++++++++++ .../platform-specific/findHostInstance.web.ts | 3 + 9 files changed, 198 insertions(+), 102 deletions(-) delete mode 100644 packages/react-native-reanimated/src/platform-specific/RNRenderer.ts delete mode 100644 packages/react-native-reanimated/src/platform-specific/RNRenderer.web.ts create mode 100644 packages/react-native-reanimated/src/platform-specific/findHostInstance.ts create mode 100644 packages/react-native-reanimated/src/platform-specific/findHostInstance.web.ts diff --git a/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts b/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts index f0bd87da036..70e345b73df 100644 --- a/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts +++ b/packages/react-native-reanimated/src/createAnimatedComponent/JSPropsUpdater.ts @@ -38,7 +38,7 @@ class JSPropsUpdaterPaper implements IJSPropsUpdater { > & IAnimatedComponentInternal ) { - const viewTag = animatedComponent._componentViewTag; + const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterPaper._tagToComponentMapping.set(viewTag, animatedComponent); if (JSPropsUpdaterPaper._tagToComponentMapping.size === 1) { const listener = (data: ListenerData) => { @@ -60,7 +60,7 @@ class JSPropsUpdaterPaper implements IJSPropsUpdater { > & IAnimatedComponentInternal ) { - const viewTag = animatedComponent._componentViewTag; + const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterPaper._tagToComponentMapping.delete(viewTag); if (JSPropsUpdaterPaper._tagToComponentMapping.size === 0) { this._reanimatedEventEmitter.removeAllListeners( @@ -100,7 +100,7 @@ class JSPropsUpdaterFabric implements IJSPropsUpdater { if (!JSPropsUpdaterFabric.isInitialized) { return; } - const viewTag = animatedComponent._componentViewTag; + const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterFabric._tagToComponentMapping.set(viewTag, animatedComponent); } @@ -113,7 +113,7 @@ class JSPropsUpdaterFabric implements IJSPropsUpdater { if (!JSPropsUpdaterFabric.isInitialized) { return; } - const viewTag = animatedComponent._componentViewTag; + const viewTag = animatedComponent.getComponentViewTag(); JSPropsUpdaterFabric._tagToComponentMapping.delete(viewTag); } } diff --git a/packages/react-native-reanimated/src/createAnimatedComponent/NativeEventsManager.ts b/packages/react-native-reanimated/src/createAnimatedComponent/NativeEventsManager.ts index da0bbb03b23..e912ae2eca8 100644 --- a/packages/react-native-reanimated/src/createAnimatedComponent/NativeEventsManager.ts +++ b/packages/react-native-reanimated/src/createAnimatedComponent/NativeEventsManager.ts @@ -39,7 +39,7 @@ export class NativeEventsManager implements INativeEventsManager { public updateEvents( prevProps: AnimatedComponentProps ) { - const computedEventTag = this.getEventViewTag(); + const computedEventTag = this.getEventViewTag(true); // If the event view tag changes, we need to completely re-mount all events if (this.#eventViewTag !== computedEventTag) { // Remove all bindings from previous props that ran on the old viewTag @@ -77,23 +77,54 @@ export class NativeEventsManager implements INativeEventsManager { }); } - private getEventViewTag() { + private getEventViewTag(componentUpdate: boolean = false) { // Get the tag for registering events - since the event emitting view can be nested inside the main component const componentAnimatedRef = this.#managedComponent - ._component as AnimatedComponentRef; - let newTag: number; + ._componentRef as AnimatedComponentRef & { + // Fabric + __nativeTag?: number; + // Paper + _nativeTag?: number; + }; if (componentAnimatedRef.getScrollableNode) { + /* + In most cases, getScrollableNode() returns a view tag, and findNodeHandle is not required. + However, to cover more exotic list cases, we will continue to use findNodeHandle + for consistency. For numerical values, findNodeHandle should return the value immediately, + as documented here: https://github.com/facebook/react/blob/91061073d57783c061889ac6720ef1ab7f0c2149/packages/react-native-renderer/src/ReactNativePublicCompat.js#L113 + */ const scrollableNode = componentAnimatedRef.getScrollableNode(); - newTag = findNodeHandle(scrollableNode) ?? -1; - } else { - newTag = - findNodeHandle( - this.#componentOptions?.setNativeProps - ? this.#managedComponent - : componentAnimatedRef - ) ?? -1; + if (typeof scrollableNode === 'number') { + return scrollableNode; + } + return findNodeHandle(scrollableNode) ?? -1; + } + if (this.#componentOptions?.setNativeProps) { + // This case ensures backward compatibility with components that + // have their own setNativeProps method passed as an option. + return findNodeHandle(this.#managedComponent) ?? -1; + } + if (!componentUpdate) { + // On the first render of a component, we may already receive a resolved view tag. + return this.#managedComponent.getComponentViewTag(); + } + if (componentAnimatedRef.__nativeTag || componentAnimatedRef._nativeTag) { + /* + Fast path for native refs, + _nativeTag is used by Paper components, + __nativeTag is used by Fabric components. + */ + return ( + componentAnimatedRef.__nativeTag ?? + componentAnimatedRef._nativeTag ?? + -1 + ); } - return newTag; + /* + When a component is updated, a child could potentially change and have a different + view tag. This can occur with a GestureDetector component. + */ + return findNodeHandle(componentAnimatedRef) ?? -1; } } diff --git a/packages/react-native-reanimated/src/createAnimatedComponent/commonTypes.ts b/packages/react-native-reanimated/src/createAnimatedComponent/commonTypes.ts index edb1c867c23..d48b3d771f4 100644 --- a/packages/react-native-reanimated/src/createAnimatedComponent/commonTypes.ts +++ b/packages/react-native-reanimated/src/createAnimatedComponent/commonTypes.ts @@ -100,15 +100,10 @@ export interface AnimatedComponentRef extends Component { export interface IAnimatedComponentInternal { _styles: StyleProps[] | null; _animatedProps?: Partial>; - /** - * Used for Shared Element Transitions, Layout Animations and Animated Styles. - * It is not related to event handling. - */ - _componentViewTag: number; _isFirstRender: boolean; jestInlineStyle: NestedArray | undefined; jestAnimatedStyle: { value: StyleProps }; - _component: AnimatedComponentRef | HTMLElement | null; + _componentRef: AnimatedComponentRef | HTMLElement | null; _sharedElementTransition: SharedTransition | null; _jsPropsUpdater: IJSPropsUpdater; _InlinePropManager: IInlinePropManager; @@ -117,6 +112,11 @@ export interface IAnimatedComponentInternal { _NativeEventsManager?: INativeEventsManager; _viewInfo?: ViewInfo; context: React.ContextType; + /** + * Used for Shared Element Transitions, Layout Animations and Animated Styles. + * It is not related to event handling. + */ + getComponentViewTag: () => number; } export type NestedArray = T | NestedArray[]; diff --git a/packages/react-native-reanimated/src/createAnimatedComponent/createAnimatedComponent.tsx b/packages/react-native-reanimated/src/createAnimatedComponent/createAnimatedComponent.tsx index 9750bb853d6..762e2693bdc 100644 --- a/packages/react-native-reanimated/src/createAnimatedComponent/createAnimatedComponent.tsx +++ b/packages/react-native-reanimated/src/createAnimatedComponent/createAnimatedComponent.tsx @@ -8,11 +8,10 @@ import type { } from 'react'; import React from 'react'; import { Platform } from 'react-native'; -import { findNodeHandle } from '../platformFunctions/findNodeHandle'; import '../layoutReanimation/animationsManager'; import invariant from 'invariant'; import { adaptViewConfig } from '../ConfigHelper'; -import { RNRenderer } from '../platform-specific/RNRenderer'; +import { findHostInstance } from '../platform-specific/findHostInstance'; import { enableLayoutAnimations } from '../core'; import { SharedTransition } from '../layoutReanimation'; import { LayoutAnimationType } from '../commonTypes'; @@ -125,11 +124,10 @@ export function createAnimatedComponent( { _styles: StyleProps[] | null = null; _animatedProps?: Partial>; - _componentViewTag = -1; _isFirstRender = true; jestInlineStyle: NestedArray | undefined; jestAnimatedStyle: { value: StyleProps } = { value: {} }; - _component: AnimatedComponentRef | HTMLElement | null = null; + _componentRef: AnimatedComponentRef | HTMLElement | null = null; _sharedElementTransition: SharedTransition | null = null; _jsPropsUpdater = new JSPropsUpdater(); _InlinePropManager = new InlinePropManager(); @@ -157,7 +155,6 @@ export function createAnimatedComponent( } componentDidMount() { - this._componentViewTag = this._getComponentViewTag(); if (!IS_WEB) { // It exists only on native platforms. We initialize it here because the ref to the animated component is available only post-mount this._NativeEventsManager = new NativeEventsManager(this, options); @@ -174,7 +171,7 @@ export function createAnimatedComponent( if (IS_WEB) { if (this.props.exiting) { - saveSnapshot(this._component as HTMLElement); + saveSnapshot(this._componentRef as HTMLElement); } if ( @@ -190,11 +187,11 @@ export function createAnimatedComponent( if (!skipEntering) { startWebLayoutAnimation( this.props, - this._component as ReanimatedHTMLElement, + this._componentRef as ReanimatedHTMLElement, LayoutAnimationType.ENTERING ); } else { - (this._component as HTMLElement).style.visibility = 'initial'; + (this._componentRef as HTMLElement).style.visibility = 'initial'; } } @@ -210,7 +207,7 @@ export function createAnimatedComponent( this._configureSharedTransition(true); } this._sharedElementTransition?.unregisterTransition( - this._componentViewTag, + this.getComponentViewTag(), true ); @@ -218,7 +215,7 @@ export function createAnimatedComponent( if ( IS_WEB && - this._component && + this._componentRef && exiting && !getReducedMotionFromConfig(exiting as CustomConfig) ) { @@ -226,7 +223,7 @@ export function createAnimatedComponent( startWebLayoutAnimation( this.props, - this._component as ReanimatedHTMLElement, + this._componentRef as ReanimatedHTMLElement, LayoutAnimationType.EXITING ); } else if (exiting && !IS_WEB && !isFabric()) { @@ -237,7 +234,7 @@ export function createAnimatedComponent( : getReduceMotionFromConfig(); if (!reduceMotionInExiting) { updateLayoutAnimations( - this._componentViewTag, + this.getComponentViewTag(), LayoutAnimationType.EXITING, maybeBuild( exiting, @@ -249,31 +246,33 @@ export function createAnimatedComponent( } } - _getComponentViewTag() { + getComponentViewTag() { return this._getViewInfo().viewTag as number; } _detachStyles() { - if (this._componentViewTag !== -1 && this._styles !== null) { + const viewTag = this.getComponentViewTag(); + if (viewTag !== -1 && this._styles !== null) { for (const style of this._styles) { - style.viewDescriptors.remove(this._componentViewTag); + style.viewDescriptors.remove(viewTag); } if (this.props.animatedProps?.viewDescriptors) { - this.props.animatedProps.viewDescriptors.remove( - this._componentViewTag - ); + this.props.animatedProps.viewDescriptors.remove(viewTag); } if (isFabric()) { - removeFromPropsRegistry(this._componentViewTag); + removeFromPropsRegistry(viewTag); } } } _updateFromNative(props: StyleProps) { if (options?.setNativeProps) { - options.setNativeProps(this._component as AnimatedComponentRef, props); + options.setNativeProps( + this._componentRef as AnimatedComponentRef, + props + ); } else { - (this._component as AnimatedComponentRef)?.setNativeProps?.(props); + (this._componentRef as AnimatedComponentRef)?.setNativeProps?.(props); } } @@ -286,24 +285,22 @@ export function createAnimatedComponent( let viewName: string | null; let shadowNodeWrapper: ShadowNodeWrapper | null = null; let viewConfig; - // Component can specify ref which should be animated when animated version of the component is created. - // Otherwise, we animate the component itself. - const component = (this._component as AnimatedComponentRef) - ?.getAnimatableRef - ? (this._component as AnimatedComponentRef).getAnimatableRef?.() - : this; if (SHOULD_BE_USE_WEB) { // At this point I assume that `_setComponentRef` was already called and `_component` is set. // `this._component` on web represents HTMLElement of our component, that's why we use casting - viewTag = this._component as HTMLElement; + viewTag = this._componentRef as HTMLElement; viewName = null; shadowNodeWrapper = null; viewConfig = null; } else { - // hostInstance can be null for a component that doesn't render anything (render function returns null). Example: svg Stop: https://github.com/react-native-svg/react-native-svg/blob/develop/src/elements/Stop.tsx - const hostInstance = RNRenderer.findHostInstance_DEPRECATED(component); + const hostInstance = findHostInstance(this); if (!hostInstance) { + /* + findHostInstance can return null for a component that doesn't render anything + (render function returns null). Example: + svg Stop: https://github.com/react-native-svg/react-native-svg/blob/develop/src/elements/Stop.tsx + */ throw new ReanimatedError( 'Cannot find host instance for this component. Maybe it renders nothing?' ); @@ -314,7 +311,7 @@ export function createAnimatedComponent( viewName = viewInfo.viewName; viewConfig = viewInfo.viewConfig; shadowNodeWrapper = isFabric() - ? getShadowNodeWrapperFromRef(this) + ? getShadowNodeWrapperFromRef(this, hostInstance) : null; } this._viewInfo = { viewTag, viewName, shadowNodeWrapper, viewConfig }; @@ -341,8 +338,6 @@ export function createAnimatedComponent( adaptViewConfig(viewConfig); } - this._componentViewTag = viewTag as number; - // remove old styles if (prevStyles) { // in most of the cases, views have only a single animated style and it remains unchanged @@ -422,7 +417,7 @@ export function createAnimatedComponent( this._InlinePropManager.attachInlineProps(this, this._getViewInfo()); if (IS_WEB && this.props.exiting) { - saveSnapshot(this._component as HTMLElement); + saveSnapshot(this._componentRef as HTMLElement); } // Snapshot won't be undefined because it comes from getSnapshotBeforeUpdate method @@ -434,7 +429,7 @@ export function createAnimatedComponent( ) { tryActivateLayoutTransition( this.props, - this._component as ReanimatedHTMLElement, + this._componentRef as ReanimatedHTMLElement, snapshot ); } @@ -453,7 +448,7 @@ export function createAnimatedComponent( ) : undefined; updateLayoutAnimations( - this._componentViewTag, + this.getComponentViewTag(), LayoutAnimationType.LAYOUT, layout ); @@ -467,7 +462,7 @@ export function createAnimatedComponent( const { sharedTransitionTag } = this.props; if (!sharedTransitionTag) { this._sharedElementTransition?.unregisterTransition( - this._componentViewTag, + this.getComponentViewTag(), isUnmounting ); this._sharedElementTransition = null; @@ -478,34 +473,42 @@ export function createAnimatedComponent( this._sharedElementTransition ?? new SharedTransition(); sharedElementTransition.registerTransition( - this._componentViewTag, + this.getComponentViewTag(), sharedTransitionTag, isUnmounting ); this._sharedElementTransition = sharedElementTransition; } + _resolveComponentRef = (ref: Component | HTMLElement | null) => { + const componentRef = ref as AnimatedComponentRef; + // Component can specify ref which should be animated when animated version of the component is created. + // Otherwise, we animate the component itself. + if (componentRef && componentRef.getAnimatableRef) { + return componentRef.getAnimatableRef(); + } + return componentRef; + }; + _setComponentRef = setAndForwardRef({ getForwardedRef: () => this.props.forwardedRef as MutableRefObject< Component, Record, unknown> >, setLocalRef: (ref) => { - // TODO update config - - const tag = findNodeHandle(ref as Component); - - // callback refs are executed twice - when the component mounts with ref, - // and with null when it unmounts - if (tag !== null) { - this._componentViewTag = tag; + if (!ref) { + // component has been unmounted + return; + } + if (ref !== this._componentRef) { + this._componentRef = this._resolveComponentRef(ref); + // if ref is changed, reset viewInfo + this._viewInfo = undefined; } + const tag = this.getComponentViewTag(); const { layout, entering, exiting, sharedTransitionTag } = this.props; - if ( - (layout || entering || exiting || sharedTransitionTag) && - tag != null - ) { + if (layout || entering || exiting || sharedTransitionTag) { if (!SHOULD_BE_USE_WEB) { enableLayoutAnimations(true, false); } @@ -545,10 +548,6 @@ export function createAnimatedComponent( ); } } - - if (ref !== this._component) { - this._component = ref; - } }, }); @@ -558,9 +557,9 @@ export function createAnimatedComponent( getSnapshotBeforeUpdate() { if ( IS_WEB && - (this._component as HTMLElement)?.getBoundingClientRect !== undefined + (this._componentRef as HTMLElement)?.getBoundingClientRect !== undefined ) { - return (this._component as HTMLElement).getBoundingClientRect(); + return (this._componentRef as HTMLElement).getBoundingClientRect(); } return null; diff --git a/packages/react-native-reanimated/src/fabricUtils.ts b/packages/react-native-reanimated/src/fabricUtils.ts index a872b9a2167..e6eff46e125 100644 --- a/packages/react-native-reanimated/src/fabricUtils.ts +++ b/packages/react-native-reanimated/src/fabricUtils.ts @@ -2,25 +2,19 @@ /* eslint-disable */ import type { ShadowNodeWrapper } from './commonTypes'; +import { + findHostInstance, + HostInstance, +} from './platform-specific/findHostInstance'; -let findHostInstance_DEPRECATED: (ref: unknown) => void; let getInternalInstanceHandleFromPublicInstance: (ref: unknown) => { stateNode: { node: unknown }; }; export function getShadowNodeWrapperFromRef( - ref: React.Component + ref: React.Component, + hostInstance?: HostInstance ): ShadowNodeWrapper { - // load findHostInstance_DEPRECATED lazily because it may not be available before render - if (findHostInstance_DEPRECATED === undefined) { - try { - findHostInstance_DEPRECATED = - require('react-native/Libraries/Renderer/shims/ReactFabric').findHostInstance_DEPRECATED; - } catch (e) { - findHostInstance_DEPRECATED = (_ref: unknown) => null; - } - } - if (getInternalInstanceHandleFromPublicInstance === undefined) { try { getInternalInstanceHandleFromPublicInstance = @@ -50,9 +44,9 @@ export function getShadowNodeWrapperFromRef( } else if (textInputRef) { resolvedRef = textInputRef; } else { - resolvedRef = getInternalInstanceHandleFromPublicInstance( - findHostInstance_DEPRECATED(ref) - ).stateNode.node; + const instance = hostInstance ?? findHostInstance(ref); + resolvedRef = + getInternalInstanceHandleFromPublicInstance(instance).stateNode.node; } return resolvedRef; diff --git a/packages/react-native-reanimated/src/platform-specific/RNRenderer.ts b/packages/react-native-reanimated/src/platform-specific/RNRenderer.ts deleted file mode 100644 index cc5c78a5005..00000000000 --- a/packages/react-native-reanimated/src/platform-specific/RNRenderer.ts +++ /dev/null @@ -1,4 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck -'use strict'; -export { default as RNRenderer } from 'react-native/Libraries/Renderer/shims/ReactNative'; diff --git a/packages/react-native-reanimated/src/platform-specific/RNRenderer.web.ts b/packages/react-native-reanimated/src/platform-specific/RNRenderer.web.ts deleted file mode 100644 index f95b74d4322..00000000000 --- a/packages/react-native-reanimated/src/platform-specific/RNRenderer.web.ts +++ /dev/null @@ -1,4 +0,0 @@ -'use strict'; -// RNRender is not used for web. An export is still defined to eliminate warnings from bundlers such as esbuild. -const RNRenderer = {}; -export { RNRenderer }; diff --git a/packages/react-native-reanimated/src/platform-specific/findHostInstance.ts b/packages/react-native-reanimated/src/platform-specific/findHostInstance.ts new file mode 100644 index 00000000000..00d56154e40 --- /dev/null +++ b/packages/react-native-reanimated/src/platform-specific/findHostInstance.ts @@ -0,0 +1,77 @@ +/* eslint-disable camelcase */ +'use strict'; + +import type { IAnimatedComponentInternal } from '../createAnimatedComponent/commonTypes'; +import { ReanimatedError } from '../errors'; +import { isFabric } from '../PlatformChecker'; + +type HostInstanceFabric = { + __internalInstanceHandle?: Record; + __nativeTag?: number; + _viewConfig?: Record; +}; + +type HostInstancePaper = { + _nativeTag?: number; + viewConfig?: Record; +}; + +export type HostInstance = HostInstanceFabric & HostInstancePaper; + +function findHostInstanceFastPath(maybeNativeRef: HostInstance) { + if ( + maybeNativeRef.__internalInstanceHandle && + maybeNativeRef.__nativeTag && + maybeNativeRef._viewConfig + ) { + // This is a native ref to a Fabric component + return maybeNativeRef; + } + if (maybeNativeRef._nativeTag && maybeNativeRef.viewConfig) { + // This is a native ref to a Paper component + return maybeNativeRef; + } + // That means it’s a ref to a non-native component, and it’s necessary + // to call `findHostInstance_DEPRECATED` on them. + return undefined; +} + +function resolveFindHostInstance_DEPRECATED() { + if (findHostInstance_DEPRECATED !== undefined) { + return; + } + if (isFabric()) { + try { + findHostInstance_DEPRECATED = + require('react-native/Libraries/Renderer/shims/ReactFabric').findHostInstance_DEPRECATED; + } catch (e) { + throw new ReanimatedError( + 'Failed to resolve findHostInstance_DEPRECATED' + ); + } + } else { + findHostInstance_DEPRECATED = + require('react-native/Libraries/Renderer/shims/ReactNative').findHostInstance_DEPRECATED; + } +} + +let findHostInstance_DEPRECATED: (ref: unknown) => HostInstance; +export function findHostInstance( + component: IAnimatedComponentInternal | React.Component +): HostInstance { + // Fast path for native refs + const hostInstance = findHostInstanceFastPath( + (component as IAnimatedComponentInternal)._componentRef as HostInstance + ); + if (hostInstance !== undefined) { + return hostInstance; + } + + resolveFindHostInstance_DEPRECATED(); + // Fabric implementation of findHostInstance_DEPRECATED doesn't accept a ref as an argument + return findHostInstance_DEPRECATED( + isFabric() + ? component + : (component as IAnimatedComponentInternal)._componentRef + ); +} diff --git a/packages/react-native-reanimated/src/platform-specific/findHostInstance.web.ts b/packages/react-native-reanimated/src/platform-specific/findHostInstance.web.ts new file mode 100644 index 00000000000..ca342dfd2d4 --- /dev/null +++ b/packages/react-native-reanimated/src/platform-specific/findHostInstance.web.ts @@ -0,0 +1,3 @@ +'use strict'; + +export function findHostInstance(_component: any): void {} From 07ac12b434e3e9aa42bc608476e5f9638c22001f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Frederiksen?= Date: Wed, 4 Dec 2024 12:46:26 +0100 Subject: [PATCH 20/36] docs: fix `useEvent` typos, tweak wording of main `README` opening summary (#6690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary This pull request makes 2 changes to the library's documentation: 1. In `useEvent` (versions 2 and 3), some typos, grammar details and instances of missing articles were corrected. 2. In the library's main `README`, it tweaks the wording of the document's opening summary to make it more clear and more fluent in its expression. I think `1` will be uncontroversial, but you might want to revert `2` if I've misunderstood what the author was trying to say. (Just noticed these things while reading the documentation this evening. Please take, edit and use these proposed changes as you see fit 🙏) --------- Co-authored-by: Kacper Kapuściak <39658211+kacperkapusciak@users.noreply.github.com> --- README.md | 6 +++--- packages/docs-reanimated/docs/advanced/useEvent.mdx | 10 +++++----- .../versioned_docs/version-2.x/api/hooks/useEvent.md | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index ab1de80b334..d7d5b17a312 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ > Reanimated 3 is here! Check out our [documentation page](https://docs.swmansion.com/react-native-reanimated/) for more information React Native Reanimated provides a more comprehensive, -low level abstraction for the Animated library API to be built -on top of and hence allow for much greater flexibility especially when it -comes to gesture based interactions. +low-level abstraction for the Animated library API on which to build, +allowing for much greater flexibility, especially when it comes to +gesture-based interactions. ### Nightly CI state diff --git a/packages/docs-reanimated/docs/advanced/useEvent.mdx b/packages/docs-reanimated/docs/advanced/useEvent.mdx index 83ffc0d98b8..2525a6d5b8b 100644 --- a/packages/docs-reanimated/docs/advanced/useEvent.mdx +++ b/packages/docs-reanimated/docs/advanced/useEvent.mdx @@ -4,7 +4,7 @@ sidebar_position: 4 # useEvent -`useEvent` is a low-level hook. It returns event handler that will be called when native event occurs. You can use it to create custom event handler hooks, like [`useScrollViewOffset`](/docs/scroll/useScrollViewOffset/) or [`useAnimatedScrollHandler`](/docs/scroll/useAnimatedScrollHandler/). +`useEvent` is a low-level hook. It returns an event handler that will be called when a native event occurs. You can use it to create custom event handler hooks, like [`useScrollViewOffset`](/docs/scroll/useScrollViewOffset/) or [`useAnimatedScrollHandler`](/docs/scroll/useAnimatedScrollHandler/). ## Reference @@ -63,22 +63,22 @@ type EventHandlerProcessed< #### `handler` -Function that receives event object with native payload, that can be passed to custom handler hook's worklets. +Function that receives an event object with a native payload, which can be passed to the custom handler hook's worklets. - `event` - event object. The payload can differ depending on the type of the event. #### `eventNames` -Array of event names that will be handled by handler. +Array of event names that will be handled by the handler. #### `rebuild` -Value indicating whether handler should be rebuilt. +Value indicating whether the handler should be rebuilt. ### Returns -The hook returns event handler that will be invoked when native event is dispatched. That handler may be connected to multiple components and will be invoked for each one's specific events. +The hook returns an event handler that will be invoked when a native event is dispatched. That handler may be connected to multiple components and will be invoked for each one's specific events. ## Example diff --git a/packages/docs-reanimated/versioned_docs/version-2.x/api/hooks/useEvent.md b/packages/docs-reanimated/versioned_docs/version-2.x/api/hooks/useEvent.md index 15325f7fd43..8abbbd924ac 100644 --- a/packages/docs-reanimated/versioned_docs/version-2.x/api/hooks/useEvent.md +++ b/packages/docs-reanimated/versioned_docs/version-2.x/api/hooks/useEvent.md @@ -4,13 +4,13 @@ title: useEvent sidebar_label: useEvent --- -This is low-level hook returning event handler that will be invoked with native events, which should be used in order to create custom event handler hook like `useAnimatedGestureHandler` or `useAnimatedScrollHandler`. +This is a low-level hook returning an event handler that will be invoked with native events, which should be used in order to create custom event handler hooks, like `useAnimatedGestureHandler` or `useAnimatedScrollHandler`. ### Arguments #### `handler` [function] -Handler will receive event object with native payload, that can be passed to custom handler hook's worklets. +Handler that will receive an event object with a native payload, which can be passed to the custom handler hook's worklets. - `event` [object] - event object. The payload can differ depending on the type of the event. @@ -21,11 +21,11 @@ Array of event names that will be handled by handler. #### `rebuilt` [boolean] -Value indicating whether handler should be rebuilt. +Value indicating whether the handler should be rebuilt. ### Returns -The hook returns event handler that will be invoked when native event is dispatched. +The hook returns an event handler that will be invoked when a native event is dispatched. ## Example From 5ffa3bbe44cd061f6ff5a08c2d202f7fc579fc91 Mon Sep 17 00:00:00 2001 From: Alec Mather Date: Wed, 4 Dec 2024 06:54:04 -0600 Subject: [PATCH 21/36] fix: Empty array & null checks in handleTabNavigatorChange method fixes #6698 (#6700) Fixes: Shared Element Transition (Solution provided) #6698 Add safety checks in handleTabNavigatorChange to prevent crash This fixes a crash that occurs when _disappearingScreens array is empty or contains invalid objects by adding appropriate null checks and bounds checking. The crash would occur when: - The _disappearingScreens array is empty - navTabScreen or its reactSuperview is null - targetScreen is null App was crashing during shared element transition because of invalid array access. Fixes #6698 --------- Co-authored-by: Krzysztof Piaskowy --- .../REASharedTransitionManager.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/react-native-reanimated/apple/reanimated/apple/LayoutReanimation/REASharedTransitionManager.m b/packages/react-native-reanimated/apple/reanimated/apple/LayoutReanimation/REASharedTransitionManager.m index 1bf674b1d6b..7e35f1bbdbd 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/LayoutReanimation/REASharedTransitionManager.m +++ b/packages/react-native-reanimated/apple/reanimated/apple/LayoutReanimation/REASharedTransitionManager.m @@ -576,10 +576,26 @@ - (void)handleTabNavigatorChange:(REAUIView *)layoutedScreen return; } + // Add safety check for disappearing screens + if ([_disappearingScreens count] == 0) { + return; + } + REAUIView *navTabScreen = _disappearingScreens[0]; REAUIView *sourceScreen = _disappearingScreens[[_disappearingScreens count] - 1]; + + // Add null checks + if (!navTabScreen || !navTabScreen.reactSuperview) { + return; + } + REAUIView *targetTabScreen = [REAScreensHelper getActiveTabForTabNavigator:navTabScreen.reactSuperview]; REAUIView *targetScreen = [REAScreensHelper findTopScreenInChildren:targetTabScreen]; + + if (!targetScreen) { + return; + } + if (!layoutedScreen && _isTabNavigator) { // just wait for the next layout computation for your screen return; From 135e431a688d87471e26497f705eb72778561e98 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Wed, 4 Dec 2024 17:50:46 +0100 Subject: [PATCH 22/36] fix: brownfield integration (#6774) ## Summary In brownfield, ` // we need only one instance because SurfacePresenter is the same during the application lifetime` is false since you can destroy RN and create it again. ## Test plan Run Reanimated in brownfield and try to create and destroy the whole RN a couple of times. --- .../apple/Fabric/REAInitializerRCTFabricSurface.h | 2 +- .../apple/reanimated/apple/REAModule.mm | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/react-native-reanimated/apple/reanimated/apple/Fabric/REAInitializerRCTFabricSurface.h b/packages/react-native-reanimated/apple/reanimated/apple/Fabric/REAInitializerRCTFabricSurface.h index bd8143b8a55..c27c2106790 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/Fabric/REAInitializerRCTFabricSurface.h +++ b/packages/react-native-reanimated/apple/reanimated/apple/Fabric/REAInitializerRCTFabricSurface.h @@ -5,7 +5,7 @@ @interface REAInitializerRCTFabricSurface : RCTFabricSurface -@property REAModule *reaModule; +@property __weak REAModule *reaModule; @end diff --git a/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm b/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm index 5ee5b74c4f7..9b48d8557f2 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm +++ b/packages/react-native-reanimated/apple/reanimated/apple/REAModule.mm @@ -193,9 +193,10 @@ - (void)setBridge:(RCTBridge *)bridge - (void)setReaSurfacePresenter { - if (reaSurface == nil) { - // we need only one instance because SurfacePresenter is the same during the application lifetime - reaSurface = [[REAInitializerRCTFabricSurface alloc] init]; + if (_surfacePresenter && ![_surfacePresenter surfaceForRootTag:reaSurface.rootTag]) { + if (!reaSurface) { + reaSurface = [[REAInitializerRCTFabricSurface alloc] init]; + } [_surfacePresenter registerSurface:reaSurface]; } reaSurface.reaModule = self; From 0445ac6dee5b4f3b4f6fcde5f774b837ec3bfa0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20=C5=BBelawski?= <40713406+tjzel@users.noreply.github.com> Date: Fri, 6 Dec 2024 10:26:14 +0100 Subject: [PATCH 23/36] refactor(Worklets): move PlatformLogger (#6794) ## Summary `PlatformLogger` remained in Reanimated during early steps of establishing Worklets Module due to how difficult it was to move it back then. Now it's very simple, so let's do it. ## Test plan See in app if `LogExample` works. --- .../NativeModules/ReanimatedModuleProxy.cpp | 2 -- .../ReanimatedWorkletRuntimeDecorator.cpp | 19 ------------------- .../ReanimatedWorkletRuntimeDecorator.h | 14 -------------- .../Tools/PlatformLogger.h | 4 ++-- .../WorkletRuntimeDecorator.cpp | 6 ++++++ .../android/PlatformLogger.cpp | 8 ++++---- .../apple}/PlatformLogger.mm | 6 +++--- 7 files changed, 15 insertions(+), 44 deletions(-) delete mode 100644 packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.cpp delete mode 100644 packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.h rename packages/react-native-reanimated/Common/cpp/{reanimated => worklets}/Tools/PlatformLogger.h (83%) rename packages/react-native-reanimated/android/src/main/cpp/{reanimated => worklets}/android/PlatformLogger.cpp (78%) rename packages/react-native-reanimated/apple/{reanimated/apple/native => worklets/apple}/PlatformLogger.mm (82%) diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp index 2be3ac637e8..77f6d501aef 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -242,7 +241,6 @@ jsi::Value ReanimatedModuleProxy::createWorkletRuntime( auto initializerShareable = extractShareableOrThrow( rt, initializer, "[Reanimated] Initializer must be a worklet."); workletRuntime->runGuarded(initializerShareable); - ReanimatedWorkletRuntimeDecorator::decorate(workletRuntime->getJSIRuntime()); return jsi::Object::createFromHostObject(rt, workletRuntime); } diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.cpp deleted file mode 100644 index acd03e73677..00000000000 --- a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -#include -#include -#include - -namespace reanimated { - -using namespace worklets; - -void ReanimatedWorkletRuntimeDecorator::decorate(jsi::Runtime &rt) { - jsi_utils::installJsiFunction( - rt, "_log", [](jsi::Runtime &rt, const jsi::Value &value) { - PlatformLogger::log(stringifyJSIValue(rt, value)); - }); -} - -} // namespace reanimated diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.h b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.h deleted file mode 100644 index da7f2a923cd..00000000000 --- a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/ReanimatedWorkletRuntimeDecorator.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include - -using namespace facebook; - -namespace reanimated { - -class ReanimatedWorkletRuntimeDecorator { - public: - static void decorate(jsi::Runtime &rt); -}; - -} // namespace reanimated diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/Tools/PlatformLogger.h b/packages/react-native-reanimated/Common/cpp/worklets/Tools/PlatformLogger.h similarity index 83% rename from packages/react-native-reanimated/Common/cpp/reanimated/Tools/PlatformLogger.h rename to packages/react-native-reanimated/Common/cpp/worklets/Tools/PlatformLogger.h index 37db18e3326..de58cb93098 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/Tools/PlatformLogger.h +++ b/packages/react-native-reanimated/Common/cpp/worklets/Tools/PlatformLogger.h @@ -2,7 +2,7 @@ #include -namespace reanimated { +namespace worklets { class PlatformLogger { public: @@ -13,4 +13,4 @@ class PlatformLogger { static void log(const bool b); }; -} // namespace reanimated +} // namespace worklets diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp index 07caee39767..4d677927155 100644 --- a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +++ b/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -76,6 +77,11 @@ void WorkletRuntimeDecorator::decorate( evalWithSourceUrl)); #endif // NDEBUG + jsi_utils::installJsiFunction( + rt, "_log", [](jsi::Runtime &rt, const jsi::Value &value) { + PlatformLogger::log(stringifyJSIValue(rt, value)); + }); + jsi_utils::installJsiFunction( rt, "_toString", [](jsi::Runtime &rt, const jsi::Value &value) { return jsi::String::createFromUtf8(rt, stringifyJSIValue(rt, value)); diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/PlatformLogger.cpp b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/PlatformLogger.cpp similarity index 78% rename from packages/react-native-reanimated/android/src/main/cpp/reanimated/android/PlatformLogger.cpp rename to packages/react-native-reanimated/android/src/main/cpp/worklets/android/PlatformLogger.cpp index 03495d35a03..e931aa904a4 100644 --- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/PlatformLogger.cpp +++ b/packages/react-native-reanimated/android/src/main/cpp/worklets/android/PlatformLogger.cpp @@ -1,10 +1,10 @@ #include -#include +#include -constexpr const auto tag = "Reanimated"; +constexpr const auto tag = "Worklets"; -namespace reanimated { +namespace worklets { void PlatformLogger::log(const char *str) { __android_log_print(ANDROID_LOG_VERBOSE, tag, "%s", str); @@ -26,4 +26,4 @@ void PlatformLogger::log(const bool b) { log(b ? "true" : "false"); } -} // namespace reanimated +} // namespace worklets diff --git a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformLogger.mm b/packages/react-native-reanimated/apple/worklets/apple/PlatformLogger.mm similarity index 82% rename from packages/react-native-reanimated/apple/reanimated/apple/native/PlatformLogger.mm rename to packages/react-native-reanimated/apple/worklets/apple/PlatformLogger.mm index bca68ec2dd3..129180e05c5 100644 --- a/packages/react-native-reanimated/apple/reanimated/apple/native/PlatformLogger.mm +++ b/packages/react-native-reanimated/apple/worklets/apple/PlatformLogger.mm @@ -1,7 +1,7 @@ #import -#import +#import -namespace reanimated { +namespace worklets { void PlatformLogger::log(const char *str) { @@ -28,4 +28,4 @@ log(b ? "true" : "false"); } -} // namespace reanimated +} // namespace worklets From 48785970173235514eb81b2b7b5084ff3986129c Mon Sep 17 00:00:00 2001 From: Krzysztof Piaskowy Date: Fri, 6 Dec 2024 14:48:02 +0100 Subject: [PATCH 24/36] Cache `worklets` (#6758) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Currently, every time we want to execute a shareable worklet, we need to call `toJSValue()` to convert Reanimated's Shareable into a runnable JavaScript function. This operation can be quite expensive for larger methods that have many dependencies in their closure (such as objects and other worklets). Previously, the result of `toJSValue()` wasn't cached, which meant we had to convert the same shareable multiple times, especially on every call to `runOnUI()` and in response to events - potentially on every frame. This happens because the part of the code - `runGuarded` - is called frequently. You can see this code [here](https://github.com/software-mansion/react-native-reanimated/blob/3.17.0-rc.0/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h#L36). This PR introduces the retention of all worklets and caches the result of `toJSValue()` per runtime. ⚠️ This change is potentially risky, and it's challenging to predict if there are any edge cases where caching everything might not be appropriate. However, at this moment, we haven't found any regressions related to memory issues or crashes. ⚠️ This PR changes the default behavior of worklets. Previously, worklets were stateless and destroyed their closure after every invocation, but now the closure will persist as long as the worklet lives. #### stateless vs stateful example ```js export default function Example() { let counter = {value: 0}; const workletFunction = () => { 'worklet'; counter.value++; console.log(counter); }; return