@react-native-ohos/react-native-reanimated 4.0.2 → 4.1.0-beta.1

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 (196) hide show
  1. package/CHANGELOG.md +1070 -0
  2. package/LICENSE +21 -0
  3. package/README.md +842 -0
  4. package/compatibility.json +20 -26
  5. package/harmony/reanimated/BuildProfile.ets +1 -1
  6. package/harmony/reanimated/index.ets +4 -2
  7. package/harmony/reanimated/oh-package-lock.json5 +1 -1
  8. package/harmony/reanimated/oh-package.json5 +1 -1
  9. package/harmony/reanimated/src/main/cpp/CMakeLists.txt +23 -6
  10. package/harmony/reanimated/src/main/cpp/Common/NativeView/CMakeLists.txt +56 -0
  11. package/harmony/reanimated/src/main/cpp/Common/NativeView/react/renderer/components/rnreanimated/ComponentDescriptors.h +19 -0
  12. package/harmony/reanimated/src/main/cpp/Common/NativeView/react/renderer/components/rnreanimated/REASharedTransitionBoundaryComponentDescriptor.h +30 -0
  13. package/harmony/reanimated/src/main/cpp/Common/NativeView/react/renderer/components/rnreanimated/REASharedTransitionBoundaryShadowNode.cpp +15 -0
  14. package/harmony/reanimated/src/main/cpp/Common/NativeView/react/renderer/components/rnreanimated/REASharedTransitionBoundaryShadowNode.h +41 -0
  15. package/harmony/reanimated/src/main/cpp/Common/NativeView/react/renderer/components/rnreanimated/REASharedTransitionBoundaryState.h +30 -0
  16. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.cpp +8 -9
  17. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.h +3 -6
  18. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/InterpolatorRegistry.cpp +203 -150
  19. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/InterpolatorRegistry.h +1 -6
  20. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/definitions.h +2 -7
  21. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSAngle.cpp +0 -1
  22. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSColor.cpp +2 -18
  23. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSDiscreteArray.cpp +11 -11
  24. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSDiscreteArray.h +2 -6
  25. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSLength.cpp +4 -1
  26. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSNumber.cpp +5 -0
  27. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSNumber.h +8 -0
  28. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValue.h +27 -46
  29. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValueVariant.cpp +20 -20
  30. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/CSSValueVariant.h +2 -2
  31. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/common/values/complex/CSSDropShadow.h +3 -3
  32. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSAnimationConfig.cpp +10 -2
  33. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSAnimationConfig.h +5 -3
  34. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSKeyframesConfig.cpp +20 -17
  35. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSKeyframesConfig.h +5 -8
  36. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSTransitionConfig.cpp +33 -66
  37. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/CSSTransitionConfig.h +29 -22
  38. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/common.cpp +14 -2
  39. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/configs/common.h +8 -2
  40. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimation.cpp +50 -91
  41. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimation.h +43 -18
  42. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimationsGroup.cpp +63 -0
  43. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSAnimationsGroup.h +37 -0
  44. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSLoopAnimation.cpp +100 -0
  45. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSLoopAnimation.h +49 -0
  46. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSPlatformAnimation.h +13 -0
  47. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSPlatformAnimationFactory.h +32 -0
  48. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/transition/CSSLoopTransition.cpp +156 -0
  49. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/transition/CSSLoopTransition.h +71 -0
  50. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/transition/CSSPlatformTransitionProxy.cpp +141 -0
  51. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/transition/CSSPlatformTransitionProxy.h +104 -0
  52. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/transition/CSSTransition.cpp +97 -0
  53. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/transition/CSSTransition.h +69 -0
  54. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/EasingConfigs.cpp +89 -0
  55. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/easing/EasingConfigs.h +36 -0
  56. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/InterpolatorFactory.cpp +12 -0
  57. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/InterpolatorFactory.h +11 -2
  58. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/PropertyInterpolator.cpp +2 -3
  59. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/PropertyInterpolator.h +3 -5
  60. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperation.cpp +3 -3
  61. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/filters/FilterOperation.h +1 -1
  62. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.cpp +38 -37
  63. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.h +3 -6
  64. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.cpp +54 -32
  65. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h +5 -7
  66. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/OperationsStyleInterpolator.cpp +46 -46
  67. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/OperationsStyleInterpolator.h +8 -7
  68. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/operations/StyleOperation.h +4 -57
  69. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/AnimationStyleInterpolator.cpp +23 -0
  70. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/AnimationStyleInterpolator.h +10 -8
  71. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/AnimationStyleInterpolatorFactory.cpp +77 -0
  72. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/AnimationStyleInterpolatorFactory.h +38 -0
  73. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.cpp +47 -68
  74. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/styles/TransitionStyleInterpolator.h +21 -9
  75. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperation.cpp +4 -1
  76. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp +35 -78
  77. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.h +44 -13
  78. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/transforms/operations/matrix.cpp +13 -11
  79. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ResolvableValueInterpolator.cpp +4 -0
  80. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/SimpleValueInterpolator.cpp +7 -3
  81. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ValueInterpolator.cpp +20 -27
  82. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/interpolation/values/ValueInterpolator.h +12 -9
  83. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp +63 -36
  84. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +6 -8
  85. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/AnimationProgressProvider.cpp +55 -46
  86. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/AnimationProgressProvider.h +8 -5
  87. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/RawProgressProvider.cpp +1 -2
  88. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/RawProgressProvider.h +3 -2
  89. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/TransitionProgressProvider.cpp +76 -71
  90. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/progress/TransitionProgressProvider.h +17 -14
  91. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +145 -273
  92. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h +43 -44
  93. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSKeyframesRegistry.cpp +19 -19
  94. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSKeyframesRegistry.h +16 -12
  95. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.cpp +95 -114
  96. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.h +38 -25
  97. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp +9 -34
  98. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h +0 -10
  99. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/CSSLengthArray.cpp +47 -0
  100. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/CSSLengthArray.h +24 -0
  101. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/CSSLengthVector.cpp +87 -0
  102. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/CSSLengthVector.h +28 -0
  103. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGPath.cpp +326 -0
  104. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGPath.h +65 -0
  105. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStops.cpp +164 -0
  106. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStops.h +51 -0
  107. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.cpp +14 -66
  108. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.h +7 -18
  109. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/platform.cpp +284 -0
  110. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/platform.h +31 -0
  111. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/props.cpp +13 -132
  112. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/props.h +3 -21
  113. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/reversingShortening.h +43 -0
  114. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Compat/WorkletsApi.h +13 -0
  115. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Events/UIEventHandler.cpp +33 -0
  116. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Events/UIEventHandler.h +39 -0
  117. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Events/UIEventHandlerRegistry.cpp +95 -0
  118. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Events/UIEventHandlerRegistry.h +40 -0
  119. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +20 -23
  120. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +2 -6
  121. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +26 -18
  122. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +4 -8
  123. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp +16 -28
  124. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h +3 -4
  125. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +72 -24
  126. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +17 -7
  127. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/OperationsLoop.cpp +152 -0
  128. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/OperationsLoop.h +86 -0
  129. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/PropsLayoutFilter.h +98 -0
  130. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +162 -28
  131. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +69 -11
  132. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp +41 -17
  133. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h +14 -3
  134. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/updates/propNameFromString.h +130 -0
  135. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.cpp +1 -0
  136. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.h +5 -7
  137. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.cpp +7 -4
  138. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +52 -9
  139. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +174 -62
  140. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h +12 -11
  141. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +251 -128
  142. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h +23 -19
  143. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +34 -6
  144. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +71 -64
  145. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +938 -700
  146. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +123 -76
  147. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/SynchronousPropsBufferSerializer.cpp +313 -0
  148. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/SynchronousPropsBufferSerializer.h +18 -0
  149. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/PseudoStyles/PseudoSelector.h +41 -0
  150. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/PseudoStyles/PseudoStylesRegistry.cpp +113 -0
  151. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/PseudoStyles/PseudoStylesRegistry.h +73 -0
  152. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp +4 -4
  153. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp +23 -48
  154. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h +13 -14
  155. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +20 -3
  156. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReaJSIUtils.h +227 -0
  157. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedVersion.cpp +51 -14
  158. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedVersion.h +2 -5
  159. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/SingleInstanceChecker.h +76 -0
  160. package/harmony/reanimated/src/main/cpp/OHOSCSSPlatformTransitions.cpp +353 -0
  161. package/harmony/reanimated/src/main/cpp/OHOSCSSPlatformTransitions.h +95 -0
  162. package/harmony/reanimated/src/main/cpp/PseudoSelectorManager.cpp +140 -0
  163. package/harmony/reanimated/src/main/cpp/PseudoSelectorManager.h +52 -0
  164. package/harmony/reanimated/src/main/cpp/REASharedTransitionBoundaryComponentInstance.cpp +45 -0
  165. package/harmony/reanimated/src/main/cpp/REASharedTransitionBoundaryComponentInstance.h +33 -0
  166. package/harmony/reanimated/src/main/cpp/REASharedTransitionBoundaryJSIBinder.h +20 -0
  167. package/harmony/reanimated/src/main/cpp/ReanimatedModule.cpp +98 -18
  168. package/harmony/reanimated/src/main/cpp/ReanimatedModule.h +4 -2
  169. package/harmony/reanimated/src/main/cpp/ReanimatedNodesManager.cpp +1 -1
  170. package/harmony/reanimated/src/main/cpp/ReanimatedNodesManager.h +1 -1
  171. package/harmony/reanimated/src/main/cpp/ReanimatedPackage.cpp +24 -1
  172. package/harmony/reanimated/src/main/cpp/ReanimatedPackage.h +7 -2
  173. package/harmony/reanimated/src/main/cpp/ReanimatedSensor.cpp +88 -57
  174. package/harmony/reanimated/src/main/cpp/ReanimatedSensor.h +4 -2
  175. package/harmony/reanimated/src/main/cpp/ReanimatedSensorContainer.cpp +1 -1
  176. package/harmony/reanimated/src/main/cpp/ReanimatedSensorContainer.h +1 -1
  177. package/harmony/reanimated/src/main/cpp/ReanimatedUIScheduler.cpp +9 -7
  178. package/harmony/reanimated/src/main/cpp/ReanimatedUIScheduler.h +6 -5
  179. package/harmony/reanimated/src/main/cpp/TransformParser.h +1 -1
  180. package/harmony/reanimated/src/main/cpp/codegen/react/renderer/components/rnreanimated/EventEmitters.h +19 -0
  181. package/harmony/reanimated/src/main/cpp/codegen/react/renderer/components/rnreanimated/Props.h +31 -0
  182. package/harmony/reanimated/src/main/ets/KeyboardState.ts +11 -0
  183. package/harmony/reanimated/src/main/ets/ReanimatedModule.ts +106 -17
  184. package/harmony/reanimated/src/main/ets/{ReanimatedPackage.ts → ReanimatedPackage.ets} +4 -3
  185. package/harmony/reanimated.har +0 -0
  186. package/package.json +52 -24
  187. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSTransition.cpp +0 -145
  188. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/core/CSSTransition.h +0 -47
  189. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGLength.cpp +0 -93
  190. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/svg/values/SVGLength.h +0 -36
  191. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.cpp +0 -75
  192. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/CSS/utils/DelayedItemsManager.h +0 -45
  193. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp +0 -183
  194. package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h +0 -93
  195. package/harmony/reanimated/src/main/ets/AnimationManager.ts +0 -61
  196. /package/harmony/reanimated/{ts.ts → ts.ets} +0 -0
@@ -1,27 +1,34 @@
1
+ #include <cxxreact/ReactNativeVersion.h>
2
+ #include <jsi/JSIDynamic.h>
1
3
  #include <jsi/jsi.h>
4
+ #include <react/debug/react_native_assert.h>
5
+ #include <react/featureflags/ReactNativeFeatureFlags.h>
6
+ #include <react/renderer/core/RawProps.h>
7
+ #include <react/renderer/scheduler/Scheduler.h>
8
+ #include <react/renderer/uimanager/UIManagerBinding.h>
9
+ #include <react/renderer/uimanager/primitives.h>
10
+ #include <reanimated/CSS/configs/CSSTransitionConfig.h>
11
+ #include <reanimated/CSS/easing/EasingFunctions.h>
12
+ #include <reanimated/Compat/WorkletsApi.h>
13
+ #include <reanimated/Events/UIEventHandler.h>
14
+ #include <reanimated/Fabric/updates/PropsLayoutFilter.h>
15
+ #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h>
16
+ #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h>
2
17
  #include <reanimated/NativeModules/PropValueProcessor.h>
3
18
  #include <reanimated/NativeModules/ReanimatedModuleProxy.h>
19
+ #include <reanimated/NativeModules/SynchronousPropsBufferSerializer.h>
4
20
  #include <reanimated/RuntimeDecorators/UIRuntimeDecorator.h>
5
21
  #include <reanimated/Tools/FeatureFlags.h>
22
+ #include <reanimated/Tools/ReaJSIUtils.h>
6
23
  #include <reanimated/Tools/ReanimatedSystraceSection.h>
7
24
 
8
- #include <worklets/Registries/EventHandlerRegistry.h>
9
- #include <worklets/SharedItems/Serializable.h>
10
- #include <worklets/Tools/WorkletEventHandler.h>
11
-
12
25
  #ifdef __ANDROID__
13
26
  #include <fbjni/fbjni.h>
14
27
  #endif // __ANDROID__
15
28
 
16
- #include <react/renderer/scheduler/Scheduler.h>
17
- #include <react/renderer/uimanager/UIManagerBinding.h>
18
- #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h>
19
- #include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h>
20
-
29
+ #include <algorithm>
21
30
  #include <functional>
22
- #include <iomanip>
23
31
  #include <memory>
24
- #include <sstream>
25
32
  #include <string>
26
33
  #include <unordered_map>
27
34
  #include <unordered_set>
@@ -30,66 +37,255 @@
30
37
 
31
38
  namespace reanimated {
32
39
 
33
- #if REACT_NATIVE_MINOR_VERSION >= 81
40
+ using namespace worklets;
41
+
34
42
  static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
35
43
  jsi::Runtime &rt,
36
44
  const jsi::Value &shadowNodeWrapper) {
37
45
  return Bridging<std::shared_ptr<const ShadowNode>>::fromJs(rt, shadowNodeWrapper);
38
46
  }
47
+
48
+ namespace {
49
+
50
+ #if REACT_NATIVE_VERSION_MINOR >= 85
51
+ void mergeAnimatedProps(AnimatedProps &target, AnimatedProps &&source) {
52
+ if (source.rawProps) {
53
+ if (target.rawProps) {
54
+ auto mergedRawProps = target.rawProps->toDynamic();
55
+ mergedRawProps.merge_patch(source.rawProps->toDynamic());
56
+ target.rawProps = std::make_unique<RawProps>(std::move(mergedRawProps));
57
+ } else {
58
+ target.rawProps = std::move(source.rawProps);
59
+ }
60
+ }
61
+
62
+ for (auto &prop : source.props) {
63
+ target.props.push_back(std::move(prop));
64
+ }
65
+ }
66
+ #endif
67
+
68
+ #ifdef ANDROID
69
+ constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
70
+ return StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
71
+ !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS");
72
+ }
73
+ #elif __APPLE__
74
+ constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
75
+ return StaticFeatureFlags::getFlag("IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
76
+ !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS");
77
+ }
78
+ #elif defined(__OHOS__)
79
+ // OHOS follows the Apple-style synchronous path (per-tag folly::dynamic), see
80
+ // PlatformDepMethodsHolder.h and ReanimatedModule.cpp synchronouslyUpdateUIPropsFunction
81
+ constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
82
+ return StaticFeatureFlags::getFlag("IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
83
+ !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS");
84
+ }
85
+ #else
86
+ constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
87
+ return false;
88
+ }
39
89
  #endif
40
90
 
91
+ std::pair<UpdatesBatch, UpdatesBatch> partitionUpdates(
92
+ const UpdatesBatch &updatesBatch,
93
+ const bool allowPartialUpdates) {
94
+ static const std::unordered_set<std::string> synchronousPropNames = {
95
+ "opacity",
96
+ "elevation",
97
+ "zIndex",
98
+ "shadowColor",
99
+ #if __APPLE__
100
+ "shadowOffset",
101
+ "shadowOpacity",
102
+ "shadowRadius",
103
+ #endif // __APPLE__
104
+ "backgroundColor",
105
+ // "color", // not supported
106
+ "tintColor",
107
+ "placeholderTextColor",
108
+ "borderRadius",
109
+ "borderTopLeftRadius",
110
+ "borderTopRightRadius",
111
+ "borderTopStartRadius",
112
+ "borderTopEndRadius",
113
+ "borderBottomLeftRadius",
114
+ "borderBottomRightRadius",
115
+ "borderBottomStartRadius",
116
+ "borderBottomEndRadius",
117
+ "borderStartStartRadius",
118
+ "borderStartEndRadius",
119
+ "borderEndStartRadius",
120
+ "borderEndEndRadius",
121
+ "borderColor",
122
+ "borderTopColor",
123
+ "borderBottomColor",
124
+ "borderLeftColor",
125
+ "borderRightColor",
126
+ "borderStartColor",
127
+ "borderEndColor",
128
+ "borderBlockColor",
129
+ "borderBlockStartColor",
130
+ "borderBlockEndColor",
131
+ "outlineColor",
132
+ "outlineOffset",
133
+ "outlineWidth",
134
+ "transform",
135
+ };
136
+
137
+ const auto isSynchronous = [&](const std::string &keyStr, [[maybe_unused]] const folly::dynamic &value) {
138
+ if (!synchronousPropNames.contains(keyStr)) {
139
+ return false;
140
+ }
141
+ #ifdef ANDROID
142
+ // The Android synchronous path serializes color props into an int buffer via `value.asInt()`,
143
+ // so non-numeric color values (e.g. PlatformColor) must fall back to the shadow tree commit path.
144
+ const bool isColorProp = keyStr.find("Color") != std::string::npos;
145
+ if (isColorProp && !value.isNumber()) {
146
+ return false;
147
+ }
148
+ #endif // ANDROID
149
+ return true;
150
+ };
151
+
152
+ UpdatesBatch synchronousUpdatesBatch;
153
+ UpdatesBatch shadowTreeUpdatesBatch;
154
+
155
+ for (const auto &[shadowNodeFamily, props] : updatesBatch) {
156
+ if (allowPartialUpdates) {
157
+ folly::dynamic synchronousProps = folly::dynamic::object();
158
+ folly::dynamic shadowTreeProps = folly::dynamic::object();
159
+
160
+ for (const auto &[key, value] : props.items()) {
161
+ const auto keyStr = key.asString();
162
+ if (isSynchronous(keyStr, value)) {
163
+ synchronousProps[keyStr] = value;
164
+ } else {
165
+ shadowTreeProps[keyStr] = value;
166
+ }
167
+ }
168
+
169
+ if (!synchronousProps.empty()) {
170
+ synchronousUpdatesBatch.emplace_back(shadowNodeFamily, std::move(synchronousProps));
171
+ }
172
+
173
+ if (!shadowTreeProps.empty()) {
174
+ shadowTreeUpdatesBatch.emplace_back(shadowNodeFamily, std::move(shadowTreeProps));
175
+ }
176
+ } else {
177
+ const bool hasOnlySynchronousProps = std::all_of(props.items().begin(), props.items().end(), [&](const auto &kv) {
178
+ return isSynchronous(kv.first.asString(), kv.second);
179
+ });
180
+
181
+ if (hasOnlySynchronousProps) {
182
+ synchronousUpdatesBatch.emplace_back(shadowNodeFamily, props);
183
+ } else {
184
+ shadowTreeUpdatesBatch.emplace_back(shadowNodeFamily, props);
185
+ }
186
+ }
187
+ }
188
+
189
+ return {std::move(synchronousUpdatesBatch), std::move(shadowTreeUpdatesBatch)};
190
+ }
191
+
192
+ } // namespace
193
+
41
194
  ReanimatedModuleProxy::ReanimatedModuleProxy(
42
- const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
195
+ const std::shared_ptr<WorkletRuntime> &uiRuntime,
196
+ const std::shared_ptr<UIScheduler> &uiScheduler,
43
197
  jsi::Runtime &rnRuntime,
44
198
  const std::shared_ptr<CallInvoker> &jsCallInvoker,
45
199
  const PlatformDepMethodsHolder &platformDepMethodsHolder,
46
200
  const bool isReducedMotion)
47
- : ReanimatedModuleProxySpec(jsCallInvoker),
48
- isReducedMotion_(isReducedMotion),
49
- workletsModuleProxy_(workletsModuleProxy),
50
- eventHandlerRegistry_(std::make_unique<EventHandlerRegistry>()),
201
+ : isReducedMotion_(isReducedMotion),
202
+ uiRuntime_(uiRuntime),
203
+ uiScheduler_(uiScheduler),
204
+ jsInvoker_(jsCallInvoker),
205
+ eventHandlerRegistry_(std::make_unique<UIEventHandlerRegistry>()),
51
206
  requestRender_(platformDepMethodsHolder.requestRender),
52
207
  animatedSensorModule_(platformDepMethodsHolder),
53
- jsLogger_(std::make_shared<JSLogger>(workletsModuleProxy->getJSScheduler())),
54
- layoutAnimationsManager_(std::make_shared<LayoutAnimationsManager>(jsLogger_)),
208
+ layoutAnimationsManager_(std::make_shared<LayoutAnimationsManager>()),
55
209
  getAnimationTimestamp_(platformDepMethodsHolder.getAnimationTimestamp),
56
210
  #ifdef __APPLE__
57
211
  forceScreenSnapshot_(platformDepMethodsHolder.forceScreenSnapshotFunction),
58
212
  #endif
59
- animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
60
213
  staticPropsRegistry_(std::make_shared<StaticPropsRegistry>()),
61
214
  updatesRegistryManager_(std::make_shared<UpdatesRegistryManager>(staticPropsRegistry_)),
215
+ operationsLoop_(std::make_shared<OperationsLoop>(
216
+ uiScheduler,
217
+ platformDepMethodsHolder.requestRender,
218
+ platformDepMethodsHolder.getAnimationTimestamp,
219
+ updatesRegistryManager_)),
220
+ animatedPropsRegistry_(std::make_shared<AnimatedPropsRegistry>()),
62
221
  viewStylesRepository_(std::make_shared<ViewStylesRepository>(staticPropsRegistry_, animatedPropsRegistry_)),
63
- cssAnimationKeyframesRegistry_(std::make_shared<CSSKeyframesRegistry>(viewStylesRepository_)),
64
- cssAnimationsRegistry_(std::make_shared<CSSAnimationsRegistry>()),
65
- cssTransitionsRegistry_(std::make_shared<CSSTransitionsRegistry>(staticPropsRegistry_, getAnimationTimestamp_)),
222
+ cssAnimationKeyframesRegistry_(std::make_shared<CSSKeyframesRegistry>()),
223
+ cssAnimationsRegistry_(std::make_shared<CSSAnimationsRegistry>(
224
+ operationsLoop_,
225
+ cssAnimationKeyframesRegistry_,
226
+ platformDepMethodsHolder.platformAnimationFactory)),
227
+ cssTransitionsRegistry_(std::make_shared<CSSTransitionsRegistry>(
228
+ viewStylesRepository_,
229
+ operationsLoop_,
230
+ std::make_shared<CSSPlatformTransitionProxy>(
231
+ platformDepMethodsHolder.cssCanRouteProperty,
232
+ platformDepMethodsHolder.cssApplyTransitionJSI,
233
+ platformDepMethodsHolder.cssApplyTransitionDynamic,
234
+ platformDepMethodsHolder.cssRemoveTransition))),
235
+ pseudoStylesRegistry_(std::make_shared<PseudoStylesRegistry>(
236
+ platformDepMethodsHolder.attachPseudoSelector,
237
+ platformDepMethodsHolder.detachPseudoSelector,
238
+ cssTransitionsRegistry_,
239
+ updatesRegistryManager_)),
66
240
  synchronouslyUpdateUIPropsFunction_(platformDepMethodsHolder.synchronouslyUpdateUIPropsFunction),
67
241
  #ifdef ANDROID
68
242
  filterUnmountedTagsFunction_(platformDepMethodsHolder.filterUnmountedTagsFunction),
69
243
  #endif // ANDROID
70
244
  subscribeForKeyboardEventsFunction_(platformDepMethodsHolder.subscribeForKeyboardEvents),
71
245
  unsubscribeFromKeyboardEventsFunction_(platformDepMethodsHolder.unsubscribeFromKeyboardEvents) {
72
- auto lock = updatesRegistryManager_->lock();
73
246
  // Add registries in order of their priority (from the lowest to the
74
- // highest)
75
- // CSS transitions should be overriden by animated style animations;
76
- // animated style animations should be overriden by CSS animations
247
+ // highest). CSS transitions should be overriden by animated style
248
+ // animations; animated style animations should be overriden by CSS
249
+ // animations.
77
250
  updatesRegistryManager_->addRegistry(cssTransitionsRegistry_);
78
251
  updatesRegistryManager_->addRegistry(animatedPropsRegistry_);
79
252
  updatesRegistryManager_->addRegistry(cssAnimationsRegistry_);
253
+
254
+ #ifdef ANDROID
255
+ // Pre-allocate the synchronous props buffers so the first frame doesn't pay
256
+ // for vector growth allocations.
257
+ if constexpr (StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS")) {
258
+ synchronousPropsIntBuffer_.reserve(1024);
259
+ synchronousPropsDoubleBuffer_.reserve(1024);
260
+ }
261
+ #endif // ANDROID
80
262
  }
81
263
 
82
264
  void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMethodsHolder) {
83
- auto onRenderCallback = [weakThis = weak_from_this()](const double timestampMs) {
84
- auto strongThis = weakThis.lock();
85
- if (!strongThis) {
86
- return;
87
- }
88
-
89
- strongThis->renderRequested_ = false;
90
- strongThis->onRender(timestampMs);
91
- };
92
- onRenderCallback_ = std::move(onRenderCallback);
265
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
266
+ // Backend path: callbacks are drained later inside runGrandCallback under
267
+ // the manager lock; no wrap needed here.
268
+ requestRender_ = [weakThis = weak_from_this()](std::function<void(const double)> callback) {
269
+ auto strongThis = weakThis.lock();
270
+ if (!strongThis) {
271
+ return;
272
+ }
273
+ strongThis->pendingFrameCallbacks_.push_back(std::move(callback));
274
+ strongThis->startBackendIfNeeded();
275
+ };
276
+ } else {
277
+ // Non-backend path: wrap the platform RAF callback so the subsystem work
278
+ // runs under the manager lock.
279
+ requestRender_ = [weakThis = weak_from_this(), platformRequestRender = platformDepMethodsHolder.requestRender](
280
+ std::function<void(const double)> callback) {
281
+ platformRequestRender([weakThis, callback = std::move(callback)](const double timestamp) {
282
+ if (auto strongThis = weakThis.lock()) {
283
+ auto lock = strongThis->updatesRegistryManager_->lock();
284
+ callback(timestamp);
285
+ }
286
+ });
287
+ };
288
+ }
93
289
 
94
290
  auto updateProps = [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &operations) {
95
291
  auto strongThis = weakThis.lock();
@@ -98,6 +294,7 @@ void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMeth
98
294
  }
99
295
 
100
296
  const auto timestamp = strongThis->getAnimationTimestamp_();
297
+ auto lock = strongThis->updatesRegistryManager_->lock();
101
298
  strongThis->animatedPropsRegistry_->update(rt, operations, timestamp);
102
299
  };
103
300
 
@@ -121,8 +318,10 @@ void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMeth
121
318
 
122
319
  strongThis->dispatchCommand(rt, shadowNodeValue, commandNameValue, argsValue);
123
320
  };
321
+
124
322
  ProgressLayoutAnimationFunction progressLayoutAnimation =
125
323
  [weakThis = weak_from_this()](jsi::Runtime &rt, int tag, const jsi::Object &newStyle) {
324
+ // Always on UI thread.
126
325
  auto strongThis = weakThis.lock();
127
326
  if (!strongThis) {
128
327
  return;
@@ -131,34 +330,19 @@ void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMeth
131
330
  if (!surfaceId) {
132
331
  return;
133
332
  }
333
+ // The flush set is drained by `executeLayoutAnimationsRequests`, driven
334
+ // by `runGrandCallback` (backend) or a JS `requestAnimationFrameFinalizer` (non-backend).
134
335
  strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
135
336
  };
136
337
 
137
- auto requestLayoutAnimationRender = [weakThis = weak_from_this()](double) {
138
- auto strongThis = weakThis.lock();
139
- if (!strongThis) {
140
- return;
141
- }
142
- strongThis->layoutAnimationRenderRequested_ = false;
143
- };
144
-
145
- EndLayoutAnimationFunction endLayoutAnimation = [weakThis = weak_from_this(), requestLayoutAnimationRender](
146
- int tag, bool shouldRemove) {
338
+ EndLayoutAnimationFunction endLayoutAnimation = [weakThis = weak_from_this()](int tag, bool shouldRemove) {
339
+ // Always on UI thread.
147
340
  auto strongThis = weakThis.lock();
148
341
  if (!strongThis) {
149
342
  return;
150
343
  }
151
344
 
152
345
  auto surfaceId = strongThis->layoutAnimationsProxy_->endLayoutAnimation(tag, shouldRemove);
153
-
154
- if (!strongThis->layoutAnimationRenderRequested_) {
155
- strongThis->layoutAnimationRenderRequested_ = true;
156
- // if an animation has duration 0, performOperations would not get
157
- // called for it so we call requestRender to have it called in the
158
- // next frame
159
- strongThis->requestRender_(requestLayoutAnimationRender);
160
- }
161
-
162
346
  if (!surfaceId) {
163
347
  return;
164
348
  }
@@ -175,7 +359,30 @@ void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMeth
175
359
  return strongThis->obtainProp(rt, shadowNodeWrapper, propName);
176
360
  };
177
361
 
178
- jsi::Runtime &uiRuntime = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
362
+ std::optional<worklets::RequestAnimationFrameHostFunction> requestAnimationFrame;
363
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
364
+ requestAnimationFrame = [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &callback) {
365
+ auto strongThis = weakThis.lock();
366
+ if (!strongThis) {
367
+ return;
368
+ }
369
+
370
+ auto callbackFunction = std::make_shared<jsi::Function>(callback.asObject(rt).asFunction(rt));
371
+ strongThis->pendingAnimationFrameCallbackFromWorklets_ =
372
+ [callbackFunction = std::move(callbackFunction),
373
+ weakRuntime = getWeakRuntimeFromJSIRuntime(rt)](double timestamp) {
374
+ auto runtime = weakRuntime.lock();
375
+ if (!runtime) {
376
+ return;
377
+ }
378
+
379
+ runSyncOnRuntime(runtime, *callbackFunction, jsi::Value(timestamp));
380
+ };
381
+ strongThis->startBackendIfNeeded();
382
+ };
383
+ }
384
+
385
+ jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(uiRuntime_);
179
386
  UIRuntimeDecorator::decorate(
180
387
  uiRuntime,
181
388
  obtainProp,
@@ -186,14 +393,11 @@ void ReanimatedModuleProxy::init(const PlatformDepMethodsHolder &platformDepMeth
186
393
  platformDepMethodsHolder.setGestureStateFunction,
187
394
  progressLayoutAnimation,
188
395
  endLayoutAnimation,
189
- platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction);
396
+ platformDepMethodsHolder.maybeFlushUIUpdatesQueueFunction,
397
+ requestAnimationFrame);
190
398
  }
191
399
 
192
400
  ReanimatedModuleProxy::~ReanimatedModuleProxy() {
193
- invalidate();
194
- }
195
-
196
- void ReanimatedModuleProxy::invalidate() {
197
401
  // event handler registry and frame callbacks store some JSI values from UI
198
402
  // runtime, so they have to go away before we tear down the runtime
199
403
  eventHandlerRegistry_.reset();
@@ -208,17 +412,17 @@ jsi::Value ReanimatedModuleProxy::registerEventHandler(
208
412
 
209
413
  uint64_t newRegistrationId = NEXT_EVENT_HANDLER_ID++;
210
414
  auto eventNameStr = eventName.asString(rt).utf8(rt);
211
- auto handlerSerializable = extractSerializableOrThrow<SerializableWorklet>(
212
- rt, worklet, "[Reanimated] Event handler must be a serializable worklet.");
415
+ auto handlerSerializable = extractSerializable(
416
+ rt, worklet, "[Reanimated] Event handler must be a serializable worklet.", Serializable::ValueType::WorkletType);
213
417
  int emitterReactTagInt = emitterReactTag.asNumber();
214
418
 
215
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
419
+ scheduleOnUI(uiScheduler_, [=, weakThis = weak_from_this()]() {
216
420
  auto strongThis = weakThis.lock();
217
421
  if (!strongThis) {
218
422
  return;
219
423
  }
220
424
  auto handler =
221
- std::make_shared<WorkletEventHandler>(newRegistrationId, eventNameStr, emitterReactTagInt, handlerSerializable);
425
+ std::make_shared<UIEventHandler>(newRegistrationId, eventNameStr, emitterReactTagInt, handlerSerializable);
222
426
  strongThis->eventHandlerRegistry_->registerEventHandler(handler);
223
427
  });
224
428
 
@@ -227,7 +431,7 @@ jsi::Value ReanimatedModuleProxy::registerEventHandler(
227
431
 
228
432
  void ReanimatedModuleProxy::unregisterEventHandler(jsi::Runtime &, const jsi::Value &registrationId) {
229
433
  uint64_t id = registrationId.asNumber();
230
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
434
+ scheduleOnUI(uiScheduler_, [=, weakThis = weak_from_this()]() {
231
435
  auto strongThis = weakThis.lock();
232
436
  if (!strongThis) {
233
437
  return;
@@ -253,15 +457,15 @@ jsi::Value ReanimatedModuleProxy::getViewProp(
253
457
  const auto propNameStr = propName.asString(rnRuntime).utf8(rnRuntime);
254
458
  const auto funPtr = std::make_shared<jsi::Function>(callback.getObject(rnRuntime).asFunction(rnRuntime));
255
459
  const auto shadowNode = shadowNodeFromValue(rnRuntime, shadowNodeWrapper);
256
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([=, weakThis = weak_from_this()]() {
460
+ scheduleOnUI(uiScheduler_, [=, weakThis = weak_from_this()]() {
257
461
  auto strongThis = weakThis.lock();
258
462
  if (!strongThis) {
259
463
  return;
260
464
  }
261
- jsi::Runtime &uiRuntime = strongThis->workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
465
+ jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(strongThis->uiRuntime_);
262
466
  const auto resultStr = strongThis->obtainPropFromShadowNode(uiRuntime, propNameStr, shadowNode);
263
467
 
264
- strongThis->workletsModuleProxy_->getJSScheduler()->scheduleOnJS([=](jsi::Runtime &rnRuntime) {
468
+ strongThis->jsInvoker_->invokeAsync([=](jsi::Runtime &rnRuntime) {
265
469
  const auto resultValue = jsi::String::createFromUtf8(rnRuntime, resultStr);
266
470
  funPtr->call(rnRuntime, resultValue);
267
471
  });
@@ -270,7 +474,9 @@ jsi::Value ReanimatedModuleProxy::getViewProp(
270
474
  }
271
475
 
272
476
  jsi::Value ReanimatedModuleProxy::getStaticFeatureFlag(jsi::Runtime &rt, const jsi::Value &name) {
273
- return reanimated::StaticFeatureFlags::getFlag(name.asString(rt).utf8(rt));
477
+ const auto flagName = name.asString(rt).utf8(rt);
478
+ const auto result = reanimated::StaticFeatureFlags::getFlag(flagName);
479
+ return result;
274
480
  }
275
481
 
276
482
  jsi::Value
@@ -294,8 +500,8 @@ jsi::Value ReanimatedModuleProxy::configureLayoutAnimationBatch(
294
500
  if (config.isUndefined()) {
295
501
  batchItem.config = nullptr;
296
502
  } else {
297
- batchItem.config = extractSerializableOrThrow<SerializableObject>(
298
- rt, config, "[Reanimated] Layout animation config must be an object.");
503
+ batchItem.config = extractSerializable(
504
+ rt, config, "[Reanimated] Layout animation config must be an object.", Serializable::ValueType::ObjectType);
299
505
  }
300
506
  auto sharedTag = item.getProperty(rt, "sharedTransitionTag");
301
507
  if (!sharedTag.isUndefined()) {
@@ -317,18 +523,6 @@ bool ReanimatedModuleProxy::isAnyHandlerWaitingForEvent(const std::string &event
317
523
  return eventHandlerRegistry_->isAnyHandlerWaitingForEvent(eventName, emitterReactTag);
318
524
  }
319
525
 
320
- void ReanimatedModuleProxy::maybeRequestRender() {
321
- if (!renderRequested_) {
322
- renderRequested_ = true;
323
- requestRender_(onRenderCallback_);
324
- }
325
- }
326
-
327
- void ReanimatedModuleProxy::onRender(double timestampMs) {
328
- ReanimatedSystraceSection s("ReanimatedModuleProxy::onRender");
329
- // NOOP
330
- }
331
-
332
526
  jsi::Value ReanimatedModuleProxy::registerSensor(
333
527
  jsi::Runtime &rt,
334
528
  const jsi::Value &sensorType,
@@ -336,7 +530,7 @@ jsi::Value ReanimatedModuleProxy::registerSensor(
336
530
  const jsi::Value &iosReferenceFrame,
337
531
  const jsi::Value &sensorDataHandler) {
338
532
  return animatedSensorModule_.registerSensor(
339
- rt, workletsModuleProxy_->getUIWorkletRuntime(), sensorType, interval, iosReferenceFrame, sensorDataHandler);
533
+ rt, uiRuntime_, sensorType, interval, iosReferenceFrame, sensorDataHandler);
340
534
  }
341
535
 
342
536
  void ReanimatedModuleProxy::unregisterSensor(jsi::Runtime &, const jsi::Value &sensorId) {
@@ -348,16 +542,13 @@ void ReanimatedModuleProxy::cleanupSensors() {
348
542
  }
349
543
 
350
544
  void ReanimatedModuleProxy::setViewStyle(jsi::Runtime &rt, const jsi::Value &viewTag, const jsi::Value &viewStyle) {
351
- const auto tag = viewTag.asNumber();
352
- staticPropsRegistry_->set(rt, tag, viewStyle);
353
- if (staticPropsRegistry_->hasObservers(tag)) {
354
- maybeRunCSSLoop();
355
- }
545
+ auto lock = updatesRegistryManager_->lock();
546
+ staticPropsRegistry_->set(rt, viewTag.asNumber(), viewStyle);
356
547
  }
357
548
 
358
549
  void ReanimatedModuleProxy::markNodeAsRemovable(jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper) {
359
- auto lock = updatesRegistryManager_->lock();
360
550
  auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
551
+ auto lock = updatesRegistryManager_->lock();
361
552
  updatesRegistryManager_->markNodeAsRemovable(shadowNode);
362
553
  }
363
554
 
@@ -369,94 +560,99 @@ void ReanimatedModuleProxy::unmarkNodeAsRemovable(jsi::Runtime &rt, const jsi::V
369
560
  void ReanimatedModuleProxy::registerCSSKeyframes(
370
561
  jsi::Runtime &rt,
371
562
  const jsi::Value &animationName,
372
- const jsi::Value &viewName,
563
+ const jsi::Value &compoundComponentName,
373
564
  const jsi::Value &keyframesConfig) {
374
- // Convert react view name to Fabric component name
375
- const auto componentName = componentNameByReactViewName(viewName.asString(rt).utf8(rt));
565
+ const auto compoundComponentNameStr = compoundComponentName.asString(rt).utf8(rt);
566
+ auto parsedConfig =
567
+ parseCSSAnimationKeyframesConfig(rt, keyframesConfig, compoundComponentNameStr, viewStylesRepository_);
568
+
569
+ auto lock = updatesRegistryManager_->lock();
376
570
  cssAnimationKeyframesRegistry_->set(
377
- animationName.asString(rt).utf8(rt),
378
- componentName,
379
- parseCSSAnimationKeyframesConfig(rt, keyframesConfig, componentName, viewStylesRepository_));
571
+ animationName.asString(rt).utf8(rt), compoundComponentNameStr, std::move(parsedConfig));
380
572
  }
381
573
 
382
574
  void ReanimatedModuleProxy::unregisterCSSKeyframes(
383
575
  jsi::Runtime &rt,
384
576
  const jsi::Value &animationName,
385
- const jsi::Value &viewName) {
577
+ const jsi::Value &compoundComponentName) {
578
+ auto lock = updatesRegistryManager_->lock();
386
579
  cssAnimationKeyframesRegistry_->remove(
387
- animationName.asString(rt).utf8(rt), componentNameByReactViewName(viewName.asString(rt).utf8(rt)));
580
+ animationName.asString(rt).utf8(rt), compoundComponentName.asString(rt).utf8(rt));
388
581
  }
389
582
 
390
583
  void ReanimatedModuleProxy::applyCSSAnimations(
391
584
  jsi::Runtime &rt,
392
585
  const jsi::Value &shadowNodeWrapper,
586
+ const jsi::Value &compoundComponentName,
393
587
  const jsi::Value &animationUpdates) {
394
588
  auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
395
- const auto timestamp = getCssTimestamp();
589
+ const auto compoundComponentNameStr = compoundComponentName.asString(rt).utf8(rt);
396
590
  const auto updates = parseCSSAnimationUpdates(rt, animationUpdates);
397
591
 
398
- CSSAnimationsMap newAnimations;
399
-
400
- if (!updates.newAnimationSettings.empty()) {
401
- // animationNames always exists when newAnimationSettings is not empty
402
- const auto animationNames = updates.animationNames.value();
403
- const auto animationNamesCount = animationNames.size();
404
-
405
- for (const auto &[index, settings] : updates.newAnimationSettings) {
406
- if (index >= animationNamesCount) {
407
- throw std::invalid_argument("[Reanimated] index is out of bounds of animationNames");
408
- }
409
-
410
- const auto &animationName = animationNames[index];
411
- const auto &keyframesConfig = cssAnimationKeyframesRegistry_->get(animationName, shadowNode->getComponentName());
412
-
413
- newAnimations.emplace(
414
- index, std::make_shared<CSSAnimation>(rt, shadowNode, animationName, keyframesConfig, settings, timestamp));
415
- }
416
- }
417
-
418
- {
419
- auto lock = cssAnimationsRegistry_->lock();
420
- cssAnimationsRegistry_->apply(
421
- rt, shadowNode, updates.animationNames, newAnimations, updates.settingsUpdates, timestamp);
422
- }
423
-
424
- maybeRunCSSLoop();
592
+ auto lock = updatesRegistryManager_->lock();
593
+ cssAnimationsRegistry_->apply(shadowNode, compoundComponentNameStr, updates);
425
594
  }
426
595
 
427
596
  void ReanimatedModuleProxy::unregisterCSSAnimations(const jsi::Value &viewTag) {
428
- auto lock = cssAnimationsRegistry_->lock();
597
+ auto lock = updatesRegistryManager_->lock();
429
598
  cssAnimationsRegistry_->remove(viewTag.asNumber());
430
599
  }
431
600
 
432
- void ReanimatedModuleProxy::registerCSSTransition(
601
+ void ReanimatedModuleProxy::runCSSTransition(
433
602
  jsi::Runtime &rt,
434
603
  const jsi::Value &shadowNodeWrapper,
435
604
  const jsi::Value &transitionConfig) {
436
605
  auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
606
+ auto config = parseCSSTransitionConfig(rt, shadowNode->getComponentName(), transitionConfig);
437
607
 
438
- auto transition = std::make_shared<CSSTransition>(
439
- std::move(shadowNode), parseCSSTransitionConfig(rt, transitionConfig), viewStylesRepository_);
608
+ auto lock = updatesRegistryManager_->lock();
609
+ cssTransitionsRegistry_->updateConfigOrRun(rt, shadowNode, std::move(config));
610
+ }
440
611
 
441
- {
442
- auto lock = cssTransitionsRegistry_->lock();
443
- cssTransitionsRegistry_->add(transition);
444
- }
445
- maybeRunCSSLoop();
612
+ void ReanimatedModuleProxy::unregisterCSSTransition(jsi::Runtime &rt, const jsi::Value &viewTag) {
613
+ auto lock = updatesRegistryManager_->lock();
614
+ cssTransitionsRegistry_->remove(viewTag.asNumber());
446
615
  }
447
616
 
448
- void ReanimatedModuleProxy::updateCSSTransition(
617
+ void ReanimatedModuleProxy::registerPseudoStyles(
449
618
  jsi::Runtime &rt,
450
- const jsi::Value &viewTag,
451
- const jsi::Value &configUpdates) {
452
- auto lock = cssTransitionsRegistry_->lock();
453
- cssTransitionsRegistry_->updateSettings(viewTag.asNumber(), parsePartialCSSTransitionConfig(rt, configUpdates));
454
- maybeRunCSSLoop();
619
+ const jsi::Value &shadowNodeWrapper,
620
+ const jsi::Value &config) {
621
+ const auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
622
+ const auto tag = shadowNode->getTag();
623
+ const auto configObj = config.asObject(rt);
624
+
625
+ const auto defaultStyle = jsi::dynamicFromValue(rt, configObj.getProperty(rt, "defaultStyle"));
626
+ const auto selectorsArray = configObj.getProperty(rt, "selectors").asObject(rt).asArray(rt);
627
+ const auto selectorsCount = selectorsArray.size(rt);
628
+
629
+ std::vector<PseudoStylesRegistry::SelectorRegistration> selectors;
630
+ selectors.reserve(selectorsCount);
631
+
632
+ auto lock = updatesRegistryManager_->lock();
633
+
634
+ for (size_t i = 0; i < selectorsCount; ++i) {
635
+ const auto entryObj = selectorsArray.getValueAtIndex(rt, i).asObject(rt);
636
+ const auto selectorEnum = pseudoSelectorFromString(stringFromValue(rt, entryObj.getProperty(rt, "selector")));
637
+ if (!selectorEnum) {
638
+ continue;
639
+ }
640
+
641
+ auto transitionConfig =
642
+ css::parseCSSTransitionConfig(rt, shadowNode->getComponentName(), entryObj.getProperty(rt, "transition"));
643
+ // TODO - clean up pseudo selectors registration not to have to clear the changedProperties object
644
+ transitionConfig.changedProperties.clear();
645
+ cssTransitionsRegistry_->updateConfigOrRun(rt, shadowNode, std::move(transitionConfig));
646
+
647
+ selectors.push_back({*selectorEnum, jsi::dynamicFromValue(rt, entryObj.getProperty(rt, "selectorStyle"))});
648
+ }
649
+
650
+ pseudoStylesRegistry_->registerPseudoStyles(tag, shadowNode, defaultStyle, selectors);
455
651
  }
456
652
 
457
- void ReanimatedModuleProxy::unregisterCSSTransition(jsi::Runtime &rt, const jsi::Value &viewTag) {
458
- auto lock = cssTransitionsRegistry_->lock();
459
- cssTransitionsRegistry_->remove(viewTag.asNumber());
653
+ void ReanimatedModuleProxy::unregisterPseudoStyles(jsi::Runtime &, const jsi::Value &viewTag) {
654
+ auto lock = updatesRegistryManager_->lock();
655
+ pseudoStylesRegistry_->remove(viewTag.asNumber());
460
656
  }
461
657
 
462
658
  jsi::Value ReanimatedModuleProxy::getSettledUpdates(jsi::Runtime &rt) {
@@ -464,18 +660,14 @@ jsi::Value ReanimatedModuleProxy::getSettledUpdates(jsi::Runtime &rt) {
464
660
  StaticFeatureFlags::getFlag("FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS") &&
465
661
  "getSettledUpdates requires FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS static feature flag to be enabled");
466
662
 
663
+ constexpr double SETTLED_ANIMATION_THRESHOLD_MS = 1000;
664
+
467
665
  // TODO(future): use unified timestamp
468
666
  const auto currentTimestamp = getAnimationTimestamp_();
469
667
 
470
- const auto lock = animatedPropsRegistry_->lock();
471
-
472
- // TODO: fix bug when threshold difference is smaller than 1 second
473
668
  // TODO(future): flush updates from CSS animations and CSS transitions registries
474
- animatedPropsRegistry_->removeUpdatesOlderThanTimestamp(currentTimestamp - 2000); // 2 seconds
475
-
476
- // TODO(future): find a better way to obtain timestamp for removing updates
477
- // TODO(future): move removing old updates to separate method
478
- return animatedPropsRegistry_->getUpdatesOlderThanTimestamp(rt, currentTimestamp - 1000); // 1 second
669
+ auto lock = updatesRegistryManager_->lock();
670
+ return animatedPropsRegistry_->collectSettledUpdates(rt, currentTimestamp - SETTLED_ANIMATION_THRESHOLD_MS);
479
671
  }
480
672
 
481
673
  bool ReanimatedModuleProxy::handleEvent(
@@ -485,8 +677,7 @@ bool ReanimatedModuleProxy::handleEvent(
485
677
  double currentTime) {
486
678
  ReanimatedSystraceSection s("ReanimatedModuleProxy::handleEvent");
487
679
 
488
- eventHandlerRegistry_->processEvent(
489
- workletsModuleProxy_->getUIWorkletRuntime(), currentTime, eventName, emitterReactTag, payload);
680
+ eventHandlerRegistry_->processEvent(uiRuntime_, currentTime, eventName, emitterReactTag, payload);
490
681
 
491
682
  // TODO: return true if Reanimated successfully handled the event
492
683
  // to avoid sending it to JavaScript
@@ -514,12 +705,12 @@ bool ReanimatedModuleProxy::handleRawEvent(const RawEvent &rawEvent, double curr
514
705
 
515
706
  if constexpr (StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
516
707
  if (eventType == "onTransitionProgress") {
517
- jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
708
+ jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(uiRuntime_);
518
709
  const auto &eventPayload = rawEvent.eventPayload;
519
- jsi::Object payload = eventPayload->asJSIValue(rt).asObject(rt);
520
- auto progress = payload.getProperty(rt, "progress").asNumber();
521
- auto closing = static_cast<bool>(payload.getProperty(rt, "closing").asNumber());
522
- auto goingForward = static_cast<bool>(payload.getProperty(rt, "goingForward").asNumber());
710
+ jsi::Object payload = eventPayload->asJSIValue(uiRuntime).asObject(uiRuntime);
711
+ auto progress = payload.getProperty(uiRuntime, "progress").asNumber();
712
+ auto closing = static_cast<bool>(payload.getProperty(uiRuntime, "closing").asNumber());
713
+ auto goingForward = static_cast<bool>(payload.getProperty(uiRuntime, "goingForward").asNumber());
523
714
 
524
715
  if (!layoutAnimationsProxy_) {
525
716
  return false;
@@ -551,76 +742,43 @@ bool ReanimatedModuleProxy::handleRawEvent(const RawEvent &rawEvent, double curr
551
742
  return false;
552
743
  }
553
744
 
554
- jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
745
+ jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(uiRuntime_);
555
746
  const auto &eventPayload = rawEvent.eventPayload;
556
- jsi::Value payload = eventPayload->asJSIValue(rt);
747
+ jsi::Value payload = eventPayload->asJSIValue(uiRuntime);
748
+
749
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
750
+ return handleEventAndFlush(eventType, tag, payload, GrandCallbackSource::Event);
751
+ }
557
752
 
558
753
  auto res = handleEvent(eventType, tag, payload, currentTime);
559
754
  // TODO: we should call performOperations conditionally if event is handled
560
755
  // (res == true), but for now handleEvent always returns false. Thankfully,
561
756
  // performOperations does not trigger a lot of code if there is nothing to
562
757
  // be done so this is fine for now.
563
- performOperations(true);
758
+ performOperations();
564
759
  return res;
565
760
  }
566
761
 
567
- void ReanimatedModuleProxy::cssLoopCallback(const double /*timestampMs*/) {
568
- shouldUpdateCssAnimations_ = true;
569
- if (cssAnimationsRegistry_->hasUpdates() || cssTransitionsRegistry_->hasUpdates()
570
- #ifdef ANDROID
571
- || updatesRegistryManager_->hasPropsToRevert()
572
- #endif // ANDROID
573
- ) {
574
- requestRender_([weakThis = weak_from_this()](const double newTimestampMs) {
575
- if (auto strongThis = weakThis.lock()) {
576
- strongThis->cssLoopCallback(newTimestampMs);
577
- }
578
- });
579
- } else {
580
- cssLoopRunning_ = false;
762
+ void ReanimatedModuleProxy::executeLayoutAnimationsRequests() {
763
+ std::set<SurfaceId> flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
764
+ for (const auto surfaceId : flushRequestsCopy) {
765
+ uiManager_->getShadowTreeRegistry().visit(
766
+ surfaceId, [](const ShadowTree &shadowTree) { shadowTree.notifyDelegatesOfUpdates(); });
581
767
  }
582
768
  }
583
769
 
584
- void ReanimatedModuleProxy::maybeRunCSSLoop() {
585
- if (cssLoopRunning_) {
770
+ void ReanimatedModuleProxy::performOperations() {
771
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
772
+ react_native_assert(
773
+ false && "[Reanimated] performOperations must not be called when USE_ANIMATION_BACKEND is enabled");
586
774
  return;
587
775
  }
588
776
 
589
- cssLoopRunning_ = true;
590
-
591
- workletsModuleProxy_->getUIScheduler()->scheduleOnUI([weakThis = weak_from_this()]() {
592
- auto strongThis = weakThis.lock();
593
- if (!strongThis) {
594
- return;
595
- }
596
- strongThis->requestRender_([weakThis](const double timestampMs) {
597
- if (auto strongThis = weakThis.lock()) {
598
- strongThis->cssLoopCallback(timestampMs);
599
- }
600
- });
601
- });
602
- }
603
-
604
- double ReanimatedModuleProxy::getCssTimestamp() {
605
- if (cssLoopRunning_) {
606
- return currentCssTimestamp_;
607
- }
608
- currentCssTimestamp_ = getAnimationTimestamp_();
609
- return currentCssTimestamp_;
610
- }
611
-
612
- void ReanimatedModuleProxy::performOperations(const bool isTriggeredByEvent) {
613
777
  ReanimatedSystraceSection s("ReanimatedModuleProxy::performOperations");
614
778
 
615
- if (!isTriggeredByEvent) {
616
- auto flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
617
- for (const auto surfaceId : flushRequestsCopy) {
618
- uiManager_->getShadowTreeRegistry().visit(
619
- surfaceId, [](const ShadowTree &shadowTree) { shadowTree.notifyDelegatesOfUpdates(); });
620
- }
621
- }
779
+ executeLayoutAnimationsRequests();
622
780
 
623
- jsi::Runtime &rt = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
781
+ jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(uiRuntime_);
624
782
 
625
783
  UpdatesBatch updatesBatch;
626
784
  {
@@ -628,510 +786,261 @@ void ReanimatedModuleProxy::performOperations(const bool isTriggeredByEvent) {
628
786
 
629
787
  auto lock = updatesRegistryManager_->lock();
630
788
 
631
- if (shouldUpdateCssAnimations_) {
632
- currentCssTimestamp_ = getAnimationTimestamp_();
633
- auto lock = cssTransitionsRegistry_->lock();
789
+ if (cssTransitionsRegistry_->needsFlush()) {
634
790
  // Update CSS transitions and flush updates
635
- cssTransitionsRegistry_->update(currentCssTimestamp_);
636
791
  cssTransitionsRegistry_->flushUpdates(updatesBatch);
637
792
  }
638
793
 
639
- {
640
- auto lock = animatedPropsRegistry_->lock();
641
- // Flush all animated props updates
642
- animatedPropsRegistry_->flushUpdates(updatesBatch);
643
- }
794
+ // Flush all animated props updates
795
+ animatedPropsRegistry_->flushUpdates(updatesBatch);
644
796
 
645
- if (shouldUpdateCssAnimations_) {
646
- auto lock = cssAnimationsRegistry_->lock();
797
+ if (cssAnimationsRegistry_->needsFlush()) {
647
798
  // Update CSS animations and flush updates
648
- cssAnimationsRegistry_->update(currentCssTimestamp_);
649
799
  cssAnimationsRegistry_->flushUpdates(updatesBatch);
650
800
  }
801
+ }
651
802
 
652
- shouldUpdateCssAnimations_ = false;
653
-
654
- #ifdef ANDROID
655
- if constexpr (
656
- StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
657
- !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
658
- static const std::unordered_set<std::string> synchronousProps = {
659
- "opacity",
660
- "elevation",
661
- "zIndex",
662
- // "shadowOpacity", // not supported on Android
663
- // "shadowRadius", // not supported on Android
664
- "backgroundColor",
665
- // "color", // TODO: fix animating color of Animated.Text
666
- "tintColor",
667
- "borderRadius",
668
- "borderTopLeftRadius",
669
- "borderTopRightRadius",
670
- "borderTopStartRadius",
671
- "borderTopEndRadius",
672
- "borderBottomLeftRadius",
673
- "borderBottomRightRadius",
674
- "borderBottomStartRadius",
675
- "borderBottomEndRadius",
676
- "borderStartStartRadius",
677
- "borderStartEndRadius",
678
- "borderEndStartRadius",
679
- "borderEndEndRadius",
680
- "borderColor",
681
- "borderTopColor",
682
- "borderBottomColor",
683
- "borderLeftColor",
684
- "borderRightColor",
685
- "borderStartColor",
686
- "borderEndColor",
687
- "transform",
688
- };
689
-
690
- // NOTE: Keep in sync with NativeProxy.java
691
- static constexpr auto CMD_START_OF_VIEW = 1;
692
- static constexpr auto CMD_START_OF_TRANSFORM = 2;
693
- static constexpr auto CMD_END_OF_TRANSFORM = 3;
694
- static constexpr auto CMD_END_OF_VIEW = 4;
695
-
696
- static constexpr auto CMD_OPACITY = 10;
697
- static constexpr auto CMD_ELEVATION = 11;
698
- static constexpr auto CMD_Z_INDEX = 12;
699
- static constexpr auto CMD_SHADOW_OPACITY = 13;
700
- static constexpr auto CMD_SHADOW_RADIUS = 14;
701
- static constexpr auto CMD_BACKGROUND_COLOR = 15;
702
- static constexpr auto CMD_COLOR = 16;
703
- static constexpr auto CMD_TINT_COLOR = 17;
704
-
705
- static constexpr auto CMD_BORDER_RADIUS = 20;
706
- static constexpr auto CMD_BORDER_TOP_LEFT_RADIUS = 21;
707
- static constexpr auto CMD_BORDER_TOP_RIGHT_RADIUS = 22;
708
- static constexpr auto CMD_BORDER_TOP_START_RADIUS = 23;
709
- static constexpr auto CMD_BORDER_TOP_END_RADIUS = 24;
710
- static constexpr auto CMD_BORDER_BOTTOM_LEFT_RADIUS = 25;
711
- static constexpr auto CMD_BORDER_BOTTOM_RIGHT_RADIUS = 26;
712
- static constexpr auto CMD_BORDER_BOTTOM_START_RADIUS = 27;
713
- static constexpr auto CMD_BORDER_BOTTOM_END_RADIUS = 28;
714
- static constexpr auto CMD_BORDER_START_START_RADIUS = 29;
715
- static constexpr auto CMD_BORDER_START_END_RADIUS = 30;
716
- static constexpr auto CMD_BORDER_END_START_RADIUS = 31;
717
- static constexpr auto CMD_BORDER_END_END_RADIUS = 32;
718
-
719
- static constexpr auto CMD_BORDER_COLOR = 40;
720
- static constexpr auto CMD_BORDER_TOP_COLOR = 41;
721
- static constexpr auto CMD_BORDER_BOTTOM_COLOR = 42;
722
- static constexpr auto CMD_BORDER_LEFT_COLOR = 43;
723
- static constexpr auto CMD_BORDER_RIGHT_COLOR = 44;
724
- static constexpr auto CMD_BORDER_START_COLOR = 45;
725
- static constexpr auto CMD_BORDER_END_COLOR = 46;
726
-
727
- static constexpr auto CMD_TRANSFORM_TRANSLATE_X = 100;
728
- static constexpr auto CMD_TRANSFORM_TRANSLATE_Y = 101;
729
- static constexpr auto CMD_TRANSFORM_SCALE = 102;
730
- static constexpr auto CMD_TRANSFORM_SCALE_X = 103;
731
- static constexpr auto CMD_TRANSFORM_SCALE_Y = 104;
732
- static constexpr auto CMD_TRANSFORM_ROTATE = 105;
733
- static constexpr auto CMD_TRANSFORM_ROTATE_X = 106;
734
- static constexpr auto CMD_TRANSFORM_ROTATE_Y = 107;
735
- static constexpr auto CMD_TRANSFORM_ROTATE_Z = 108;
736
- static constexpr auto CMD_TRANSFORM_SKEW_X = 109;
737
- static constexpr auto CMD_TRANSFORM_SKEW_Y = 110;
738
- static constexpr auto CMD_TRANSFORM_MATRIX = 111;
739
- static constexpr auto CMD_TRANSFORM_PERSPECTIVE = 112;
740
-
741
- static constexpr auto CMD_UNIT_DEG = 200;
742
- static constexpr auto CMD_UNIT_RAD = 201;
743
- static constexpr auto CMD_UNIT_PX = 202;
744
- static constexpr auto CMD_UNIT_PERCENT = 203;
745
-
746
- const auto propNameToCommand = [](const std::string &name) {
747
- if (name == "opacity")
748
- return CMD_OPACITY;
749
-
750
- if (name == "elevation")
751
- return CMD_ELEVATION;
752
-
753
- if (name == "zIndex")
754
- return CMD_Z_INDEX;
755
-
756
- if (name == "shadowOpacity")
757
- return CMD_SHADOW_OPACITY;
758
-
759
- if (name == "shadowRadius")
760
- return CMD_SHADOW_RADIUS;
761
-
762
- if (name == "backgroundColor")
763
- return CMD_BACKGROUND_COLOR;
764
-
765
- if (name == "color")
766
- return CMD_COLOR;
767
-
768
- if (name == "tintColor")
769
- return CMD_TINT_COLOR;
770
-
771
- if (name == "borderRadius")
772
- return CMD_BORDER_RADIUS;
773
-
774
- if (name == "borderTopLeftRadius")
775
- return CMD_BORDER_TOP_LEFT_RADIUS;
776
-
777
- if (name == "borderTopRightRadius")
778
- return CMD_BORDER_TOP_RIGHT_RADIUS;
779
-
780
- if (name == "borderTopStartRadius")
781
- return CMD_BORDER_TOP_START_RADIUS;
782
-
783
- if (name == "borderTopEndRadius")
784
- return CMD_BORDER_TOP_END_RADIUS;
785
-
786
- if (name == "borderBottomLeftRadius")
787
- return CMD_BORDER_BOTTOM_LEFT_RADIUS;
788
-
789
- if (name == "borderBottomRightRadius")
790
- return CMD_BORDER_BOTTOM_RIGHT_RADIUS;
791
-
792
- if (name == "borderBottomStartRadius")
793
- return CMD_BORDER_BOTTOM_START_RADIUS;
794
-
795
- if (name == "borderBottomEndRadius")
796
- return CMD_BORDER_BOTTOM_END_RADIUS;
797
-
798
- if (name == "borderStartStartRadius")
799
- return CMD_BORDER_START_START_RADIUS;
800
-
801
- if (name == "borderStartEndRadius")
802
- return CMD_BORDER_START_END_RADIUS;
803
-
804
- if (name == "borderEndStartRadius")
805
- return CMD_BORDER_END_START_RADIUS;
806
-
807
- if (name == "borderEndEndRadius")
808
- return CMD_BORDER_END_END_RADIUS;
809
-
810
- if (name == "borderColor")
811
- return CMD_BORDER_COLOR;
812
-
813
- if (name == "borderTopColor")
814
- return CMD_BORDER_TOP_COLOR;
815
-
816
- if (name == "borderBottomColor")
817
- return CMD_BORDER_BOTTOM_COLOR;
818
-
819
- if (name == "borderLeftColor")
820
- return CMD_BORDER_LEFT_COLOR;
821
-
822
- if (name == "borderRightColor")
823
- return CMD_BORDER_RIGHT_COLOR;
824
-
825
- if (name == "borderStartColor")
826
- return CMD_BORDER_START_COLOR;
803
+ if constexpr (shouldUseSynchronousUpdatesInPerformOperations()) {
804
+ applySynchronousUpdates(updatesBatch, false);
805
+ }
827
806
 
828
- if (name == "borderEndColor")
829
- return CMD_BORDER_END_COLOR;
807
+ if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
808
+ // It may happen that `performOperations` is called on the UI thread
809
+ // while React Native tries to commit a new tree on the JS thread.
810
+ // In this case, we should skip the commit here and let React Native do
811
+ // it. The commit will include the current values from the updates manager
812
+ // which will be applied in ReanimatedCommitHook.
813
+ if (!updatesBatch.empty()) {
814
+ updatesRegistryManager_->pleaseCommitAfterPause();
815
+ }
816
+ return;
817
+ }
830
818
 
831
- if (name == "transform")
832
- return CMD_START_OF_TRANSFORM; // TODO: use CMD_TRANSFORM?
819
+ commitUpdates(uiRuntime, updatesBatch);
820
+ }
833
821
 
834
- throw std::runtime_error("[Reanimated] Unsupported style: " + name);
835
- };
822
+ void ReanimatedModuleProxy::performNonLayoutOperations() {
823
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::performNonLayoutOperations");
836
824
 
837
- const auto transformNameToCommand = [](const std::string &name) {
838
- if (name == "translateX")
839
- return CMD_TRANSFORM_TRANSLATE_X;
825
+ UpdatesBatch updatesBatch;
826
+ {
827
+ auto lock = updatesRegistryManager_->lock();
828
+ updatesBatch = animatedPropsRegistry_->getPendingUpdates();
829
+ }
830
+ applySynchronousUpdates(updatesBatch, true);
831
+ }
840
832
 
841
- if (name == "translateY")
842
- return CMD_TRANSFORM_TRANSLATE_Y;
833
+ #if REACT_NATIVE_VERSION_MINOR >= 85
834
+ AnimationMutations ReanimatedModuleProxy::collectNonLayoutAnimationUpdates() {
835
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::collectNonLayoutAnimationUpdates");
843
836
 
844
- if (name == "scale")
845
- return CMD_TRANSFORM_SCALE;
837
+ AnimationMutations mutations;
838
+ jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(uiRuntime_);
839
+ {
840
+ auto lock = updatesRegistryManager_->lock();
841
+ animatedPropsRegistry_->flushNonLayoutUpdates(uiRuntime, mutations);
842
+ }
843
+ return mutations;
844
+ }
846
845
 
847
- if (name == "scaleX")
848
- return CMD_TRANSFORM_SCALE_X;
846
+ std::shared_ptr<UIManagerAnimationBackend> ReanimatedModuleProxy::getAnimationBackend() {
847
+ react_native_assert(
848
+ uiManager_ != nullptr && "[Reanimated] Animation Backend used before the uiManager was registered");
849
+ auto locked = uiManager_->unstable_getAnimationBackend().lock();
850
+ // UIManager owns the backend, so this is just a sanity check.
851
+ react_native_assert(
852
+ locked != nullptr &&
853
+ "[Reanimated] Animation Backend is null (UIManager not wired to a backend yet or already torn down)");
854
+ return locked;
855
+ }
856
+ #endif
849
857
 
850
- if (name == "scaleY")
851
- return CMD_TRANSFORM_SCALE_Y;
858
+ void ReanimatedModuleProxy::startBackendIfNeeded() {
859
+ #if REACT_NATIVE_VERSION_MINOR >= 85
860
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
861
+ if (isAnimationRunning_) {
862
+ return;
863
+ }
864
+ animationBackendCallbackId_ =
865
+ getAnimationBackend()->start([weakThis = weak_from_this()](AnimationTimestamp timestamp) {
866
+ auto strongThis = weakThis.lock();
867
+ if (!strongThis) {
868
+ return AnimationMutations{};
869
+ }
870
+ return strongThis->runGrandCallback(timestamp, GrandCallbackSource::AnimationLoop);
871
+ });
872
+ isAnimationRunning_ = true;
873
+ }
874
+ #endif
875
+ }
852
876
 
853
- if (name == "rotate")
854
- return CMD_TRANSFORM_ROTATE;
877
+ void ReanimatedModuleProxy::stopBackendIfIdle(const bool producedMutations) {
878
+ #if REACT_NATIVE_VERSION_MINOR >= 85
879
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
880
+ const bool hasWork = producedMutations || !pendingFrameCallbacks_.empty() ||
881
+ pendingAnimationFrameCallbackFromWorklets_ != nullptr || operationsLoop_->hasOngoingOperations() ||
882
+ animatedPropsRegistry_->hasPendingAnimatedPropsUpdates() || shouldFlushRegistry_ ||
883
+ !layoutAnimationFlushRequests_.empty();
884
+ if (!hasWork) {
885
+ getAnimationBackend()->stop(animationBackendCallbackId_);
886
+ isAnimationRunning_ = false;
887
+ }
888
+ }
889
+ #endif
890
+ }
855
891
 
856
- if (name == "rotateX")
857
- return CMD_TRANSFORM_ROTATE_X;
892
+ #if REACT_NATIVE_VERSION_MINOR >= 85
893
+ AnimationMutations ReanimatedModuleProxy::mutationsFromAnimatedPropsBatch(
894
+ UpdatesBatchAnimatedProps &&animatedPropsBatch) {
895
+ // This is a temporary fix, in reanimated we can sometimes produce multiple updates for the same view
896
+ // In that case Animation Backend will only apply the last one.
897
+ // Until the fix is implemented there, we will keep the merging logic here.
898
+ AnimationMutations mutations;
899
+ mutations.batch.reserve(animatedPropsBatch.size());
900
+ std::unordered_map<Tag, size_t> mutationIndexByTag;
901
+ for (auto &[shadowNodeFamily, animatedProps, hasLayoutUpdates] : animatedPropsBatch) {
902
+ const auto tag = shadowNodeFamily->getTag();
903
+
904
+ const auto it = mutationIndexByTag.find(tag);
905
+ if (it == mutationIndexByTag.end()) {
906
+ mutationIndexByTag.emplace(tag, mutations.batch.size());
907
+ mutations.batch.push_back(AnimationMutation{tag, shadowNodeFamily, std::move(animatedProps), hasLayoutUpdates});
908
+ } else {
909
+ auto &mutation = mutations.batch[it->second];
910
+ mutation.hasLayoutUpdates |= hasLayoutUpdates;
911
+ mergeAnimatedProps(mutation.props, std::move(animatedProps));
912
+ }
913
+ }
914
+ return mutations;
915
+ }
858
916
 
859
- if (name == "rotateY")
860
- return CMD_TRANSFORM_ROTATE_Y;
917
+ AnimationMutations ReanimatedModuleProxy::runGrandCallback(
918
+ const AnimationTimestamp timestamp,
919
+ const GrandCallbackSource source) {
920
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::runGrandCallback");
921
+
922
+ switch (source) {
923
+ case GrandCallbackSource::AnimationLoop: {
924
+ // Worklet callbacks and layout animation flushes run outside the manager
925
+ // lock: they touch only UI-thread state and may re-enter the proxy (via
926
+ // requestAnimationFrame or the commit hook).
927
+ executeWorkletsForFrame(timestamp);
928
+ executeLayoutAnimationsRequests();
929
+
930
+ AnimationMutations mutations;
931
+ {
932
+ auto lock = updatesRegistryManager_->lock();
933
+ executeOperationsLoop(timestamp);
934
+ mutations = executeOperationsAndCollectUpdates(timestamp);
935
+ stopBackendIfIdle(!mutations.batch.empty());
936
+ }
937
+ return mutations;
938
+ }
861
939
 
862
- if (name == "rotateZ")
863
- return CMD_TRANSFORM_ROTATE_Z;
940
+ case GrandCallbackSource::Event: {
941
+ executeLayoutAnimationsRequests();
942
+ return collectEventUpdates();
943
+ }
864
944
 
865
- if (name == "skewX")
866
- return CMD_TRANSFORM_SKEW_X;
945
+ case GrandCallbackSource::EventInAndroidDraw:
946
+ return collectNonLayoutAnimationUpdates();
947
+ }
867
948
 
868
- if (name == "skewY")
869
- return CMD_TRANSFORM_SKEW_Y;
949
+ return AnimationMutations{};
950
+ }
870
951
 
871
- if (name == "matrix")
872
- return CMD_TRANSFORM_MATRIX;
952
+ void ReanimatedModuleProxy::executeOperationsLoop(const AnimationTimestamp timestamp) {
953
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::executeOperationsLoop");
873
954
 
874
- if (name == "perspective")
875
- return CMD_TRANSFORM_PERSPECTIVE;
955
+ auto pendingFrameCallbacks = std::exchange(pendingFrameCallbacks_, {});
956
+ for (auto &cb : pendingFrameCallbacks) {
957
+ cb(timestamp.count());
958
+ }
959
+ }
876
960
 
877
- throw std::runtime_error("[Reanimated] Unsupported transform: " + name);
878
- };
961
+ void ReanimatedModuleProxy::executeWorkletsForFrame(const AnimationTimestamp timestamp) {
962
+ if (!pendingAnimationFrameCallbackFromWorklets_) {
963
+ return;
964
+ }
965
+ auto cb = std::exchange(pendingAnimationFrameCallbackFromWorklets_, nullptr);
966
+ cb(timestamp.count());
967
+ }
879
968
 
880
- UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
969
+ AnimationMutations ReanimatedModuleProxy::executeOperationsAndCollectUpdates(const AnimationTimestamp timestamp) {
970
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::executeOperationsAndCollectUpdates");
881
971
 
882
- for (const auto &[shadowNode, props] : updatesBatch) {
883
- bool hasOnlySynchronousProps = true;
884
- for (const auto &[key, value] : props.items()) {
885
- const auto keyStr = key.asString();
886
- if (!synchronousProps.contains(keyStr) ||
887
- ((keyStr == "color" || keyStr.find("Color") != std::string::npos) && !value.isInt())) {
888
- hasOnlySynchronousProps = false;
889
- break;
890
- }
891
- }
892
- if (hasOnlySynchronousProps) {
893
- synchronousUpdatesBatch.emplace_back(shadowNode, props);
894
- } else {
895
- shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
896
- }
897
- }
972
+ UpdatesBatchAnimatedProps batch;
898
973
 
899
- if (!synchronousUpdatesBatch.empty()) {
900
- std::vector<int> intBuffer;
901
- std::vector<double> doubleBuffer;
902
- intBuffer.reserve(1024);
903
- doubleBuffer.reserve(1024);
904
-
905
- for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
906
- intBuffer.push_back(CMD_START_OF_VIEW);
907
- intBuffer.push_back(shadowNode->getTag());
908
- for (const auto &[key, value] : props.items()) {
909
- const auto command = propNameToCommand(key.getString());
910
- switch (command) {
911
- case CMD_OPACITY:
912
- case CMD_ELEVATION:
913
- case CMD_Z_INDEX:
914
- case CMD_SHADOW_OPACITY:
915
- case CMD_SHADOW_RADIUS:
916
- intBuffer.push_back(command);
917
- doubleBuffer.push_back(value.asDouble());
918
- break;
919
-
920
- case CMD_BACKGROUND_COLOR:
921
- case CMD_COLOR:
922
- case CMD_TINT_COLOR:
923
- case CMD_BORDER_COLOR:
924
- case CMD_BORDER_TOP_COLOR:
925
- case CMD_BORDER_BOTTOM_COLOR:
926
- case CMD_BORDER_LEFT_COLOR:
927
- case CMD_BORDER_RIGHT_COLOR:
928
- case CMD_BORDER_START_COLOR:
929
- case CMD_BORDER_END_COLOR:
930
- intBuffer.push_back(command);
931
- intBuffer.push_back(value.asInt());
932
- break;
933
-
934
- case CMD_BORDER_RADIUS:
935
- case CMD_BORDER_TOP_LEFT_RADIUS:
936
- case CMD_BORDER_TOP_RIGHT_RADIUS:
937
- case CMD_BORDER_TOP_START_RADIUS:
938
- case CMD_BORDER_TOP_END_RADIUS:
939
- case CMD_BORDER_BOTTOM_LEFT_RADIUS:
940
- case CMD_BORDER_BOTTOM_RIGHT_RADIUS:
941
- case CMD_BORDER_BOTTOM_START_RADIUS:
942
- case CMD_BORDER_BOTTOM_END_RADIUS:
943
- case CMD_BORDER_START_START_RADIUS:
944
- case CMD_BORDER_START_END_RADIUS:
945
- case CMD_BORDER_END_START_RADIUS:
946
- case CMD_BORDER_END_END_RADIUS:
947
- intBuffer.push_back(command);
948
- if (value.isDouble()) {
949
- intBuffer.push_back(CMD_UNIT_PX);
950
- doubleBuffer.push_back(value.getDouble());
951
- } else if (value.isString()) {
952
- const auto &valueStr = value.getString();
953
- if (!valueStr.ends_with("%")) {
954
- throw std::runtime_error("[Reanimated] Border radius string must be a percentage");
955
- }
956
- intBuffer.push_back(CMD_UNIT_PERCENT);
957
- doubleBuffer.push_back(std::stof(valueStr.substr(0, -1)));
958
- } else {
959
- throw std::runtime_error("[Reanimated] Border radius value must be either a number or a string");
960
- }
961
- break;
962
-
963
- case CMD_START_OF_TRANSFORM:
964
- intBuffer.push_back(command);
965
- react_native_assert(value.isArray() && "[Reanimated] Transform value must be an array");
966
- for (const auto &item : value) {
967
- react_native_assert(item.isObject() && "[Reanimated] Transform array item must be an object");
968
- react_native_assert(
969
- item.size() == 1 && "[Reanimated] Transform array item must have exactly one key-value pair");
970
- const auto transformCommand = transformNameToCommand(item.keys().begin()->getString());
971
- const auto &transformValue = *item.values().begin();
972
- switch (transformCommand) {
973
- case CMD_TRANSFORM_SCALE:
974
- case CMD_TRANSFORM_SCALE_X:
975
- case CMD_TRANSFORM_SCALE_Y:
976
- case CMD_TRANSFORM_PERSPECTIVE: {
977
- intBuffer.push_back(transformCommand);
978
- doubleBuffer.push_back(transformValue.asDouble());
979
- break;
980
- }
981
-
982
- case CMD_TRANSFORM_TRANSLATE_X:
983
- case CMD_TRANSFORM_TRANSLATE_Y: {
984
- intBuffer.push_back(transformCommand);
985
- if (transformValue.isDouble()) {
986
- intBuffer.push_back(CMD_UNIT_PX);
987
- doubleBuffer.push_back(transformValue.getDouble());
988
- } else if (transformValue.isString()) {
989
- const auto &transformValueStr = transformValue.getString();
990
- if (!transformValueStr.ends_with("%")) {
991
- throw std::runtime_error("[Reanimated] String translate must be a percentage");
992
- }
993
- intBuffer.push_back(CMD_UNIT_PERCENT);
994
- doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -1)));
995
- } else {
996
- throw std::runtime_error("[Reanimated] Translate value must be either a number or a string");
997
- }
998
- break;
999
- }
1000
-
1001
- case CMD_TRANSFORM_ROTATE:
1002
- case CMD_TRANSFORM_ROTATE_X:
1003
- case CMD_TRANSFORM_ROTATE_Y:
1004
- case CMD_TRANSFORM_ROTATE_Z:
1005
- case CMD_TRANSFORM_SKEW_X:
1006
- case CMD_TRANSFORM_SKEW_Y: {
1007
- const auto &transformValueStr = transformValue.getString();
1008
- intBuffer.push_back(transformCommand);
1009
- if (transformValueStr.ends_with("deg")) {
1010
- intBuffer.push_back(CMD_UNIT_DEG);
1011
- } else if (transformValueStr.ends_with("rad")) {
1012
- intBuffer.push_back(CMD_UNIT_RAD);
1013
- } else {
1014
- throw std::runtime_error("[Reanimated] Unsupported rotation unit: " + transformValueStr);
1015
- }
1016
- doubleBuffer.push_back(std::stof(transformValueStr.substr(0, -3)));
1017
- break;
1018
- }
1019
-
1020
- case CMD_TRANSFORM_MATRIX: {
1021
- intBuffer.push_back(transformCommand);
1022
- react_native_assert(transformValue.isArray() && "[Reanimated] Matrix must be an array");
1023
- int size = transformValue.size();
1024
- intBuffer.push_back(size);
1025
- for (int i = 0; i < size; i++) {
1026
- doubleBuffer.push_back(transformValue[i].asDouble());
1027
- }
1028
- break;
1029
- }
1030
- }
1031
- }
1032
- intBuffer.push_back(CMD_END_OF_TRANSFORM);
1033
- break;
1034
- }
1035
- }
1036
- intBuffer.push_back(CMD_END_OF_VIEW);
1037
- }
1038
- synchronouslyUpdateUIPropsFunction_(intBuffer, doubleBuffer);
1039
- }
974
+ (void)timestamp;
975
+ cssTransitionsRegistry_->flushUpdates(batch);
976
+ animatedPropsRegistry_->flushUpdates(batch);
977
+ cssAnimationsRegistry_->flushUpdates(batch);
1040
978
 
1041
- updatesBatch = std::move(shadowTreeUpdatesBatch);
1042
- }
1043
- #endif // ANDROID
979
+ return mutationsFromAnimatedPropsBatch(std::move(batch));
980
+ }
1044
981
 
1045
- #if __APPLE__
1046
- if constexpr (
1047
- StaticFeatureFlags::getFlag("IOS_SYNCHRONOUSLY_UPDATE_UI_PROPS") &&
1048
- !StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) {
1049
- static const std::unordered_set<std::string> synchronousProps = {
1050
- "opacity",
1051
- "elevation",
1052
- "zIndex",
1053
- "shadowOpacity",
1054
- "shadowRadius",
1055
- "backgroundColor",
1056
- // "color", // TODO: fix animating color of Animated.Text
1057
- "tintColor",
1058
- "borderRadius",
1059
- "borderTopLeftRadius",
1060
- "borderTopRightRadius",
1061
- "borderTopStartRadius",
1062
- "borderTopEndRadius",
1063
- "borderBottomLeftRadius",
1064
- "borderBottomRightRadius",
1065
- "borderBottomStartRadius",
1066
- "borderBottomEndRadius",
1067
- "borderStartStartRadius",
1068
- "borderStartEndRadius",
1069
- "borderEndStartRadius",
1070
- "borderEndEndRadius",
1071
- "borderColor",
1072
- "borderTopColor",
1073
- "borderBottomColor",
1074
- "borderLeftColor",
1075
- "borderRightColor",
1076
- "borderStartColor",
1077
- "borderEndColor",
1078
- "transform",
1079
- };
982
+ AnimationMutations ReanimatedModuleProxy::collectEventUpdates() {
983
+ ReanimatedSystraceSection s("ReanimatedModuleProxy::collectEventUpdates");
1080
984
 
1081
- UpdatesBatch synchronousUpdatesBatch, shadowTreeUpdatesBatch;
985
+ UpdatesBatchAnimatedProps batch;
986
+ auto lock = updatesRegistryManager_->lock();
987
+ animatedPropsRegistry_->flushUpdates(batch);
1082
988
 
1083
- for (const auto &[shadowNode, props] : updatesBatch) {
1084
- bool hasOnlySynchronousProps = true;
1085
- for (const auto &key : props.keys()) {
1086
- const auto keyStr = key.asString();
1087
- if (!synchronousProps.contains(keyStr)) {
1088
- hasOnlySynchronousProps = false;
1089
- break;
1090
- }
1091
- }
1092
- if (hasOnlySynchronousProps) {
1093
- synchronousUpdatesBatch.emplace_back(shadowNode, props);
1094
- } else {
1095
- shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
1096
- }
1097
- }
989
+ return mutationsFromAnimatedPropsBatch(std::move(batch));
990
+ }
991
+ #endif
1098
992
 
1099
- for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
1100
- synchronouslyUpdateUIPropsFunction_(shadowNode->getTag(), props);
1101
- }
993
+ bool ReanimatedModuleProxy::handleEventAndFlush(
994
+ const std::string &eventName,
995
+ const int emitterReactTag,
996
+ const jsi::Value &payload,
997
+ const GrandCallbackSource source) {
998
+ bool handled = false;
999
+ #if REACT_NATIVE_VERSION_MINOR >= 85 && (REACT_NATIVE_VERSION_MINOR > 85 || REACT_NATIVE_VERSION_PATCH >= 2)
1000
+ getAnimationBackend()->pushAnimationMutations([&, source](AnimationTimestamp timestamp) {
1001
+ handled = handleEvent(eventName, emitterReactTag, payload, timestamp.count());
1002
+ return runGrandCallback(timestamp, source);
1003
+ });
1004
+ #else
1005
+ (void)eventName;
1006
+ (void)emitterReactTag;
1007
+ (void)payload;
1008
+ (void)source;
1009
+ #endif
1010
+ return handled;
1011
+ }
1102
1012
 
1103
- updatesBatch = std::move(shadowTreeUpdatesBatch);
1104
- }
1105
- #endif // __APPLE__
1013
+ void ReanimatedModuleProxy::applySynchronousUpdates(UpdatesBatch &updatesBatch, const bool allowPartialUpdates) {
1014
+ auto [synchronousUpdatesBatch, shadowTreeUpdatesBatch] = partitionUpdates(updatesBatch, allowPartialUpdates);
1106
1015
 
1107
- if ((updatesBatch.size() > 0) && updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1108
- updatesRegistryManager_->pleaseCommitAfterPause();
1109
- }
1016
+ #ifdef ANDROID
1017
+ if (!synchronousUpdatesBatch.empty()) {
1018
+ serializeSynchronousPropsToBuffers(
1019
+ synchronousUpdatesBatch, synchronousPropsIntBuffer_, synchronousPropsDoubleBuffer_);
1020
+ synchronouslyUpdateUIPropsFunction_(synchronousPropsIntBuffer_, synchronousPropsDoubleBuffer_);
1110
1021
  }
1022
+ #endif // ANDROID
1111
1023
 
1112
- if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
1113
- // It may happen that `performOperations` is called on the UI thread
1114
- // while React Native tries to commit a new tree on the JS thread.
1115
- // In this case, we should skip the commit here and let React Native do
1116
- // it. The commit will include the current values from the updates manager
1117
- // which will be applied in ReanimatedCommitHook.
1118
- return;
1024
+ #if defined(__APPLE__) || defined(__OHOS__)
1025
+ for (const auto &[shadowNodeFamily, props] : synchronousUpdatesBatch) {
1026
+ synchronouslyUpdateUIPropsFunction_(shadowNodeFamily->getTag(), props);
1119
1027
  }
1028
+ #endif // defined(__APPLE__) || defined(__OHOS__)
1120
1029
 
1121
- commitUpdates(rt, updatesBatch);
1122
-
1123
- // Clear the entire cache after the commit
1124
- // (we don't know if the view is updated from outside of Reanimated
1125
- // so we have to clear the entire cache)
1126
- viewStylesRepository_->clearNodesCache();
1030
+ updatesBatch = std::move(shadowTreeUpdatesBatch);
1127
1031
  }
1128
1032
 
1129
1033
  void ReanimatedModuleProxy::requestFlushRegistry() {
1130
- requestRender_([weakThis = weak_from_this()](const double timestamp) {
1131
- if (auto strongThis = weakThis.lock()) {
1132
- strongThis->shouldFlushRegistry_ = true;
1133
- }
1134
- });
1034
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
1035
+ shouldFlushRegistry_ = true;
1036
+ startBackendIfNeeded();
1037
+ } else {
1038
+ requestRender_([weakThis = weak_from_this()](const double) {
1039
+ if (auto strongThis = weakThis.lock()) {
1040
+ strongThis->shouldFlushRegistry_ = true;
1041
+ }
1042
+ });
1043
+ }
1135
1044
  }
1136
1045
 
1137
1046
  void ReanimatedModuleProxy::commitUpdates(jsi::Runtime &rt, const UpdatesBatch &updatesBatch) {
@@ -1140,33 +1049,41 @@ void ReanimatedModuleProxy::commitUpdates(jsi::Runtime &rt, const UpdatesBatch &
1140
1049
  const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
1141
1050
 
1142
1051
  std::unordered_map<SurfaceId, PropsMap> propsMapBySurface;
1052
+ PropsMap collectedProps;
1053
+ bool flushRegistry;
1143
1054
 
1055
+ // Release the lock before shadowTree.commit - it re-enters via ReanimatedCommitHook.
1056
+ {
1057
+ auto lock = updatesRegistryManager_->lock();
1144
1058
  #ifdef ANDROID
1145
- updatesRegistryManager_->collectPropsToRevertBySurface(propsMapBySurface);
1059
+ updatesRegistryManager_->collectPropsToRevertBySurface(propsMapBySurface);
1146
1060
  #endif
1061
+ flushRegistry = shouldFlushRegistry_.exchange(false);
1062
+ if (flushRegistry) {
1063
+ collectedProps = updatesRegistryManager_->collectProps();
1064
+ }
1065
+ }
1147
1066
 
1148
- if (shouldFlushRegistry_) {
1149
- shouldFlushRegistry_ = false;
1150
- const auto propsMap = updatesRegistryManager_->collectProps();
1151
- for (auto const &[family, props] : propsMap) {
1152
- const auto surfaceId = family->getSurfaceId();
1153
- auto &propsVector = propsMapBySurface[surfaceId][family];
1067
+ if (flushRegistry) {
1068
+ for (auto const &[family, props] : collectedProps) {
1069
+ auto &propsVector = propsMapBySurface[family->getSurfaceId()][family];
1154
1070
  for (const auto &prop : props) {
1155
1071
  propsVector.emplace_back(prop);
1156
1072
  }
1157
1073
  }
1158
1074
  } else {
1159
- for (auto const &[shadowNode, props] : updatesBatch) {
1160
- SurfaceId surfaceId = shadowNode->getSurfaceId();
1161
- auto family = &shadowNode->getFamily();
1162
- react_native_assert(family->getSurfaceId() == surfaceId);
1163
- propsMapBySurface[surfaceId][family].emplace_back(props);
1075
+ for (auto const &[shadowNodeFamily, props] : updatesBatch) {
1076
+ propsMapBySurface[shadowNodeFamily->getSurfaceId()][shadowNodeFamily].emplace_back(props);
1164
1077
  }
1165
1078
  }
1166
1079
 
1167
- for (const auto &entry : propsMapBySurface) {
1168
- const SurfaceId surfaceId = entry.first;
1169
- const PropsMap &propsMap = entry.second;
1080
+ // OHOS patch: clang 15 doesn't allow capturing a structured binding in a
1081
+ // lambda (P1091 fully landed in clang 16), so `propsMap` below is accessed
1082
+ // through a plain reference to the same map value instead of capturing the
1083
+ // binding itself.
1084
+ for (auto const &entry : propsMapBySurface) {
1085
+ const auto &surfaceId = entry.first;
1086
+ auto &propsMap = entry.second;
1170
1087
  shadowTreeRegistry.visit(surfaceId, [&](ShadowTree const &shadowTree) {
1171
1088
  const auto status = shadowTree.commit(
1172
1089
  [&](RootShadowNode const &oldRootShadowNode) -> RootShadowNode::Unshared {
@@ -1190,6 +1107,7 @@ void ReanimatedModuleProxy::commitUpdates(jsi::Runtime &rt, const UpdatesBatch &
1190
1107
 
1191
1108
  #ifdef ANDROID
1192
1109
  if (status == ShadowTree::CommitStatus::Succeeded) {
1110
+ auto lock = updatesRegistryManager_->lock();
1193
1111
  updatesRegistryManager_->clearPropsToRevert(surfaceId);
1194
1112
  }
1195
1113
  #else
@@ -1223,7 +1141,7 @@ void ReanimatedModuleProxy::dispatchCommand(
1223
1141
 
1224
1142
  jsi::String
1225
1143
  ReanimatedModuleProxy::obtainProp(jsi::Runtime &rt, const jsi::Value &shadowNodeWrapper, const jsi::Value &propName) {
1226
- jsi::Runtime &uiRuntime = workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime();
1144
+ jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(uiRuntime_);
1227
1145
  const auto propNameStr = propName.asString(rt).utf8(rt);
1228
1146
  const auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
1229
1147
  const auto resultStr = obtainPropFromShadowNode(uiRuntime, propNameStr, shadowNode);
@@ -1266,6 +1184,23 @@ void ReanimatedModuleProxy::initializeFabric(const std::shared_ptr<UIManager> &u
1266
1184
  uiManager_ = uiManager;
1267
1185
  viewStylesRepository_->setUIManager(uiManager_);
1268
1186
 
1187
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
1188
+ react_native_assert(
1189
+ (REACT_NATIVE_VERSION_MINOR > 85 || (REACT_NATIVE_VERSION_MINOR == 85 && REACT_NATIVE_VERSION_PATCH >= 2)) &&
1190
+ "[Reanimated] USE_ANIMATION_BACKEND requires React Native 0.85.2 or newer.");
1191
+
1192
+ #if REACT_NATIVE_VERSION_MINOR >= 85
1193
+ if (!ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
1194
+ react_native_assert(
1195
+ false &&
1196
+ "[Reanimated] USE_ANIMATION_BACKEND flag is enabled, "
1197
+ "but ReactNativeFeatureFlags::useSharedAnimatedBackend is disabled. "
1198
+ "Enable the Experimental Release level in React Native, "
1199
+ "or disable the Reanimated Feature Flag");
1200
+ }
1201
+ #endif
1202
+ }
1203
+
1269
1204
  initializeLayoutAnimationsProxy();
1270
1205
 
1271
1206
  const std::function<void()> request = [weakThis = weak_from_this()]() {
@@ -1276,7 +1211,15 @@ void ReanimatedModuleProxy::initializeFabric(const std::shared_ptr<UIManager> &u
1276
1211
 
1277
1212
  strongThis->requestFlushRegistry();
1278
1213
  };
1279
- mountHook_ = std::make_shared<ReanimatedMountHook>(uiManager_, updatesRegistryManager_, request);
1214
+
1215
+ if constexpr (StaticFeatureFlags::getFlag("USE_ANIMATION_BACKEND")) {
1216
+ // TODO: we don't use the mount hook here, but we still need a way to handleNodeRemovals
1217
+ // for now we leave this to leak the memory, a fix will come in a follow-up
1218
+ } else {
1219
+ mountHook_ =
1220
+ std::make_shared<ReanimatedMountHook>(uiManager_, updatesRegistryManager_, viewStylesRepository_, request);
1221
+ }
1222
+
1280
1223
  commitHook_ = std::make_shared<ReanimatedCommitHook>(uiManager_, updatesRegistryManager_, layoutAnimationsProxy_);
1281
1224
  }
1282
1225
 
@@ -1293,10 +1236,10 @@ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
1293
1236
  layoutAnimationsManager_,
1294
1237
  componentDescriptorRegistry,
1295
1238
  scheduler->getContextContainer(),
1296
- workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime(),
1297
- workletsModuleProxy_->getUIScheduler()
1239
+ getJSIRuntimeFromWorkletRuntime(uiRuntime_),
1240
+ uiScheduler_
1298
1241
  #ifdef ANDROID
1299
- ,
1242
+ ,
1300
1243
  filterUnmountedTagsFunction_,
1301
1244
  uiManager_,
1302
1245
  jsInvoker_
@@ -1311,10 +1254,10 @@ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
1311
1254
  layoutAnimationsManager_,
1312
1255
  componentDescriptorRegistry,
1313
1256
  scheduler->getContextContainer(),
1314
- workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime(),
1315
- workletsModuleProxy_->getUIScheduler()
1257
+ getJSIRuntimeFromWorkletRuntime(uiRuntime_),
1258
+ uiScheduler_
1316
1259
  #ifdef ANDROID
1317
- ,
1260
+ ,
1318
1261
  filterUnmountedTagsFunction_,
1319
1262
  uiManager_,
1320
1263
  jsInvoker_
@@ -1342,6 +1285,7 @@ std::function<std::string()> ReanimatedModuleProxy::createRegistriesLeakCheck()
1342
1285
 
1343
1286
  std::string result = "";
1344
1287
 
1288
+ auto lock = strongThis->updatesRegistryManager_->lock();
1345
1289
  result += "AnimatedPropsRegistry: " + format(strongThis->animatedPropsRegistry_->isEmpty());
1346
1290
  result += "\nCSSAnimationsRegistry: " + format(strongThis->cssAnimationsRegistry_->isEmpty());
1347
1291
  result += "\nCSSTransitionsRegistry: " + format(strongThis->cssTransitionsRegistry_->isEmpty());
@@ -1358,16 +1302,18 @@ jsi::Value ReanimatedModuleProxy::subscribeForKeyboardEvents(
1358
1302
  const jsi::Value &handlerWorklet,
1359
1303
  const jsi::Value &isStatusBarTranslucent,
1360
1304
  const jsi::Value &isNavigationBarTranslucent) {
1361
- auto serializableHandler = extractSerializableOrThrow<SerializableWorklet>(
1362
- rt, handlerWorklet, "[Reanimated] Keyboard event handler must be a worklet.");
1305
+ auto serializableHandler = extractSerializable(
1306
+ rt,
1307
+ handlerWorklet,
1308
+ "[Reanimated] Keyboard event handler must be a worklet.",
1309
+ Serializable::ValueType::WorkletType);
1363
1310
  return subscribeForKeyboardEventsFunction_(
1364
1311
  [=, weakThis = weak_from_this()](int keyboardState, int height) {
1365
1312
  auto strongThis = weakThis.lock();
1366
1313
  if (!strongThis) {
1367
1314
  return;
1368
1315
  }
1369
- strongThis->workletsModuleProxy_->getUIWorkletRuntime()->runSync(
1370
- serializableHandler, jsi::Value(keyboardState), jsi::Value(height));
1316
+ runSyncOnRuntime(strongThis->uiRuntime_, serializableHandler, jsi::Value(keyboardState), jsi::Value(height));
1371
1317
  },
1372
1318
  isStatusBarTranslucent.getBool(),
1373
1319
  isNavigationBarTranslucent.getBool());
@@ -1377,4 +1323,296 @@ void ReanimatedModuleProxy::unsubscribeFromKeyboardEvents(jsi::Runtime &, const
1377
1323
  unsubscribeFromKeyboardEventsFunction_(listenerId.asNumber());
1378
1324
  }
1379
1325
 
1326
+ void ReanimatedModuleProxy::toggleSlowAnimationsOnUIRuntime() const {
1327
+ this->jsInvoker_->invokeAsync([](jsi::Runtime &rt) {
1328
+ const auto toggleFn = rt.global().getProperty(rt, "__toggleSlowAnimationsOnUIRuntime");
1329
+ if (!(toggleFn.isObject() && toggleFn.asObject(rt).isFunction(rt))) [[unlikely]] {
1330
+ throw std::runtime_error("[Reanimated] __toggleSlowAnimationsOnUIRuntime function missing on global.");
1331
+ }
1332
+
1333
+ toggleFn.asObject(rt).asFunction(rt).call(rt);
1334
+ });
1335
+ }
1336
+
1337
+ jsi::Object ReanimatedModuleProxy::toOptimizedObject(jsi::Runtime &rt) {
1338
+ using jsi_utils::addMethod;
1339
+ using jsi_utils::at;
1340
+
1341
+ auto obj = jsi::Object(rt);
1342
+
1343
+ addMethod<3>(
1344
+ rt,
1345
+ obj,
1346
+ "registerEventHandler",
1347
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[3]) {
1348
+ auto strongThis = weakThis.lock();
1349
+ if (!strongThis) {
1350
+ return jsi::Value::undefined();
1351
+ }
1352
+ return strongThis->registerEventHandler(rt, at<0>(args), at<1>(args), at<2>(args));
1353
+ });
1354
+
1355
+ addMethod<1>(
1356
+ rt,
1357
+ obj,
1358
+ "unregisterEventHandler",
1359
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1360
+ auto strongThis = weakThis.lock();
1361
+ if (!strongThis) {
1362
+ return;
1363
+ }
1364
+ strongThis->unregisterEventHandler(rt, at<0>(args));
1365
+ });
1366
+
1367
+ addMethod<3>(
1368
+ rt,
1369
+ obj,
1370
+ "getViewProp",
1371
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[3]) {
1372
+ auto strongThis = weakThis.lock();
1373
+ if (!strongThis) {
1374
+ return jsi::Value::undefined();
1375
+ }
1376
+ return strongThis->getViewProp(rt, at<0>(args), at<1>(args), at<2>(args));
1377
+ });
1378
+
1379
+ addMethod<4>(
1380
+ rt,
1381
+ obj,
1382
+ "registerSensor",
1383
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[4]) {
1384
+ auto strongThis = weakThis.lock();
1385
+ if (!strongThis) {
1386
+ return jsi::Value::undefined();
1387
+ }
1388
+ return strongThis->registerSensor(rt, at<0>(args), at<1>(args), at<2>(args), at<3>(args));
1389
+ });
1390
+
1391
+ addMethod<1>(
1392
+ rt,
1393
+ obj,
1394
+ "unregisterSensor",
1395
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1396
+ auto strongThis = weakThis.lock();
1397
+ if (!strongThis) {
1398
+ return;
1399
+ }
1400
+ strongThis->unregisterSensor(rt, at<0>(args));
1401
+ });
1402
+
1403
+ addMethod<1>(
1404
+ rt,
1405
+ obj,
1406
+ "getStaticFeatureFlag",
1407
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1408
+ auto strongThis = weakThis.lock();
1409
+ if (!strongThis) {
1410
+ return jsi::Value::undefined();
1411
+ }
1412
+ return strongThis->getStaticFeatureFlag(rt, at<0>(args));
1413
+ });
1414
+
1415
+ addMethod<2>(
1416
+ rt,
1417
+ obj,
1418
+ "setDynamicFeatureFlag",
1419
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
1420
+ auto strongThis = weakThis.lock();
1421
+ if (!strongThis) {
1422
+ return jsi::Value::undefined();
1423
+ }
1424
+ return strongThis->setDynamicFeatureFlag(rt, at<0>(args), at<1>(args));
1425
+ });
1426
+
1427
+ addMethod<3>(
1428
+ rt,
1429
+ obj,
1430
+ "subscribeForKeyboardEvents",
1431
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[3]) {
1432
+ auto strongThis = weakThis.lock();
1433
+ if (!strongThis) {
1434
+ return jsi::Value::undefined();
1435
+ }
1436
+ return strongThis->subscribeForKeyboardEvents(rt, at<0>(args), at<1>(args), at<2>(args));
1437
+ });
1438
+
1439
+ addMethod<1>(
1440
+ rt,
1441
+ obj,
1442
+ "unsubscribeFromKeyboardEvents",
1443
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1444
+ auto strongThis = weakThis.lock();
1445
+ if (!strongThis) {
1446
+ return;
1447
+ }
1448
+ strongThis->unsubscribeFromKeyboardEvents(rt, at<0>(args));
1449
+ });
1450
+
1451
+ addMethod<1>(
1452
+ rt,
1453
+ obj,
1454
+ "configureLayoutAnimationBatch",
1455
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1456
+ auto strongThis = weakThis.lock();
1457
+ if (!strongThis) {
1458
+ return jsi::Value::undefined();
1459
+ }
1460
+ return strongThis->configureLayoutAnimationBatch(rt, at<0>(args));
1461
+ });
1462
+
1463
+ addMethod<2>(
1464
+ rt,
1465
+ obj,
1466
+ "setShouldAnimateExitingForTag",
1467
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
1468
+ auto strongThis = weakThis.lock();
1469
+ if (!strongThis) {
1470
+ return;
1471
+ }
1472
+ strongThis->setShouldAnimateExiting(rt, at<0>(args), at<1>(args));
1473
+ });
1474
+
1475
+ addMethod<2>(
1476
+ rt,
1477
+ obj,
1478
+ "setViewStyle",
1479
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
1480
+ auto strongThis = weakThis.lock();
1481
+ if (!strongThis) {
1482
+ return;
1483
+ }
1484
+ strongThis->setViewStyle(rt, at<0>(args), at<1>(args));
1485
+ });
1486
+
1487
+ addMethod<1>(
1488
+ rt,
1489
+ obj,
1490
+ "markNodeAsRemovable",
1491
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1492
+ auto strongThis = weakThis.lock();
1493
+ if (!strongThis) {
1494
+ return;
1495
+ }
1496
+ strongThis->markNodeAsRemovable(rt, at<0>(args));
1497
+ });
1498
+
1499
+ addMethod<1>(
1500
+ rt,
1501
+ obj,
1502
+ "unmarkNodeAsRemovable",
1503
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1504
+ auto strongThis = weakThis.lock();
1505
+ if (!strongThis) {
1506
+ return;
1507
+ }
1508
+ strongThis->unmarkNodeAsRemovable(rt, at<0>(args));
1509
+ });
1510
+
1511
+ addMethod<3>(
1512
+ rt,
1513
+ obj,
1514
+ "registerCSSKeyframes",
1515
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[3]) {
1516
+ auto strongThis = weakThis.lock();
1517
+ if (!strongThis) {
1518
+ return;
1519
+ }
1520
+ strongThis->registerCSSKeyframes(rt, at<0>(args), at<1>(args), at<2>(args));
1521
+ });
1522
+
1523
+ addMethod<2>(
1524
+ rt,
1525
+ obj,
1526
+ "unregisterCSSKeyframes",
1527
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
1528
+ auto strongThis = weakThis.lock();
1529
+ if (!strongThis) {
1530
+ return;
1531
+ }
1532
+ strongThis->unregisterCSSKeyframes(rt, at<0>(args), at<1>(args));
1533
+ });
1534
+
1535
+ addMethod<3>(
1536
+ rt,
1537
+ obj,
1538
+ "applyCSSAnimations",
1539
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[3]) {
1540
+ auto strongThis = weakThis.lock();
1541
+ if (!strongThis) {
1542
+ return;
1543
+ }
1544
+ strongThis->applyCSSAnimations(rt, at<0>(args), at<1>(args), at<2>(args));
1545
+ });
1546
+
1547
+ addMethod<1>(
1548
+ rt,
1549
+ obj,
1550
+ "unregisterCSSAnimations",
1551
+ [weakThis = weak_from_this()](jsi::Runtime &, const jsi::Value &, const jsi::Value(&args)[1]) {
1552
+ auto strongThis = weakThis.lock();
1553
+ if (!strongThis) {
1554
+ return;
1555
+ }
1556
+ strongThis->unregisterCSSAnimations(at<0>(args));
1557
+ });
1558
+
1559
+ addMethod<2>(
1560
+ rt,
1561
+ obj,
1562
+ "runCSSTransition",
1563
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
1564
+ auto strongThis = weakThis.lock();
1565
+ if (!strongThis) {
1566
+ return;
1567
+ }
1568
+ strongThis->runCSSTransition(rt, at<0>(args), at<1>(args));
1569
+ });
1570
+
1571
+ addMethod<1>(
1572
+ rt,
1573
+ obj,
1574
+ "unregisterCSSTransition",
1575
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1576
+ auto strongThis = weakThis.lock();
1577
+ if (!strongThis) {
1578
+ return;
1579
+ }
1580
+ strongThis->unregisterCSSTransition(rt, at<0>(args));
1581
+ });
1582
+
1583
+ addMethod<0>(rt, obj, "getSettledUpdates", [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &) {
1584
+ auto strongThis = weakThis.lock();
1585
+ if (!strongThis) {
1586
+ return jsi::Value::undefined();
1587
+ }
1588
+ return strongThis->getSettledUpdates(rt);
1589
+ });
1590
+
1591
+ addMethod<2>(
1592
+ rt,
1593
+ obj,
1594
+ "registerPseudoStyles",
1595
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[2]) {
1596
+ auto strongThis = weakThis.lock();
1597
+ if (!strongThis) {
1598
+ return;
1599
+ }
1600
+ strongThis->registerPseudoStyles(rt, at<0>(args), at<1>(args));
1601
+ });
1602
+
1603
+ addMethod<1>(
1604
+ rt,
1605
+ obj,
1606
+ "unregisterPseudoStyles",
1607
+ [weakThis = weak_from_this()](jsi::Runtime &rt, const jsi::Value &, const jsi::Value(&args)[1]) {
1608
+ auto strongThis = weakThis.lock();
1609
+ if (!strongThis) {
1610
+ return;
1611
+ }
1612
+ strongThis->unregisterPseudoStyles(rt, at<0>(args));
1613
+ });
1614
+
1615
+ return obj;
1616
+ }
1617
+
1380
1618
  } // namespace reanimated