react-native-reanimated 3.17.0 → 3.17.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/Common/cpp/reanimated/Fabric/PropsRegistry.cpp +27 -0
  2. package/Common/cpp/reanimated/Fabric/PropsRegistry.h +9 -0
  3. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +11 -6
  4. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +48 -46
  5. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +10 -4
  6. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp +31 -0
  7. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h +10 -0
  8. package/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp +8 -0
  9. package/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp +1 -3
  10. package/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h +1 -1
  11. package/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +1 -5
  12. package/Common/cpp/worklets/Tools/ReanimatedJSIUtils.h +25 -0
  13. package/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  14. package/android/src/fabric/java/com/swmansion/reanimated/NativeProxy.java +14 -2
  15. package/android/src/fabric/java/com/swmansion/reanimated/ReaCompatibility.java +0 -5
  16. package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +2 -23
  17. package/android/src/main/cpp/reanimated/android/NativeProxy.h +0 -6
  18. package/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp +2 -2
  19. package/android/src/main/java/com/swmansion/reanimated/NodesManager.java +0 -4
  20. package/android/src/main/java/com/swmansion/reanimated/nativeProxy/NativeProxyCommon.java +0 -6
  21. package/android/src/main/java/com/swmansion/worklets/WorkletsModule.java +16 -5
  22. package/android/src/paper/java/com/swmansion/reanimated/NativeProxy.java +14 -2
  23. package/android/src/paper/java/com/swmansion/reanimated/ReaCompatibility.java +0 -3
  24. package/apple/reanimated/apple/REAModule.mm +15 -0
  25. package/apple/reanimated/apple/REANodesManager.h +0 -1
  26. package/apple/reanimated/apple/REANodesManager.mm +1 -20
  27. package/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.h +0 -3
  28. package/apple/reanimated/apple/native/PlatformDepMethodsHolderImpl.mm +1 -20
  29. package/lib/module/Easing.js.map +1 -1
  30. package/lib/module/PlatformChecker.js +4 -0
  31. package/lib/module/PlatformChecker.js.map +1 -1
  32. package/lib/module/ReanimatedModule/NativeReanimated.js +46 -2
  33. package/lib/module/ReanimatedModule/NativeReanimated.js.map +1 -1
  34. package/lib/module/ReanimatedModule/js-reanimated/JSReanimated.js +6 -0
  35. package/lib/module/ReanimatedModule/js-reanimated/JSReanimated.js.map +1 -1
  36. package/lib/module/UpdateProps.js +3 -3
  37. package/lib/module/UpdateProps.js.map +1 -1
  38. package/lib/module/animation/styleAnimation.js +9 -3
  39. package/lib/module/animation/styleAnimation.js.map +1 -1
  40. package/lib/module/animation/util.js +31 -10
  41. package/lib/module/animation/util.js.map +1 -1
  42. package/lib/module/commonTypes.js.map +1 -1
  43. package/lib/module/component/FlatList.js +11 -19
  44. package/lib/module/component/FlatList.js.map +1 -1
  45. package/lib/module/component/LayoutAnimationConfig.js +9 -10
  46. package/lib/module/component/LayoutAnimationConfig.js.map +1 -1
  47. package/lib/module/component/PerformanceMonitor.js +10 -21
  48. package/lib/module/component/PerformanceMonitor.js.map +1 -1
  49. package/lib/module/component/ScrollView.js +4 -6
  50. package/lib/module/component/ScrollView.js.map +1 -1
  51. package/lib/module/core.js +6 -0
  52. package/lib/module/core.js.map +1 -1
  53. package/lib/module/createAnimatedComponent/PropsFilter.js +3 -2
  54. package/lib/module/createAnimatedComponent/PropsFilter.js.map +1 -1
  55. package/lib/module/createAnimatedComponent/createAnimatedComponent.js +54 -29
  56. package/lib/module/createAnimatedComponent/createAnimatedComponent.js.map +1 -1
  57. package/lib/module/createAnimatedComponent/setAndForwardRef.js +2 -0
  58. package/lib/module/createAnimatedComponent/setAndForwardRef.js.map +1 -1
  59. package/lib/module/hook/useAnimatedRef.js +1 -1
  60. package/lib/module/hook/useAnimatedRef.js.map +1 -1
  61. package/lib/module/hook/useAnimatedStyle.js +7 -7
  62. package/lib/module/hook/useAnimatedStyle.js.map +1 -1
  63. package/lib/module/jestUtils.js +40 -20
  64. package/lib/module/jestUtils.js.map +1 -1
  65. package/lib/module/layoutReanimation/animationBuilder/ComplexAnimationBuilder.js.map +1 -1
  66. package/lib/module/layoutReanimation/animationBuilder/Keyframe.js.map +1 -1
  67. package/lib/module/layoutReanimation/defaultTransitions/CurvedTransition.js.map +1 -1
  68. package/lib/module/platform-specific/findHostInstance.js +1 -1
  69. package/lib/module/platform-specific/findHostInstance.js.map +1 -1
  70. package/lib/module/platform-specific/jsVersion.js +1 -1
  71. package/lib/module/processBoxShadow.js +1 -0
  72. package/lib/module/processBoxShadow.js.map +1 -1
  73. package/lib/module/reactUtils.js +23 -7
  74. package/lib/module/reactUtils.js.map +1 -1
  75. package/lib/typescript/Easing.d.ts +1 -3
  76. package/lib/typescript/Easing.d.ts.map +1 -1
  77. package/lib/typescript/PlatformChecker.d.ts +1 -0
  78. package/lib/typescript/PlatformChecker.d.ts.map +1 -1
  79. package/lib/typescript/ReanimatedModule/NativeReanimated.d.ts.map +1 -1
  80. package/lib/typescript/ReanimatedModule/js-reanimated/JSReanimated.d.ts.map +1 -1
  81. package/lib/typescript/ReanimatedModule/reanimatedModuleProxy.d.ts +2 -0
  82. package/lib/typescript/ReanimatedModule/reanimatedModuleProxy.d.ts.map +1 -1
  83. package/lib/typescript/UpdateProps.d.ts +1 -1
  84. package/lib/typescript/UpdateProps.d.ts.map +1 -1
  85. package/lib/typescript/animation/styleAnimation.d.ts.map +1 -1
  86. package/lib/typescript/animation/util.d.ts +3 -1
  87. package/lib/typescript/animation/util.d.ts.map +1 -1
  88. package/lib/typescript/commonTypes.d.ts +3 -2
  89. package/lib/typescript/commonTypes.d.ts.map +1 -1
  90. package/lib/typescript/component/FlatList.d.ts.map +1 -1
  91. package/lib/typescript/component/LayoutAnimationConfig.d.ts +1 -1
  92. package/lib/typescript/component/LayoutAnimationConfig.d.ts.map +1 -1
  93. package/lib/typescript/component/ScrollView.d.ts.map +1 -1
  94. package/lib/typescript/core.d.ts +3 -1
  95. package/lib/typescript/core.d.ts.map +1 -1
  96. package/lib/typescript/createAnimatedComponent/PropsFilter.d.ts.map +1 -1
  97. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +6 -2
  98. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts.map +1 -1
  99. package/lib/typescript/createAnimatedComponent/createAnimatedComponent.d.ts.map +1 -1
  100. package/lib/typescript/createAnimatedComponent/setAndForwardRef.d.ts +2 -3
  101. package/lib/typescript/createAnimatedComponent/setAndForwardRef.d.ts.map +1 -1
  102. package/lib/typescript/hook/commonTypes.d.ts +4 -3
  103. package/lib/typescript/hook/commonTypes.d.ts.map +1 -1
  104. package/lib/typescript/hook/useAnimatedStyle.d.ts.map +1 -1
  105. package/lib/typescript/jestUtils.d.ts +1 -0
  106. package/lib/typescript/jestUtils.d.ts.map +1 -1
  107. package/lib/typescript/layoutReanimation/animationBuilder/ComplexAnimationBuilder.d.ts +4 -3
  108. package/lib/typescript/layoutReanimation/animationBuilder/ComplexAnimationBuilder.d.ts.map +1 -1
  109. package/lib/typescript/layoutReanimation/animationBuilder/Keyframe.d.ts.map +1 -1
  110. package/lib/typescript/layoutReanimation/defaultTransitions/CurvedTransition.d.ts +13 -12
  111. package/lib/typescript/layoutReanimation/defaultTransitions/CurvedTransition.d.ts.map +1 -1
  112. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  113. package/lib/typescript/processBoxShadow.d.ts.map +1 -1
  114. package/lib/typescript/reactUtils.d.ts +2 -0
  115. package/lib/typescript/reactUtils.d.ts.map +1 -1
  116. package/package.json +14 -14
  117. package/plugin/index.js +2 -2
  118. package/src/Easing.ts +1 -1
  119. package/src/PlatformChecker.ts +5 -0
  120. package/src/ReanimatedModule/NativeReanimated.ts +56 -2
  121. package/src/ReanimatedModule/js-reanimated/JSReanimated.ts +13 -0
  122. package/src/ReanimatedModule/reanimatedModuleProxy.ts +3 -0
  123. package/src/UpdateProps.ts +3 -3
  124. package/src/animation/styleAnimation.ts +18 -7
  125. package/src/animation/util.ts +37 -9
  126. package/src/commonTypes.ts +3 -2
  127. package/src/component/FlatList.tsx +5 -2
  128. package/src/component/LayoutAnimationConfig.tsx +8 -5
  129. package/src/component/ScrollView.tsx +3 -2
  130. package/src/core.ts +9 -0
  131. package/src/createAnimatedComponent/PropsFilter.tsx +3 -3
  132. package/src/createAnimatedComponent/commonTypes.ts +4 -2
  133. package/src/createAnimatedComponent/createAnimatedComponent.tsx +85 -33
  134. package/src/createAnimatedComponent/setAndForwardRef.ts +4 -5
  135. package/src/hook/commonTypes.ts +6 -3
  136. package/src/hook/useAnimatedRef.ts +1 -1
  137. package/src/hook/useAnimatedStyle.ts +27 -10
  138. package/src/jestUtils.ts +75 -26
  139. package/src/layoutReanimation/animationBuilder/ComplexAnimationBuilder.ts +4 -3
  140. package/src/layoutReanimation/animationBuilder/Keyframe.ts +3 -2
  141. package/src/layoutReanimation/defaultTransitions/CurvedTransition.ts +27 -12
  142. package/src/platform-specific/findHostInstance.ts +1 -1
  143. package/src/platform-specific/jsVersion.ts +1 -1
  144. package/src/privateGlobals.d.ts +1 -1
  145. package/src/processBoxShadow.ts +1 -0
  146. package/src/reactUtils.tsx +54 -0
  147. package/lib/module/PropsRegistry.js +0 -25
  148. package/lib/module/PropsRegistry.js.map +0 -1
  149. package/lib/typescript/PropsRegistry.d.ts +0 -2
  150. package/lib/typescript/PropsRegistry.d.ts.map +0 -1
  151. package/src/PropsRegistry.ts +0 -26
  152. package/src/reactUtils.ts +0 -22
@@ -32,6 +32,33 @@ void PropsRegistry::for_each(std::function<void(
32
32
  }
33
33
  }
34
34
 
35
+ void PropsRegistry::markNodeAsRemovable(const ShadowNode::Shared &shadowNode) {
36
+ removableShadowNodes_[shadowNode->getTag()] = shadowNode;
37
+ }
38
+
39
+ void PropsRegistry::unmarkNodeAsRemovable(Tag viewTag) {
40
+ removableShadowNodes_.erase(viewTag);
41
+ }
42
+
43
+ void PropsRegistry::handleNodeRemovals(const RootShadowNode &rootShadowNode) {
44
+ for (auto it = removableShadowNodes_.begin();
45
+ it != removableShadowNodes_.end();) {
46
+ const auto &shadowNode = it->second;
47
+ const auto &family = shadowNode->getFamily();
48
+ const auto &ancestors = family.getAncestors(rootShadowNode);
49
+
50
+ // Skip if the node hasn't been removed
51
+ if (!ancestors.empty()) {
52
+ ++it;
53
+ continue;
54
+ }
55
+
56
+ const auto tag = shadowNode->getTag();
57
+ map_.erase(tag);
58
+ it = removableShadowNodes_.erase(it);
59
+ }
60
+ }
61
+
35
62
  void PropsRegistry::remove(const Tag tag) {
36
63
  map_.erase(tag);
37
64
  }
@@ -45,8 +45,17 @@ class PropsRegistry {
45
45
  return shouldCommitAfterPause_.exchange(false);
46
46
  }
47
47
 
48
+ bool isEmpty() {
49
+ return map_.empty();
50
+ }
51
+
52
+ void markNodeAsRemovable(const ShadowNode::Shared &shadowNode);
53
+ void unmarkNodeAsRemovable(Tag viewTag);
54
+ void handleNodeRemovals(const RootShadowNode &rootShadowNode);
55
+
48
56
  private:
49
57
  std::unordered_map<Tag, std::pair<ShadowNode::Shared, folly::dynamic>> map_;
58
+ std::unordered_map<Tag, ShadowNode::Shared> removableShadowNodes_;
50
59
 
51
60
  mutable std::mutex mutex_; // Protects `map_`.
52
61
 
@@ -17,7 +17,7 @@ ReanimatedMountHook::~ReanimatedMountHook() noexcept {
17
17
  }
18
18
 
19
19
  void ReanimatedMountHook::shadowTreeDidMount(
20
- RootShadowNode::Shared const &rootShadowNode,
20
+ const RootShadowNode::Shared &rootShadowNode,
21
21
  double) noexcept {
22
22
  auto reaShadowNode =
23
23
  std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(
@@ -32,11 +32,16 @@ void ReanimatedMountHook::shadowTreeDidMount(
32
32
  return;
33
33
  }
34
34
 
35
- // When commit from React Native has finished, we reset the skip commit flag
36
- // in order to allow Reanimated to commit its tree
37
- propsRegistry_->unpauseReanimatedCommits();
38
- if (!propsRegistry_->shouldCommitAfterPause()) {
39
- return;
35
+ {
36
+ auto lock = propsRegistry_->createLock();
37
+ propsRegistry_->handleNodeRemovals(*rootShadowNode);
38
+
39
+ // When commit from React Native has finished, we reset the skip commit flag
40
+ // in order to allow Reanimated to commit its tree
41
+ propsRegistry_->unpauseReanimatedCommits();
42
+ if (!propsRegistry_->shouldCommitAfterPause()) {
43
+ return;
44
+ }
40
45
  }
41
46
 
42
47
  const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
@@ -64,8 +64,6 @@ ReanimatedModuleProxy::ReanimatedModuleProxy(
64
64
  layoutAnimationsManager_(
65
65
  std::make_shared<LayoutAnimationsManager>(jsLogger_)),
66
66
  #ifdef RCT_NEW_ARCH_ENABLED
67
- synchronouslyUpdateUIPropsFunction_(
68
- platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction),
69
67
  propsRegistry_(std::make_shared<PropsRegistry>()),
70
68
  #else
71
69
  obtainPropFunction_(platformDepMethodsHolder.obtainPropFunction),
@@ -205,7 +203,6 @@ void ReanimatedModuleProxy::init(
205
203
  UIRuntimeDecorator::decorate(
206
204
  uiRuntime,
207
205
  #ifdef RCT_NEW_ARCH_ENABLED
208
- removeFromPropsRegistry,
209
206
  obtainProp,
210
207
  updateProps,
211
208
  measure,
@@ -489,7 +486,6 @@ jsi::Value ReanimatedModuleProxy::configureProps(
489
486
  auto nativePropsArray = nativeProps.asObject(rt).asArray(rt);
490
487
  for (size_t i = 0; i < nativePropsArray.size(rt); ++i) {
491
488
  auto name = nativePropsArray.getValueAtIndex(rt, i).asString(rt).utf8(rt);
492
- nativePropNames_.insert(name);
493
489
  animatablePropNames_.insert(name);
494
490
  }
495
491
  #else
@@ -600,20 +596,18 @@ void ReanimatedModuleProxy::cleanupSensors() {
600
596
  }
601
597
 
602
598
  #ifdef RCT_NEW_ARCH_ENABLED
603
- bool ReanimatedModuleProxy::isThereAnyLayoutProp(
599
+
600
+ void ReanimatedModuleProxy::markNodeAsRemovable(
604
601
  jsi::Runtime &rt,
605
- const jsi::Object &props) {
606
- const jsi::Array propNames = props.getPropertyNames(rt);
607
- for (size_t i = 0; i < propNames.size(rt); ++i) {
608
- const std::string propName =
609
- propNames.getValueAtIndex(rt, i).asString(rt).utf8(rt);
610
- bool isLayoutProp =
611
- nativePropNames_.find(propName) != nativePropNames_.end();
612
- if (isLayoutProp) {
613
- return true;
614
- }
615
- }
616
- return false;
602
+ const jsi::Value &shadowNodeWrapper) {
603
+ auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
604
+ propsRegistry_->markNodeAsRemovable(shadowNode);
605
+ }
606
+
607
+ void ReanimatedModuleProxy::unmarkNodeAsRemovable(
608
+ jsi::Runtime &rt,
609
+ const jsi::Value &viewTag) {
610
+ propsRegistry_->unmarkNodeAsRemovable(viewTag.asNumber());
617
611
  }
618
612
 
619
613
  jsi::Value ReanimatedModuleProxy::filterNonAnimatableProps(
@@ -760,25 +754,6 @@ void ReanimatedModuleProxy::performOperations() {
760
754
  jsPropsUpdater.call(rt, viewTag, nonAnimatableProps);
761
755
  }
762
756
 
763
- bool hasLayoutUpdates = false;
764
-
765
- for (const auto &[shadowNode, props] : copiedOperationsQueue) {
766
- if (isThereAnyLayoutProp(rt, props->asObject(rt))) {
767
- hasLayoutUpdates = true;
768
- break;
769
- }
770
- }
771
-
772
- if (!hasLayoutUpdates) {
773
- // If there's no layout props to be updated, we can apply the updates
774
- // directly onto the components and skip the commit.
775
- for (const auto &[shadowNode, props] : copiedOperationsQueue) {
776
- Tag tag = shadowNode->getTag();
777
- synchronouslyUpdateUIPropsFunction_(rt, tag, props->asObject(rt));
778
- }
779
- return;
780
- }
781
-
782
757
  if (propsRegistry_->shouldReanimatedSkipCommit()) {
783
758
  // It may happen that `performOperations` is called on the UI thread
784
759
  // while React Native tries to commit a new tree on the JS thread.
@@ -829,15 +804,6 @@ void ReanimatedModuleProxy::performOperations() {
829
804
  }
830
805
  }
831
806
 
832
- void ReanimatedModuleProxy::removeFromPropsRegistry(
833
- jsi::Runtime &rt,
834
- const jsi::Value &viewTags) {
835
- auto array = viewTags.asObject(rt).asArray(rt);
836
- for (size_t i = 0, size = array.size(rt); i < size; ++i) {
837
- tagsToRemove_.push_back(array.getValueAtIndex(rt, i).asNumber());
838
- }
839
- }
840
-
841
807
  void ReanimatedModuleProxy::dispatchCommand(
842
808
  jsi::Runtime &rt,
843
809
  const jsi::Value &shadowNodeValue,
@@ -846,7 +812,19 @@ void ReanimatedModuleProxy::dispatchCommand(
846
812
  ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
847
813
  std::string commandName = stringFromValue(rt, commandNameValue);
848
814
  folly::dynamic args = commandArgsFromValue(rt, argsValue);
849
- uiManager_->dispatchCommand(shadowNode, commandName, args);
815
+ const auto &scheduler = static_cast<Scheduler *>(uiManager_->getDelegate());
816
+
817
+ if (!scheduler) {
818
+ return;
819
+ }
820
+
821
+ const auto &schedulerDelegate = scheduler->getDelegate();
822
+
823
+ if (schedulerDelegate) {
824
+ const auto shadowView = ShadowView(*shadowNode);
825
+ schedulerDelegate->schedulerDidDispatchCommand(
826
+ shadowView, commandName, args);
827
+ }
850
828
  }
851
829
 
852
830
  jsi::String ReanimatedModuleProxy::obtainProp(
@@ -936,6 +914,30 @@ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
936
914
  }
937
915
  }
938
916
 
917
+ #ifdef IS_REANIMATED_EXAMPLE_APP
918
+
919
+ std::string format(bool b) {
920
+ return b ? "✅" : "❌";
921
+ }
922
+
923
+ std::function<std::string()>
924
+ ReanimatedModuleProxy::createRegistriesLeakCheck() {
925
+ return [weakThis = weak_from_this()]() {
926
+ auto strongThis = weakThis.lock();
927
+ if (!strongThis) {
928
+ return std::string("");
929
+ }
930
+
931
+ std::string result = "";
932
+
933
+ result += "PropsRegistry: " + format(strongThis->propsRegistry_->isEmpty());
934
+
935
+ return result;
936
+ };
937
+ }
938
+
939
+ #endif // IS_REANIMATED_EXAMPLE_APP
940
+
939
941
  #endif // RCT_NEW_ARCH_ENABLED
940
942
 
941
943
  jsi::Value ReanimatedModuleProxy::subscribeForKeyboardEvents(
@@ -124,6 +124,12 @@ class ReanimatedModuleProxy
124
124
 
125
125
  void performOperations();
126
126
 
127
+ void markNodeAsRemovable(
128
+ jsi::Runtime &rt,
129
+ const jsi::Value &shadowNodeWrapper) override;
130
+ void unmarkNodeAsRemovable(jsi::Runtime &rt, const jsi::Value &viewTag)
131
+ override;
132
+
127
133
  void dispatchCommand(
128
134
  jsi::Runtime &rt,
129
135
  const jsi::Value &shadowNodeValue,
@@ -145,6 +151,10 @@ class ReanimatedModuleProxy
145
151
  jsi::Runtime &rt,
146
152
  const std::string &propName,
147
153
  const ShadowNode::Shared &shadowNode);
154
+
155
+ #ifdef IS_REANIMATED_EXAMPLE_APP
156
+ std::function<std::string()> createRegistriesLeakCheck();
157
+ #endif // IS_REANIMATED_EXAMPLE_APP
148
158
  #endif
149
159
 
150
160
  jsi::Value registerSensor(
@@ -191,7 +201,6 @@ class ReanimatedModuleProxy
191
201
  void requestAnimationFrame(jsi::Runtime &rt, const jsi::Value &callback);
192
202
 
193
203
  #ifdef RCT_NEW_ARCH_ENABLED
194
- bool isThereAnyLayoutProp(jsi::Runtime &rt, const jsi::Object &props);
195
204
  jsi::Value filterNonAnimatableProps(
196
205
  jsi::Runtime &rt,
197
206
  const jsi::Value &props);
@@ -213,9 +222,6 @@ class ReanimatedModuleProxy
213
222
  std::shared_ptr<LayoutAnimationsManager> layoutAnimationsManager_;
214
223
 
215
224
  #ifdef RCT_NEW_ARCH_ENABLED
216
- const SynchronouslyUpdateUIPropsFunction synchronouslyUpdateUIPropsFunction_;
217
-
218
- std::unordered_set<std::string> nativePropNames_; // filled by configureProps
219
225
  std::unordered_set<std::string>
220
226
  animatablePropNames_; // filled by configureProps
221
227
  std::shared_ptr<UIManager> uiManager_;
@@ -160,6 +160,30 @@ static jsi::Value REANIMATED_SPEC_PREFIX(setShouldAnimateExiting)(
160
160
  return jsi::Value::undefined();
161
161
  }
162
162
 
163
+ #ifdef RCT_NEW_ARCH_ENABLED
164
+
165
+ static jsi::Value REANIMATED_SPEC_PREFIX(markNodeAsRemovable)(
166
+ jsi::Runtime &rt,
167
+ TurboModule &turboModule,
168
+ const jsi::Value *args,
169
+ size_t) {
170
+ static_cast<ReanimatedModuleProxySpec *>(&turboModule)
171
+ ->markNodeAsRemovable(rt, std::move(args[0]));
172
+ return jsi::Value::undefined();
173
+ }
174
+
175
+ static jsi::Value REANIMATED_SPEC_PREFIX(unmarkNodeAsRemovable)(
176
+ jsi::Runtime &rt,
177
+ TurboModule &turboModule,
178
+ const jsi::Value *args,
179
+ size_t) {
180
+ static_cast<ReanimatedModuleProxySpec *>(&turboModule)
181
+ ->unmarkNodeAsRemovable(rt, std::move(args[0]));
182
+ return jsi::Value::undefined();
183
+ }
184
+
185
+ #endif // RCT_NEW_ARCH_ENABLED
186
+
163
187
  ReanimatedModuleProxySpec::ReanimatedModuleProxySpec(
164
188
  const std::shared_ptr<CallInvoker> &jsInvoker)
165
189
  : TurboModule("NativeReanimated", jsInvoker) {
@@ -196,5 +220,12 @@ ReanimatedModuleProxySpec::ReanimatedModuleProxySpec(
196
220
  MethodMetadata{1, REANIMATED_SPEC_PREFIX(configureLayoutAnimationBatch)};
197
221
  methodMap_["setShouldAnimateExitingForTag"] =
198
222
  MethodMetadata{2, REANIMATED_SPEC_PREFIX(setShouldAnimateExiting)};
223
+
224
+ #ifdef RCT_NEW_ARCH_ENABLED
225
+ methodMap_["markNodeAsRemovable"] =
226
+ MethodMetadata{1, REANIMATED_SPEC_PREFIX(markNodeAsRemovable)};
227
+ methodMap_["unmarkNodeAsRemovable"] =
228
+ MethodMetadata{1, REANIMATED_SPEC_PREFIX(unmarkNodeAsRemovable)};
229
+ #endif // RCT_NEW_ARCH_ENABLED
199
230
  }
200
231
  } // namespace reanimated
@@ -94,6 +94,16 @@ class JSI_EXPORT ReanimatedModuleProxySpec : public TurboModule {
94
94
  jsi::Runtime &rt,
95
95
  const jsi::Value &viewTag,
96
96
  const jsi::Value &shouldAnimate) = 0;
97
+
98
+ #ifdef RCT_NEW_ARCH_ENABLED
99
+ // Cleanup
100
+ virtual void markNodeAsRemovable(
101
+ jsi::Runtime &rt,
102
+ const jsi::Value &shadowNodeWrapper) = 0;
103
+ virtual void unmarkNodeAsRemovable(
104
+ jsi::Runtime &rt,
105
+ const jsi::Value &viewTag) = 0;
106
+ #endif // RCT_NEW_ARCH_ENABLED
97
107
  };
98
108
 
99
109
  } // namespace reanimated
@@ -1,4 +1,5 @@
1
1
  #include <reanimated/RuntimeDecorators/RNRuntimeDecorator.h>
2
+ #include <worklets/Tools/ReanimatedJSIUtils.h>
2
3
  #include <worklets/Tools/ReanimatedVersion.h>
3
4
 
4
5
  namespace reanimated {
@@ -32,6 +33,13 @@ void RNRuntimeDecorator::decorate(
32
33
  #ifndef NDEBUG
33
34
  checkJSVersion(rnRuntime, reanimatedModuleProxy->getJSLogger());
34
35
  #endif // NDEBUG
36
+
37
+ #if defined(IS_REANIMATED_EXAMPLE_APP) && defined(RCT_NEW_ARCH_ENABLED)
38
+ jsi_utils::installJsiFunction(
39
+ rnRuntime,
40
+ "_registriesLeakCheck",
41
+ reanimatedModuleProxy->createRegistriesLeakCheck());
42
+ #endif // defined(IS_REANIMATED_EXAMPLE_APP) && defined(RCT_NEW_ARCH_ENABLED)
35
43
  injectReanimatedCppVersion(rnRuntime);
36
44
 
37
45
  rnRuntime.global().setProperty(
@@ -8,7 +8,7 @@ using namespace worklets;
8
8
  void UIRuntimeDecorator::decorate(
9
9
  jsi::Runtime &uiRuntime,
10
10
  #ifdef RCT_NEW_ARCH_ENABLED
11
- const RemoveFromPropsRegistryFunction removeFromPropsRegistry,
11
+ // nothing
12
12
  #else
13
13
  const ScrollToFunction scrollTo,
14
14
  #endif
@@ -26,8 +26,6 @@ void UIRuntimeDecorator::decorate(
26
26
 
27
27
  #ifdef RCT_NEW_ARCH_ENABLED
28
28
  jsi_utils::installJsiFunction(uiRuntime, "_updatePropsFabric", updateProps);
29
- jsi_utils::installJsiFunction(
30
- uiRuntime, "_removeFromPropsRegistry", removeFromPropsRegistry);
31
29
  jsi_utils::installJsiFunction(
32
30
  uiRuntime, "_dispatchCommandFabric", dispatchCommand);
33
31
  jsi_utils::installJsiFunction(uiRuntime, "_measureFabric", measure);
@@ -16,7 +16,7 @@ class UIRuntimeDecorator {
16
16
  static void decorate(
17
17
  jsi::Runtime &uiRuntime,
18
18
  #ifdef RCT_NEW_ARCH_ENABLED
19
- const RemoveFromPropsRegistryFunction removeFromPropsRegistry,
19
+ // nothing
20
20
  #else
21
21
  const ScrollToFunction scrollTo,
22
22
  #endif
@@ -20,12 +20,8 @@ namespace reanimated {
20
20
 
21
21
  #ifdef RCT_NEW_ARCH_ENABLED
22
22
 
23
- using SynchronouslyUpdateUIPropsFunction =
24
- std::function<void(jsi::Runtime &rt, Tag tag, const jsi::Object &props)>;
25
23
  using UpdatePropsFunction =
26
24
  std::function<void(jsi::Runtime &rt, const jsi::Value &operations)>;
27
- using RemoveFromPropsRegistryFunction =
28
- std::function<void(jsi::Runtime &rt, const jsi::Value &viewTags)>;
29
25
  using ObtainPropFunction = std::function<jsi::Value(
30
26
  jsi::Runtime &rt,
31
27
  const jsi::Value &shadowNodeWrapper,
@@ -79,7 +75,7 @@ using MaybeFlushUIUpdatesQueueFunction = std::function<void()>;
79
75
  struct PlatformDepMethodsHolder {
80
76
  RequestRenderFunction requestRender;
81
77
  #ifdef RCT_NEW_ARCH_ENABLED
82
- SynchronouslyUpdateUIPropsFunction synchronouslyUpdateUIPropsFunction;
78
+ // nothing
83
79
  #else
84
80
  UpdatePropsFunction updatePropsFunction;
85
81
  ScrollToFunction scrollToFunction;
@@ -108,6 +108,16 @@ inline jsi::Value apply(
108
108
  return std::apply(function, std::move(args));
109
109
  }
110
110
 
111
+ // calls string-returning `function` with `args`,
112
+ // and returns the string
113
+ template <typename... Args>
114
+ inline jsi::Value apply(
115
+ jsi::Runtime &rt,
116
+ std::function<std::string(Args...)> function,
117
+ std::tuple<Args...> args) {
118
+ return jsi::String::createFromUtf8(rt, std::apply(function, std::move(args)));
119
+ }
120
+
111
121
  // calls void-returning `function` with `args`,
112
122
  // and returns `undefined`
113
123
  template <typename... Args>
@@ -132,6 +142,21 @@ jsi::HostFunctionType createHostFunction(Fun function) {
132
142
  };
133
143
  }
134
144
 
145
+ // returns a function with JSI calling convention
146
+ // from a native function `function` returning a string
147
+ template <typename... Args>
148
+ jsi::HostFunctionType createHostFunction(
149
+ std::function<std::string(Args...)> function) {
150
+ return [function](
151
+ jsi::Runtime &rt,
152
+ const jsi::Value &,
153
+ const jsi::Value *args,
154
+ const size_t count) {
155
+ auto argz = getArgsForFunction(function, rt, args, count);
156
+ return apply(rt, function, std::move(argz));
157
+ };
158
+ }
159
+
135
160
  // used to determine if `function<Ret(Args...)>`
136
161
  // takes `Runtime &` as its first argument
137
162
  template <typename... Args>
@@ -1,5 +1,5 @@
1
1
  distributionBase=GRADLE_USER_HOME
2
2
  distributionPath=wrapper/dists
3
- distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
3
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
4
4
  zipStoreBase=GRADLE_USER_HOME
5
5
  zipStorePath=wrapper/dists
@@ -16,6 +16,7 @@ import com.swmansion.worklets.JSCallInvokerResolver;
16
16
  import com.swmansion.worklets.WorkletsModule;
17
17
  import java.util.HashMap;
18
18
  import java.util.Objects;
19
+ import java.util.concurrent.atomic.AtomicBoolean;
19
20
 
20
21
  /**
21
22
  * @noinspection JavaJniMissingFunction
@@ -25,6 +26,12 @@ public class NativeProxy extends NativeProxyCommon {
25
26
  @SuppressWarnings("unused")
26
27
  private final HybridData mHybridData;
27
28
 
29
+ /**
30
+ * Invalidating concurrently could be fatal. It shouldn't happen in a normal flow, but it doesn't
31
+ * cost us much to add synchronization for extra safety.
32
+ */
33
+ private final AtomicBoolean mInvalidated = new AtomicBoolean(false);
34
+
28
35
  public @OptIn(markerClass = FrameworkAPI.class) NativeProxy(
29
36
  ReactApplicationContext context, WorkletsModule workletsModule) {
30
37
  super(context);
@@ -72,8 +79,13 @@ public class NativeProxy extends NativeProxyCommon {
72
79
 
73
80
  private native void invalidateCpp();
74
81
 
75
- public void invalidate() {
76
- invalidateCpp();
82
+ protected void invalidate() {
83
+ if (mInvalidated.getAndSet(true)) {
84
+ return;
85
+ }
86
+ if (mHybridData != null && mHybridData.isValid()) {
87
+ invalidateCpp();
88
+ }
77
89
  }
78
90
 
79
91
  public static NativeMethodsHolder createNativeMethodsHolder(
@@ -1,7 +1,6 @@
1
1
  package com.swmansion.reanimated;
2
2
 
3
3
  import com.facebook.react.bridge.ReactApplicationContext;
4
- import com.facebook.react.bridge.ReadableMap;
5
4
  import com.facebook.react.fabric.FabricUIManager;
6
5
  import com.facebook.react.uimanager.UIManagerHelper;
7
6
  import com.facebook.react.uimanager.common.UIManagerType;
@@ -26,8 +25,4 @@ class ReaCompatibility {
26
25
  fabricUIManager.getEventDispatcher().removeListener(nodesManager);
27
26
  }
28
27
  }
29
-
30
- public void synchronouslyUpdateUIProps(int viewTag, ReadableMap uiProps) {
31
- fabricUIManager.synchronouslyUpdateViewOnUIThread(viewTag, uiProps);
32
- }
33
28
  }
@@ -318,26 +318,6 @@ std::vector<std::pair<std::string, double>> NativeProxy::measure(int viewTag) {
318
318
  }
319
319
  #endif // RCT_NEW_ARCH_ENABLED
320
320
 
321
- #ifdef RCT_NEW_ARCH_ENABLED
322
- inline jni::local_ref<ReadableMap::javaobject> castReadableMap(
323
- jni::local_ref<ReadableNativeMap::javaobject> const &nativeMap) {
324
- return make_local(reinterpret_cast<ReadableMap::javaobject>(nativeMap.get()));
325
- }
326
-
327
- void NativeProxy::synchronouslyUpdateUIProps(
328
- jsi::Runtime &rt,
329
- Tag tag,
330
- const jsi::Object &props) {
331
- static const auto method =
332
- getJniMethod<void(int, jni::local_ref<ReadableMap::javaobject>)>(
333
- "synchronouslyUpdateUIProps");
334
- jni::local_ref<ReadableMap::javaobject> uiProps =
335
- castReadableMap(ReadableNativeMap::newObjectCxxArgs(
336
- jsi::dynamicFromValue(rt, jsi::Value(rt, props))));
337
- method(javaPart_.get(), tag, uiProps);
338
- }
339
- #endif
340
-
341
321
  int NativeProxy::registerSensor(
342
322
  int sensorType,
343
323
  int interval,
@@ -456,8 +436,7 @@ PlatformDepMethodsHolder NativeProxy::getPlatformDependentMethods() {
456
436
  auto requestRender = bindThis(&NativeProxy::requestRender);
457
437
 
458
438
  #ifdef RCT_NEW_ARCH_ENABLED
459
- auto synchronouslyUpdateUIPropsFunction =
460
- bindThis(&NativeProxy::synchronouslyUpdateUIProps);
439
+ // nothing
461
440
  #else
462
441
  auto configurePropsFunction = bindThis(&NativeProxy::configureProps);
463
442
  #endif
@@ -491,7 +470,7 @@ PlatformDepMethodsHolder NativeProxy::getPlatformDependentMethods() {
491
470
  return {
492
471
  requestRender,
493
472
  #ifdef RCT_NEW_ARCH_ENABLED
494
- synchronouslyUpdateUIPropsFunction,
473
+ // nothing
495
474
  #else
496
475
  updatePropsFunction,
497
476
  scrollToFunction,
@@ -181,12 +181,6 @@ class NativeProxy : public jni::HybridClass<NativeProxy>,
181
181
  // std::shared_ptr<EventListener> eventListener_;
182
182
  #endif // RCT_NEW_ARCH_ENABLED
183
183
  void installJSIBindings();
184
- #ifdef RCT_NEW_ARCH_ENABLED
185
- void synchronouslyUpdateUIProps(
186
- jsi::Runtime &rt,
187
- Tag viewTag,
188
- const jsi::Object &props);
189
- #endif
190
184
  PlatformDepMethodsHolder getPlatformDependentMethods();
191
185
  void setupLayoutAnimations();
192
186
 
@@ -48,8 +48,8 @@ void AndroidUIScheduler::triggerUI() {
48
48
  void AndroidUIScheduler::scheduleTriggerOnUI() {
49
49
  static const auto method =
50
50
  javaPart_->getClass()->getMethod<void()>("scheduleTriggerOnUI");
51
- if(!javaPart_) {
52
- return;
51
+ if (!javaPart_) {
52
+ return;
53
53
  }
54
54
  method(javaPart_.get());
55
55
  }
@@ -440,10 +440,6 @@ public class NodesManager implements EventDispatcherListener {
440
440
  }
441
441
  }
442
442
 
443
- public void synchronouslyUpdateUIProps(int viewTag, ReadableMap uiProps) {
444
- compatibility.synchronouslyUpdateUIProps(viewTag, uiProps);
445
- }
446
-
447
443
  public String obtainProp(int viewTag, String propName) {
448
444
  View view;
449
445
  try {
@@ -9,7 +9,6 @@ import com.facebook.proguard.annotations.DoNotStrip;
9
9
  import com.facebook.react.bridge.NativeModule;
10
10
  import com.facebook.react.bridge.ReactApplicationContext;
11
11
  import com.facebook.react.bridge.ReadableArray;
12
- import com.facebook.react.bridge.ReadableMap;
13
12
  import com.facebook.react.bridge.ReadableNativeArray;
14
13
  import com.facebook.soloader.SoLoader;
15
14
  import com.swmansion.common.GestureHandlerStateManager;
@@ -129,11 +128,6 @@ public abstract class NativeProxyCommon {
129
128
  mNodesManager.updateProps(viewTag, props);
130
129
  }
131
130
 
132
- @DoNotStrip
133
- public void synchronouslyUpdateUIProps(int viewTag, ReadableMap uiProps) {
134
- mNodesManager.synchronouslyUpdateUIProps(viewTag, uiProps);
135
- }
136
-
137
131
  @DoNotStrip
138
132
  public String obtainProp(int viewTag, String propName) {
139
133
  return mNodesManager.obtainProp(viewTag, propName);
@@ -12,6 +12,7 @@ import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
12
12
  import com.facebook.soloader.SoLoader;
13
13
  import com.swmansion.reanimated.NativeWorkletsModuleSpec;
14
14
  import java.util.Objects;
15
+ import java.util.concurrent.atomic.AtomicBoolean;
15
16
 
16
17
  /**
17
18
  * @noinspection JavaJniMissingFunction
@@ -38,6 +39,12 @@ public class WorkletsModule extends NativeWorkletsModuleSpec {
38
39
  return mAndroidUIScheduler;
39
40
  }
40
41
 
42
+ /**
43
+ * Invalidating concurrently could be fatal. It shouldn't happen in a normal flow, but it doesn't
44
+ * cost us much to add synchronization for extra safety.
45
+ */
46
+ private final AtomicBoolean mInvalidated = new AtomicBoolean(false);
47
+
41
48
  @OptIn(markerClass = FrameworkAPI.class)
42
49
  private native HybridData initHybrid(
43
50
  long jsContext,
@@ -69,11 +76,15 @@ public class WorkletsModule extends NativeWorkletsModuleSpec {
69
76
  }
70
77
 
71
78
  public void invalidate() {
72
- // We have to destroy extra runtimes when invalidate is called. If we clean
73
- // it up later instead there's a chance the runtime will retain references
74
- // to invalidated memory and will crash on its destruction.
75
- invalidateCpp();
76
-
79
+ if (mInvalidated.getAndSet(true)) {
80
+ return;
81
+ }
82
+ if (mHybridData != null && mHybridData.isValid()) {
83
+ // We have to destroy extra runtimes when invalidate is called. If we clean
84
+ // it up later instead there's a chance the runtime will retain references
85
+ // to invalidated memory and will crash on its destruction.
86
+ invalidateCpp();
87
+ }
77
88
  mAndroidUIScheduler.deactivate();
78
89
  }
79
90