diff --git a/ReactCommon/fabric/uimanager/ShadowTree.cpp b/ReactCommon/fabric/uimanager/ShadowTree.cpp index 48823af51bb..54e2759ab5d 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.cpp +++ b/ReactCommon/fabric/uimanager/ShadowTree.cpp @@ -98,6 +98,35 @@ bool ShadowTree::complete( return complete(oldRootShadowNode, newRootShadowNode); } +bool ShadowTree::completeByReplacingShadowNode( + const SharedShadowNode &oldShadowNode, + const SharedShadowNode &newShadowNode) const { + auto rootShadowNode = getRootShadowNode(); + std::vector> ancestors; + oldShadowNode->constructAncestorPath(*rootShadowNode, ancestors); + + if (ancestors.size() == 0) { + return false; + } + + 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 complete(sharedChildren); +} + bool ShadowTree::complete( const SharedRootShadowNode &oldRootShadowNode, const UnsharedRootShadowNode &newRootShadowNode) const { diff --git a/ReactCommon/fabric/uimanager/ShadowTree.h b/ReactCommon/fabric/uimanager/ShadowTree.h index a7398699df6..dca2a89e019 100644 --- a/ReactCommon/fabric/uimanager/ShadowTree.h +++ b/ReactCommon/fabric/uimanager/ShadowTree.h @@ -77,6 +77,16 @@ class ShadowTree final { */ bool complete(const SharedShadowNodeUnsharedList &rootChildNodes) 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. */