react-native 0.66.0 → 0.67.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/Libraries/ActionSheetIOS/ActionSheetIOS.js +14 -1
  2. package/Libraries/ActionSheetIOS/NativeActionSheetManager.js +2 -0
  3. package/Libraries/Animated/AnimatedEvent.js +23 -4
  4. package/Libraries/Animated/NativeAnimatedHelper.js +2 -2
  5. package/Libraries/Animated/components/AnimatedImage.js +3 -3
  6. package/Libraries/Animated/components/AnimatedScrollView.js +3 -3
  7. package/Libraries/Animated/components/AnimatedText.js +3 -3
  8. package/Libraries/Animated/components/AnimatedView.js +1 -3
  9. package/Libraries/Animated/createAnimatedComponent.js +3 -34
  10. package/Libraries/Components/Button.js +3 -0
  11. package/Libraries/Components/DatePicker/DatePickerIOS.ios.js +3 -6
  12. package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js +4 -7
  13. package/Libraries/Components/ScrollView/AndroidHorizontalScrollViewNativeComponent.js +1 -0
  14. package/Libraries/Components/ScrollView/ScrollView.js +17 -16
  15. package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +268 -252
  16. package/Libraries/Components/View/View.js +1 -1
  17. package/Libraries/Components/View/ViewAccessibility.js +1 -1
  18. package/Libraries/Core/ExceptionsManager.js +45 -80
  19. package/Libraries/Core/ExtendedError.js +0 -1
  20. package/Libraries/Core/ReactNativeVersion.js +2 -2
  21. package/Libraries/Core/setUpBatchedBridge.js +1 -1
  22. package/Libraries/Core/setUpGlobals.js +2 -4
  23. package/Libraries/Core/setUpTimers.js +2 -2
  24. package/Libraries/Image/Image.ios.js +6 -0
  25. package/Libraries/Image/ImageBackground.js +10 -8
  26. package/Libraries/Image/ImageProps.js +28 -0
  27. package/Libraries/Image/RCTImageView.mm +4 -0
  28. package/Libraries/LogBox/Data/LogBoxData.js +18 -19
  29. package/Libraries/LogBox/UI/LogBoxImages/alert-triangle.png +0 -0
  30. package/Libraries/LogBox/UI/LogBoxImages/chevron-left.png +0 -0
  31. package/Libraries/LogBox/UI/LogBoxImages/chevron-right.png +0 -0
  32. package/Libraries/LogBox/UI/LogBoxImages/close.png +0 -0
  33. package/Libraries/LogBox/UI/LogBoxImages/loader.png +0 -0
  34. package/Libraries/NativeAnimation/Nodes/RCTPropsAnimatedNode.m +0 -3
  35. package/Libraries/NativeAnimation/RCTNativeAnimatedModule.mm +6 -3
  36. package/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.h +1 -2
  37. package/Libraries/NativeAnimation/RCTNativeAnimatedTurboModule.mm +2 -1
  38. package/Libraries/NewAppScreen/components/logo.png +0 -0
  39. package/Libraries/PermissionsAndroid/NativePermissionsAndroid.js +2 -1
  40. package/Libraries/PermissionsAndroid/PermissionsAndroid.js +2 -0
  41. package/Libraries/Pressability/Pressability.js +13 -13
  42. package/Libraries/Pressability/PressabilityPerformanceEventEmitter.js +1 -1
  43. package/Libraries/PushNotificationIOS/RCTPushNotificationManager.mm +0 -1
  44. package/Libraries/ReactNative/AppRegistry.js +4 -2
  45. package/Libraries/Renderer/REVISION +1 -1
  46. package/Libraries/Renderer/implementations/ReactFabric-dev.fb.js +1569 -875
  47. package/Libraries/Renderer/implementations/ReactFabric-prod.fb.js +529 -319
  48. package/Libraries/Renderer/implementations/ReactFabric-profiling.fb.js +570 -362
  49. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.fb.js +1592 -891
  50. package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.fb.js +521 -311
  51. package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.fb.js +562 -354
  52. package/Libraries/Share/Share.js +1 -1
  53. package/Libraries/StyleSheet/normalizeColor.js +2 -2
  54. package/Libraries/Text/TextInput/Multiline/RCTUITextView.m +4 -2
  55. package/Libraries/Text/TextInput/RCTBaseTextInputView.m +2 -12
  56. package/Libraries/Text/TextInput/RCTInputAccessoryViewContent.m +4 -11
  57. package/Libraries/Text/TextProps.js +1 -7
  58. package/Libraries/TurboModule/TurboModuleRegistry.js +1 -1
  59. package/Libraries/Utilities/HMRClient.js +1 -1
  60. package/README.md +1 -1
  61. package/React/Base/RCTBridge+Private.h +8 -0
  62. package/React/Base/RCTBridge.h +4 -0
  63. package/React/Base/RCTBridge.m +19 -7
  64. package/React/Base/RCTBridgeModule.h +2 -11
  65. package/React/Base/RCTBundleURLProvider.h +1 -1
  66. package/React/Base/RCTBundleURLProvider.mm +5 -3
  67. package/React/Base/RCTConstants.h +0 -6
  68. package/React/Base/RCTConstants.m +0 -15
  69. package/React/Base/RCTConvert.h +1 -1
  70. package/React/Base/RCTDefines.h +12 -3
  71. package/React/Base/RCTEventDispatcherProtocol.h +2 -0
  72. package/React/Base/RCTJSThread.h +29 -0
  73. package/React/Base/RCTJSThread.m +19 -0
  74. package/React/Base/RCTRootView.h +15 -0
  75. package/React/Base/RCTRootView.m +15 -0
  76. package/React/Base/RCTTouchHandler.m +1 -9
  77. package/React/Base/RCTUtils.h +3 -0
  78. package/React/Base/RCTUtils.m +14 -7
  79. package/React/Base/RCTVersion.m +2 -2
  80. package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.h +11 -0
  81. package/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingProxyRootView.mm +35 -1
  82. package/React/CoreModules/RCTAccessibilityManager+Internal.h +24 -0
  83. package/React/CoreModules/RCTAccessibilityManager.mm +18 -3
  84. package/React/CoreModules/RCTActionSheetManager.mm +14 -5
  85. package/React/CoreModules/RCTAppearance.mm +3 -1
  86. package/React/CoreModules/RCTDevLoadingView.mm +5 -10
  87. package/React/CoreModules/RCTDevSettings.mm +6 -6
  88. package/React/CoreModules/RCTDevSplitBundleLoader.mm +1 -1
  89. package/React/CoreModules/RCTDeviceInfo.mm +4 -4
  90. package/React/CoreModules/RCTEventDispatcher.mm +5 -0
  91. package/React/CoreModules/RCTExceptionsManager.mm +11 -24
  92. package/React/CoreModules/RCTPerfMonitor.mm +9 -4
  93. package/React/CoreModules/RCTRedBox.mm +1 -5
  94. package/React/CxxBridge/RCTCxxBridge.mm +18 -1
  95. package/React/DevSupport/RCTPackagerConnection.h +3 -0
  96. package/React/DevSupport/RCTPackagerConnection.mm +9 -5
  97. package/React/FBReactNativeSpec/FBReactNativeSpec.podspec +11 -3
  98. package/React/Fabric/Mounting/ComponentViews/Modal/RCTModalHostViewComponentView.mm +0 -3
  99. package/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +16 -0
  100. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +6 -0
  101. package/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +3 -5
  102. package/React/Fabric/Mounting/RCTMountingManager.mm +15 -1
  103. package/React/Fabric/RCTScheduler.mm +12 -5
  104. package/React/Fabric/RCTSurfacePresenter.mm +0 -4
  105. package/React/Fabric/RCTSurfaceTouchHandler.mm +6 -20
  106. package/React/Fabric/Surface/RCTFabricSurface.mm +1 -3
  107. package/React/React-RCTFabric.podspec +0 -1
  108. package/React/Views/RCTFont.mm +54 -38
  109. package/React/Views/RCTView.m +1 -6
  110. package/React/Views/RCTViewManager.m +3 -2
  111. package/React/Views/SafeAreaView/RCTSafeAreaView.m +1 -5
  112. package/React/Views/ScrollView/RCTScrollView.m +5 -15
  113. package/React/Views/ScrollView/RCTScrollViewManager.m +0 -7
  114. package/React/Views/UIView+React.m +2 -11
  115. package/React-Core.podspec +0 -1
  116. package/ReactAndroid/build.gradle +11 -5
  117. package/ReactAndroid/gradle.properties +1 -1
  118. package/ReactAndroid/src/androidTest/java/com/facebook/react/tests/BUCK +0 -1
  119. package/ReactAndroid/src/androidTest/js/TestBundle.js +0 -7
  120. package/ReactAndroid/src/main/java/com/facebook/hermes/instrumentation/BUCK +2 -1
  121. package/ReactAndroid/src/main/java/com/facebook/hermes/reactexecutor/HermesExecutor.java +14 -8
  122. package/ReactAndroid/src/main/java/com/facebook/react/BUCK +0 -1
  123. package/ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java +7 -0
  124. package/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +7 -0
  125. package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +63 -26
  126. package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerBuilder.java +50 -2
  127. package/ReactAndroid/src/main/java/com/facebook/react/ReactNativeHost.java +31 -0
  128. package/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +17 -1
  129. package/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +2 -0
  130. package/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +13 -2
  131. package/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +1 -0
  132. package/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactCxxErrorHandler.java +39 -0
  133. package/ReactAndroid/src/main/java/com/facebook/react/bridge/RuntimeScheduler.java +21 -0
  134. package/ReactAndroid/src/main/java/com/facebook/react/common/BUCK +2 -2
  135. package/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegate.java +40 -0
  136. package/ReactAndroid/src/main/java/com/facebook/react/common/SurfaceDelegateFactory.java +24 -0
  137. package/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/jni/BUCK +0 -6
  138. package/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +16 -0
  139. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BUCK +1 -0
  140. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/BridgeDevSupportManager.java +5 -2
  141. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.java +102 -0
  142. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +35 -11
  143. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerFactory.java +5 -72
  144. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DisabledDevSupportManager.java +12 -0
  145. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxDialogSurfaceDelegate.java +92 -0
  146. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/LogBoxModule.java +27 -42
  147. package/ReactAndroid/src/main/java/com/facebook/react/devsupport/interfaces/DevSupportManager.java +14 -0
  148. package/ReactAndroid/src/main/java/com/facebook/react/fabric/Binding.java +5 -4
  149. package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +3 -7
  150. package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +41 -2
  151. package/ReactAndroid/src/main/java/com/facebook/react/fabric/events/EventEmitterWrapper.java +8 -3
  152. package/ReactAndroid/src/main/java/com/facebook/react/fabric/events/FabricEventEmitter.java +43 -9
  153. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Android.mk +2 -1
  154. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.cpp +69 -0
  155. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/AsyncEventBeatV2.h +40 -0
  156. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/BUCK +2 -6
  157. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +84 -32
  158. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.h +4 -2
  159. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.cpp +20 -2
  160. package/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/EventEmitterWrapper.h +2 -1
  161. package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +9 -1
  162. package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/SurfaceMountingManager.java +19 -4
  163. package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/IntBufferBatchMountItem.java +6 -2
  164. package/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/BUCK +2 -1
  165. package/ReactAndroid/src/main/java/com/facebook/react/jscexecutor/JSCExecutor.java +6 -1
  166. package/ReactAndroid/src/main/java/com/facebook/react/modules/appearance/AppearanceModule.java +10 -1
  167. package/ReactAndroid/src/main/java/com/facebook/react/modules/blob/jni/BUCK +0 -6
  168. package/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/BUCK +4 -1
  169. package/ReactAndroid/src/main/java/com/facebook/react/modules/clipboard/ClipboardModule.java +9 -8
  170. package/ReactAndroid/src/main/java/com/facebook/react/modules/core/ExceptionsManagerModule.java +7 -19
  171. package/ReactAndroid/src/main/java/com/facebook/react/modules/core/{JavaScriptTimerManager.java → JavaScriptTimerExecutor.java} +1 -1
  172. package/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java +7 -7
  173. package/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.java +2 -2
  174. package/ReactAndroid/src/main/java/com/facebook/react/modules/i18nmanager/I18nManagerModule.java +7 -1
  175. package/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.java +23 -19
  176. package/ReactAndroid/src/main/java/com/facebook/react/modules/network/ForwardingCookieHandler.java +1 -4
  177. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +2 -2
  178. package/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/ReconnectingWebSocket.java +8 -8
  179. package/ReactAndroid/src/main/java/com/facebook/react/processing/ReactPropertyProcessor.java +1 -1
  180. package/ReactAndroid/src/main/java/com/facebook/react/reactperflogger/jni/BUCK +0 -6
  181. package/ReactAndroid/src/main/java/com/facebook/react/shell/BUCK +0 -1
  182. package/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +0 -5
  183. package/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni/BUCK +0 -12
  184. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.java +1 -1
  185. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/TouchTargetHelper.java +75 -10
  186. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.java +19 -22
  187. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventCategoryDef.java +42 -0
  188. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/EventDispatcherImpl.java +7 -1
  189. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/LockFreeEventDispatcherImpl.java +2 -2
  190. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTEventEmitter.java +7 -0
  191. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/RCTModernEventEmitter.java +2 -1
  192. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ReactEventEmitter.java +17 -9
  193. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEvent.java +43 -8
  194. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchEventType.java +15 -16
  195. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/events/TouchesHelper.java +108 -19
  196. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/jni/BUCK +0 -6
  197. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +79 -4
  198. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollViewManager.java +5 -0
  199. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +94 -3
  200. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewHelper.java +21 -1
  201. package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollViewManager.java +5 -0
  202. package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextAnchorViewManager.java +0 -4
  203. package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.java +16 -0
  204. package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextView.java +9 -1
  205. package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +20 -1
  206. package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java +25 -6
  207. package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManagerMapBuffer.java +25 -5
  208. package/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditTextInputConnectionWrapper.java +3 -0
  209. package/ReactAndroid/src/main/java/com/facebook/react/views/view/CanvasUtil.java +92 -0
  210. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewBackgroundDrawable.java +8 -8
  211. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +19 -0
  212. package/ReactAndroid/src/main/jni/react/jni/Android.mk +3 -2
  213. package/ReactAndroid/src/main/jni/react/jni/BUCK +4 -5
  214. package/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.cpp +49 -7
  215. package/ReactAndroid/src/main/jni/react/jni/CatalystInstanceImpl.h +15 -2
  216. package/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.cpp +18 -0
  217. package/ReactAndroid/src/main/jni/react/jni/JReactCxxErrorHandler.h +25 -0
  218. package/{ReactCommon/react/renderer/core/Constants.cpp → ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.cpp} +6 -8
  219. package/ReactAndroid/src/main/jni/react/jni/JRuntimeScheduler.h +30 -0
  220. package/ReactAndroid/src/main/jni/react/perftests/BUCK +0 -4
  221. package/ReactAndroid/src/main/third-party/android/androidx/BUCK +6 -6
  222. package/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java +43 -0
  223. package/ReactAndroid/src/test/java/com/facebook/react/modules/clipboard/ClipboardModuleTest.java +3 -1
  224. package/ReactCommon/React-Fabric.podspec +9 -1
  225. package/ReactCommon/better/BUCK +0 -6
  226. package/ReactCommon/callinvoker/BUCK +2 -8
  227. package/ReactCommon/cxxreact/BUCK +1 -16
  228. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  229. package/ReactCommon/hermes/inspector/tools/msggen/package.json +7 -4
  230. package/ReactCommon/hermes/inspector/tools/msggen/yarn.lock +13 -10
  231. package/ReactCommon/jsi/BUCK +0 -9
  232. package/ReactCommon/jsinspector/BUCK +0 -5
  233. package/ReactCommon/logger/BUCK +0 -5
  234. package/ReactCommon/react/config/BUCK +0 -6
  235. package/ReactCommon/react/debug/BUCK +0 -6
  236. package/ReactCommon/react/nativemodule/core/BUCK +0 -5
  237. package/ReactCommon/react/nativemodule/core/platform/ios/RCTTurboModuleManager.mm +14 -31
  238. package/ReactCommon/react/nativemodule/samples/BUCK +0 -7
  239. package/ReactCommon/react/renderer/animations/BUCK +1 -4
  240. package/ReactCommon/react/renderer/animations/LayoutAnimationCallbackWrapper.h +34 -0
  241. package/ReactCommon/react/renderer/animations/LayoutAnimationDriver.cpp +5 -26
  242. package/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h +8 -14
  243. package/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +912 -1147
  244. package/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h +80 -245
  245. package/ReactCommon/react/renderer/animations/conversions.h +212 -0
  246. package/ReactCommon/react/renderer/animations/primitives.h +104 -0
  247. package/ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp +3 -3
  248. package/ReactCommon/react/renderer/animations/utils.cpp +71 -0
  249. package/ReactCommon/react/renderer/animations/utils.h +80 -0
  250. package/ReactCommon/react/renderer/attributedstring/AttributedString.h +0 -1
  251. package/ReactCommon/react/renderer/attributedstring/BUCK +0 -6
  252. package/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +7 -3
  253. package/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +12 -2
  254. package/ReactCommon/react/renderer/attributedstring/TextAttributes.h +1 -1
  255. package/ReactCommon/react/renderer/attributedstring/conversions.h +58 -3
  256. package/ReactCommon/react/renderer/attributedstring/primitives.h +18 -1
  257. package/ReactCommon/react/renderer/componentregistry/BUCK +0 -6
  258. package/ReactCommon/react/renderer/componentregistry/native/BUCK +0 -6
  259. package/ReactCommon/react/renderer/components/image/BUCK +0 -6
  260. package/ReactCommon/react/renderer/components/image/ImageComponentDescriptor.h +0 -2
  261. package/ReactCommon/react/renderer/components/inputaccessory/BUCK +0 -6
  262. package/ReactCommon/react/renderer/components/inputaccessory/InputAccessoryComponentDescriptor.h +0 -4
  263. package/ReactCommon/react/renderer/components/legacyviewmanagerinterop/BUCK +0 -6
  264. package/ReactCommon/react/renderer/components/modal/BUCK +0 -6
  265. package/ReactCommon/react/renderer/components/modal/ModalHostViewComponentDescriptor.h +0 -5
  266. package/ReactCommon/react/renderer/components/progressbar/BUCK +0 -6
  267. package/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/AndroidProgressBarComponentDescriptor.h +0 -3
  268. package/ReactCommon/react/renderer/components/root/BUCK +0 -6
  269. package/ReactCommon/react/renderer/components/safeareaview/BUCK +0 -6
  270. package/ReactCommon/react/renderer/components/scrollview/BUCK +0 -6
  271. package/ReactCommon/react/renderer/components/slider/BUCK +0 -6
  272. package/ReactCommon/react/renderer/components/slider/SliderComponentDescriptor.h +0 -3
  273. package/ReactCommon/react/renderer/components/switch/BUCK +0 -6
  274. package/ReactCommon/react/renderer/components/switch/androidswitch/react/renderer/components/androidswitch/AndroidSwitchComponentDescriptor.h +0 -3
  275. package/ReactCommon/react/renderer/components/text/BUCK +0 -6
  276. package/ReactCommon/react/renderer/components/text/ParagraphComponentDescriptor.h +1 -20
  277. package/ReactCommon/react/renderer/components/textinput/BUCK +0 -6
  278. package/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputComponentDescriptor.h +0 -3
  279. package/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputProps.h +2 -0
  280. package/ReactCommon/react/renderer/components/textinput/iostextinput/BUCK +0 -6
  281. package/ReactCommon/react/renderer/components/textinput/iostextinput/TextInputComponentDescriptor.h +0 -3
  282. package/ReactCommon/react/renderer/components/unimplementedview/BUCK +0 -6
  283. package/ReactCommon/react/renderer/components/unimplementedview/UnimplementedViewComponentDescriptor.cpp +0 -4
  284. package/ReactCommon/react/renderer/components/view/Android.mk +1 -1
  285. package/ReactCommon/react/renderer/components/view/BUCK +0 -6
  286. package/ReactCommon/react/renderer/components/view/Touch.h +1 -32
  287. package/ReactCommon/react/renderer/components/view/ViewComponentDescriptor.h +0 -23
  288. package/ReactCommon/react/renderer/components/view/ViewPropsInterpolation.h +2 -3
  289. package/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +3 -3
  290. package/ReactCommon/react/renderer/components/view/ViewShadowNode.h +1 -1
  291. package/ReactCommon/react/renderer/components/view/accessibilityPropsConversions.h +4 -0
  292. package/ReactCommon/react/renderer/core/BUCK +2 -6
  293. package/ReactCommon/react/renderer/core/ConcreteComponentDescriptor.h +14 -9
  294. package/ReactCommon/react/renderer/core/ConcreteShadowNode.h +1 -10
  295. package/ReactCommon/react/renderer/core/EventEmitter.cpp +9 -4
  296. package/ReactCommon/react/renderer/core/EventEmitter.h +2 -1
  297. package/ReactCommon/react/renderer/core/Props.h +1 -0
  298. package/ReactCommon/react/renderer/core/PropsParserContext.h +3 -2
  299. package/ReactCommon/react/renderer/core/RawEvent.h +7 -5
  300. package/ReactCommon/react/renderer/core/RawPropsKey.cpp +10 -2
  301. package/ReactCommon/react/renderer/core/ReactPrimitives.h +0 -2
  302. package/ReactCommon/react/renderer/core/ShadowNode.cpp +7 -10
  303. package/ReactCommon/react/renderer/core/ShadowNodeFamily.h +1 -0
  304. package/ReactCommon/react/renderer/debug/BUCK +0 -6
  305. package/ReactCommon/react/renderer/element/BUCK +0 -6
  306. package/ReactCommon/react/renderer/graphics/Android.mk +1 -1
  307. package/ReactCommon/react/renderer/graphics/BUCK +0 -6
  308. package/ReactCommon/react/renderer/graphics/React-graphics.podspec +0 -1
  309. package/ReactCommon/react/renderer/graphics/Transform.cpp +1 -1
  310. package/ReactCommon/react/renderer/graphics/Transform.h +1 -1
  311. package/ReactCommon/react/renderer/imagemanager/BUCK +0 -6
  312. package/ReactCommon/react/renderer/leakchecker/BUCK +0 -6
  313. package/ReactCommon/react/renderer/mapbuffer/BUCK +0 -6
  314. package/ReactCommon/react/renderer/mounting/Android.mk +2 -1
  315. package/ReactCommon/react/renderer/mounting/BUCK +0 -6
  316. package/ReactCommon/react/renderer/mounting/MountingOverrideDelegate.h +1 -1
  317. package/ReactCommon/react/renderer/mounting/ShadowViewMutation.cpp +12 -0
  318. package/ReactCommon/react/renderer/mounting/ShadowViewMutation.h +10 -1
  319. package/ReactCommon/react/renderer/runtimescheduler/Android.mk +2 -1
  320. package/ReactCommon/react/renderer/runtimescheduler/BUCK +1 -7
  321. package/ReactCommon/react/renderer/runtimescheduler/ErrorUtils.h +36 -0
  322. package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +28 -20
  323. package/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +4 -2
  324. package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp +4 -3
  325. package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h +4 -2
  326. package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.cpp +32 -0
  327. package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.h +36 -0
  328. package/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerClock.h +4 -2
  329. package/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h +4 -3
  330. package/ReactCommon/react/renderer/runtimescheduler/Task.cpp +4 -2
  331. package/ReactCommon/react/renderer/runtimescheduler/Task.h +4 -2
  332. package/ReactCommon/react/renderer/runtimescheduler/primitives.h +4 -2
  333. package/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +26 -1
  334. package/ReactCommon/react/renderer/runtimescheduler/tests/StubErrorUtils.h +72 -0
  335. package/ReactCommon/react/renderer/scheduler/BUCK +0 -6
  336. package/ReactCommon/react/renderer/scheduler/Scheduler.cpp +1 -4
  337. package/ReactCommon/react/renderer/scheduler/Scheduler.h +1 -1
  338. package/ReactCommon/react/renderer/scheduler/SurfaceHandler.h +4 -4
  339. package/ReactCommon/react/renderer/telemetry/BUCK +0 -6
  340. package/ReactCommon/react/renderer/templateprocessor/BUCK +0 -6
  341. package/ReactCommon/react/renderer/textlayoutmanager/BUCK +0 -6
  342. package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.h +2 -0
  343. package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/RCTAttributedTextUtils.mm +19 -0
  344. package/ReactCommon/react/renderer/timeline/BUCK +6 -12
  345. package/ReactCommon/react/renderer/uimanager/BUCK +0 -6
  346. package/ReactCommon/react/renderer/uimanager/UIManagerAnimationDelegate.h +1 -1
  347. package/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +2 -2
  348. package/ReactCommon/react/renderer/uimanager/UIManagerBinding.h +1 -1
  349. package/ReactCommon/react/test_utils/BUCK +3 -6
  350. package/ReactCommon/react/{renderer/core/Constants.h → test_utils/MockSurfaceHandler.h} +9 -7
  351. package/ReactCommon/react/utils/BUCK +0 -6
  352. package/ReactCommon/react/utils/ContextContainer.h +0 -27
  353. package/ReactCommon/reactperflogger/BUCK +0 -4
  354. package/ReactCommon/runtimeexecutor/BUCK +0 -6
  355. package/ReactCommon/yoga/BUCK +1 -5
  356. package/android/com/facebook/react/react-native/{0.66.0/react-native-0.66.0.aar → 0.67.0-rc.2/react-native-0.67.0-rc.2.aar} +0 -0
  357. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.md5 +1 -0
  358. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.sha1 +1 -0
  359. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.sha256 +1 -0
  360. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.aar.sha512 +1 -0
  361. package/android/com/facebook/react/react-native/{0.66.0/react-native-0.66.0.module → 0.67.0-rc.2/react-native-0.67.0-rc.2.module} +16 -17
  362. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.md5 +1 -0
  363. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.sha1 +1 -0
  364. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.sha256 +1 -0
  365. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.module.sha512 +1 -0
  366. package/android/com/facebook/react/react-native/{0.66.0/react-native-0.66.0.pom → 0.67.0-rc.2/react-native-0.67.0-rc.2.pom} +2 -2
  367. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.md5 +1 -0
  368. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.sha1 +1 -0
  369. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.sha256 +1 -0
  370. package/android/com/facebook/react/react-native/0.67.0-rc.2/react-native-0.67.0-rc.2.pom.sha512 +1 -0
  371. package/android/com/facebook/react/react-native/maven-metadata.xml +4 -4
  372. package/android/com/facebook/react/react-native/maven-metadata.xml.md5 +1 -1
  373. package/android/com/facebook/react/react-native/maven-metadata.xml.sha1 +1 -1
  374. package/android/com/facebook/react/react-native/maven-metadata.xml.sha256 +1 -1
  375. package/android/com/facebook/react/react-native/maven-metadata.xml.sha512 +1 -1
  376. package/flow/global.js +45 -0
  377. package/index.js +15 -10
  378. package/jest/mockModal.js +31 -0
  379. package/jest/setup.js +5 -3
  380. package/package.json +8 -9
  381. package/react.gradle +53 -18
  382. package/scripts/find-node.sh +13 -0
  383. package/scripts/generate-specs-cli.js +18 -0
  384. package/scripts/ios-configure-glog.sh +4 -0
  385. package/scripts/react-native-xcode.sh +7 -7
  386. package/scripts/react_native_pods.rb +200 -57
  387. package/template/Gemfile +6 -0
  388. package/template/Gemfile.lock +100 -0
  389. package/template/_bundle/config +2 -0
  390. package/template/_flowconfig +1 -1
  391. package/template/_ruby-version +1 -0
  392. package/template/android/app/build.gradle +1 -1
  393. package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +36 -0
  394. package/template/android/app/src/main/res/values/styles.xml +1 -0
  395. package/template/android/build.gradle +7 -3
  396. package/template/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  397. package/template/android/gradle.properties +1 -1
  398. package/template/ios/HelloWorld.xcodeproj/project.pbxproj +0 -2
  399. package/template/package.json +1 -1
  400. package/third-party-podspecs/RCT-Folly.podspec +1 -1
  401. package/third-party-podspecs/glog.podspec +0 -1
  402. package/Libraries/Components/DatePickerAndroid/DatePickerAndroid.android.js +0 -87
  403. package/Libraries/Components/DatePickerAndroid/DatePickerAndroid.ios.js +0 -30
  404. package/Libraries/Components/DatePickerAndroid/DatePickerAndroidTypes.js +0 -30
  405. package/Libraries/Components/StaticContainer.react.js +0 -51
  406. package/Libraries/Components/Touchable/ensurePositiveDelayProps.js +0 -25
  407. package/Libraries/Interaction/InteractionMixin.js +0 -54
  408. package/Libraries/ReactNative/queryLayoutByID.js +0 -58
  409. package/ReactAndroid/src/androidTest/java/com/facebook/react/tests/DatePickerDialogTestCase.java +0 -172
  410. package/ReactAndroid/src/androidTest/js/DatePickerDialogTestModule.js +0 -45
  411. package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/BUCK +0 -27
  412. package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogFragment.java +0 -137
  413. package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerDialogModule.java +0 -153
  414. package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DatePickerMode.java +0 -15
  415. package/ReactAndroid/src/main/java/com/facebook/react/modules/datepicker/DismissableDatePickerDialog.java +0 -117
  416. package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/BUCK +0 -20
  417. package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/RuntimeSchedulerManager.java +0 -39
  418. package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/Android.mk +0 -34
  419. package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/BUCK +0 -35
  420. package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/OnLoad.cpp +0 -15
  421. package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.cpp +0 -46
  422. package/ReactAndroid/src/main/java/com/facebook/react/runtimescheduler/jni/RuntimeSchedulerManager.h +0 -40
  423. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidViewPagerManagerDelegate.java +0 -57
  424. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/AndroidViewPagerManagerInterface.java +0 -23
  425. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/BUCK +0 -19
  426. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerDelegate.java +0 -62
  427. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/DatePickerManagerInterface.java +0 -25
  428. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/InputAccessoryViewManagerDelegate.java +0 -33
  429. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/InputAccessoryViewManagerInterface.java +0 -17
  430. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerDelegate.java +0 -51
  431. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/PullToRefreshViewManagerInterface.java +0 -21
  432. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerDelegate.java +0 -63
  433. package/ReactAndroid/src/main/java/com/facebook/react/viewmanagers/SwitchManagerInterface.java +0 -24
  434. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.md5 +0 -1
  435. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.sha1 +0 -1
  436. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.sha256 +0 -1
  437. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.aar.sha512 +0 -1
  438. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.md5 +0 -1
  439. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.sha1 +0 -1
  440. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.sha256 +0 -1
  441. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.module.sha512 +0 -1
  442. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.md5 +0 -1
  443. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.sha1 +0 -1
  444. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.sha256 +0 -1
  445. package/android/com/facebook/react/react-native/0.66.0/react-native-0.66.0.pom.sha512 +0 -1
  446. package/scripts/generate-specs.sh +0 -99
  447. package/template/_editorconfig +0 -3
  448. package/template/_gitattributes +0 -3
@@ -8,25 +8,24 @@
8
8
  #include "LayoutAnimationKeyFrameManager.h"
9
9
 
10
10
  #include <algorithm>
11
- #include <chrono>
12
11
 
13
12
  #include <react/debug/flags.h>
14
13
  #include <react/debug/react_native_assert.h>
15
14
 
15
+ #include <logger/react_native_log.h>
16
+ #include <react/renderer/animations/conversions.h>
17
+ #include <react/renderer/animations/utils.h>
16
18
  #include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
19
+ #include <react/renderer/components/image/ImageProps.h>
17
20
  #include <react/renderer/components/view/ViewProps.h>
18
21
  #include <react/renderer/core/ComponentDescriptor.h>
19
22
  #include <react/renderer/core/LayoutMetrics.h>
20
- #include <react/renderer/core/LayoutableShadowNode.h>
21
23
  #include <react/renderer/core/Props.h>
22
24
  #include <react/renderer/core/PropsParserContext.h>
23
25
  #include <react/renderer/core/RawValue.h>
24
26
  #include <react/renderer/mounting/MountingCoordinator.h>
25
- #include <react/renderer/mounting/ShadowViewMutation.h>
26
-
27
- #include <react/renderer/mounting/Differentiator.h>
28
- #include <react/renderer/mounting/ShadowTreeRevision.h>
29
27
  #include <react/renderer/mounting/ShadowView.h>
28
+ #include <react/renderer/mounting/ShadowViewMutation.h>
30
29
 
31
30
  #include <glog/logging.h>
32
31
 
@@ -74,6 +73,7 @@ void PrintMutationInstruction(
74
73
  return stream;
75
74
  }(LOG(ERROR));
76
75
  }
76
+
77
77
  void PrintMutationInstructionRelative(
78
78
  std::string message,
79
79
  ShadowViewMutation const &mutation,
@@ -85,199 +85,27 @@ void PrintMutationInstructionRelative(
85
85
  }
86
86
  #endif
87
87
 
88
- static better::optional<AnimationType> parseAnimationType(std::string param) {
89
- if (param == "spring") {
90
- return AnimationType::Spring;
91
- }
92
- if (param == "linear") {
93
- return AnimationType::Linear;
94
- }
95
- if (param == "easeInEaseOut") {
96
- return AnimationType::EaseInEaseOut;
97
- }
98
- if (param == "easeIn") {
99
- return AnimationType::EaseIn;
100
- }
101
- if (param == "easeOut") {
102
- return AnimationType::EaseOut;
103
- }
104
- if (param == "keyboard") {
105
- return AnimationType::Keyboard;
106
- }
107
-
108
- LOG(ERROR) << "Error parsing animation type: " << param;
109
- return {};
110
- }
111
-
112
- static better::optional<AnimationProperty> parseAnimationProperty(
113
- std::string param) {
114
- if (param == "opacity") {
115
- return AnimationProperty::Opacity;
116
- }
117
- if (param == "scaleX") {
118
- return AnimationProperty::ScaleX;
119
- }
120
- if (param == "scaleY") {
121
- return AnimationProperty::ScaleY;
122
- }
123
- if (param == "scaleXY") {
124
- return AnimationProperty::ScaleXY;
125
- }
126
-
127
- LOG(ERROR) << "Error parsing animation property: " << param;
128
- return {};
129
- }
130
-
131
- static better::optional<AnimationConfig> parseAnimationConfig(
132
- folly::dynamic const &config,
133
- double defaultDuration,
134
- bool parsePropertyType) {
135
- if (config.empty() || !config.isObject()) {
136
- return AnimationConfig{
137
- AnimationType::Linear,
138
- AnimationProperty::NotApplicable,
139
- defaultDuration,
140
- 0,
141
- 0,
142
- 0};
143
- }
144
-
145
- auto const typeIt = config.find("type");
146
- if (typeIt == config.items().end()) {
147
- LOG(ERROR) << "Error parsing animation config: could not find field `type`";
148
- return {};
149
- }
150
- auto const animationTypeParam = typeIt->second;
151
- if (animationTypeParam.empty() || !animationTypeParam.isString()) {
152
- LOG(ERROR)
153
- << "Error parsing animation config: could not unwrap field `type`";
154
- return {};
155
- }
156
- const auto animationType = parseAnimationType(animationTypeParam.asString());
157
- if (!animationType) {
158
- LOG(ERROR)
159
- << "Error parsing animation config: could not parse field `type`";
160
- return {};
161
- }
162
-
163
- AnimationProperty animationProperty = AnimationProperty::NotApplicable;
164
- if (parsePropertyType) {
165
- auto const propertyIt = config.find("property");
166
- if (propertyIt == config.items().end()) {
167
- LOG(ERROR)
168
- << "Error parsing animation config: could not find field `property`";
169
- return {};
170
- }
171
- auto const animationPropertyParam = propertyIt->second;
172
- if (animationPropertyParam.empty() || !animationPropertyParam.isString()) {
173
- LOG(ERROR)
174
- << "Error parsing animation config: could not unwrap field `property`";
175
- return {};
176
- }
177
- const auto animationPropertyParsed =
178
- parseAnimationProperty(animationPropertyParam.asString());
179
- if (!animationPropertyParsed) {
180
- LOG(ERROR)
181
- << "Error parsing animation config: could not parse field `property`";
182
- return {};
183
- }
184
- animationProperty = *animationPropertyParsed;
185
- }
186
-
187
- double duration = defaultDuration;
188
- double delay = 0;
189
- double springDamping = 0.5;
190
- double initialVelocity = 0;
191
-
192
- auto const durationIt = config.find("duration");
193
- if (durationIt != config.items().end()) {
194
- if (durationIt->second.isDouble()) {
195
- duration = durationIt->second.asDouble();
196
- } else {
197
- LOG(ERROR)
198
- << "Error parsing animation config: field `duration` must be a number";
199
- return {};
200
- }
201
- }
202
-
203
- auto const delayIt = config.find("delay");
204
- if (delayIt != config.items().end()) {
205
- if (delayIt->second.isDouble()) {
206
- delay = delayIt->second.asDouble();
207
- } else {
208
- LOG(ERROR)
209
- << "Error parsing animation config: field `delay` must be a number";
210
- return {};
211
- }
212
- }
213
-
214
- auto const springDampingIt = config.find("springDamping");
215
- if (springDampingIt != config.items().end() &&
216
- springDampingIt->second.isDouble()) {
217
- if (springDampingIt->second.isDouble()) {
218
- springDamping = springDampingIt->second.asDouble();
219
- } else {
220
- LOG(ERROR)
221
- << "Error parsing animation config: field `springDamping` must be a number";
222
- return {};
223
- }
224
- }
225
-
226
- auto const initialVelocityIt = config.find("initialVelocity");
227
- if (initialVelocityIt != config.items().end()) {
228
- if (initialVelocityIt->second.isDouble()) {
229
- initialVelocity = initialVelocityIt->second.asDouble();
230
- } else {
231
- LOG(ERROR)
232
- << "Error parsing animation config: field `initialVelocity` must be a number";
233
- return {};
234
- }
235
- }
236
-
237
- return better::optional<AnimationConfig>(AnimationConfig{
238
- *animationType,
239
- animationProperty,
240
- duration,
241
- delay,
242
- springDamping,
243
- initialVelocity});
88
+ static inline float
89
+ interpolateFloats(float coefficient, float oldValue, float newValue) {
90
+ return oldValue + (newValue - oldValue) * coefficient;
244
91
  }
245
92
 
246
- // Parse animation config from JS
247
- static better::optional<LayoutAnimationConfig> parseLayoutAnimationConfig(
248
- folly::dynamic const &config) {
249
- if (config.empty() || !config.isObject()) {
250
- return {};
251
- }
252
-
253
- const auto durationIt = config.find("duration");
254
- if (durationIt == config.items().end() || !durationIt->second.isDouble()) {
255
- return {};
256
- }
257
- const double duration = durationIt->second.asDouble();
258
-
259
- const auto createConfigIt = config.find("create");
260
- const auto createConfig = createConfigIt == config.items().end()
261
- ? better::optional<AnimationConfig>(AnimationConfig{})
262
- : parseAnimationConfig(createConfigIt->second, duration, true);
263
-
264
- const auto updateConfigIt = config.find("update");
265
- const auto updateConfig = updateConfigIt == config.items().end()
266
- ? better::optional<AnimationConfig>(AnimationConfig{})
267
- : parseAnimationConfig(updateConfigIt->second, duration, false);
93
+ #pragma mark -
268
94
 
269
- const auto deleteConfigIt = config.find("delete");
270
- const auto deleteConfig = deleteConfigIt == config.items().end()
271
- ? better::optional<AnimationConfig>(AnimationConfig{})
272
- : parseAnimationConfig(deleteConfigIt->second, duration, true);
95
+ LayoutAnimationKeyFrameManager::LayoutAnimationKeyFrameManager(
96
+ RuntimeExecutor runtimeExecutor,
97
+ ContextContainer::Shared &contextContainer,
98
+ LayoutAnimationStatusDelegate *delegate)
99
+ : runtimeExecutor_(runtimeExecutor),
100
+ contextContainer_(contextContainer),
101
+ layoutAnimationStatusDelegate_(delegate),
102
+ now_([]() {
103
+ return std::chrono::duration_cast<std::chrono::milliseconds>(
104
+ std::chrono::high_resolution_clock::now().time_since_epoch())
105
+ .count();
106
+ }) {}
273
107
 
274
- if (!createConfig || !updateConfig || !deleteConfig) {
275
- return {};
276
- }
277
-
278
- return better::optional<LayoutAnimationConfig>(LayoutAnimationConfig{
279
- duration, *createConfig, *updateConfig, *deleteConfig});
280
- }
108
+ #pragma mark UIManagerAnimationDelegate methods
281
109
 
282
110
  /**
283
111
  * Globally configure next LayoutAnimation.
@@ -323,24 +151,9 @@ void LayoutAnimationKeyFrameManager::uiManagerDidConfigureNextLayoutAnimation(
323
151
  }
324
152
  }
325
153
 
326
- void LayoutAnimationKeyFrameManager::uiManagerDidConfigureNextLayoutAnimation(
327
- LayoutAnimation layoutAnimation) const {
328
- currentAnimation_ = better::optional<LayoutAnimation>{layoutAnimation};
329
- }
330
-
331
- void LayoutAnimationKeyFrameManager::setLayoutAnimationStatusDelegate(
332
- LayoutAnimationStatusDelegate *delegate) const {
333
- std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
334
- layoutAnimationStatusDelegate_ = delegate;
335
- }
336
-
337
- bool LayoutAnimationKeyFrameManager::shouldOverridePullTransaction() const {
338
- return shouldAnimateFrame();
339
- }
340
-
341
- void LayoutAnimationKeyFrameManager::stopSurface(SurfaceId surfaceId) {
342
- std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
343
- surfaceIdsToStop_.push_back(surfaceId);
154
+ void LayoutAnimationKeyFrameManager::setComponentDescriptorRegistry(
155
+ const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {
156
+ componentDescriptorRegistry_ = componentDescriptorRegistry;
344
157
  }
345
158
 
346
159
  bool LayoutAnimationKeyFrameManager::shouldAnimateFrame() const {
@@ -348,608 +161,182 @@ bool LayoutAnimationKeyFrameManager::shouldAnimateFrame() const {
348
161
  return currentAnimation_ || !inflightAnimations_.empty();
349
162
  }
350
163
 
351
- static inline const float
352
- interpolateFloats(float coefficient, float oldValue, float newValue) {
353
- return oldValue + (newValue - oldValue) * coefficient;
164
+ void LayoutAnimationKeyFrameManager::stopSurface(SurfaceId surfaceId) {
165
+ std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
166
+ surfaceIdsToStop_.insert(surfaceId);
354
167
  }
355
168
 
356
- std::pair<double, double>
357
- LayoutAnimationKeyFrameManager::calculateAnimationProgress(
358
- uint64_t now,
359
- const LayoutAnimation &animation,
360
- const AnimationConfig &mutationConfig) const {
361
- if (mutationConfig.animationType == AnimationType::None) {
362
- return {1, 1};
363
- }
364
-
365
- uint64_t startTime = animation.startTime;
366
- uint64_t delay = mutationConfig.delay;
367
- uint64_t endTime = startTime + delay + mutationConfig.duration;
368
-
369
- static const float PI = 3.14159265358979323846;
370
-
371
- if (now >= endTime) {
372
- return {1, 1};
373
- }
374
- if (now < startTime + delay) {
375
- return {0, 0};
376
- }
169
+ #pragma mark - MountingOverrideDelegate methods
377
170
 
378
- double linearTimeProgression = 1 -
379
- (double)(endTime - delay - now) / (double)(endTime - animation.startTime);
380
-
381
- if (mutationConfig.animationType == AnimationType::Linear) {
382
- return {linearTimeProgression, linearTimeProgression};
383
- } else if (mutationConfig.animationType == AnimationType::EaseIn) {
384
- // This is an accelerator-style interpolator.
385
- // In the future, this parameter (2.0) could be adjusted. This has been the
386
- // default for Classic RN forever.
387
- return {linearTimeProgression, pow(linearTimeProgression, 2.0)};
388
- } else if (mutationConfig.animationType == AnimationType::EaseOut) {
389
- // This is an decelerator-style interpolator.
390
- // In the future, this parameter (2.0) could be adjusted. This has been the
391
- // default for Classic RN forever.
392
- return {linearTimeProgression, 1.0 - pow(1 - linearTimeProgression, 2.0)};
393
- } else if (mutationConfig.animationType == AnimationType::EaseInEaseOut) {
394
- // This is a combination of accelerate+decelerate.
395
- // The animation starts and ends slowly, and speeds up in the middle.
396
- return {
397
- linearTimeProgression,
398
- cos((linearTimeProgression + 1.0) * PI) / 2 + 0.5};
399
- } else if (mutationConfig.animationType == AnimationType::Spring) {
400
- // Using mSpringDamping in this equation is not really the exact
401
- // mathematical springDamping, but a good approximation We need to replace
402
- // this equation with the right Factor that accounts for damping and
403
- // friction
404
- double damping = mutationConfig.springDamping;
405
- return {
406
- linearTimeProgression,
407
- (1 +
408
- pow(2, -10 * linearTimeProgression) *
409
- sin((linearTimeProgression - damping / 4) * PI * 2 / damping))};
410
- } else {
411
- return {linearTimeProgression, linearTimeProgression};
412
- }
171
+ bool LayoutAnimationKeyFrameManager::shouldOverridePullTransaction() const {
172
+ return shouldAnimateFrame();
413
173
  }
414
174
 
415
- void LayoutAnimationKeyFrameManager::
416
- adjustImmediateMutationIndicesForDelayedMutations(
417
- SurfaceId surfaceId,
418
- ShadowViewMutation &mutation,
419
- bool skipLastAnimation,
420
- bool lastAnimationOnly) const {
421
- bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove;
422
- react_native_assert(
423
- isRemoveMutation || mutation.type == ShadowViewMutation::Type::Insert);
424
-
425
- // TODO: turn all of this into a lambda and share code?
426
- if (mutation.mutatedViewIsVirtual()) {
427
- PrintMutationInstruction(
428
- "[IndexAdjustment] Not calling adjustImmediateMutationIndicesForDelayedMutations, is virtual, for:",
429
- mutation);
430
- return;
431
- }
432
-
433
- PrintMutationInstruction(
434
- "[IndexAdjustment] Calling adjustImmediateMutationIndicesForDelayedMutations for:",
435
- mutation);
436
-
437
- // First, collect all final mutations that could impact this immediate
438
- // mutation.
439
- std::vector<ShadowViewMutation *> candidateMutations{};
440
-
441
- for (auto inflightAnimationIt =
442
- inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
443
- inflightAnimationIt != inflightAnimations_.rend();
444
- inflightAnimationIt++) {
445
- auto &inflightAnimation = *inflightAnimationIt;
446
- if (inflightAnimation.surfaceId != surfaceId) {
447
- continue;
448
- }
449
- if (inflightAnimation.completed) {
450
- continue;
451
- }
175
+ better::optional<MountingTransaction>
176
+ LayoutAnimationKeyFrameManager::pullTransaction(
177
+ SurfaceId surfaceId,
178
+ MountingTransaction::Number transactionNumber,
179
+ TransactionTelemetry const &telemetry,
180
+ ShadowViewMutationList mutations) const {
181
+ simulateImagePropsMemoryAccess(mutations);
182
+ // Current time in milliseconds
183
+ uint64_t now = now_();
452
184
 
453
- for (auto it = inflightAnimation.keyFrames.begin();
454
- it != inflightAnimation.keyFrames.end();
455
- it++) {
456
- auto &animatedKeyFrame = *it;
185
+ bool inflightAnimationsExistInitially = !inflightAnimations_.empty();
186
+ deleteAnimationsForStoppedSurfaces();
457
187
 
458
- if (animatedKeyFrame.invalidated) {
459
- continue;
188
+ if (!mutations.empty()) {
189
+ #ifdef RN_SHADOW_TREE_INTROSPECTION
190
+ {
191
+ std::stringstream ss(getDebugDescription(mutations, {}));
192
+ std::string to;
193
+ while (std::getline(ss, to, '\n')) {
194
+ LOG(ERROR)
195
+ << "LayoutAnimationKeyFrameManager.cpp: got mutation list: Line: "
196
+ << to;
460
197
  }
198
+ };
199
+ #endif
461
200
 
462
- // Detect if they're in the same view hierarchy, but not equivalent
463
- // We've already detected direct conflicts and removed them.
464
- if (animatedKeyFrame.parentView.tag != mutation.parentShadowView.tag) {
201
+ // DEBUG ONLY: list existing inflight animations
202
+ #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
203
+ LOG(ERROR) << "BEGINNING DISPLAYING ONGOING inflightAnimations_!";
204
+ int i = 0;
205
+ int j = 0;
206
+ for (auto const &inflightAnimation : inflightAnimations_) {
207
+ i++;
208
+ j = 0;
209
+ if (inflightAnimation.completed) {
465
210
  continue;
466
211
  }
467
-
468
- for (auto &delayedMutation : animatedKeyFrame.finalMutationsForKeyFrame) {
469
- if (delayedMutation.type != ShadowViewMutation::Type::Remove) {
470
- continue;
471
- }
472
- if (delayedMutation.mutatedViewIsVirtual()) {
212
+ for (auto &keyframe : inflightAnimation.keyFrames) {
213
+ j++;
214
+ if (keyframe.invalidated) {
473
215
  continue;
474
216
  }
475
- if (delayedMutation.oldChildShadowView.tag ==
476
- (isRemoveMutation ? mutation.oldChildShadowView.tag
477
- : mutation.newChildShadowView.tag)) {
478
- continue;
217
+ for (const auto &finalMutationForKeyFrame :
218
+ keyframe.finalMutationsForKeyFrame) {
219
+ if (finalMutationForKeyFrame.mutatedViewIsVirtual()) {
220
+ std::string msg = "Animation " + std::to_string(i) + " keyframe " +
221
+ std::to_string(j) + ": Final Animation";
222
+ PrintMutationInstruction(msg, finalMutationForKeyFrame);
223
+ } else {
224
+ LOG(ERROR) << "Animation " << i << " keyframe " << j
225
+ << ": on tag: [" << keyframe.viewStart.tag << "]";
226
+ }
479
227
  }
480
-
481
- PrintMutationInstructionRelative(
482
- "[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations CANDIDATE for:",
483
- mutation,
484
- delayedMutation);
485
- candidateMutations.push_back(&delayedMutation);
486
228
  }
487
229
  }
230
+ LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!";
231
+ #endif
488
232
 
489
- if (lastAnimationOnly) {
490
- break;
233
+ PropsParserContext propsParserContext{surfaceId, *contextContainer_};
234
+
235
+ // What to do if we detect a conflict? Get current value and make
236
+ // that the baseline of the next animation. Scale the remaining time
237
+ // in the animation
238
+ // Types of conflicts and how we handle them:
239
+ // Update -> update: remove the previous update, make it the baseline of the
240
+ // next update (with current progress) Update -> remove: same, with final
241
+ // mutation being a remove Insert -> update: treat as update->update Insert
242
+ // -> remove: same, as update->remove Remove -> update/insert: not possible
243
+ // We just collect pairs here of <Mutation, AnimationConfig> and delete them
244
+ // from active animations. If another animation is queued up from the
245
+ // current mutations then these deleted mutations will serve as the baseline
246
+ // for the next animation. If not, the current mutations are executed
247
+ // immediately without issues.
248
+ std::vector<AnimationKeyFrame> conflictingAnimations{};
249
+ getAndEraseConflictingAnimations(
250
+ surfaceId, mutations, conflictingAnimations);
251
+
252
+ // Are we animating this list of mutations?
253
+ better::optional<LayoutAnimation> currentAnimation{};
254
+ {
255
+ std::lock_guard<std::mutex> lock(currentAnimationMutex_);
256
+ if (currentAnimation_) {
257
+ currentAnimation = std::move(currentAnimation_);
258
+ currentAnimation_.reset();
259
+ }
491
260
  }
492
- }
493
261
 
494
- // While the mutation keeps being affected, keep checking. We use the vector
495
- // so we only perform one adjustment per delayed mutation. See comments at
496
- // bottom of adjustDelayedMutationIndicesForMutation for further explanation.
497
- bool changed = true;
498
- int adjustedDelta = 0;
499
- while (changed) {
500
- changed = false;
501
- candidateMutations.erase(
502
- std::remove_if(
503
- candidateMutations.begin(),
504
- candidateMutations.end(),
505
- [&changed, &mutation, &adjustedDelta, &isRemoveMutation](
506
- ShadowViewMutation *candidateMutation) {
507
- bool indexConflicts =
508
- (candidateMutation->index < mutation.index ||
509
- (isRemoveMutation &&
510
- candidateMutation->index == mutation.index));
511
- if (indexConflicts) {
512
- mutation.index++;
513
- adjustedDelta++;
514
- changed = true;
515
- PrintMutationInstructionRelative(
516
- "[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations: Adjusting mutation UPWARD",
517
- mutation,
518
- *candidateMutation);
519
- return true;
520
- }
521
- return false;
522
- }),
523
- candidateMutations.end());
524
- }
525
- }
526
-
527
- void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation(
528
- SurfaceId surfaceId,
529
- ShadowViewMutation const &mutation,
530
- bool skipLastAnimation) const {
531
- bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove;
532
- bool isInsertMutation = mutation.type == ShadowViewMutation::Type::Insert;
533
- auto tag = isRemoveMutation ? mutation.oldChildShadowView.tag
534
- : mutation.newChildShadowView.tag;
535
- react_native_assert(isRemoveMutation || isInsertMutation);
536
-
537
- if (mutation.mutatedViewIsVirtual()) {
538
- PrintMutationInstruction(
539
- "[IndexAdjustment] Not calling adjustDelayedMutationIndicesForMutation, is virtual, for:",
540
- mutation);
541
- return;
542
- }
543
-
544
- // First, collect all final mutations that could impact this immediate
545
- // mutation.
546
- std::vector<ShadowViewMutation *> candidateMutations{};
547
-
548
- for (auto inflightAnimationIt =
549
- inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
550
- inflightAnimationIt != inflightAnimations_.rend();
551
- inflightAnimationIt++) {
552
- auto &inflightAnimation = *inflightAnimationIt;
553
-
554
- if (inflightAnimation.surfaceId != surfaceId) {
555
- continue;
556
- }
557
- if (inflightAnimation.completed) {
558
- continue;
559
- }
560
-
561
- for (auto it = inflightAnimation.keyFrames.begin();
562
- it != inflightAnimation.keyFrames.end();
563
- it++) {
564
- auto &animatedKeyFrame = *it;
565
-
566
- if (animatedKeyFrame.invalidated) {
567
- continue;
568
- }
569
-
570
- // Detect if they're in the same view hierarchy, but not equivalent
571
- // (We've already detected direct conflicts and handled them above)
572
- if (animatedKeyFrame.parentView.tag != mutation.parentShadowView.tag) {
573
- continue;
574
- }
262
+ if (currentAnimation.hasValue()) {
263
+ LayoutAnimation animation = std::move(currentAnimation).value();
264
+ animation.surfaceId = surfaceId;
265
+ animation.startTime = now;
575
266
 
576
- for (auto &finalAnimationMutation :
577
- animatedKeyFrame.finalMutationsForKeyFrame) {
578
- if (finalAnimationMutation.oldChildShadowView.tag == tag) {
579
- continue;
267
+ // Pre-process list to:
268
+ // Catch remove+reinsert (reorders)
269
+ // Catch delete+create (reparenting) (this should be optimized away at
270
+ // the diffing level eventually?)
271
+ // TODO: to prevent this step we could tag Remove/Insert mutations as
272
+ // being moves on the Differ level, since we know that there? We could use
273
+ // TinyMap here, but it's not exposed by Differentiator (yet).
274
+ better::set<Tag> insertedTags;
275
+ better::set<Tag> deletedTags;
276
+ better::set<Tag> reparentedTags; // tags that are deleted and recreated
277
+ std::unordered_map<Tag, ShadowViewMutation> movedTags;
278
+ for (const auto &mutation : mutations) {
279
+ if (mutation.type == ShadowViewMutation::Type::Insert) {
280
+ insertedTags.insert(mutation.newChildShadowView.tag);
580
281
  }
581
-
582
- if (finalAnimationMutation.type != ShadowViewMutation::Type::Remove) {
583
- continue;
282
+ if (mutation.type == ShadowViewMutation::Type::Delete) {
283
+ deletedTags.insert(mutation.oldChildShadowView.tag);
584
284
  }
585
- if (finalAnimationMutation.mutatedViewIsVirtual()) {
586
- continue;
285
+ if (mutation.type == ShadowViewMutation::Type::Create) {
286
+ if (deletedTags.find(mutation.newChildShadowView.tag) !=
287
+ deletedTags.end()) {
288
+ reparentedTags.insert(mutation.newChildShadowView.tag);
289
+ }
587
290
  }
588
-
589
- PrintMutationInstructionRelative(
590
- "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: CANDIDATE:",
591
- mutation,
592
- finalAnimationMutation);
593
- candidateMutations.push_back(&finalAnimationMutation);
594
291
  }
595
- }
596
- }
597
-
598
- // Because the finalAnimations are not sorted in any way, it is possible to
599
- // have some sequence like:
600
- // * DELAYED REMOVE 10 from {TAG}
601
- // * DELAYED REMOVE 9 from {TAG}
602
- // * ...
603
- // * DELAYED REMOVE 5 from {TAG}
604
- // with mutation: INSERT 6/REMOVE 6. This would cause the first few mutations
605
- // to *not* be adjusted, even though they would be impacted by mutation or
606
- // vice-versa after later adjustments are applied. Therefore, we just keep
607
- // recursing while there are any changes. This isn't great, but is good enough
608
- // for now until we change these data-structures.
609
- bool changed = true;
610
- while (changed) {
611
- changed = false;
612
- candidateMutations.erase(
613
- std::remove_if(
614
- candidateMutations.begin(),
615
- candidateMutations.end(),
616
- [&mutation, &isRemoveMutation, &isInsertMutation, &changed](
617
- ShadowViewMutation *candidateMutation) {
618
- if (isRemoveMutation &&
619
- mutation.index <= candidateMutation->index) {
620
- candidateMutation->index--;
621
- changed = true;
622
- PrintMutationInstructionRelative(
623
- "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation DOWNWARD",
624
- mutation,
625
- *candidateMutation);
626
- return true;
627
- } else if (
628
- isInsertMutation &&
629
- mutation.index <= candidateMutation->index) {
630
- candidateMutation->index++;
631
- changed = true;
632
- PrintMutationInstructionRelative(
633
- "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation UPWARD",
634
- mutation,
635
- *candidateMutation);
636
- return true;
637
- }
638
- return false;
639
- }),
640
- candidateMutations.end());
641
- }
642
- }
643
-
644
- void LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations(
645
- SurfaceId surfaceId,
646
- ShadowViewMutationList const &mutations,
647
- std::vector<AnimationKeyFrame> &conflictingAnimations) const {
648
- ShadowViewMutationList localConflictingMutations{};
649
- for (auto const &mutation : mutations) {
650
- bool mutationIsCreateOrDelete =
651
- mutation.type == ShadowViewMutation::Type::Create ||
652
- mutation.type == ShadowViewMutation::Type::Delete;
653
- auto const &baselineShadowView =
654
- (mutation.type == ShadowViewMutation::Type::Insert ||
655
- mutation.type == ShadowViewMutation::Type::Create)
656
- ? mutation.newChildShadowView
657
- : mutation.oldChildShadowView;
658
- auto baselineTag = baselineShadowView.tag;
659
292
 
660
- for (auto &inflightAnimation : inflightAnimations_) {
661
- if (inflightAnimation.surfaceId != surfaceId) {
662
- continue;
663
- }
664
- if (inflightAnimation.completed) {
665
- continue;
666
- }
293
+ // Process mutations list into operations that can be sent to platform
294
+ // immediately, and those that need to be animated Deletions, removals,
295
+ // updates are delayed and animated. Creations and insertions are sent to
296
+ // platform and then "animated in" with opacity updates. Upon completion,
297
+ // removals and deletions are sent to platform
298
+ ShadowViewMutation::List immediateMutations;
667
299
 
668
- for (auto it = inflightAnimation.keyFrames.begin();
669
- it != inflightAnimation.keyFrames.end();) {
670
- auto &animatedKeyFrame = *it;
300
+ // Remove operations that are actually moves should be copied to
301
+ // "immediate mutations". The corresponding "insert" will also be executed
302
+ // immediately and animated as an update.
303
+ std::vector<AnimationKeyFrame> keyFramesToAnimate;
304
+ auto const layoutAnimationConfig = animation.layoutAnimationConfig;
305
+ for (auto const &mutation : mutations) {
306
+ ShadowView baselineShadowView =
307
+ (mutation.type == ShadowViewMutation::Type::Delete ||
308
+ mutation.type == ShadowViewMutation::Type::Remove ||
309
+ mutation.type == ShadowViewMutation::Type::Update
310
+ ? mutation.oldChildShadowView
311
+ : mutation.newChildShadowView);
312
+ react_native_assert(baselineShadowView.tag > 0);
313
+ bool haveComponentDescriptor =
314
+ hasComponentDescriptorForShadowView(baselineShadowView);
671
315
 
672
- if (animatedKeyFrame.invalidated) {
316
+ // Immediately execute any mutations on a root node
317
+ if (baselineShadowView.traits.check(
318
+ ShadowNodeTraits::Trait::RootNodeKind)) {
319
+ immediateMutations.push_back(mutation);
673
320
  continue;
674
321
  }
675
322
 
676
- // A conflict is when either: the animated node itself is mutated
677
- // directly; or, the parent of the node is created or deleted. In cases
678
- // of reparenting - say, the parent is deleted but the node was moved to
679
- // a different parent first - the reparenting (remove/insert) conflict
680
- // will be detected before we process the parent DELETE.
681
- // Parent deletion is important because deleting a parent recursively
682
- // deletes all children. If we previously deferred deletion of a child,
683
- // we need to force deletion/removal to happen immediately.
684
- bool conflicting = animatedKeyFrame.tag == baselineTag ||
685
- (mutationIsCreateOrDelete &&
686
- animatedKeyFrame.parentView.tag == baselineTag &&
687
- animatedKeyFrame.parentView.tag != 0);
688
-
689
- // Conflicting animation detected: if we're mutating a tag under
690
- // animation, or deleting the parent of a tag under animation, or
691
- // reparenting.
692
- if (conflicting) {
693
- animatedKeyFrame.invalidated = true;
694
-
695
- // We construct a list of all conflicting animations, whether or not
696
- // they have a "final mutation" to execute. This is important with,
697
- // for example, "insert" mutations where the final update needs to set
698
- // opacity to "1", even if there's no final ShadowNode update.
699
- // TODO: don't animate virtual views in the first place?
700
- bool isVirtual = false;
701
- for (const auto &finalMutationForKeyFrame :
702
- animatedKeyFrame.finalMutationsForKeyFrame) {
703
- isVirtual =
704
- isVirtual || finalMutationForKeyFrame.mutatedViewIsVirtual();
323
+ better::optional<ShadowViewMutation> executeMutationImmediately{};
705
324
 
706
- #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
707
- PrintMutationInstructionRelative(
708
- "Found mutation that conflicts with existing in-flight animation:",
709
- mutation,
710
- finalMutationForKeyFrame);
711
- #endif
712
- }
325
+ bool isRemoveReinserted =
326
+ mutation.type == ShadowViewMutation::Type::Remove &&
327
+ insertedTags.find(mutation.oldChildShadowView.tag) !=
328
+ insertedTags.end();
713
329
 
714
- conflictingAnimations.push_back(animatedKeyFrame);
715
- for (const auto &finalMutationForKeyFrame :
716
- animatedKeyFrame.finalMutationsForKeyFrame) {
717
- if (!isVirtual ||
718
- finalMutationForKeyFrame.type ==
719
- ShadowViewMutation::Type::Delete) {
720
- localConflictingMutations.push_back(finalMutationForKeyFrame);
721
- }
722
- }
330
+ // Reparenting can result in a node being removed, inserted (moved) and
331
+ // also deleted and created in the same frame, with the same props etc.
332
+ // This should eventually be optimized out of the diffing algorithm, but
333
+ // for now we detect reparenting and prevent the corresponding
334
+ // Delete/Create instructions from being animated.
335
+ bool isReparented =
336
+ reparentedTags.find(baselineShadowView.tag) != reparentedTags.end();
723
337
 
724
- // Delete from existing animation
725
- it = inflightAnimation.keyFrames.erase(it);
726
- } else {
727
- it++;
728
- }
729
- }
730
- }
731
- }
732
-
733
- // Recurse, in case conflicting mutations conflict with other existing
734
- // animations
735
- if (!localConflictingMutations.empty()) {
736
- getAndEraseConflictingAnimations(
737
- surfaceId, localConflictingMutations, conflictingAnimations);
738
- }
739
- }
740
-
741
- void LayoutAnimationKeyFrameManager::setClockNow(
742
- std::function<uint64_t()> now) {
743
- now_ = now;
744
- }
745
-
746
- better::optional<MountingTransaction>
747
- LayoutAnimationKeyFrameManager::pullTransaction(
748
- SurfaceId surfaceId,
749
- MountingTransaction::Number transactionNumber,
750
- TransactionTelemetry const &telemetry,
751
- ShadowViewMutationList mutations) const {
752
- // Current time in milliseconds
753
- uint64_t now = now_();
754
-
755
- bool inflightAnimationsExistInitially = !inflightAnimations_.empty();
756
-
757
- // Execute stopSurface on any ongoing animations
758
- if (inflightAnimationsExistInitially) {
759
- std::vector<SurfaceId> surfaceIdsToStop{};
760
- {
761
- std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
762
- surfaceIdsToStop = surfaceIdsToStop_;
763
- surfaceIdsToStop_ = {};
764
- }
765
-
766
- for (auto it = inflightAnimations_.begin();
767
- it != inflightAnimations_.end();) {
768
- const auto &animation = *it;
769
-
770
- if (std::find(
771
- surfaceIdsToStop.begin(),
772
- surfaceIdsToStop.end(),
773
- animation.surfaceId) != surfaceIdsToStop.end()) {
774
- #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
775
- LOG(ERROR)
776
- << "LayoutAnimations: stopping animation due to stopSurface on "
777
- << surfaceId;
778
- #endif
779
- it = inflightAnimations_.erase(it);
780
- } else {
781
- it++;
782
- }
783
- }
784
- }
785
-
786
- if (!mutations.empty()) {
787
- #ifdef RN_SHADOW_TREE_INTROSPECTION
788
- {
789
- std::stringstream ss(getDebugDescription(mutations, {}));
790
- std::string to;
791
- while (std::getline(ss, to, '\n')) {
792
- LOG(ERROR)
793
- << "LayoutAnimationKeyFrameManager.cpp: got mutation list: Line: "
794
- << to;
795
- }
796
- };
797
- #endif
798
-
799
- // DEBUG ONLY: list existing inflight animations
800
- #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
801
- LOG(ERROR) << "BEGINNING DISPLAYING ONGOING inflightAnimations_!";
802
- int i = 0;
803
- int j = 0;
804
- for (auto const &inflightAnimation : inflightAnimations_) {
805
- i++;
806
- j = 0;
807
- if (inflightAnimation.completed) {
808
- continue;
809
- }
810
- for (auto &keyframe : inflightAnimation.keyFrames) {
811
- j++;
812
- if (keyframe.invalidated) {
813
- continue;
814
- }
815
- for (const auto &finalMutationForKeyFrame :
816
- keyframe.finalMutationsForKeyFrame) {
817
- if (finalMutationForKeyFrame.mutatedViewIsVirtual()) {
818
- std::string msg = "Animation " + std::to_string(i) + " keyframe " +
819
- std::to_string(j) + ": Final Animation";
820
- PrintMutationInstruction(msg, finalMutationForKeyFrame);
821
- } else {
822
- LOG(ERROR) << "Animation " << i << " keyframe " << j
823
- << ": on tag: [" << keyframe.viewStart.tag << "]";
824
- }
825
- }
826
- }
827
- }
828
- LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!";
829
- #endif
830
-
831
- // Stub PropsParserContext used for cloneProps.
832
- // This is/should be safe because cloning doesn't actually need to
833
- // parse props, and just copies them; therefore there should be no
834
- // need to actually use anything in the PropsParserContext.
835
- // If this ever changes, the LayoutAnimations API will need to change
836
- // to pass in a real PropsParserContext.
837
- ContextContainer contextContainer{};
838
- PropsParserContext propsParserContext{surfaceId, contextContainer};
839
-
840
- // What to do if we detect a conflict? Get current value and make
841
- // that the baseline of the next animation. Scale the remaining time
842
- // in the animation
843
- // Types of conflicts and how we handle them:
844
- // Update -> update: remove the previous update, make it the baseline of the
845
- // next update (with current progress) Update -> remove: same, with final
846
- // mutation being a remove Insert -> update: treat as update->update Insert
847
- // -> remove: same, as update->remove Remove -> update/insert: not possible
848
- // We just collect pairs here of <Mutation, AnimationConfig> and delete them
849
- // from active animations. If another animation is queued up from the
850
- // current mutations then these deleted mutations will serve as the baseline
851
- // for the next animation. If not, the current mutations are executed
852
- // immediately without issues.
853
- std::vector<AnimationKeyFrame> conflictingAnimations{};
854
- getAndEraseConflictingAnimations(
855
- surfaceId, mutations, conflictingAnimations);
856
-
857
- // Are we animating this list of mutations?
858
- better::optional<LayoutAnimation> currentAnimation{};
859
- {
860
- std::lock_guard<std::mutex> lock(currentAnimationMutex_);
861
- if (currentAnimation_) {
862
- currentAnimation = std::move(currentAnimation_);
863
- currentAnimation_ = {};
864
- }
865
- }
866
-
867
- if (currentAnimation) {
868
- LayoutAnimation animation = std::move(currentAnimation.value());
869
- currentAnimation = {};
870
- animation.surfaceId = surfaceId;
871
- animation.startTime = now;
872
-
873
- // Pre-process list to:
874
- // Catch remove+reinsert (reorders)
875
- // Catch delete+create (reparenting) (this should be optimized away at
876
- // the diffing level eventually?)
877
- // TODO: to prevent this step we could tag Remove/Insert mutations as
878
- // being moves on the Differ level, since we know that there? We could use
879
- // TinyMap here, but it's not exposed by Differentiator (yet).
880
- std::vector<Tag> insertedTags;
881
- std::vector<Tag> deletedTags;
882
- std::vector<Tag> reparentedTags; // tags that are deleted and recreated
883
- std::unordered_map<Tag, ShadowViewMutation> movedTags;
884
- for (const auto &mutation : mutations) {
885
- if (mutation.type == ShadowViewMutation::Type::Insert) {
886
- insertedTags.push_back(mutation.newChildShadowView.tag);
887
- }
888
- if (mutation.type == ShadowViewMutation::Type::Delete) {
889
- deletedTags.push_back(mutation.oldChildShadowView.tag);
890
- }
891
- if (mutation.type == ShadowViewMutation::Type::Create) {
892
- if (std::find(
893
- deletedTags.begin(),
894
- deletedTags.end(),
895
- mutation.newChildShadowView.tag) != deletedTags.end()) {
896
- reparentedTags.push_back(mutation.newChildShadowView.tag);
897
- }
898
- }
899
- }
900
-
901
- // Process mutations list into operations that can be sent to platform
902
- // immediately, and those that need to be animated Deletions, removals,
903
- // updates are delayed and animated. Creations and insertions are sent to
904
- // platform and then "animated in" with opacity updates. Upon completion,
905
- // removals and deletions are sent to platform
906
- ShadowViewMutation::List immediateMutations;
907
-
908
- // Remove operations that are actually moves should be copied to
909
- // "immediate mutations". The corresponding "insert" will also be executed
910
- // immediately and animated as an update.
911
- std::vector<AnimationKeyFrame> keyFramesToAnimate;
912
- std::vector<AnimationKeyFrame> movesToAnimate;
913
- auto const layoutAnimationConfig = animation.layoutAnimationConfig;
914
- for (auto const &mutation : mutations) {
915
- ShadowView baselineShadowView =
916
- (mutation.type == ShadowViewMutation::Type::Delete ||
917
- mutation.type == ShadowViewMutation::Type::Remove ||
918
- mutation.type == ShadowViewMutation::Type::Update
919
- ? mutation.oldChildShadowView
920
- : mutation.newChildShadowView);
921
- react_native_assert(baselineShadowView.tag > 0);
922
- bool haveComponentDescriptor =
923
- hasComponentDescriptorForShadowView(baselineShadowView);
924
-
925
- // Immediately execute any mutations on a root node
926
- if (baselineShadowView.traits.check(
927
- ShadowNodeTraits::Trait::RootNodeKind)) {
928
- immediateMutations.push_back(mutation);
929
- continue;
930
- }
931
-
932
- better::optional<ShadowViewMutation> executeMutationImmediately{};
933
-
934
- bool isRemoveReinserted =
935
- mutation.type == ShadowViewMutation::Type::Remove &&
936
- std::find(
937
- insertedTags.begin(),
938
- insertedTags.end(),
939
- mutation.oldChildShadowView.tag) != insertedTags.end();
940
-
941
- // Reparenting can result in a node being removed, inserted (moved) and
942
- // also deleted and created in the same frame, with the same props etc.
943
- // This should eventually be optimized out of the diffing algorithm, but
944
- // for now we detect reparenting and prevent the corresponding
945
- // Delete/Create instructions from being animated.
946
- bool isReparented = std::find(
947
- reparentedTags.begin(),
948
- reparentedTags.end(),
949
- baselineShadowView.tag) != reparentedTags.end();
950
-
951
- if (isRemoveReinserted) {
952
- movedTags.insert({mutation.oldChildShadowView.tag, mutation});
338
+ if (isRemoveReinserted) {
339
+ movedTags.insert({mutation.oldChildShadowView.tag, mutation});
953
340
  }
954
341
 
955
342
  // Inserts that follow a "remove" of the same tag should be treated as
@@ -979,16 +366,6 @@ LayoutAnimationKeyFrameManager::pullTransaction(
979
366
  bool haveConfiguration =
980
367
  mutationConfig.animationType != AnimationType::None;
981
368
 
982
- if (wasInsertedTagRemoved && haveConfiguration) {
983
- movesToAnimate.push_back(AnimationKeyFrame{
984
- {},
985
- AnimationConfigurationType::Update,
986
- mutation.newChildShadowView.tag,
987
- mutation.parentShadowView,
988
- movedIt->second.oldChildShadowView,
989
- mutation.newChildShadowView});
990
- }
991
-
992
369
  // Creates and inserts should also be executed immediately.
993
370
  // Mutations that would otherwise be animated, but have no
994
371
  // configuration, are also executed immediately.
@@ -1051,12 +428,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1051
428
  // that is being referenced by the REMOVE mutation.
1052
429
  if (keyframe.type == AnimationConfigurationType::Update &&
1053
430
  mutation.oldChildShadowView.tag > 0) {
1054
- executeMutationImmediately = ShadowViewMutation{
1055
- mutation.type,
1056
- mutation.parentShadowView,
1057
- keyframe.viewPrev,
1058
- {},
1059
- mutation.index};
431
+ executeMutationImmediately =
432
+ ShadowViewMutation::RemoveMutation(
433
+ mutation.parentShadowView,
434
+ keyframe.viewPrev,
435
+ mutation.index);
1060
436
  }
1061
437
  }
1062
438
  }
@@ -1093,13 +469,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1093
469
  getComponentDescriptorForShadowView(baselineShadowView)
1094
470
  .cloneProps(propsParserContext, viewStart.props, {});
1095
471
 
1096
- // Dynamic cast, because - we don't know the type of this
1097
- // ShadowNode, it could be Image or Text or something else with
1098
- // different base props.
1099
- const auto viewProps =
1100
- dynamic_cast<const ViewProps *>(props.get());
1101
- if (viewProps != nullptr) {
1102
- const_cast<ViewProps *>(viewProps)->opacity = 0;
472
+ if (baselineShadowView.traits.check(
473
+ ShadowNodeTraits::Trait::ViewKind)) {
474
+ auto const &viewProps =
475
+ *std::static_pointer_cast<ViewProps const>(props);
476
+ const_cast<ViewProps &>(viewProps).opacity = 0;
1103
477
  }
1104
478
 
1105
479
  react_native_assert(props != nullptr);
@@ -1117,14 +491,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1117
491
  auto props =
1118
492
  getComponentDescriptorForShadowView(baselineShadowView)
1119
493
  .cloneProps(propsParserContext, viewStart.props, {});
1120
-
1121
- // Dynamic cast, because - we don't know the type of this
1122
- // ShadowNode, it could be Image or Text or something else with
1123
- // different base props.
1124
- const auto viewProps =
1125
- dynamic_cast<const ViewProps *>(props.get());
1126
- if (viewProps != nullptr) {
1127
- const_cast<ViewProps *>(viewProps)->transform =
494
+ if (baselineShadowView.traits.check(
495
+ ShadowNodeTraits::Trait::ViewKind)) {
496
+ auto const &viewProps =
497
+ *std::static_pointer_cast<ViewProps const>(props);
498
+ const_cast<ViewProps &>(viewProps).transform =
1128
499
  Transform::Scale(isScaleX ? 0 : 1, isScaleY ? 0 : 1, 1);
1129
500
  }
1130
501
 
@@ -1139,14 +510,14 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1139
510
  mutation);
1140
511
 
1141
512
  keyFrame = AnimationKeyFrame{
1142
- {},
1143
- AnimationConfigurationType::Create,
1144
- tag,
1145
- parent,
1146
- viewStart,
1147
- viewFinal,
1148
- baselineShadowView,
1149
- 0};
513
+ /* .finalMutationsForKeyFrame = */ {},
514
+ /* .type = */ AnimationConfigurationType::Create,
515
+ /* .tag = */ tag,
516
+ /* .parentView = */ parent,
517
+ /* .viewStart = */ viewStart,
518
+ /* .viewEnd = */ viewFinal,
519
+ /* .viewPrev = */ baselineShadowView,
520
+ /* .initialProgress = */ 0};
1150
521
  } else if (mutation.type == ShadowViewMutation::Type::Delete) {
1151
522
  // This is just for assertion purposes.
1152
523
  // The NDEBUG check here is to satisfy the compiler in certain environments
@@ -1177,14 +548,14 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1177
548
  mutation);
1178
549
 
1179
550
  keyFrame = AnimationKeyFrame{
1180
- {mutation},
1181
- AnimationConfigurationType::Update,
1182
- tag,
1183
- parent,
1184
- viewStart,
1185
- viewFinal,
1186
- baselineShadowView,
1187
- 0};
551
+ /* .finalMutationsForKeyFrame = */ {mutation},
552
+ /* .type = */ AnimationConfigurationType::Update,
553
+ /* .tag = */ tag,
554
+ /* .parentView = */ parent,
555
+ /* .viewStart = */ viewStart,
556
+ /* .viewEnd = */ viewFinal,
557
+ /* .viewPrev = */ baselineShadowView,
558
+ /* .initialProgress = */ 0};
1188
559
  } else {
1189
560
  // This should just be "Remove" instructions that are not animated
1190
561
  // (either this is a "move", or there's a corresponding "Delete"
@@ -1221,13 +592,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1221
592
  getComponentDescriptorForShadowView(baselineShadowView)
1222
593
  .cloneProps(propsParserContext, viewFinal.props, {});
1223
594
 
1224
- // Dynamic cast, because - we don't know the type of this
1225
- // ShadowNode, it could be Image or Text or something else with
1226
- // different base props.
1227
- const auto viewProps =
1228
- dynamic_cast<const ViewProps *>(props.get());
1229
- if (viewProps != nullptr) {
1230
- const_cast<ViewProps *>(viewProps)->opacity = 0;
595
+ if (baselineShadowView.traits.check(
596
+ ShadowNodeTraits::Trait::ViewKind)) {
597
+ auto const &viewProps =
598
+ *std::static_pointer_cast<ViewProps const>(props);
599
+ const_cast<ViewProps &>(viewProps).opacity = 0;
1231
600
  }
1232
601
 
1233
602
  react_native_assert(props != nullptr);
@@ -1248,13 +617,11 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1248
617
  getComponentDescriptorForShadowView(baselineShadowView)
1249
618
  .cloneProps(propsParserContext, viewFinal.props, {});
1250
619
 
1251
- // Dynamic cast, because - we don't know the type of this
1252
- // ShadowNode, it could be Image or Text or something else with
1253
- // different base props.
1254
- const auto viewProps =
1255
- dynamic_cast<const ViewProps *>(props.get());
1256
- if (viewProps != nullptr) {
1257
- const_cast<ViewProps *>(viewProps)->transform =
620
+ if (baselineShadowView.traits.check(
621
+ ShadowNodeTraits::Trait::ViewKind)) {
622
+ auto const &viewProps =
623
+ *std::static_pointer_cast<ViewProps const>(props);
624
+ const_cast<ViewProps &>(viewProps).transform =
1258
625
  Transform::Scale(isScaleX ? 0 : 1, isScaleY ? 0 : 1, 1);
1259
626
  }
1260
627
 
@@ -1269,14 +636,14 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1269
636
  mutation);
1270
637
 
1271
638
  keyFrame = AnimationKeyFrame{
1272
- {mutation, deleteMutation},
1273
- AnimationConfigurationType::Delete,
1274
- tag,
1275
- parent,
1276
- viewStart,
1277
- viewFinal,
1278
- baselineShadowView,
1279
- 0};
639
+ /* .finalMutationsForKeyFrame */ {mutation, deleteMutation},
640
+ /* .type */ AnimationConfigurationType::Delete,
641
+ /* .tag */ tag,
642
+ /* .parentView */ parent,
643
+ /* .viewStart */ viewStart,
644
+ /* .viewEnd */ viewFinal,
645
+ /* .viewPrev */ baselineShadowView,
646
+ /* .initialProgress */ 0};
1280
647
  } else {
1281
648
  PrintMutationInstruction(
1282
649
  "Executing Remove Immediately, due to reordering operation",
@@ -1415,7 +782,7 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1415
782
  // don't want to queue up any final UPDATE mutations here.
1416
783
  bool shouldGenerateSyntheticMutations =
1417
784
  keyFrame.generateFinalSyntheticMutations;
1418
- bool numFinalMutations = keyFrame.finalMutationsForKeyFrame.size();
785
+ auto numFinalMutations = keyFrame.finalMutationsForKeyFrame.size();
1419
786
  bool onlyMutationIsUpdate =
1420
787
  (numFinalMutations == 1 &&
1421
788
  keyFrame.finalMutationsForKeyFrame[0].type ==
@@ -1575,340 +942,738 @@ LayoutAnimationKeyFrameManager::pullTransaction(
1575
942
  "Conflict with non-animated mutation");
1576
943
  }
1577
944
 
1578
- // Make sure that all operations execute in the proper order.
1579
- // REMOVE operations with highest indices must operate first.
1580
- std::stable_sort(
1581
- finalMutationsForConflictingAnimations.begin(),
1582
- finalMutationsForConflictingAnimations.end(),
1583
- &shouldFirstComeBeforeSecondMutation);
945
+ // Make sure that all operations execute in the proper order.
946
+ // REMOVE operations with highest indices must operate first.
947
+ std::stable_sort(
948
+ finalMutationsForConflictingAnimations.begin(),
949
+ finalMutationsForConflictingAnimations.end(),
950
+ &shouldFirstComeBeforeSecondMutation);
951
+
952
+ #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
953
+ LOG(ERROR)
954
+ << "No Animation: Adjust delayed mutations based on all finalMutationsForConflictingAnimations";
955
+ #endif
956
+ for (auto const &mutation : finalMutationsForConflictingAnimations) {
957
+ if (mutation.type == ShadowViewMutation::Type::Remove ||
958
+ mutation.type == ShadowViewMutation::Type::Insert) {
959
+ adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
960
+ }
961
+ }
962
+
963
+ // The ShadowTree layer doesn't realize that certain operations have
964
+ // been delayed, so we must adjust all Remove and Insert operations
965
+ // based on what else has been deferred, whether we are executing this
966
+ // immediately or later.
967
+ #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
968
+ LOG(ERROR)
969
+ << "No Animation: Adjust mutations based on remaining delayed mutations / adjust delayed, based on each";
970
+ #endif
971
+ for (auto &mutation : mutations) {
972
+ if (mutation.type == ShadowViewMutation::Type::Remove ||
973
+ mutation.type == ShadowViewMutation::Type::Insert) {
974
+ adjustImmediateMutationIndicesForDelayedMutations(
975
+ surfaceId, mutation);
976
+ adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
977
+ }
978
+ }
979
+
980
+ // Append mutations to this list and swap - so that the final
981
+ // conflicting mutations happen before any other mutations
982
+ finalMutationsForConflictingAnimations.insert(
983
+ finalMutationsForConflictingAnimations.end(),
984
+ mutations.begin(),
985
+ mutations.end());
986
+ mutations = finalMutationsForConflictingAnimations;
987
+ }
988
+ } // if (mutations)
989
+
990
+ // We never commit a different root or modify anything -
991
+ // we just send additional mutations to the mounting layer until the
992
+ // animations are finished and the mounting layer (view) represents exactly
993
+ // what is in the most recent shadow tree
994
+ // Add animation mutations to the end of our existing mutations list in this
995
+ // function.
996
+ ShadowViewMutationList mutationsForAnimation{};
997
+ animationMutationsForFrame(surfaceId, mutationsForAnimation, now);
998
+
999
+ // If any delayed removes were executed, update remaining delayed keyframes
1000
+ #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1001
+ LOG(ERROR)
1002
+ << "Adjust all delayed mutations based on final mutations generated by animation driver";
1003
+ #endif
1004
+ for (auto const &mutation : mutationsForAnimation) {
1005
+ if (mutation.type == ShadowViewMutation::Type::Remove) {
1006
+ adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
1007
+ }
1008
+ }
1009
+
1010
+ mutations.insert(
1011
+ mutations.end(),
1012
+ mutationsForAnimation.begin(),
1013
+ mutationsForAnimation.end());
1014
+
1015
+ // DEBUG ONLY: list existing inflight animations
1016
+ #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1017
+ LOG(ERROR) << "FINISHING DISPLAYING ONGOING inflightAnimations_!";
1018
+ int i = 0;
1019
+ int j = 0;
1020
+ for (auto const &inflightAnimation : inflightAnimations_) {
1021
+ i++;
1022
+ j = 0;
1023
+ if (inflightAnimation.completed) {
1024
+ continue;
1025
+ }
1026
+ for (auto &keyframe : inflightAnimation.keyFrames) {
1027
+ j++;
1028
+ if (keyframe.invalidated) {
1029
+ continue;
1030
+ }
1031
+ for (auto const &finalMutation : keyframe.finalMutationsForKeyFrame) {
1032
+ if (!finalMutation.mutatedViewIsVirtual()) {
1033
+ std::string msg = "Animation " + std::to_string(i) + " keyframe " +
1034
+ std::to_string(j) + ": Final Animation";
1035
+ PrintMutationInstruction(msg, finalMutation);
1036
+ }
1037
+ }
1038
+ }
1039
+ }
1040
+ LOG(ERROR) << "FINISHING DONE DISPLAYING ONGOING inflightAnimations_!";
1041
+ #endif
1042
+
1043
+ // Signal to delegate if all animations are complete, or if we were not
1044
+ // animating anything and now some animation exists.
1045
+ if (inflightAnimationsExistInitially && inflightAnimations_.empty()) {
1046
+ std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
1047
+ if (layoutAnimationStatusDelegate_ != nullptr) {
1048
+ layoutAnimationStatusDelegate_->onAllAnimationsComplete();
1049
+ }
1050
+ } else if (
1051
+ !inflightAnimationsExistInitially && !inflightAnimations_.empty()) {
1052
+ std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
1053
+ if (layoutAnimationStatusDelegate_ != nullptr) {
1054
+ layoutAnimationStatusDelegate_->onAnimationStarted();
1055
+ }
1056
+ }
1057
+
1058
+ simulateImagePropsMemoryAccess(mutations);
1059
+
1060
+ return MountingTransaction{
1061
+ surfaceId, transactionNumber, std::move(mutations), telemetry};
1062
+ }
1063
+
1064
+ void LayoutAnimationKeyFrameManager::uiManagerDidConfigureNextLayoutAnimation(
1065
+ LayoutAnimation layoutAnimation) const {
1066
+ currentAnimation_ = better::optional<LayoutAnimation>{layoutAnimation};
1067
+ }
1068
+
1069
+ void LayoutAnimationKeyFrameManager::setLayoutAnimationStatusDelegate(
1070
+ LayoutAnimationStatusDelegate *delegate) const {
1071
+ std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
1072
+ layoutAnimationStatusDelegate_ = delegate;
1073
+ }
1074
+
1075
+ void LayoutAnimationKeyFrameManager::setClockNow(
1076
+ std::function<uint64_t()> now) {
1077
+ now_ = now;
1078
+ }
1079
+
1080
+ void LayoutAnimationKeyFrameManager::enableSkipInvalidatedKeyFrames() {
1081
+ skipInvalidatedKeyFrames_ = true;
1082
+ }
1083
+
1084
+ void LayoutAnimationKeyFrameManager::enableCrashOnMissingComponentDescriptor() {
1085
+ crashOnMissingComponentDescriptor_ = true;
1086
+ }
1087
+
1088
+ void LayoutAnimationKeyFrameManager::enableSimulateImagePropsMemoryAccess() {
1089
+ simulateImagePropsMemoryAccess_ = true;
1090
+ }
1091
+
1092
+ #pragma mark - Protected
1093
+
1094
+ bool LayoutAnimationKeyFrameManager::hasComponentDescriptorForShadowView(
1095
+ ShadowView const &shadowView) const {
1096
+ auto hasComponentDescriptor =
1097
+ componentDescriptorRegistry_->hasComponentDescriptorAt(
1098
+ shadowView.componentHandle);
1099
+
1100
+ if (crashOnMissingComponentDescriptor_ && !hasComponentDescriptor) {
1101
+ LOG(FATAL) << "Component descriptor with handle: "
1102
+ << shadowView.componentHandle
1103
+ << " doesn't exist. The component name: "
1104
+ << shadowView.componentName;
1105
+ }
1106
+
1107
+ return hasComponentDescriptor;
1108
+ }
1109
+
1110
+ ComponentDescriptor const &
1111
+ LayoutAnimationKeyFrameManager::getComponentDescriptorForShadowView(
1112
+ ShadowView const &shadowView) const {
1113
+ return componentDescriptorRegistry_->at(shadowView.componentHandle);
1114
+ }
1115
+
1116
+ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView(
1117
+ double progress,
1118
+ ShadowView const &startingView,
1119
+ ShadowView const &finalView) const {
1120
+ react_native_assert(startingView.tag > 0);
1121
+ react_native_assert(finalView.tag > 0);
1122
+ if (!hasComponentDescriptorForShadowView(startingView)) {
1123
+ LOG(ERROR) << "No ComponentDescriptor for ShadowView being animated: ["
1124
+ << startingView.tag << "]";
1125
+ react_native_assert(false);
1126
+ return finalView;
1127
+ }
1128
+
1129
+ ComponentDescriptor const &componentDescriptor =
1130
+ getComponentDescriptorForShadowView(startingView);
1131
+
1132
+ // Base the mutated view on the finalView, so that the following stay
1133
+ // consistent:
1134
+ // - state
1135
+ // - eventEmitter
1136
+ // For now, we do not allow interpolation of state. And we probably never
1137
+ // will, so make sure we always keep the mounting layer consistent with the
1138
+ // "final" state.
1139
+ auto mutatedShadowView = ShadowView(finalView);
1140
+ react_native_assert(mutatedShadowView.tag > 0);
1141
+
1142
+ react_native_assert(startingView.props != nullptr);
1143
+ react_native_assert(finalView.props != nullptr);
1144
+ if (startingView.props == nullptr || finalView.props == nullptr) {
1145
+ return finalView;
1146
+ }
1147
+
1148
+ // Animate opacity or scale/transform
1149
+ PropsParserContext propsParserContext{
1150
+ finalView.surfaceId, *contextContainer_};
1151
+ mutatedShadowView.props = componentDescriptor.interpolateProps(
1152
+ propsParserContext, progress, startingView.props, finalView.props);
1153
+ react_native_assert(mutatedShadowView.props != nullptr);
1154
+ if (mutatedShadowView.props == nullptr) {
1155
+ return finalView;
1156
+ }
1157
+
1158
+ // Interpolate LayoutMetrics
1159
+ LayoutMetrics const &finalLayoutMetrics = finalView.layoutMetrics;
1160
+ LayoutMetrics const &baselineLayoutMetrics = startingView.layoutMetrics;
1161
+ LayoutMetrics interpolatedLayoutMetrics = finalLayoutMetrics;
1162
+ interpolatedLayoutMetrics.frame.origin.x = interpolateFloats(
1163
+ progress,
1164
+ baselineLayoutMetrics.frame.origin.x,
1165
+ finalLayoutMetrics.frame.origin.x);
1166
+ interpolatedLayoutMetrics.frame.origin.y = interpolateFloats(
1167
+ progress,
1168
+ baselineLayoutMetrics.frame.origin.y,
1169
+ finalLayoutMetrics.frame.origin.y);
1170
+ interpolatedLayoutMetrics.frame.size.width = interpolateFloats(
1171
+ progress,
1172
+ baselineLayoutMetrics.frame.size.width,
1173
+ finalLayoutMetrics.frame.size.width);
1174
+ interpolatedLayoutMetrics.frame.size.height = interpolateFloats(
1175
+ progress,
1176
+ baselineLayoutMetrics.frame.size.height,
1177
+ finalLayoutMetrics.frame.size.height);
1178
+ mutatedShadowView.layoutMetrics = interpolatedLayoutMetrics;
1179
+
1180
+ return mutatedShadowView;
1181
+ }
1182
+
1183
+ void LayoutAnimationKeyFrameManager::callCallback(
1184
+ LayoutAnimationCallbackWrapper const &callback) const {
1185
+ runtimeExecutor_(
1186
+ [callback](jsi::Runtime &runtime) { callback.call(runtime); });
1187
+ }
1188
+
1189
+ void LayoutAnimationKeyFrameManager::queueFinalMutationsForCompletedKeyFrame(
1190
+ AnimationKeyFrame const &keyframe,
1191
+ ShadowViewMutation::List &mutationsList,
1192
+ bool interrupted,
1193
+ const std::string &logPrefix) const {
1194
+ if (skipInvalidatedKeyFrames_ && keyframe.invalidated) {
1195
+ return;
1196
+ }
1197
+ if (keyframe.finalMutationsForKeyFrame.size() > 0) {
1198
+ // TODO: modularize this segment, it is repeated 2x in KeyFrameManager
1199
+ // as well.
1200
+ ShadowView prev = keyframe.viewPrev;
1201
+ for (auto const &finalMutation : keyframe.finalMutationsForKeyFrame) {
1202
+ PrintMutationInstruction(
1203
+ logPrefix + ": Queuing up Final Mutation:", finalMutation);
1204
+ // Copy so that if something else mutates the inflight animations,
1205
+ // it won't change this mutation after this point.
1206
+ switch (finalMutation.type) {
1207
+ // For CREATE/INSERT this will contain CREATE, INSERT in that order.
1208
+ // For REMOVE/DELETE, same.
1209
+ case ShadowViewMutation::Type::Create:
1210
+ mutationsList.push_back(ShadowViewMutation::CreateMutation(
1211
+ finalMutation.newChildShadowView));
1212
+ break;
1213
+ case ShadowViewMutation::Type::Delete:
1214
+ mutationsList.push_back(ShadowViewMutation::DeleteMutation(prev));
1215
+ break;
1216
+ case ShadowViewMutation::Type::Insert:
1217
+ mutationsList.push_back(ShadowViewMutation::InsertMutation(
1218
+ finalMutation.parentShadowView,
1219
+ finalMutation.newChildShadowView,
1220
+ finalMutation.index));
1221
+ break;
1222
+ case ShadowViewMutation::Type::Remove:
1223
+ mutationsList.push_back(ShadowViewMutation::RemoveMutation(
1224
+ finalMutation.parentShadowView, prev, finalMutation.index));
1225
+ break;
1226
+ case ShadowViewMutation::Type::Update:
1227
+ mutationsList.push_back(ShadowViewMutation::UpdateMutation(
1228
+ prev, finalMutation.newChildShadowView));
1229
+ break;
1230
+ }
1231
+ if (finalMutation.newChildShadowView.tag > 0) {
1232
+ prev = finalMutation.newChildShadowView;
1233
+ }
1234
+ }
1235
+ } else {
1236
+ // If there's no final mutation associated, create a mutation that
1237
+ // corresponds to the animation being 100% complete. This is
1238
+ // important for, for example, INSERT mutations being animated from
1239
+ // opacity 0 to 1. If the animation is interrupted we must force the
1240
+ // View to be at opacity 1. For Android - since it passes along only
1241
+ // deltas, not an entire bag of props - generate an "animation"
1242
+ // frame corresponding to a final update for this view. Only then,
1243
+ // generate an update that will cause the ShadowTree to be
1244
+ // consistent with the Mounting layer by passing viewEnd,
1245
+ // unmodified, to the mounting layer. This helps with, for example,
1246
+ // opacity animations.
1247
+ // This is necessary for INSERT (create) and UPDATE (update) mutations, but
1248
+ // not REMOVE/DELETE mutations ("delete" animations).
1249
+ if (interrupted) {
1250
+ auto mutatedShadowView =
1251
+ createInterpolatedShadowView(1, keyframe.viewStart, keyframe.viewEnd);
1252
+ auto generatedPenultimateMutation = ShadowViewMutation::UpdateMutation(
1253
+ keyframe.viewPrev, mutatedShadowView);
1254
+ react_native_assert(
1255
+ generatedPenultimateMutation.oldChildShadowView.tag > 0);
1256
+ react_native_assert(
1257
+ generatedPenultimateMutation.newChildShadowView.tag > 0);
1258
+ PrintMutationInstruction(
1259
+ "Queueing up penultimate mutation instruction - synthetic",
1260
+ generatedPenultimateMutation);
1261
+ mutationsList.push_back(generatedPenultimateMutation);
1262
+
1263
+ auto generatedMutation = ShadowViewMutation::UpdateMutation(
1264
+ mutatedShadowView, keyframe.viewEnd);
1265
+ react_native_assert(generatedMutation.oldChildShadowView.tag > 0);
1266
+ react_native_assert(generatedMutation.newChildShadowView.tag > 0);
1267
+ PrintMutationInstruction(
1268
+ "Queueing up final mutation instruction - synthetic",
1269
+ generatedMutation);
1270
+ mutationsList.push_back(generatedMutation);
1271
+ } else {
1272
+ auto mutation = ShadowViewMutation::UpdateMutation(
1273
+ keyframe.viewPrev, keyframe.viewEnd);
1274
+ PrintMutationInstruction(
1275
+ logPrefix +
1276
+ "Animation Complete: Queuing up Final Synthetic Mutation:",
1277
+ mutation);
1278
+ react_native_assert(mutation.oldChildShadowView.tag > 0);
1279
+ react_native_assert(mutation.newChildShadowView.tag > 0);
1280
+ mutationsList.push_back(std::move(mutation));
1281
+ }
1282
+ }
1283
+ }
1284
+
1285
+ #pragma mark - Private
1286
+
1287
+ void LayoutAnimationKeyFrameManager::
1288
+ adjustImmediateMutationIndicesForDelayedMutations(
1289
+ SurfaceId surfaceId,
1290
+ ShadowViewMutation &mutation,
1291
+ bool skipLastAnimation,
1292
+ bool lastAnimationOnly) const {
1293
+ bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove;
1294
+ react_native_assert(
1295
+ isRemoveMutation || mutation.type == ShadowViewMutation::Type::Insert);
1296
+
1297
+ // TODO: turn all of this into a lambda and share code?
1298
+ if (mutation.mutatedViewIsVirtual()) {
1299
+ PrintMutationInstruction(
1300
+ "[IndexAdjustment] Not calling adjustImmediateMutationIndicesForDelayedMutations, is virtual, for:",
1301
+ mutation);
1302
+ return;
1303
+ }
1304
+
1305
+ PrintMutationInstruction(
1306
+ "[IndexAdjustment] Calling adjustImmediateMutationIndicesForDelayedMutations for:",
1307
+ mutation);
1308
+
1309
+ // First, collect all final mutations that could impact this immediate
1310
+ // mutation.
1311
+ std::vector<ShadowViewMutation *> candidateMutations{};
1312
+
1313
+ for (auto inflightAnimationIt =
1314
+ inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
1315
+ inflightAnimationIt != inflightAnimations_.rend();
1316
+ inflightAnimationIt++) {
1317
+ auto &inflightAnimation = *inflightAnimationIt;
1318
+ if (inflightAnimation.surfaceId != surfaceId) {
1319
+ continue;
1320
+ }
1321
+ if (inflightAnimation.completed) {
1322
+ continue;
1323
+ }
1324
+
1325
+ for (auto it = inflightAnimation.keyFrames.begin();
1326
+ it != inflightAnimation.keyFrames.end();
1327
+ it++) {
1328
+ auto &animatedKeyFrame = *it;
1329
+
1330
+ if (animatedKeyFrame.invalidated) {
1331
+ continue;
1332
+ }
1584
1333
 
1585
- #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1586
- LOG(ERROR)
1587
- << "No Animation: Adjust delayed mutations based on all finalMutationsForConflictingAnimations";
1588
- #endif
1589
- for (auto const &mutation : finalMutationsForConflictingAnimations) {
1590
- if (mutation.type == ShadowViewMutation::Type::Remove ||
1591
- mutation.type == ShadowViewMutation::Type::Insert) {
1592
- adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
1593
- }
1334
+ // Detect if they're in the same view hierarchy, but not equivalent
1335
+ // We've already detected direct conflicts and removed them.
1336
+ if (animatedKeyFrame.parentView.tag != mutation.parentShadowView.tag) {
1337
+ continue;
1594
1338
  }
1595
1339
 
1596
- // The ShadowTree layer doesn't realize that certain operations have
1597
- // been delayed, so we must adjust all Remove and Insert operations
1598
- // based on what else has been deferred, whether we are executing this
1599
- // immediately or later.
1600
- #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1601
- LOG(ERROR)
1602
- << "No Animation: Adjust mutations based on remaining delayed mutations / adjust delayed, based on each";
1603
- #endif
1604
- for (auto &mutation : mutations) {
1605
- if (mutation.type == ShadowViewMutation::Type::Remove ||
1606
- mutation.type == ShadowViewMutation::Type::Insert) {
1607
- adjustImmediateMutationIndicesForDelayedMutations(
1608
- surfaceId, mutation);
1609
- adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
1340
+ for (auto &delayedMutation : animatedKeyFrame.finalMutationsForKeyFrame) {
1341
+ if (delayedMutation.type != ShadowViewMutation::Type::Remove) {
1342
+ continue;
1343
+ }
1344
+ if (delayedMutation.mutatedViewIsVirtual()) {
1345
+ continue;
1346
+ }
1347
+ if (delayedMutation.oldChildShadowView.tag ==
1348
+ (isRemoveMutation ? mutation.oldChildShadowView.tag
1349
+ : mutation.newChildShadowView.tag)) {
1350
+ continue;
1610
1351
  }
1352
+
1353
+ PrintMutationInstructionRelative(
1354
+ "[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations CANDIDATE for:",
1355
+ mutation,
1356
+ delayedMutation);
1357
+ candidateMutations.push_back(&delayedMutation);
1611
1358
  }
1359
+ }
1612
1360
 
1613
- // Append mutations to this list and swap - so that the final
1614
- // conflicting mutations happen before any other mutations
1615
- finalMutationsForConflictingAnimations.insert(
1616
- finalMutationsForConflictingAnimations.end(),
1617
- mutations.begin(),
1618
- mutations.end());
1619
- mutations = finalMutationsForConflictingAnimations;
1361
+ if (lastAnimationOnly) {
1362
+ break;
1620
1363
  }
1621
- } // if (mutations)
1364
+ }
1622
1365
 
1623
- // We never commit a different root or modify anything -
1624
- // we just send additional mutations to the mounting layer until the
1625
- // animations are finished and the mounting layer (view) represents exactly
1626
- // what is in the most recent shadow tree
1627
- // Add animation mutations to the end of our existing mutations list in this
1628
- // function.
1629
- ShadowViewMutationList mutationsForAnimation{};
1630
- animationMutationsForFrame(surfaceId, mutationsForAnimation, now);
1366
+ // While the mutation keeps being affected, keep checking. We use the vector
1367
+ // so we only perform one adjustment per delayed mutation. See comments at
1368
+ // bottom of adjustDelayedMutationIndicesForMutation for further explanation.
1369
+ bool changed = true;
1370
+ int adjustedDelta = 0;
1371
+ while (changed) {
1372
+ changed = false;
1373
+ candidateMutations.erase(
1374
+ std::remove_if(
1375
+ candidateMutations.begin(),
1376
+ candidateMutations.end(),
1377
+ [&changed, &mutation, &adjustedDelta, &isRemoveMutation](
1378
+ ShadowViewMutation *candidateMutation) {
1379
+ bool indexConflicts =
1380
+ (candidateMutation->index < mutation.index ||
1381
+ (isRemoveMutation &&
1382
+ candidateMutation->index == mutation.index));
1383
+ if (indexConflicts) {
1384
+ mutation.index++;
1385
+ adjustedDelta++;
1386
+ changed = true;
1387
+ PrintMutationInstructionRelative(
1388
+ "[IndexAdjustment] adjustImmediateMutationIndicesForDelayedMutations: Adjusting mutation UPWARD",
1389
+ mutation,
1390
+ *candidateMutation);
1391
+ return true;
1392
+ }
1393
+ return false;
1394
+ }),
1395
+ candidateMutations.end());
1396
+ }
1397
+ }
1631
1398
 
1632
- // If any delayed removes were executed, update remaining delayed keyframes
1633
- #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1634
- LOG(ERROR)
1635
- << "Adjust all delayed mutations based on final mutations generated by animation driver";
1636
- #endif
1637
- for (auto const &mutation : mutationsForAnimation) {
1638
- if (mutation.type == ShadowViewMutation::Type::Remove) {
1639
- adjustDelayedMutationIndicesForMutation(surfaceId, mutation);
1640
- }
1399
+ void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation(
1400
+ SurfaceId surfaceId,
1401
+ ShadowViewMutation const &mutation,
1402
+ bool skipLastAnimation) const {
1403
+ bool isRemoveMutation = mutation.type == ShadowViewMutation::Type::Remove;
1404
+ bool isInsertMutation = mutation.type == ShadowViewMutation::Type::Insert;
1405
+ auto tag = isRemoveMutation ? mutation.oldChildShadowView.tag
1406
+ : mutation.newChildShadowView.tag;
1407
+ react_native_assert(isRemoveMutation || isInsertMutation);
1408
+
1409
+ if (mutation.mutatedViewIsVirtual()) {
1410
+ PrintMutationInstruction(
1411
+ "[IndexAdjustment] Not calling adjustDelayedMutationIndicesForMutation, is virtual, for:",
1412
+ mutation);
1413
+ return;
1641
1414
  }
1642
1415
 
1643
- mutations.insert(
1644
- mutations.end(),
1645
- mutationsForAnimation.begin(),
1646
- mutationsForAnimation.end());
1416
+ // First, collect all final mutations that could impact this immediate
1417
+ // mutation.
1418
+ std::vector<ShadowViewMutation *> candidateMutations{};
1647
1419
 
1648
- // DEBUG ONLY: list existing inflight animations
1649
- #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1650
- LOG(ERROR) << "FINISHING DISPLAYING ONGOING inflightAnimations_!";
1651
- int i = 0;
1652
- int j = 0;
1653
- for (auto const &inflightAnimation : inflightAnimations_) {
1654
- i++;
1655
- j = 0;
1420
+ for (auto inflightAnimationIt =
1421
+ inflightAnimations_.rbegin() + (skipLastAnimation ? 1 : 0);
1422
+ inflightAnimationIt != inflightAnimations_.rend();
1423
+ inflightAnimationIt++) {
1424
+ auto &inflightAnimation = *inflightAnimationIt;
1425
+
1426
+ if (inflightAnimation.surfaceId != surfaceId) {
1427
+ continue;
1428
+ }
1656
1429
  if (inflightAnimation.completed) {
1657
1430
  continue;
1658
1431
  }
1659
- for (auto &keyframe : inflightAnimation.keyFrames) {
1660
- j++;
1661
- if (keyframe.invalidated) {
1432
+
1433
+ for (auto it = inflightAnimation.keyFrames.begin();
1434
+ it != inflightAnimation.keyFrames.end();
1435
+ it++) {
1436
+ auto &animatedKeyFrame = *it;
1437
+
1438
+ if (animatedKeyFrame.invalidated) {
1439
+ continue;
1440
+ }
1441
+
1442
+ // Detect if they're in the same view hierarchy, but not equivalent
1443
+ // (We've already detected direct conflicts and handled them above)
1444
+ if (animatedKeyFrame.parentView.tag != mutation.parentShadowView.tag) {
1445
+ continue;
1446
+ }
1447
+
1448
+ for (auto &finalAnimationMutation :
1449
+ animatedKeyFrame.finalMutationsForKeyFrame) {
1450
+ if (finalAnimationMutation.oldChildShadowView.tag == tag) {
1451
+ continue;
1452
+ }
1453
+
1454
+ if (finalAnimationMutation.type != ShadowViewMutation::Type::Remove) {
1455
+ continue;
1456
+ }
1457
+ if (finalAnimationMutation.mutatedViewIsVirtual()) {
1458
+ continue;
1459
+ }
1460
+
1461
+ PrintMutationInstructionRelative(
1462
+ "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: CANDIDATE:",
1463
+ mutation,
1464
+ finalAnimationMutation);
1465
+ candidateMutations.push_back(&finalAnimationMutation);
1466
+ }
1467
+ }
1468
+ }
1469
+
1470
+ // Because the finalAnimations are not sorted in any way, it is possible to
1471
+ // have some sequence like:
1472
+ // * DELAYED REMOVE 10 from {TAG}
1473
+ // * DELAYED REMOVE 9 from {TAG}
1474
+ // * ...
1475
+ // * DELAYED REMOVE 5 from {TAG}
1476
+ // with mutation: INSERT 6/REMOVE 6. This would cause the first few mutations
1477
+ // to *not* be adjusted, even though they would be impacted by mutation or
1478
+ // vice-versa after later adjustments are applied. Therefore, we just keep
1479
+ // recursing while there are any changes. This isn't great, but is good enough
1480
+ // for now until we change these data-structures.
1481
+ bool changed = true;
1482
+ while (changed) {
1483
+ changed = false;
1484
+ candidateMutations.erase(
1485
+ std::remove_if(
1486
+ candidateMutations.begin(),
1487
+ candidateMutations.end(),
1488
+ [&mutation, &isRemoveMutation, &isInsertMutation, &changed](
1489
+ ShadowViewMutation *candidateMutation) {
1490
+ if (isRemoveMutation &&
1491
+ mutation.index <= candidateMutation->index) {
1492
+ candidateMutation->index--;
1493
+ changed = true;
1494
+ PrintMutationInstructionRelative(
1495
+ "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation DOWNWARD",
1496
+ mutation,
1497
+ *candidateMutation);
1498
+ return true;
1499
+ } else if (
1500
+ isInsertMutation &&
1501
+ mutation.index <= candidateMutation->index) {
1502
+ candidateMutation->index++;
1503
+ changed = true;
1504
+ PrintMutationInstructionRelative(
1505
+ "[IndexAdjustment] adjustDelayedMutationIndicesForMutation: Adjusting mutation UPWARD",
1506
+ mutation,
1507
+ *candidateMutation);
1508
+ return true;
1509
+ }
1510
+ return false;
1511
+ }),
1512
+ candidateMutations.end());
1513
+ }
1514
+ }
1515
+
1516
+ void LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations(
1517
+ SurfaceId surfaceId,
1518
+ ShadowViewMutationList const &mutations,
1519
+ std::vector<AnimationKeyFrame> &conflictingAnimations) const {
1520
+ ShadowViewMutationList localConflictingMutations{};
1521
+ for (auto const &mutation : mutations) {
1522
+ bool mutationIsCreateOrDelete =
1523
+ mutation.type == ShadowViewMutation::Type::Create ||
1524
+ mutation.type == ShadowViewMutation::Type::Delete;
1525
+ auto const &baselineShadowView =
1526
+ (mutation.type == ShadowViewMutation::Type::Insert ||
1527
+ mutation.type == ShadowViewMutation::Type::Create)
1528
+ ? mutation.newChildShadowView
1529
+ : mutation.oldChildShadowView;
1530
+ auto baselineTag = baselineShadowView.tag;
1531
+
1532
+ for (auto &inflightAnimation : inflightAnimations_) {
1533
+ if (inflightAnimation.surfaceId != surfaceId) {
1662
1534
  continue;
1663
1535
  }
1664
- for (auto const &finalMutation : keyframe.finalMutationsForKeyFrame) {
1665
- if (!finalMutation.mutatedViewIsVirtual()) {
1666
- std::string msg = "Animation " + std::to_string(i) + " keyframe " +
1667
- std::to_string(j) + ": Final Animation";
1668
- PrintMutationInstruction(msg, finalMutation);
1669
- }
1536
+ if (inflightAnimation.completed) {
1537
+ continue;
1670
1538
  }
1671
- }
1672
- }
1673
- LOG(ERROR) << "FINISHING DONE DISPLAYING ONGOING inflightAnimations_!";
1674
- #endif
1675
-
1676
- // Signal to delegate if all animations are complete, or if we were not
1677
- // animating anything and now some animation exists.
1678
- if (inflightAnimationsExistInitially && inflightAnimations_.empty()) {
1679
- std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
1680
- if (layoutAnimationStatusDelegate_ != nullptr) {
1681
- layoutAnimationStatusDelegate_->onAllAnimationsComplete();
1682
- }
1683
- } else if (
1684
- !inflightAnimationsExistInitially && !inflightAnimations_.empty()) {
1685
- std::lock_guard<std::mutex> lock(layoutAnimationStatusDelegateMutex_);
1686
- if (layoutAnimationStatusDelegate_ != nullptr) {
1687
- layoutAnimationStatusDelegate_->onAnimationStarted();
1688
- }
1689
- }
1690
-
1691
- return MountingTransaction{
1692
- surfaceId, transactionNumber, std::move(mutations), telemetry};
1693
- }
1694
1539
 
1695
- bool LayoutAnimationKeyFrameManager::hasComponentDescriptorForShadowView(
1696
- ShadowView const &shadowView) const {
1697
- return componentDescriptorRegistry_->hasComponentDescriptorAt(
1698
- shadowView.componentHandle);
1699
- }
1540
+ for (auto it = inflightAnimation.keyFrames.begin();
1541
+ it != inflightAnimation.keyFrames.end();) {
1542
+ auto &animatedKeyFrame = *it;
1700
1543
 
1701
- ComponentDescriptor const &
1702
- LayoutAnimationKeyFrameManager::getComponentDescriptorForShadowView(
1703
- ShadowView const &shadowView) const {
1704
- return componentDescriptorRegistry_->at(shadowView.componentHandle);
1705
- }
1544
+ if (animatedKeyFrame.invalidated) {
1545
+ continue;
1546
+ }
1706
1547
 
1707
- void LayoutAnimationKeyFrameManager::setComponentDescriptorRegistry(
1708
- const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {
1709
- componentDescriptorRegistry_ = componentDescriptorRegistry;
1710
- }
1548
+ // A conflict is when either: the animated node itself is mutated
1549
+ // directly; or, the parent of the node is created or deleted. In cases
1550
+ // of reparenting - say, the parent is deleted but the node was moved to
1551
+ // a different parent first - the reparenting (remove/insert) conflict
1552
+ // will be detected before we process the parent DELETE.
1553
+ // Parent deletion is important because deleting a parent recursively
1554
+ // deletes all children. If we previously deferred deletion of a child,
1555
+ // we need to force deletion/removal to happen immediately.
1556
+ bool conflicting = animatedKeyFrame.tag == baselineTag ||
1557
+ (mutationIsCreateOrDelete &&
1558
+ animatedKeyFrame.parentView.tag == baselineTag &&
1559
+ animatedKeyFrame.parentView.tag != 0);
1711
1560
 
1712
- /**
1713
- * Given a `progress` between 0 and 1, a mutation and LayoutAnimation config,
1714
- * return a ShadowView with mutated props and/or LayoutMetrics.
1715
- *
1716
- * @param progress
1717
- * @param layoutAnimation
1718
- * @param animatedMutation
1719
- * @return
1720
- */
1721
- ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView(
1722
- double progress,
1723
- ShadowView startingView,
1724
- ShadowView finalView) const {
1725
- react_native_assert(startingView.tag > 0);
1726
- react_native_assert(finalView.tag > 0);
1727
- if (!hasComponentDescriptorForShadowView(startingView)) {
1728
- LOG(ERROR) << "No ComponentDescriptor for ShadowView being animated: ["
1729
- << startingView.tag << "]";
1730
- react_native_assert(false);
1731
- return finalView;
1732
- }
1561
+ // Conflicting animation detected: if we're mutating a tag under
1562
+ // animation, or deleting the parent of a tag under animation, or
1563
+ // reparenting.
1564
+ if (conflicting) {
1565
+ animatedKeyFrame.invalidated = true;
1733
1566
 
1734
- // Stub PropsParserContext used for interpolateProps.
1735
- // This is/should be safe because interpolating doesn't actually need to
1736
- // parse props, and just copies them; therefore there should be no
1737
- // need to actually use anything in the PropsParserContext.
1738
- // If this ever changes, the LayoutAnimations API will need to change
1739
- // to pass in a real PropsParserContext.
1740
- ContextContainer contextContainer{};
1741
- PropsParserContext propsParserContext{-1, contextContainer};
1567
+ // We construct a list of all conflicting animations, whether or not
1568
+ // they have a "final mutation" to execute. This is important with,
1569
+ // for example, "insert" mutations where the final update needs to set
1570
+ // opacity to "1", even if there's no final ShadowNode update.
1571
+ // TODO: don't animate virtual views in the first place?
1572
+ bool isVirtual = false;
1573
+ for (const auto &finalMutationForKeyFrame :
1574
+ animatedKeyFrame.finalMutationsForKeyFrame) {
1575
+ isVirtual =
1576
+ isVirtual || finalMutationForKeyFrame.mutatedViewIsVirtual();
1742
1577
 
1743
- ComponentDescriptor const &componentDescriptor =
1744
- getComponentDescriptorForShadowView(startingView);
1578
+ #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1579
+ PrintMutationInstructionRelative(
1580
+ "Found mutation that conflicts with existing in-flight animation:",
1581
+ mutation,
1582
+ finalMutationForKeyFrame);
1583
+ #endif
1584
+ }
1745
1585
 
1746
- // Base the mutated view on the finalView, so that the following stay
1747
- // consistent:
1748
- // - state
1749
- // - eventEmitter
1750
- // For now, we do not allow interpolation of state. And we probably never
1751
- // will, so make sure we always keep the mounting layer consistent with the
1752
- // "final" state.
1753
- auto mutatedShadowView = ShadowView(finalView);
1754
- react_native_assert(mutatedShadowView.tag > 0);
1586
+ conflictingAnimations.push_back(animatedKeyFrame);
1587
+ for (const auto &finalMutationForKeyFrame :
1588
+ animatedKeyFrame.finalMutationsForKeyFrame) {
1589
+ if (!isVirtual ||
1590
+ finalMutationForKeyFrame.type ==
1591
+ ShadowViewMutation::Type::Delete) {
1592
+ localConflictingMutations.push_back(finalMutationForKeyFrame);
1593
+ }
1594
+ }
1755
1595
 
1756
- react_native_assert(startingView.props != nullptr);
1757
- react_native_assert(finalView.props != nullptr);
1758
- if (startingView.props == nullptr || finalView.props == nullptr) {
1759
- return finalView;
1596
+ // Delete from existing animation
1597
+ it = inflightAnimation.keyFrames.erase(it);
1598
+ } else {
1599
+ it++;
1600
+ }
1601
+ }
1602
+ }
1760
1603
  }
1761
1604
 
1762
- // Animate opacity or scale/transform
1763
- mutatedShadowView.props = componentDescriptor.interpolateProps(
1764
- propsParserContext, progress, startingView.props, finalView.props);
1765
- react_native_assert(mutatedShadowView.props != nullptr);
1766
- if (mutatedShadowView.props == nullptr) {
1767
- return finalView;
1605
+ // Recurse, in case conflicting mutations conflict with other existing
1606
+ // animations
1607
+ if (!localConflictingMutations.empty()) {
1608
+ getAndEraseConflictingAnimations(
1609
+ surfaceId, localConflictingMutations, conflictingAnimations);
1768
1610
  }
1769
-
1770
- // Interpolate LayoutMetrics
1771
- LayoutMetrics const &finalLayoutMetrics = finalView.layoutMetrics;
1772
- LayoutMetrics const &baselineLayoutMetrics = startingView.layoutMetrics;
1773
- LayoutMetrics interpolatedLayoutMetrics = finalLayoutMetrics;
1774
- interpolatedLayoutMetrics.frame.origin.x = interpolateFloats(
1775
- progress,
1776
- baselineLayoutMetrics.frame.origin.x,
1777
- finalLayoutMetrics.frame.origin.x);
1778
- interpolatedLayoutMetrics.frame.origin.y = interpolateFloats(
1779
- progress,
1780
- baselineLayoutMetrics.frame.origin.y,
1781
- finalLayoutMetrics.frame.origin.y);
1782
- interpolatedLayoutMetrics.frame.size.width = interpolateFloats(
1783
- progress,
1784
- baselineLayoutMetrics.frame.size.width,
1785
- finalLayoutMetrics.frame.size.width);
1786
- interpolatedLayoutMetrics.frame.size.height = interpolateFloats(
1787
- progress,
1788
- baselineLayoutMetrics.frame.size.height,
1789
- finalLayoutMetrics.frame.size.height);
1790
- mutatedShadowView.layoutMetrics = interpolatedLayoutMetrics;
1791
-
1792
- return mutatedShadowView;
1793
1611
  }
1794
1612
 
1795
- void LayoutAnimationKeyFrameManager::queueFinalMutationsForCompletedKeyFrame(
1796
- AnimationKeyFrame const &keyframe,
1797
- ShadowViewMutation::List &mutationsList,
1798
- bool interrupted,
1799
- std::string logPrefix) const {
1800
- if (keyframe.finalMutationsForKeyFrame.size() > 0) {
1801
- // TODO: modularize this segment, it is repeated 2x in KeyFrameManager
1802
- // as well.
1803
- ShadowView prev = keyframe.viewPrev;
1804
- for (auto const &finalMutation : keyframe.finalMutationsForKeyFrame) {
1805
- PrintMutationInstruction(
1806
- logPrefix + ": Queuing up Final Mutation:", finalMutation);
1807
- // Copy so that if something else mutates the inflight animations,
1808
- // it won't change this mutation after this point.
1809
- auto mutation = ShadowViewMutation{
1810
- finalMutation.type,
1811
- finalMutation.parentShadowView,
1812
- prev,
1813
- finalMutation.newChildShadowView,
1814
- finalMutation.index};
1815
- react_native_assert(mutation.oldChildShadowView.tag > 0);
1816
- react_native_assert(
1817
- mutation.newChildShadowView.tag > 0 ||
1818
- finalMutation.type == ShadowViewMutation::Remove ||
1819
- finalMutation.type == ShadowViewMutation::Delete);
1820
- mutationsList.push_back(mutation);
1821
- if (finalMutation.newChildShadowView.tag > 0) {
1822
- prev = finalMutation.newChildShadowView;
1823
- }
1613
+ void LayoutAnimationKeyFrameManager::deleteAnimationsForStoppedSurfaces()
1614
+ const {
1615
+ bool inflightAnimationsExistInitially = !inflightAnimations_.empty();
1616
+
1617
+ // Execute stopSurface on any ongoing animations
1618
+ if (inflightAnimationsExistInitially) {
1619
+ better::set<SurfaceId> surfaceIdsToStop{};
1620
+ {
1621
+ std::lock_guard<std::mutex> lock(surfaceIdsToStopMutex_);
1622
+ surfaceIdsToStop = surfaceIdsToStop_;
1623
+ surfaceIdsToStop_.clear();
1824
1624
  }
1825
- } else {
1826
- // If there's no final mutation associated, create a mutation that
1827
- // corresponds to the animation being 100% complete. This is
1828
- // important for, for example, INSERT mutations being animated from
1829
- // opacity 0 to 1. If the animation is interrupted we must force the
1830
- // View to be at opacity 1. For Android - since it passes along only
1831
- // deltas, not an entire bag of props - generate an "animation"
1832
- // frame corresponding to a final update for this view. Only then,
1833
- // generate an update that will cause the ShadowTree to be
1834
- // consistent with the Mounting layer by passing viewEnd,
1835
- // unmodified, to the mounting layer. This helps with, for example,
1836
- // opacity animations.
1837
- // This is necessary for INSERT (create) and UPDATE (update) mutations, but
1838
- // not REMOVE/DELETE mutations ("delete" animations).
1839
- if (interrupted) {
1840
- auto mutatedShadowView =
1841
- createInterpolatedShadowView(1, keyframe.viewStart, keyframe.viewEnd);
1842
- auto generatedPenultimateMutation = ShadowViewMutation::UpdateMutation(
1843
- keyframe.viewPrev, mutatedShadowView);
1844
- react_native_assert(
1845
- generatedPenultimateMutation.oldChildShadowView.tag > 0);
1846
- react_native_assert(
1847
- generatedPenultimateMutation.newChildShadowView.tag > 0);
1848
- PrintMutationInstruction(
1849
- "Queueing up penultimate mutation instruction - synthetic",
1850
- generatedPenultimateMutation);
1851
- mutationsList.push_back(generatedPenultimateMutation);
1852
1625
 
1853
- auto generatedMutation = ShadowViewMutation::UpdateMutation(
1854
- mutatedShadowView, keyframe.viewEnd);
1855
- react_native_assert(generatedMutation.oldChildShadowView.tag > 0);
1856
- react_native_assert(generatedMutation.newChildShadowView.tag > 0);
1857
- PrintMutationInstruction(
1858
- "Queueing up final mutation instruction - synthetic",
1859
- generatedMutation);
1860
- mutationsList.push_back(generatedMutation);
1861
- } else {
1862
- auto mutation = ShadowViewMutation{
1863
- ShadowViewMutation::Type::Update,
1864
- keyframe.parentView,
1865
- keyframe.viewPrev,
1866
- keyframe.viewEnd,
1867
- -1};
1868
- PrintMutationInstruction(
1869
- logPrefix +
1870
- "Animation Complete: Queuing up Final Synthetic Mutation:",
1871
- mutation);
1872
- react_native_assert(mutation.oldChildShadowView.tag > 0);
1873
- react_native_assert(mutation.newChildShadowView.tag > 0);
1874
- mutationsList.push_back(mutation);
1626
+ for (auto it = inflightAnimations_.begin();
1627
+ it != inflightAnimations_.end();) {
1628
+ const auto &animation = *it;
1629
+
1630
+ #ifdef LAYOUT_ANIMATION_VERBOSE_LOGGING
1631
+ LOG(ERROR)
1632
+ << "LayoutAnimations: stopping animation due to stopSurface on "
1633
+ << surfaceId;
1634
+ #endif
1635
+ if (surfaceIdsToStop.find(animation.surfaceId) !=
1636
+ surfaceIdsToStop.end()) {
1637
+ it = inflightAnimations_.erase(it);
1638
+ } else {
1639
+ it++;
1640
+ }
1875
1641
  }
1876
1642
  }
1877
1643
  }
1878
1644
 
1879
- void LayoutAnimationKeyFrameManager::callCallback(
1880
- const LayoutAnimationCallbackWrapper &callback) const {
1881
- if (callback.readyForCleanup()) {
1645
+ void LayoutAnimationKeyFrameManager::simulateImagePropsMemoryAccess(
1646
+ ShadowViewMutationList const &mutations) const {
1647
+ if (!simulateImagePropsMemoryAccess_) {
1882
1648
  return;
1883
1649
  }
1884
-
1885
- // Callbacks can only be called once. Replace the callsite with an empty
1886
- // CallbackWrapper. We use a unique_ptr to avoid copying into the vector.
1887
- std::unique_ptr<LayoutAnimationCallbackWrapper> copiedCallback(
1888
- std::make_unique<LayoutAnimationCallbackWrapper>(callback));
1889
-
1890
- // Call the callback that is being retained in the vector
1891
- copiedCallback->call(runtimeExecutor_);
1892
-
1893
- // Protect with a mutex: this can be called on failure callbacks in the JS
1894
- // thread and success callbacks on the UI thread
1895
- {
1896
- std::lock_guard<std::mutex> lock(callbackWrappersPendingMutex_);
1897
-
1898
- // Clean any stale data in the retention vector
1899
- callbackWrappersPending_.erase(
1900
- std::remove_if(
1901
- callbackWrappersPending_.begin(),
1902
- callbackWrappersPending_.end(),
1903
- [](const std::unique_ptr<LayoutAnimationCallbackWrapper> &wrapper) {
1904
- return wrapper->readyForCleanup();
1905
- }),
1906
- callbackWrappersPending_.end());
1907
-
1908
- // Hold onto a reference to the callback, only while
1909
- // LayoutAnimationKeyFrameManager is alive and the callback hasn't
1910
- // completed yet.
1911
- callbackWrappersPending_.push_back(std::move(copiedCallback));
1650
+ for (auto const &mutation : mutations) {
1651
+ if (mutation.type != ShadowViewMutation::Type::Insert) {
1652
+ continue;
1653
+ }
1654
+ if (strcmp(mutation.newChildShadowView.componentName, "Image") == 0) {
1655
+ auto const &imageProps = *std::static_pointer_cast<ImageProps const>(
1656
+ mutation.newChildShadowView.props);
1657
+ int temp = 0;
1658
+ switch (imageProps.resizeMode) {
1659
+ case ImageResizeMode::Cover:
1660
+ temp = 1;
1661
+ break;
1662
+ case ImageResizeMode::Contain:
1663
+ temp = 2;
1664
+ break;
1665
+ case ImageResizeMode::Stretch:
1666
+ temp = 3;
1667
+ break;
1668
+ case ImageResizeMode::Center:
1669
+ temp = 4;
1670
+ break;
1671
+ case ImageResizeMode::Repeat:
1672
+ temp = 5;
1673
+ break;
1674
+ }
1675
+ (void)temp;
1676
+ }
1912
1677
  }
1913
1678
  }
1914
1679