mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fabric: RootShadowNode::clone was renamed/moved to ShadowNode::cloneTree
Summary: Cloning subtrees is not something specific to a RootNode, so it makes sense to have it in ShadowNode. Soon we will use that to clone subtrees inside Paragraph component to implement Inline Views. Changelog: [Internal] Fabric-specific internal change. Reviewed By: mdvacca Differential Revision: D20090666 fbshipit-source-id: 0a64ef9bda438cd55d5fd21d3ad83b36221fa89e
This commit is contained in:
committed by
Facebook Github Bot
parent
011b470961
commit
1aab70d0e2
@@ -46,40 +46,5 @@ RootShadowNode::Unshared RootShadowNode::clone(
|
||||
return newRootShadowNode;
|
||||
}
|
||||
|
||||
RootShadowNode::Unshared RootShadowNode::clone(
|
||||
ShadowNodeFamily const &shadowNodeFamily,
|
||||
std::function<ShadowNode::Unshared(ShadowNode const &oldShadowNode)>
|
||||
callback) const {
|
||||
auto ancestors = shadowNodeFamily.getAncestors(*this);
|
||||
|
||||
if (ancestors.size() == 0) {
|
||||
return RootShadowNode::Unshared{nullptr};
|
||||
}
|
||||
|
||||
auto &parent = ancestors.back();
|
||||
auto &oldShadowNode = parent.first.get().getChildren().at(parent.second);
|
||||
|
||||
auto newShadowNode = callback(*oldShadowNode);
|
||||
|
||||
auto childNode = newShadowNode;
|
||||
|
||||
for (auto it = ancestors.rbegin(); it != ancestors.rend(); ++it) {
|
||||
auto &parentNode = it->first.get();
|
||||
auto childIndex = it->second;
|
||||
|
||||
auto children = parentNode.getChildren();
|
||||
assert(ShadowNode::sameFamily(*children.at(childIndex), *childNode));
|
||||
children[childIndex] = childNode;
|
||||
|
||||
childNode = parentNode.clone({
|
||||
ShadowNodeFragment::propsPlaceholder(),
|
||||
std::make_shared<SharedShadowNodeList>(children),
|
||||
});
|
||||
}
|
||||
|
||||
return std::const_pointer_cast<RootShadowNode>(
|
||||
std::static_pointer_cast<RootShadowNode const>(childNode));
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
||||
@@ -47,19 +47,6 @@ class RootShadowNode final
|
||||
RootShadowNode::Unshared clone(
|
||||
LayoutConstraints const &layoutConstraints,
|
||||
LayoutContext const &layoutContext) const;
|
||||
|
||||
/*
|
||||
* Clones the node (and partially the tree starting from the node) by
|
||||
* replacing a `oldShadowNode` (which corresponds to a given `shadowNode`)
|
||||
* with a node that `callback` returns. `oldShadowNode` might not be the same
|
||||
* as `shadowNode` but they must share the same family.
|
||||
*
|
||||
* Returns `nullptr` if the operation cannot be performed successfully.
|
||||
*/
|
||||
RootShadowNode::Unshared clone(
|
||||
ShadowNodeFamily const &shadowNodeFamily,
|
||||
std::function<ShadowNode::Unshared(ShadowNode const &oldShadowNode)>
|
||||
callback) const;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
||||
@@ -78,13 +78,15 @@ TEST(ElementTest, testYogaDirtyFlag) {
|
||||
/*
|
||||
* Cloning props without changing them must *not* dirty Yoga nodes.
|
||||
*/
|
||||
auto newRootShadowNode = rootShadowNode->clone(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto &componentDescriptor = oldShadowNode.getComponentDescriptor();
|
||||
auto props = componentDescriptor.cloneProps(
|
||||
oldShadowNode.getProps(), RawProps());
|
||||
return oldShadowNode.clone(ShadowNodeFragment{props});
|
||||
});
|
||||
auto newRootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(rootShadowNode->cloneTree(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto &componentDescriptor =
|
||||
oldShadowNode.getComponentDescriptor();
|
||||
auto props = componentDescriptor.cloneProps(
|
||||
oldShadowNode.getProps(), RawProps());
|
||||
return oldShadowNode.clone(ShadowNodeFragment{props});
|
||||
}));
|
||||
|
||||
EXPECT_FALSE(newRootShadowNode->layoutIfNeeded());
|
||||
}
|
||||
@@ -93,21 +95,22 @@ TEST(ElementTest, testYogaDirtyFlag) {
|
||||
/*
|
||||
* Changing *non-layout* sub-props must *not* dirty Yoga nodes.
|
||||
*/
|
||||
auto newRootShadowNode = rootShadowNode->clone(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto viewProps = std::make_shared<ViewProps>();
|
||||
auto &props = *viewProps;
|
||||
auto newRootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(rootShadowNode->cloneTree(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto viewProps = std::make_shared<ViewProps>();
|
||||
auto &props = *viewProps;
|
||||
|
||||
props.nativeId = "some new native Id";
|
||||
props.foregroundColor = whiteColor();
|
||||
props.backgroundColor = blackColor();
|
||||
props.opacity = props.opacity + 0.042;
|
||||
props.zIndex = props.zIndex + 42;
|
||||
props.shouldRasterize = !props.shouldRasterize;
|
||||
props.collapsable = !props.collapsable;
|
||||
props.nativeId = "some new native Id";
|
||||
props.foregroundColor = whiteColor();
|
||||
props.backgroundColor = blackColor();
|
||||
props.opacity = props.opacity + 0.042;
|
||||
props.zIndex = props.zIndex + 42;
|
||||
props.shouldRasterize = !props.shouldRasterize;
|
||||
props.collapsable = !props.collapsable;
|
||||
|
||||
return oldShadowNode.clone(ShadowNodeFragment{viewProps});
|
||||
});
|
||||
return oldShadowNode.clone(ShadowNodeFragment{viewProps});
|
||||
}));
|
||||
|
||||
EXPECT_FALSE(newRootShadowNode->layoutIfNeeded());
|
||||
}
|
||||
@@ -116,16 +119,17 @@ TEST(ElementTest, testYogaDirtyFlag) {
|
||||
/*
|
||||
* Changing *layout* sub-props *must* dirty Yoga nodes.
|
||||
*/
|
||||
auto newRootShadowNode = rootShadowNode->clone(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto viewProps = std::make_shared<ViewProps>();
|
||||
auto &props = *viewProps;
|
||||
auto newRootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(rootShadowNode->cloneTree(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto viewProps = std::make_shared<ViewProps>();
|
||||
auto &props = *viewProps;
|
||||
|
||||
props.yogaStyle.alignContent() = YGAlignBaseline;
|
||||
props.yogaStyle.display() = YGDisplayNone;
|
||||
props.yogaStyle.alignContent() = YGAlignBaseline;
|
||||
props.yogaStyle.display() = YGDisplayNone;
|
||||
|
||||
return oldShadowNode.clone(ShadowNodeFragment{viewProps});
|
||||
});
|
||||
return oldShadowNode.clone(ShadowNodeFragment{viewProps});
|
||||
}));
|
||||
|
||||
EXPECT_TRUE(newRootShadowNode->layoutIfNeeded());
|
||||
}
|
||||
@@ -134,12 +138,13 @@ TEST(ElementTest, testYogaDirtyFlag) {
|
||||
/*
|
||||
* Removing all children *must* dirty Yoga nodes.
|
||||
*/
|
||||
auto newRootShadowNode = rootShadowNode->clone(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
return oldShadowNode.clone(
|
||||
{ShadowNodeFragment::propsPlaceholder(),
|
||||
ShadowNode::emptySharedShadowNodeSharedList()});
|
||||
});
|
||||
auto newRootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(rootShadowNode->cloneTree(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
return oldShadowNode.clone(
|
||||
{ShadowNodeFragment::propsPlaceholder(),
|
||||
ShadowNode::emptySharedShadowNodeSharedList()});
|
||||
}));
|
||||
|
||||
EXPECT_TRUE(newRootShadowNode->layoutIfNeeded());
|
||||
}
|
||||
@@ -148,17 +153,18 @@ TEST(ElementTest, testYogaDirtyFlag) {
|
||||
/*
|
||||
* Removing the last child *must* dirty Yoga nodes.
|
||||
*/
|
||||
auto newRootShadowNode = rootShadowNode->clone(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto children = oldShadowNode.getChildren();
|
||||
children.pop_back();
|
||||
auto newRootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(rootShadowNode->cloneTree(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto children = oldShadowNode.getChildren();
|
||||
children.pop_back();
|
||||
|
||||
std::reverse(children.begin(), children.end());
|
||||
std::reverse(children.begin(), children.end());
|
||||
|
||||
return oldShadowNode.clone(
|
||||
{ShadowNodeFragment::propsPlaceholder(),
|
||||
std::make_shared<ShadowNode::ListOfShared const>(children)});
|
||||
});
|
||||
return oldShadowNode.clone(
|
||||
{ShadowNodeFragment::propsPlaceholder(),
|
||||
std::make_shared<ShadowNode::ListOfShared const>(children)});
|
||||
}));
|
||||
|
||||
EXPECT_TRUE(newRootShadowNode->layoutIfNeeded());
|
||||
}
|
||||
@@ -167,16 +173,17 @@ TEST(ElementTest, testYogaDirtyFlag) {
|
||||
/*
|
||||
* Reversing a list of children *must* dirty Yoga nodes.
|
||||
*/
|
||||
auto newRootShadowNode = rootShadowNode->clone(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto children = oldShadowNode.getChildren();
|
||||
auto newRootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(rootShadowNode->cloneTree(
|
||||
innerShadowNode->getFamily(), [](ShadowNode const &oldShadowNode) {
|
||||
auto children = oldShadowNode.getChildren();
|
||||
|
||||
std::reverse(children.begin(), children.end());
|
||||
std::reverse(children.begin(), children.end());
|
||||
|
||||
return oldShadowNode.clone(
|
||||
{ShadowNodeFragment::propsPlaceholder(),
|
||||
std::make_shared<ShadowNode::ListOfShared const>(children)});
|
||||
});
|
||||
return oldShadowNode.clone(
|
||||
{ShadowNodeFragment::propsPlaceholder(),
|
||||
std::make_shared<ShadowNode::ListOfShared const>(children)});
|
||||
}));
|
||||
|
||||
EXPECT_TRUE(newRootShadowNode->layoutIfNeeded());
|
||||
}
|
||||
|
||||
@@ -242,6 +242,40 @@ int ShadowNode::getStateRevision() const {
|
||||
return stateRevision_;
|
||||
}
|
||||
|
||||
ShadowNode::Unshared ShadowNode::cloneTree(
|
||||
ShadowNodeFamily const &shadowNodeFamily,
|
||||
std::function<ShadowNode::Unshared(ShadowNode const &oldShadowNode)>
|
||||
callback) const {
|
||||
auto ancestors = shadowNodeFamily.getAncestors(*this);
|
||||
|
||||
if (ancestors.size() == 0) {
|
||||
return ShadowNode::Unshared{nullptr};
|
||||
}
|
||||
|
||||
auto &parent = ancestors.back();
|
||||
auto &oldShadowNode = parent.first.get().getChildren().at(parent.second);
|
||||
|
||||
auto newShadowNode = callback(*oldShadowNode);
|
||||
|
||||
auto childNode = newShadowNode;
|
||||
|
||||
for (auto it = ancestors.rbegin(); it != ancestors.rend(); ++it) {
|
||||
auto &parentNode = it->first.get();
|
||||
auto childIndex = it->second;
|
||||
|
||||
auto children = parentNode.getChildren();
|
||||
assert(ShadowNode::sameFamily(*children.at(childIndex), *childNode));
|
||||
children[childIndex] = childNode;
|
||||
|
||||
childNode = parentNode.clone({
|
||||
ShadowNodeFragment::propsPlaceholder(),
|
||||
std::make_shared<SharedShadowNodeList>(children),
|
||||
});
|
||||
}
|
||||
|
||||
return std::const_pointer_cast<ShadowNode>(childNode);
|
||||
}
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
|
||||
@@ -97,6 +97,18 @@ class ShadowNode : public Sealable, public DebugStringConvertible {
|
||||
*/
|
||||
UnsharedShadowNode clone(const ShadowNodeFragment &fragment) const;
|
||||
|
||||
/*
|
||||
* Clones the node (and partially the tree starting from the node) by
|
||||
* replacing a `oldShadowNode` (which corresponds to a given
|
||||
* `shadowNodeFamily`) with a node that `callback` returns.
|
||||
*
|
||||
* Returns `nullptr` if the operation cannot be performed successfully.
|
||||
*/
|
||||
ShadowNode::Unshared cloneTree(
|
||||
ShadowNodeFamily const &shadowNodeFamily,
|
||||
std::function<ShadowNode::Unshared(ShadowNode const &oldShadowNode)>
|
||||
callback) const;
|
||||
|
||||
#pragma mark - Getters
|
||||
|
||||
ComponentName getComponentName() const;
|
||||
|
||||
@@ -171,10 +171,11 @@ static void alterShadowTree(
|
||||
ShadowNodeAlteration alteration) {
|
||||
auto edge = findRandomShadowNode(entropy, rootShadowNode);
|
||||
|
||||
rootShadowNode = rootShadowNode->clone(
|
||||
edge.shadowNode->getFamily(), [&](ShadowNode const &oldShadowNode) {
|
||||
return alteration(entropy, oldShadowNode);
|
||||
});
|
||||
rootShadowNode =
|
||||
std::static_pointer_cast<RootShadowNode>(rootShadowNode->cloneTree(
|
||||
edge.shadowNode->getFamily(), [&](ShadowNode const &oldShadowNode) {
|
||||
return alteration(entropy, oldShadowNode);
|
||||
}));
|
||||
}
|
||||
|
||||
static void alterShadowTree(
|
||||
|
||||
@@ -146,12 +146,14 @@ void UIManager::setNativeProps(
|
||||
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit(
|
||||
[&](RootShadowNode::Shared const &oldRootShadowNode) {
|
||||
return oldRootShadowNode->clone(
|
||||
shadowNode.getFamily(), [&](ShadowNode const &oldShadowNode) {
|
||||
return oldShadowNode.clone({
|
||||
/* .props = */ props,
|
||||
});
|
||||
});
|
||||
return std::static_pointer_cast<RootShadowNode>(
|
||||
oldRootShadowNode->cloneTree(
|
||||
shadowNode.getFamily(),
|
||||
[&](ShadowNode const &oldShadowNode) {
|
||||
return oldShadowNode.clone({
|
||||
/* .props = */ props,
|
||||
});
|
||||
}));
|
||||
},
|
||||
true && stateReconciliationEnabled_);
|
||||
});
|
||||
@@ -197,7 +199,8 @@ void UIManager::updateState(StateUpdate const &stateUpdate) const {
|
||||
family->getSurfaceId(), [&](ShadowTree const &shadowTree) {
|
||||
shadowTree.tryCommit([&](RootShadowNode::Shared const
|
||||
&oldRootShadowNode) {
|
||||
return oldRootShadowNode->clone(
|
||||
return std::static_pointer_cast<
|
||||
RootShadowNode>(oldRootShadowNode->cloneTree(
|
||||
*family, [&](ShadowNode const &oldShadowNode) {
|
||||
auto newData =
|
||||
callback(oldShadowNode.getState()->getDataPointer());
|
||||
@@ -209,7 +212,7 @@ void UIManager::updateState(StateUpdate const &stateUpdate) const {
|
||||
/* .children = */ ShadowNodeFragment::childrenPlaceholder(),
|
||||
/* .state = */ newState,
|
||||
});
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user