Fabric: ShadowTree::completeByReplacingShadowNode was moved to RootShadowNode

Summary:
Removing additional complexity from ShadowTree should help with maintainability. Now, this class is "tricky", but short at least.
With new `commit` API, it's much more simple and expected this way.

Reviewed By: sahrens

Differential Revision: D13615365

fbshipit-source-id: 1fe851c1a2d3bdc7ac2f4a570cf0170eae3c4c67
This commit is contained in:
Valentin Shergin
2019-01-16 20:17:00 -08:00
committed by Facebook Github Bot
parent c937300f5d
commit 84cf657308
6 changed files with 50 additions and 48 deletions

View File

@@ -35,5 +35,34 @@ UnsharedRootShadowNode RootShadowNode::clone(
return newRootShadowNode;
}
UnsharedRootShadowNode RootShadowNode::clone(
const SharedShadowNode &oldShadowNode,
const SharedShadowNode &newShadowNode) const {
std::vector<std::reference_wrapper<const ShadowNode>> 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<SharedShadowNodeList>(children);
oldChild = ancestor.get().shared_from_this();
newChild = oldChild->clone(ShadowNodeFragment{.children = sharedChildren});
}
return std::make_shared<RootShadowNode>(
*this, ShadowNodeFragment{.children = sharedChildren});
}
} // namespace react
} // namespace facebook

View File

@@ -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;
};

View File

@@ -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<int>::max());
shadowTree.commit(
[&](const SharedRootShadowNode &oldRootShadowNode) {
return oldRootShadowNode->clone(layoutConstraints, layoutContext);
},
std::numeric_limits<int>::max());
});
}

View File

@@ -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<std::reference_wrapper<const ShadowNode>> 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<SharedShadowNodeList>(children);
oldChild = ancestor.get().shared_from_this();
newChild =
oldChild->clone(ShadowNodeFragment{.children = sharedChildren});
}
return std::make_shared<RootShadowNode>(
*oldRootShadowNode, ShadowNodeFragment{.children = sharedChildren});
});
}
bool ShadowTree::commit(
std::function<UnsharedRootShadowNode(
const SharedRootShadowNode &oldRootShadowNode)> transaction,

View File

@@ -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.
*/

View File

@@ -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);
});
});
}