Fabric: Devirtualizing LayoutableShadowNode::cloneAndReplaceChild

Summary:
D19963353 mentioned the infrastructure that re-routes methods calls related to adding and cloning children between YogaLayoutableShadowNode and ShadowNode. `cloneAndReplaceChild` is exactly this. It was implemented as a virtual method that is called from `ConcreteViewShadowNode`. The whole process requires building a list of children of some class and passing that as a list of pointers. Now we don't need it all that because we can call directly and statically. That change will allow us to simplify that infra even more in the future diffs.
 Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D20052022

fbshipit-source-id: ddf341c112edd8a2f79eaf74465a9a360a168541
This commit is contained in:
Valentin Shergin
2020-02-26 22:08:18 -08:00
committed by Facebook Github Bot
parent 1090b05e61
commit 7953c3e854
4 changed files with 49 additions and 51 deletions
@@ -89,32 +89,6 @@ class ConcreteViewShadowNode : public ConcreteShadowNode<
return traits;
}
void appendChild(const ShadowNode::Shared &child) {
BaseShadowNode::ensureUnsealed();
ShadowNode::appendChild(child);
auto nonConstChild = const_cast<ShadowNode *>(child.get());
auto yogaLayoutableChild =
dynamic_cast<YogaLayoutableShadowNode *>(nonConstChild);
if (yogaLayoutableChild) {
YogaLayoutableShadowNode::appendChild(yogaLayoutableChild);
}
}
LayoutableShadowNode *cloneAndReplaceChild(
LayoutableShadowNode *child,
int suggestedIndex = -1) override {
Sealable::ensureUnsealed();
auto childShadowNode = static_cast<const ConcreteViewShadowNode *>(child);
auto clonedChildShadowNode =
std::static_pointer_cast<ConcreteViewShadowNode>(
childShadowNode->clone({}));
ShadowNode::replaceChild(
*childShadowNode, clonedChildShadowNode, suggestedIndex);
return clonedChildShadowNode.get();
}
Transform getTransform() const override {
return BaseShadowNode::getConcreteProps().transform;
}
@@ -78,28 +78,45 @@ void YogaLayoutableShadowNode::enableMeasurement() {
YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector);
}
void YogaLayoutableShadowNode::appendChild(YogaLayoutableShadowNode *child) {
void YogaLayoutableShadowNode::appendChild(ShadowNode::Shared const &child) {
ensureUnsealed();
LayoutableShadowNode::appendChild(child);
auto yogaLayoutableChild =
traitCast<YogaLayoutableShadowNode const *>(child.get());
if (yogaLayoutableChild) {
appendChildYogaNode(
*const_cast<YogaLayoutableShadowNode *>(yogaLayoutableChild));
}
}
void YogaLayoutableShadowNode::appendChildYogaNode(
YogaLayoutableShadowNode &child) {
ensureUnsealed();
if (getTraits().check(ShadowNodeTraits::Trait::LeafYogaNode)) {
// This node is a declared leaf, therefore we must not add the Yoga node as
// a child.
return;
}
ensureUnsealed();
yogaNode_.setDirty(true);
auto yogaNodeRawPtr = &yogaNode_;
auto childYogaNodeRawPtr = &child->yogaNode_;
auto childYogaNodeRawPtr = &child.yogaNode_;
auto childNodePtr = &child;
if (childYogaNodeRawPtr->getOwner() != nullptr) {
child = static_cast<YogaLayoutableShadowNode *>(
cloneAndReplaceChild(child, yogaNode_.getChildren().size()));
childYogaNodeRawPtr = &child->yogaNode_;
childNodePtr =
&cloneAndReplaceChild(*childNodePtr, yogaNode_.getChildren().size());
childYogaNodeRawPtr = &childNodePtr->yogaNode_;
}
// Inserted node must have a clear owner (must not be shared).
assert(childYogaNodeRawPtr->getOwner() == nullptr);
child->ensureUnsealed();
childNodePtr->ensureUnsealed();
childYogaNodeRawPtr->setOwner(yogaNodeRawPtr);
yogaNodeRawPtr->insertChild(
@@ -125,7 +142,7 @@ void YogaLayoutableShadowNode::setChildren(
auto i = int{0};
for (auto const &child : children) {
appendChild(child);
appendChildYogaNode(*child);
isClean = isClean && !child->yogaNode_.isDirty() &&
child->yogaNode_.getStyle() == oldChildren[i++]->getStyle();
@@ -246,6 +263,15 @@ YogaLayoutableShadowNode::getLayoutableChildNodes() const {
return yogaLayoutableChildNodes;
}
YogaLayoutableShadowNode &YogaLayoutableShadowNode::cloneAndReplaceChild(
YogaLayoutableShadowNode &child,
int suggestedIndex) {
auto clonedChildShadowNode = child.clone({});
replaceChild(child, clonedChildShadowNode, suggestedIndex);
return static_cast<YogaLayoutableShadowNode &>(*clonedChildShadowNode);
}
#pragma mark - Yoga Connectors
YGNode *YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector(
@@ -260,8 +286,7 @@ YGNode *YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector(
static_cast<YogaLayoutableShadowNode *>(parentYogaNode->getContext());
auto oldNode =
static_cast<YogaLayoutableShadowNode *>(oldYogaNode->getContext());
auto clonedNode = static_cast<YogaLayoutableShadowNode *>(
parentNode->cloneAndReplaceChild(oldNode, childIndex));
auto clonedNode = &parentNode->cloneAndReplaceChild(*oldNode, childIndex);
return &clonedNode->yogaNode_;
}
@@ -47,12 +47,7 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode {
*/
void enableMeasurement();
/*
* Appends `child`'s Yoga node to the own Yoga node.
* Complements `ShadowNode::appendChild(...)` functionality from Yoga
* perspective.
*/
void appendChild(YogaLayoutableShadowNode *child);
void appendChild(ShadowNode::Shared const &child);
/*
* Sets Yoga children based on collection of `YogaLayoutableShadowNode`
@@ -111,6 +106,17 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode {
mutable YGNode yogaNode_;
private:
/*
* Appends `child`'s Yoga node to the own Yoga node.
* Complements `ShadowNode::appendChild(...)` functionality from Yoga
* perspective.
*/
void appendChildYogaNode(YogaLayoutableShadowNode &child);
YogaLayoutableShadowNode &cloneAndReplaceChild(
YogaLayoutableShadowNode &child,
int suggestedIndex);
static YGConfig &initializeYogaConfig(YGConfig &config);
static YGNode *yogaNodeCloneCallbackConnector(
YGNode *oldYogaNode,
@@ -15,6 +15,7 @@
#include <better/small_vector.h>
#include <react/core/LayoutMetrics.h>
#include <react/core/ShadowNode.h>
#include <react/core/ShadowNodeFragment.h>
#include <react/debug/DebugStringConvertible.h>
#include <react/graphics/Geometry.h>
#include <react/graphics/Transform.h>
@@ -136,14 +137,6 @@ class LayoutableShadowNode : public ShadowNode {
virtual LayoutableShadowNode::UnsharedList getLayoutableChildNodes()
const = 0;
/*
* 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,
int suggestedIndex = -1) = 0;
/*
* Sets layout metrics for the shadow node.
* Returns true if the metrics are different from previous ones.