From ec5b1fd259403b613100286fe73a0592b8d57781 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Tue, 17 Jul 2018 22:41:32 -0700 Subject: [PATCH] Fabric: Optimized ShadowNode::replaceChild() with `suggestedIndex` argument Summary: @public In most cases callsite knows probable index of replacing child node, hence it makes sense to provide this info to `replaceChild` to illuminate O(n) search in most cases. Reviewed By: mdvacca Differential Revision: D8814809 fbshipit-source-id: 0edf82878a72260365e2757beb3886ad07c7464d --- .../fabric/components/view/ConcreteViewShadowNode.h | 4 ++-- .../components/view/yoga/YogaLayoutableShadowNode.cpp | 4 ++-- ReactCommon/fabric/core/layout/LayoutableShadowNode.h | 2 +- ReactCommon/fabric/core/shadownode/ShadowNode.cpp | 10 +++++++++- ReactCommon/fabric/core/shadownode/ShadowNode.h | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/ReactCommon/fabric/components/view/ConcreteViewShadowNode.h b/ReactCommon/fabric/components/view/ConcreteViewShadowNode.h index eb79d9223..0bddc1a7e 100644 --- a/ReactCommon/fabric/components/view/ConcreteViewShadowNode.h +++ b/ReactCommon/fabric/components/view/ConcreteViewShadowNode.h @@ -108,11 +108,11 @@ public: } } - LayoutableShadowNode *cloneAndReplaceChild(LayoutableShadowNode *child) override { + LayoutableShadowNode *cloneAndReplaceChild(LayoutableShadowNode *child, int suggestedIndex = -1) override { ensureUnsealed(); auto childShadowNode = static_cast(child); auto clonedChildShadowNode = std::static_pointer_cast(childShadowNode->clone()); - ShadowNode::replaceChild(childShadowNode->shared_from_this(), clonedChildShadowNode); + ShadowNode::replaceChild(childShadowNode->shared_from_this(), clonedChildShadowNode, suggestedIndex); return clonedChildShadowNode.get(); } diff --git a/ReactCommon/fabric/components/view/yoga/YogaLayoutableShadowNode.cpp b/ReactCommon/fabric/components/view/yoga/YogaLayoutableShadowNode.cpp index df6e9d353..ddfc55180 100644 --- a/ReactCommon/fabric/components/view/yoga/YogaLayoutableShadowNode.cpp +++ b/ReactCommon/fabric/components/view/yoga/YogaLayoutableShadowNode.cpp @@ -79,7 +79,7 @@ void YogaLayoutableShadowNode::appendChild(YogaLayoutableShadowNode *child) { auto childYogaNodeRawPtr = &child->yogaNode_; if (childYogaNodeRawPtr->getOwner() != nullptr) { - child = static_cast(cloneAndReplaceChild(child)); + child = static_cast(cloneAndReplaceChild(child, yogaNode_.getChildren().size())); childYogaNodeRawPtr = &child->yogaNode_; assert(childYogaNodeRawPtr->getOwner() == nullptr); } @@ -154,7 +154,7 @@ YGNode *YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector(YGNode *oldYoga auto oldNode = static_cast(oldYogaNode->getContext()); auto clonedNode = - static_cast(parentNode->cloneAndReplaceChild(oldNode)); + static_cast(parentNode->cloneAndReplaceChild(oldNode, childIndex)); return &clonedNode->yogaNode_; } diff --git a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h index 5eb5e8b8b..febc222cf 100644 --- a/ReactCommon/fabric/core/layout/LayoutableShadowNode.h +++ b/ReactCommon/fabric/core/layout/LayoutableShadowNode.h @@ -91,7 +91,7 @@ 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. */ - virtual LayoutableShadowNode *cloneAndReplaceChild(LayoutableShadowNode *child) = 0; + virtual LayoutableShadowNode *cloneAndReplaceChild(LayoutableShadowNode *child, int suggestedIndex = -1) = 0; /* * Sets layout metrics for the shadow node. diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp index 5013b1426..91adbc16b 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.cpp +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.cpp @@ -110,10 +110,18 @@ void ShadowNode::appendChild(const SharedShadowNode &child) { nonConstChildren->push_back(child); } -void ShadowNode::replaceChild(const SharedShadowNode &oldChild, const SharedShadowNode &newChild) { +void ShadowNode::replaceChild(const SharedShadowNode &oldChild, const SharedShadowNode &newChild, int suggestedIndex) { ensureUnsealed(); auto nonConstChildren = std::const_pointer_cast(children_); + + if (suggestedIndex != -1 && suggestedIndex < nonConstChildren->size()) { + if (nonConstChildren->at(suggestedIndex) == oldChild) { + (*nonConstChildren)[suggestedIndex] = newChild; + return; + } + } + std::replace(nonConstChildren->begin(), nonConstChildren->end(), oldChild, newChild); } diff --git a/ReactCommon/fabric/core/shadownode/ShadowNode.h b/ReactCommon/fabric/core/shadownode/ShadowNode.h index 1f220f50b..a7bc76d40 100644 --- a/ReactCommon/fabric/core/shadownode/ShadowNode.h +++ b/ReactCommon/fabric/core/shadownode/ShadowNode.h @@ -93,7 +93,7 @@ public: #pragma mark - Mutating Methods void appendChild(const SharedShadowNode &child); - void replaceChild(const SharedShadowNode &oldChild, const SharedShadowNode &newChild); + void replaceChild(const SharedShadowNode &oldChild, const SharedShadowNode &newChild, int suggestedIndex = -1); void clearSourceNode(); /*