diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp b/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp index ea2de415cdf..8148f00dff0 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.cpp @@ -93,9 +93,5 @@ void LayoutableShadowNode::layoutChildren(LayoutContext layoutContext) { // Default implementation does nothing. } -SharedLayoutableShadowNode LayoutableShadowNode::cloneAndReplaceChild(const SharedLayoutableShadowNode &child) { - return child; -} - } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h index e59df8bc9ab..e3176f1f357 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h @@ -93,9 +93,8 @@ protected: /* * In case layout algorithm needs to mutate this (probably sealed) node, * it has to clone and replace it in the hierarchy before to do so. - * Default implementation does nothing and returns `child`. */ - virtual SharedLayoutableShadowNode cloneAndReplaceChild(const SharedLayoutableShadowNode &child); + virtual SharedLayoutableShadowNode cloneAndReplaceChild(const SharedLayoutableShadowNode &child) = 0; /* * Sets layout metrics for the shadow node. diff --git a/ReactCommon/fabric/view/ViewShadowNode.cpp b/ReactCommon/fabric/view/ViewShadowNode.cpp index 7b07fec2277..8bb5f33fdb8 100644 --- a/ReactCommon/fabric/view/ViewShadowNode.cpp +++ b/ReactCommon/fabric/view/ViewShadowNode.cpp @@ -7,6 +7,8 @@ #include "ViewShadowNode.h" +#include + #include namespace facebook { @@ -87,6 +89,31 @@ SharedLayoutableShadowNodeList ViewShadowNode::getChildren() const { return sharedLayoutableShadowNodeList; } +SharedLayoutableShadowNode ViewShadowNode::cloneAndReplaceChild(const SharedLayoutableShadowNode &child) { + ensureUnsealed(); + + // We cannot mutate `children_` in place here because it is a *shared* + // data structure which means other `ShadowNodes` might refer to its old value. + // So, we have to clone this and only then mutate. + auto nonConstChildrenCopy = SharedShadowNodeList(*children_); + + auto viewShadowNodeChild = std::dynamic_pointer_cast(child); + assert(viewShadowNodeChild); + + auto viewShadowNodeChildClone = std::make_shared(viewShadowNodeChild); + + std::replace( + nonConstChildrenCopy.begin(), + nonConstChildrenCopy.end(), + std::static_pointer_cast(viewShadowNodeChild), + std::static_pointer_cast(viewShadowNodeChildClone) + ); + + children_ = std::make_shared(nonConstChildrenCopy); + + return std::static_pointer_cast(viewShadowNodeChildClone); +} + #pragma mark - DebugStringConvertible SharedDebugStringConvertibleList ViewShadowNode::getDebugProps() const { diff --git a/ReactCommon/fabric/view/ViewShadowNode.h b/ReactCommon/fabric/view/ViewShadowNode.h index fffaaa20c98..4ac446556d7 100644 --- a/ReactCommon/fabric/view/ViewShadowNode.h +++ b/ReactCommon/fabric/view/ViewShadowNode.h @@ -57,6 +57,7 @@ private: #pragma mark - LayoutableShadowNode SharedLayoutableShadowNodeList getChildren() const override; + SharedLayoutableShadowNode cloneAndReplaceChild(const SharedLayoutableShadowNode &child) override; }; } // namespace react