diff --git a/React/Fabric/RCTScheduler.mm b/React/Fabric/RCTScheduler.mm index 7887d2f4f6e25a..389ae00f1b2ec7 100644 --- a/React/Fabric/RCTScheduler.mm +++ b/React/Fabric/RCTScheduler.mm @@ -122,8 +122,8 @@ - (instancetype)initWithToolbox:(SchedulerToolbox)toolbox if (reactNativeConfig->getBool("react_fabric:enabled_layout_animations_ios")) { _layoutAnimationDelegateProxy = std::make_shared((__bridge void *)self); - _animationDriver = - std::make_shared(toolbox.runtimeExecutor, _layoutAnimationDelegateProxy.get()); + _animationDriver = std::make_shared( + toolbox.runtimeExecutor, toolbox.contextContainer, _layoutAnimationDelegateProxy.get()); if (reactNativeConfig->getBool("react_fabric:enabled_skip_invalidated_key_frames_ios")) { _animationDriver->enableSkipInvalidatedKeyFrames(); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index 7c9d43bee01dd3..1854b9059ec2c8 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -587,8 +587,8 @@ void Binding::installFabricUIManager( toolbox.backgroundExecutor = backgroundExecutor_->get(); } - animationDriver_ = - std::make_shared(runtimeExecutor, this); + animationDriver_ = std::make_shared( + runtimeExecutor, contextContainer, this); scheduler_ = std::make_shared( toolbox, (animationDriver_ ? animationDriver_.get() : nullptr), this); } diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h index c5960fa50d09f5..428eb08ecad981 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h +++ b/ReactCommon/react/renderer/animations/LayoutAnimationDriver.h @@ -18,8 +18,12 @@ class LayoutAnimationDriver : public LayoutAnimationKeyFrameManager { public: LayoutAnimationDriver( RuntimeExecutor runtimeExecutor, + ContextContainer::Shared &contextContainer, LayoutAnimationStatusDelegate *delegate) - : LayoutAnimationKeyFrameManager(runtimeExecutor, delegate) {} + : LayoutAnimationKeyFrameManager( + runtimeExecutor, + contextContainer, + delegate) {} protected: virtual void animationMutationsForFrame( diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp index 5161a51058ae81..13e2f11155fe6e 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp @@ -94,8 +94,10 @@ interpolateFloats(float coefficient, float oldValue, float newValue) { LayoutAnimationKeyFrameManager::LayoutAnimationKeyFrameManager( RuntimeExecutor runtimeExecutor, + ContextContainer::Shared &contextContainer, LayoutAnimationStatusDelegate *delegate) : runtimeExecutor_(runtimeExecutor), + contextContainer_(contextContainer), layoutAnimationStatusDelegate_(delegate), now_([]() { return std::chrono::duration_cast( @@ -228,14 +230,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!"; #endif - // Stub PropsParserContext used for cloneProps. - // This is/should be safe because cloning doesn't actually need to - // parse props, and just copies them; therefore there should be no - // need to actually use anything in the PropsParserContext. - // If this ever changes, the LayoutAnimations API will need to change - // to pass in a real PropsParserContext. - ContextContainer contextContainer{}; - PropsParserContext propsParserContext{surfaceId, contextContainer}; + PropsParserContext propsParserContext{surfaceId, *contextContainer_}; // What to do if we detect a conflict? Get current value and make // that the baseline of the next animation. Scale the remaining time @@ -1131,15 +1126,6 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView( return finalView; } - // Stub PropsParserContext used for interpolateProps. - // This is/should be safe because interpolating doesn't actually need to - // parse props, and just copies them; therefore there should be no - // need to actually use anything in the PropsParserContext. - // If this ever changes, the LayoutAnimations API will need to change - // to pass in a real PropsParserContext. - ContextContainer contextContainer{}; - PropsParserContext propsParserContext{-1, contextContainer}; - ComponentDescriptor const &componentDescriptor = getComponentDescriptorForShadowView(startingView); @@ -1160,6 +1146,8 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView( } // Animate opacity or scale/transform + PropsParserContext propsParserContext{ + finalView.surfaceId, *contextContainer_}; mutatedShadowView.props = componentDescriptor.interpolateProps( propsParserContext, progress, startingView.props, finalView.props); react_native_assert(mutatedShadowView.props != nullptr); @@ -1202,7 +1190,7 @@ void LayoutAnimationKeyFrameManager::queueFinalMutationsForCompletedKeyFrame( AnimationKeyFrame const &keyframe, ShadowViewMutation::List &mutationsList, bool interrupted, - std::string logPrefix) const { + const std::string &logPrefix) const { if (skipInvalidatedKeyFrames_ && keyframe.invalidated) { return; } diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h index 8f9c3ccb77c953..528fe052dad195 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.h @@ -41,6 +41,7 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, public: LayoutAnimationKeyFrameManager( RuntimeExecutor runtimeExecutor, + ContextContainer::Shared &contextContainer, LayoutAnimationStatusDelegate *delegate); #pragma mark - UIManagerAnimationDelegate methods @@ -138,10 +139,12 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate, AnimationKeyFrame const &keyframe, ShadowViewMutation::List &mutationsList, bool interrupted, - std::string logPrefix) const; + const std::string &logPrefix) const; private: RuntimeExecutor runtimeExecutor_; + ContextContainer::Shared contextContainer_; + mutable std::mutex layoutAnimationStatusDelegateMutex_; mutable LayoutAnimationStatusDelegate *layoutAnimationStatusDelegate_{}; mutable std::mutex surfaceIdsToStopMutex_; diff --git a/ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp b/ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp index 52e07d9d87d4be..33e72268f1f689 100644 --- a/ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp +++ b/ReactCommon/react/renderer/animations/tests/LayoutAnimationTest.cpp @@ -51,7 +51,7 @@ static void testShadowNodeTreeLifeCycleLayoutAnimations( auto entropy = seed == 0 ? Entropy() : Entropy(seed); auto eventDispatcher = EventDispatcher::Shared{}; - auto contextContainer = std::make_shared(); + auto contextContainer = std::make_shared(); auto componentDescriptorParameters = ComponentDescriptorParameters{eventDispatcher, contextContainer, nullptr}; auto viewComponentDescriptor = @@ -77,8 +77,8 @@ static void testShadowNodeTreeLifeCycleLayoutAnimations( concreteComponentDescriptorProvider()); // Create Animation Driver - auto animationDriver = - std::make_shared(runtimeExecutor, nullptr); + auto animationDriver = std::make_shared( + runtimeExecutor, contextContainer, nullptr); animationDriver->setComponentDescriptorRegistry(componentDescriptorRegistry); // Mock animation timers