diff --git a/ReactCommon/fabric/components/root/RootShadowNode.cpp b/ReactCommon/fabric/components/root/RootShadowNode.cpp index 0a63bfc44..30d817bc6 100644 --- a/ReactCommon/fabric/components/root/RootShadowNode.cpp +++ b/ReactCommon/fabric/components/root/RootShadowNode.cpp @@ -35,5 +35,34 @@ UnsharedRootShadowNode RootShadowNode::clone( return newRootShadowNode; } +UnsharedRootShadowNode RootShadowNode::clone( + const SharedShadowNode &oldShadowNode, + const SharedShadowNode &newShadowNode) const { + std::vector> ancestors; + oldShadowNode->constructAncestorPath(*this, ancestors); + + if (ancestors.size() == 0) { + return UnsharedRootShadowNode{nullptr}; + } + + auto oldChild = oldShadowNode; + auto newChild = newShadowNode; + + SharedShadowNodeUnsharedList sharedChildren; + + for (const auto &ancestor : ancestors) { + auto children = ancestor.get().getChildren(); + std::replace(children.begin(), children.end(), oldChild, newChild); + + sharedChildren = std::make_shared(children); + + oldChild = ancestor.get().shared_from_this(); + newChild = oldChild->clone(ShadowNodeFragment{.children = sharedChildren}); + } + + return std::make_shared( + *this, ShadowNodeFragment{.children = sharedChildren}); +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/components/root/RootShadowNode.h b/ReactCommon/fabric/components/root/RootShadowNode.h index c008a119a..cc0596d04 100644 --- a/ReactCommon/fabric/components/root/RootShadowNode.h +++ b/ReactCommon/fabric/components/root/RootShadowNode.h @@ -46,6 +46,16 @@ class RootShadowNode final const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const; + /* + * Clones the node replacing a given old shadow node with a new one in the + * tree by cloning all nodes on the path to the root node and then complete + * the tree. Returns `nullptr` if the operation cannot be finished + * successfully. + */ + UnsharedRootShadowNode clone( + const SharedShadowNode &oldShadowNode, + const SharedShadowNode &newShadowNode) const; + private: using YogaLayoutableShadowNode::layout; }; diff --git a/ReactCommon/fabric/uimanager/Scheduler.cpp b/ReactCommon/fabric/uimanager/Scheduler.cpp index 19487c871..f30e23eea 100644 --- a/ReactCommon/fabric/uimanager/Scheduler.cpp +++ b/ReactCommon/fabric/uimanager/Scheduler.cpp @@ -151,8 +151,9 @@ Size Scheduler::measureSurface( Size size; shadowTreeRegistry_.visit(surfaceId, [&](const ShadowTree &shadowTree) { - shadowTree.commit([&] (const SharedRootShadowNode &oldRootShadowNode) { - auto rootShadowNode = oldRootShadowNode->clone(layoutConstraints, layoutContext); + shadowTree.commit([&](const SharedRootShadowNode &oldRootShadowNode) { + auto rootShadowNode = + oldRootShadowNode->clone(layoutConstraints, layoutContext); rootShadowNode->layout(); size = rootShadowNode->getLayoutMetrics().frame.size; return nullptr; @@ -168,9 +169,11 @@ void Scheduler::constraintSurfaceLayout( SystraceSection s("Scheduler::constraintSurfaceLayout"); shadowTreeRegistry_.visit(surfaceId, [&](const ShadowTree &shadowTree) { - shadowTree.commit([&] (const SharedRootShadowNode &oldRootShadowNode) { - return oldRootShadowNode->clone(layoutConstraints, layoutContext); - }, std::numeric_limits::max()); + shadowTree.commit( + [&](const SharedRootShadowNode &oldRootShadowNode) { + return oldRootShadowNode->clone(layoutConstraints, layoutContext); + }, + std::numeric_limits::max()); }); } diff --git a/ReactCommon/fabric/uimanager/ShadowTree.cpp b/ReactCommon/fabric/uimanager/ShadowTree.cpp index 630795e79..f61fa9605 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.cpp +++ b/ReactCommon/fabric/uimanager/ShadowTree.cpp @@ -55,38 +55,6 @@ SharedRootShadowNode ShadowTree::getRootShadowNode() const { return rootShadowNode_; } -bool ShadowTree::completeByReplacingShadowNode( - const SharedShadowNode &oldShadowNode, - const SharedShadowNode &newShadowNode) const { - return commit([&](const SharedRootShadowNode &oldRootShadowNode) { - std::vector> ancestors; - oldShadowNode->constructAncestorPath(*oldRootShadowNode, ancestors); - - if (ancestors.size() == 0) { - return UnsharedRootShadowNode{nullptr}; - } - - auto oldChild = oldShadowNode; - auto newChild = newShadowNode; - - SharedShadowNodeUnsharedList sharedChildren; - - for (const auto &ancestor : ancestors) { - auto children = ancestor.get().getChildren(); - std::replace(children.begin(), children.end(), oldChild, newChild); - - sharedChildren = std::make_shared(children); - - oldChild = ancestor.get().shared_from_this(); - newChild = - oldChild->clone(ShadowNodeFragment{.children = sharedChildren}); - } - - return std::make_shared( - *oldRootShadowNode, ShadowNodeFragment{.children = sharedChildren}); - }); -} - bool ShadowTree::commit( std::function transaction, diff --git a/ReactCommon/fabric/uimanager/ShadowTree.h b/ReactCommon/fabric/uimanager/ShadowTree.h index 841fb086f..68e1a9ea1 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.h +++ b/ReactCommon/fabric/uimanager/ShadowTree.h @@ -54,16 +54,6 @@ class ShadowTree final { int attempts = 1, int *revision = nullptr) const; - /* - * Replaces a given old shadow node with a new one in the tree by cloning all - * nodes on the path to the root node and then complete the tree. - * Can be called from any thread. - * Returns `true` if the operation finished successfully. - */ - bool completeByReplacingShadowNode( - const SharedShadowNode &oldShadowNode, - const SharedShadowNode &newShadowNode) const; - /* * Returns a root shadow node that represents the last committed three. */ diff --git a/ReactCommon/fabric/uimanager/UIManager.cpp b/ReactCommon/fabric/uimanager/UIManager.cpp index a5b1f70a7..147d361dd 100644 --- a/ReactCommon/fabric/uimanager/UIManager.cpp +++ b/ReactCommon/fabric/uimanager/UIManager.cpp @@ -86,7 +86,9 @@ void UIManager::setNativeProps( shadowTreeRegistry_->visit( shadowNode->getRootTag(), [&](const ShadowTree &shadowTree) { - shadowTree.completeByReplacingShadowNode(shadowNode, newShadowNode); + shadowTree.commit([&](const SharedRootShadowNode &oldRootShadowNode) { + return oldRootShadowNode->clone(shadowNode, newShadowNode); + }); }); }