diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp index c147f3707356..5ed77b7b1e81 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp @@ -411,7 +411,7 @@ std::shared_ptr ShadowNode::cloneTree( childNode = parentNode.clone( {.children = std::make_shared>>( - children)}); + std::move(children))}); } return std::const_pointer_cast(childNode); diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp index cc53b101e115..9b627c113a8e 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp @@ -429,3 +429,37 @@ TEST_F(ShadowNodeTest, cloneMultipleWithEmptyFamilySet) { EXPECT_EQ(result, nullptr); } + +TEST_F(ShadowNodeTest, cloneTree) { + auto newProps = std::make_shared(); + auto newRoot = nodeA_->cloneTree( + nodeABB_->getFamily(), [&](const ShadowNode& oldShadowNode) { + return oldShadowNode.clone({.props = newProps}); + }); + + EXPECT_EQ(newRoot->getTag(), nodeA_->getTag()); + EXPECT_NE(newRoot.get(), nodeA_.get()); + EXPECT_EQ(newRoot->getChildren().size(), 3); + EXPECT_EQ(newRoot->getChildren()[0]->getTag(), nodeAA_->getTag()); + EXPECT_EQ(newRoot->getChildren()[0]->getProps(), nodeAA_->getProps()); + EXPECT_EQ(newRoot->getChildren()[2]->getTag(), nodeAC_->getTag()); + EXPECT_EQ(newRoot->getChildren()[2]->getProps(), nodeAC_->getProps()); + + auto newNodeAB = newRoot->getChildren()[1]; + EXPECT_EQ(newNodeAB->getTag(), nodeAB_->getTag()); + EXPECT_NE(newNodeAB.get(), nodeAB_.get()); + EXPECT_EQ(newNodeAB->getChildren().size(), 2); + EXPECT_EQ(newNodeAB->getChildren()[0]->getTag(), nodeABA_->getTag()); + EXPECT_EQ(newNodeAB->getChildren()[0]->getProps(), nodeABA_->getProps()); + + auto newNodeABB = newNodeAB->getChildren()[1]; + EXPECT_EQ(newNodeABB->getTag(), nodeABB_->getTag()); + EXPECT_NE(newNodeABB.get(), nodeABB_.get()); + EXPECT_EQ(newNodeABB->getProps(), newProps); + + // The original tree is left untouched. + EXPECT_EQ(nodeA_->getChildren().size(), 3); + EXPECT_EQ(nodeA_->getChildren()[1].get(), nodeAB_.get()); + EXPECT_EQ(nodeAB_->getChildren().size(), 2); + EXPECT_EQ(nodeAB_->getChildren()[1].get(), nodeABB_.get()); +} diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerUpdateShadowTree.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerUpdateShadowTree.cpp index c691d5a897ca..8fb2e50ad313 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerUpdateShadowTree.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerUpdateShadowTree.cpp @@ -44,7 +44,7 @@ void addAncestorsToUpdateList( while (!currentShadowNode->getChildren().empty() && currentShadowNode->getTag() != shadowNode->getTag()) { ancestorShadowNodesShared[ancestorIndex] = currentShadowNode; - auto children = currentShadowNode->getChildren(); + const auto& children = currentShadowNode->getChildren(); auto childIndex = ancestors[ancestorIndex].second; currentShadowNode = children[childIndex]; ancestorIndex++; @@ -201,7 +201,8 @@ void UIManager::updateShadowTree( auto cloned = oldShadowNode->clone( {.props = newProps, .children = std::make_shared< - std::vector>>(children)}); + std::vector>>( + std::move(children))}); clonedShadowNodes.insert({oldShadowNode->getTag(), std::move(cloned)}); } else { LOG(ERROR) << "oldShadowNode is null";