diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp index c92543b032c9..89323e2386c9 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp @@ -54,10 +54,7 @@ void AnimatedPropsRegistry::update(jsi::Runtime &rt, const jsi::Value &operation } } -jsi::Value AnimatedPropsRegistry::collectSettledUpdates( - jsi::Runtime &rt, - const double settledTimestamp, - std::vector &evictedTags) { +jsi::Value AnimatedPropsRegistry::collectSettledUpdates(jsi::Runtime &rt, const double settledTimestamp) { react_native_assert(UpdatesRegistryManager::isLockedByCurrentThread()); std::vector>> updates; @@ -73,7 +70,6 @@ jsi::Value AnimatedPropsRegistry::collectSettledUpdates( // are disjoint — `update()` moves tags from the former to the latter. timestampMap_.erase(viewTag); it = updatesRegistry_.erase(it); - evictedTags.push_back(viewTag); continue; } diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h index 3ea6ab915c61..a9cb24ce5f74 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h @@ -6,7 +6,6 @@ #include #include -#include namespace reanimated { @@ -19,7 +18,7 @@ class AnimatedPropsRegistry : public UpdatesRegistry { /// Also evicts entries that have already been synced to React — by the time /// of the next call, the corresponding `settledProps` state is guaranteed to /// be committed, so the registry entries are redundant. - jsi::Value collectSettledUpdates(jsi::Runtime &rt, double settledTimestamp, std::vector &evictedTags); + jsi::Value collectSettledUpdates(jsi::Runtime &rt, double settledTimestamp); private: std::unordered_map timestampMap_; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp index e47984a0a63e..df9e93b008cc 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.cpp @@ -106,6 +106,18 @@ PropsMap UpdatesRegistryManager::collectProps() { return propsMap; } +void UpdatesRegistryManager::addRegistryProps(PropsMap &propsMap) { + react_native_assert(isLockedByCurrentThread()); + for (auto &[family, props] : propsMap) { + for (const auto ®istry : registries_) { + auto registryProps = registry->get(family->getTag()); + if (registryProps.isObject()) { + props.emplace_back(RawProps(std::move(registryProps))); + } + } + } +} + #ifdef ANDROID bool UpdatesRegistryManager::hasPropsToRevert() { diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h index e6d072b055e7..67afee9eed13 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/Fabric/updates/UpdatesRegistryManager.h @@ -48,6 +48,7 @@ class UpdatesRegistryManager { void unmarkNodeAsRemovable(Tag viewTag); void handleNodeRemovals(const RootShadowNode &rootShadowNode); PropsMap collectProps(); + void addRegistryProps(PropsMap &propsMap); #ifdef ANDROID bool hasPropsToRevert(); diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h index 2156d0e49a1c..73034c3830e9 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h @@ -105,8 +105,7 @@ class LayoutAnimationsProxyCommon : public facebook::react::MountingOverrideDele std::weak_ptr mountingOverrideDelegate); virtual void shadowTreeWillCommit(bool isSurfaceRemoval) {} virtual void surfaceDidUnmount(); - virtual void applySynchronousProps(const UpdatesBatch &, const std::unordered_set &) const {} - virtual void dropSynchronousProps(const std::vector &) const {} + virtual void applySynchronousProps(const UpdatesBatch &) const {} ~LayoutAnimationsProxyCommon() override = default; protected: diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.cpp index 02577035489c..068fcc5b5adc 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.cpp @@ -80,17 +80,9 @@ std::optional LayoutAnimationsProxyRegistry::onGestureCancel(const in return {}; } -void LayoutAnimationsProxyRegistry::applySynchronousProps( - const UpdatesBatch &updatesBatch, - const std::unordered_set &skipOverlayTags) { +void LayoutAnimationsProxyRegistry::applySynchronousProps(const UpdatesBatch &updatesBatch) { for (const auto &instance : instances()) { - instance->applySynchronousProps(updatesBatch, skipOverlayTags); - } -} - -void LayoutAnimationsProxyRegistry::dropSynchronousProps(const std::vector &tags) { - for (const auto &instance : instances()) { - instance->dropSynchronousProps(tags); + instance->applySynchronousProps(updatesBatch); } } diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.h index 222212cbc95e..9d027ab25a11 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyRegistry.h @@ -7,7 +7,6 @@ #include #include #include -#include #include namespace reanimated { @@ -26,8 +25,7 @@ class LayoutAnimationsProxyRegistry { std::optional endLayoutAnimation(int tag, bool shouldRemove); std::optional onTransitionProgress(int tag, double progress, bool isClosing, bool isGoingForward); std::optional onGestureCancel(int tag); - void applySynchronousProps(const UpdatesBatch &updatesBatch, const std::unordered_set &skipOverlayTags); - void dropSynchronousProps(const std::vector &tags); + void applySynchronousProps(const UpdatesBatch &updatesBatch); private: std::vector> instances() const; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp index 9209218c771f..f9c7edad20df 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp @@ -248,6 +248,7 @@ void LayoutAnimationsProxy_Experimental::updateLightTree( case ShadowViewMutation::Update: { auto &node = lightNodes_[mutation.newChildShadowView.tag]; react_native_assert(node && "LightNode not found"); + const auto currentProps = node->current.props; node->previous = mutation.oldChildShadowView; #ifdef ANDROID // TODO (future): We don't merge the root view as the currently stored version might not be accurate, because of @@ -266,8 +267,10 @@ void LayoutAnimationsProxy_Experimental::updateLightTree( } #else node->current = mutation.newChildShadowView; - reapplySynchronousPropsOverlay(node, propsParserContext); #endif // ANDROID + if (mutation.oldChildShadowView.props == mutation.newChildShadowView.props) { + node->current.props = currentProps; + } auto tag = mutation.newChildShadowView.tag; if (layoutAnimationsManager_->hasLayoutAnimation(tag, LAYOUT)) { layout_.push_back(node); @@ -294,9 +297,6 @@ void LayoutAnimationsProxy_Experimental::updateLightTree( if (state == UNDEFINED) { lightNodes_.erase(it); } -#ifndef ANDROID - synchronousPropsOverlay_.erase(mutation.oldChildShadowView.tag); -#endif break; } case ShadowViewMutation::Insert: { @@ -413,18 +413,10 @@ void LayoutAnimationsProxy_Experimental::applyInitialMutationsToLightTree( // Synchronous prop updates skip pullTransaction. Merge them into the light // tree so shared-transition snapshots see them. The registry broadcasts one // batch to every surface proxy; entries of other surfaces are skipped here. -void LayoutAnimationsProxy_Experimental::applySynchronousProps( - const UpdatesBatch &updatesBatch, - [[maybe_unused]] const std::unordered_set &skipOverlayTags) const { +void LayoutAnimationsProxy_Experimental::applySynchronousProps(const UpdatesBatch &updatesBatch) const { ReanimatedSystraceSection s("applySynchronousProps"); const auto lock = std::unique_lock(mutex); -#ifndef ANDROID - for (const auto tag : skipOverlayTags) { - synchronousPropsOverlay_.erase(tag); - } -#endif - for (const auto &[shadowNodeFamily, props] : updatesBatch) { if (shadowNodeFamily->getSurfaceId() != surfaceId_) { continue; @@ -445,12 +437,6 @@ void LayoutAnimationsProxy_Experimental::applySynchronousProps( auto rawProps = props; #ifdef RN_SERIALIZABLE_STATE rawProps = folly::dynamic::merge(node->current.props->rawProps, rawProps); -#endif -#ifndef ANDROID - if (!skipOverlayTags.contains(node->current.tag)) { - auto &overlayProps = synchronousPropsOverlay_[node->current.tag]; - overlayProps = overlayProps.isObject() ? folly::dynamic::merge(overlayProps, props) : props; - } #endif const PropsParserContext propsParserContext{node->current.surfaceId, *contextContainer_}; node->current.props = getComponentDescriptorForShadowView(node->current) @@ -458,31 +444,6 @@ void LayoutAnimationsProxy_Experimental::applySynchronousProps( } } -#ifndef ANDROID -// A commit that does not carry the synchronous props replaces the light tree -// props in the Update branch. Put the synchronous props back on top. The -// entry lives until the settled sync-back commits the values to React state. -void LayoutAnimationsProxy_Experimental::reapplySynchronousPropsOverlay( - const std::shared_ptr &node, - const PropsParserContext &propsParserContext) const { - const auto it = synchronousPropsOverlay_.find(node->current.tag); - if (it == synchronousPropsOverlay_.end() || !node->current.props) { - return; - } - node->current.props = getComponentDescriptorForShadowView(node->current) - .cloneProps(propsParserContext, node->current.props, RawProps(it->second)); -} -#endif // ANDROID - -void LayoutAnimationsProxy_Experimental::dropSynchronousProps([[maybe_unused]] const std::vector &tags) const { -#ifndef ANDROID - const auto lock = std::unique_lock(mutex); - for (const auto tag : tags) { - synchronousPropsOverlay_.erase(tag); - } -#endif -} - void LayoutAnimationsProxy_Experimental::startSurface( const ShadowTree &shadowTree, std::weak_ptr mountingOverrideDelegate) { diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h index ea168c41dca9..db5b4ab5f274 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.h @@ -59,9 +59,6 @@ struct LayoutAnimationsProxy_Experimental : public LayoutAnimationsProxyCommon, mutable std::vector> pendingTransactions_; mutable std::vector> containersToInsert_; mutable std::unordered_map transformForNode_; -#ifndef ANDROID - mutable std::unordered_map synchronousPropsOverlay_; -#endif mutable ForceScreenSnapshotFunction forceScreenSnapshot_; @@ -89,14 +86,7 @@ struct LayoutAnimationsProxy_Experimental : public LayoutAnimationsProxyCommon, return lightNodes_.contains(surfaceId_); } - void applySynchronousProps(const UpdatesBatch &updatesBatch, const std::unordered_set &skipOverlayTags) - const override; - void dropSynchronousProps(const std::vector &tags) const override; -#ifndef ANDROID - void reapplySynchronousPropsOverlay( - const std::shared_ptr &node, - const PropsParserContext &propsParserContext) const; -#endif + void applySynchronousProps(const UpdatesBatch &updatesBatch) const override; void reconcileContradictedRemovals(const ShadowViewMutationList &mutations, ShadowViewMutationList &filteredMutations) const; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp index ebd17fce757c..51a20c5db85b 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp @@ -674,18 +674,8 @@ jsi::Value ReanimatedModuleProxy::getSettledUpdates(jsi::Runtime &rt) { const auto currentTimestamp = getAnimationTimestamp_(); // TODO(future): flush updates from CSS animations and CSS transitions registries - std::vector evictedTags; auto lock = updatesRegistryManager_->lock(); - auto settledUpdates = - animatedPropsRegistry_->collectSettledUpdates(rt, currentTimestamp - SETTLED_ANIMATION_THRESHOLD_MS, evictedTags); - - if constexpr (StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) { - if (layoutAnimationsProxyRegistry_ && !evictedTags.empty()) { - layoutAnimationsProxyRegistry_->dropSynchronousProps(evictedTags); - } - } - - return settledUpdates; + return animatedPropsRegistry_->collectSettledUpdates(rt, currentTimestamp - SETTLED_ANIMATION_THRESHOLD_MS); } bool ReanimatedModuleProxy::handleEvent( @@ -809,19 +799,6 @@ void ReanimatedModuleProxy::performOperations() { jsi::Runtime &uiRuntime = getJSIRuntimeFromWorkletRuntime(uiRuntime_); UpdatesBatch updatesBatch; - // The settled-props sync-back manages only animated props, so updates - // flushed by the CSS registries must stay out of the synchronous props - // overlay of the layout animations proxy. - std::unordered_set skipOverlayTags; - const auto collectFlushedTags = [&](const size_t begin) { - if constexpr ( - shouldUseSynchronousUpdatesInPerformOperations() && - StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) { - for (auto i = begin; i < updatesBatch.size(); ++i) { - skipOverlayTags.insert(updatesBatch[i].first->getTag()); - } - } - }; { ReanimatedSystraceSection s2("ReanimatedModuleProxy::flushUpdates"); @@ -830,7 +807,6 @@ void ReanimatedModuleProxy::performOperations() { if (cssTransitionsRegistry_->needsFlush()) { // Update CSS transitions and flush updates cssTransitionsRegistry_->flushUpdates(updatesBatch); - collectFlushedTags(0); } // Flush all animated props updates @@ -838,14 +814,12 @@ void ReanimatedModuleProxy::performOperations() { if (cssAnimationsRegistry_->needsFlush()) { // Update CSS animations and flush updates - const auto begin = updatesBatch.size(); cssAnimationsRegistry_->flushUpdates(updatesBatch); - collectFlushedTags(begin); } } if constexpr (shouldUseSynchronousUpdatesInPerformOperations()) { - applySynchronousUpdates(updatesBatch, false, skipOverlayTags); + applySynchronousUpdates(updatesBatch, false); } if (updatesRegistryManager_->shouldReanimatedSkipCommit()) { @@ -871,7 +845,7 @@ void ReanimatedModuleProxy::performNonLayoutOperations() { auto lock = updatesRegistryManager_->lock(); updatesBatch = animatedPropsRegistry_->getPendingUpdates(); } - applySynchronousUpdates(updatesBatch, true, {}); + applySynchronousUpdates(updatesBatch, true); } #if REACT_NATIVE_VERSION_MINOR >= 85 @@ -1054,16 +1028,13 @@ bool ReanimatedModuleProxy::handleEventAndFlush( return handled; } -void ReanimatedModuleProxy::applySynchronousUpdates( - UpdatesBatch &updatesBatch, - const bool allowPartialUpdates, - const std::unordered_set &skipOverlayTags) { +void ReanimatedModuleProxy::applySynchronousUpdates(UpdatesBatch &updatesBatch, const bool allowPartialUpdates) { auto [synchronousUpdatesBatch, shadowTreeUpdatesBatch] = partitionUpdates(std::move(updatesBatch), allowPartialUpdates); if constexpr (StaticFeatureFlags::getFlag("ENABLE_SHARED_ELEMENT_TRANSITIONS")) { - if (layoutAnimationsProxyRegistry_ && (!synchronousUpdatesBatch.empty() || !skipOverlayTags.empty())) { - layoutAnimationsProxyRegistry_->applySynchronousProps(synchronousUpdatesBatch, skipOverlayTags); + if (layoutAnimationsProxyRegistry_ && !synchronousUpdatesBatch.empty()) { + layoutAnimationsProxyRegistry_->applySynchronousProps(synchronousUpdatesBatch); } } @@ -1129,6 +1100,12 @@ void ReanimatedModuleProxy::commitUpdates(jsi::Runtime &rt, const UpdatesBatch & for (auto const &[shadowNodeFamily, props] : updatesBatch) { propsMapBySurface[shadowNodeFamily->getSurfaceId()][shadowNodeFamily].emplace_back(props); } + if constexpr (shouldUseSynchronousUpdatesInPerformOperations()) { + auto lock = updatesRegistryManager_->lock(); + for (auto &[_, propsMap] : propsMapBySurface) { + updatesRegistryManager_->addRegistryProps(propsMap); + } + } } for (auto const &[surfaceId, propsMap] : propsMapBySurface) { diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h index fac0195f9f8a..83f23505268b 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -207,10 +206,7 @@ class ReanimatedModuleProxy : public std::enable_shared_from_this createRegistriesLeakCheck(); void commitUpdates(jsi::Runtime &rt, const UpdatesBatch &updatesBatch); - void applySynchronousUpdates( - UpdatesBatch &updatesBatch, - bool allowPartialUpdates, - const std::unordered_set &skipOverlayTags); + void applySynchronousUpdates(UpdatesBatch &updatesBatch, bool allowPartialUpdates); #if REACT_NATIVE_VERSION_MINOR >= 85 std::shared_ptr getAnimationBackend();