Skip to content

Commit

Permalink
Move YGCloneChildrenIfNeeded as a method on YGNode
Browse files Browse the repository at this point in the history
Reviewed By: emilsjolander

Differential Revision: D6611155

fbshipit-source-id: 463723a363e0fbd2c7686f65226eca73236bd07e
  • Loading branch information
priteshrnandgaonkar authored and facebook-github-bot committed Jan 8, 2018
1 parent 654d759 commit 28968e2
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 54 deletions.
50 changes: 33 additions & 17 deletions ReactCommon/yoga/yoga/YGNode.cpp
Expand Up @@ -155,6 +155,10 @@ void YGNode::replaceChild(YGNodeRef child, uint32_t index) {
children_[index] = child; children_[index] = child;
} }


void YGNode::replaceChild(YGNodeRef oldChild, YGNodeRef newChild) {
std::replace(children_.begin(), children_.end(), oldChild, newChild);
}

void YGNode::insertChild(YGNodeRef child, uint32_t index) { void YGNode::insertChild(YGNodeRef child, uint32_t index) {
children_.insert(children_.begin() + index, child); children_.insert(children_.begin() + index, child);
} }
Expand Down Expand Up @@ -375,21 +379,33 @@ YGNode::~YGNode() {
// deallocate here // deallocate here
} }


const YGNode& YGNode::defaultValue() { void YGNode::cloneChildrenIfNeeded() {
static const YGNode n = {nullptr, // YGNodeRemoveChild in yoga.cpp has a forked variant of this algorithm
nullptr, // optimized for deletions.
true,
YGNodeTypeDefault, const uint32_t childCount = children_.size();
nullptr, if (childCount == 0) {
nullptr, // This is an empty set. Nothing to clone.
gYGNodeStyleDefaults, return;
gYGNodeLayoutDefaults, }
0,
nullptr, const YGNodeRef firstChild = children_.front();
YGVector(), if (firstChild->getParent() == this) {
nullptr, // If the first child has this node as its parent, we assume that it is
nullptr, // already unique. We can do this because if we have it has a child, that
false, // means that its parent was at some point cloned which made that subtree
{{YGValueUndefined, YGValueUndefined}}}; // immutable. We also assume that all its sibling are cloned as well.
return n; return;
}

const YGNodeClonedFunc cloneNodeCallback = config_->cloneNodeCallback;
for (uint32_t i = 0; i < childCount; ++i) {
const YGNodeRef oldChild = children_[i];
const YGNodeRef newChild = YGNodeClone(oldChild);
replaceChild(newChild, i);
newChild->setParent(this);
if (cloneNodeCallback) {
cloneNodeCallback(oldChild, newChild, this, i);
}
}
} }
6 changes: 4 additions & 2 deletions ReactCommon/yoga/yoga/YGNode.h
Expand Up @@ -106,6 +106,8 @@ struct YGNode {
YGValue resolveFlexBasisPtr() const; YGValue resolveFlexBasisPtr() const;
void resolveDimension(); void resolveDimension();
void clearChildren(); void clearChildren();
/// Replaces the occurrences of oldChild with newChild
void replaceChild(YGNodeRef oldChild, YGNodeRef newChild);
void replaceChild(YGNodeRef child, uint32_t index); void replaceChild(YGNodeRef child, uint32_t index);
void insertChild(YGNodeRef child, uint32_t index); void insertChild(YGNodeRef child, uint32_t index);
/// Removes the first occurrence of child /// Removes the first occurrence of child
Expand All @@ -117,6 +119,6 @@ struct YGNode {
void setLayoutPadding(float padding, int index); void setLayoutPadding(float padding, int index);
void setLayoutPosition(float position, int index); void setLayoutPosition(float position, int index);


// Static methods // Other methods
static const YGNode& defaultValue(); void cloneChildrenIfNeeded();
}; };
40 changes: 5 additions & 35 deletions ReactCommon/yoga/yoga/Yoga.cpp
Expand Up @@ -348,36 +348,6 @@ static void YGNodeMarkDirtyInternal(const YGNodeRef node) {
} }
} }


static void YGCloneChildrenIfNeeded(const YGNodeRef parent) {
// YGNodeRemoveChild has a forked variant of this algorithm optimized for deletions.
const uint32_t childCount = YGNodeGetChildCount(parent);
if (childCount == 0) {
// This is an empty set. Nothing to clone.
return;
}

const YGNodeRef firstChild = YGNodeGetChild(parent, 0);
if (firstChild->getParent() == parent) {
// If the first child has this node as its parent, we assume that it is already unique.
// We can do this because if we have it has a child, that means that its parent was at some
// point cloned which made that subtree immutable.
// We also assume that all its sibling are cloned as well.
return;
}

const YGNodeClonedFunc cloneNodeCallback =
parent->getConfig()->cloneNodeCallback;
for (uint32_t i = 0; i < childCount; i++) {
const YGNodeRef oldChild = parent->getChild(i);
const YGNodeRef newChild = YGNodeClone(oldChild);
parent->replaceChild(newChild, i);
newChild->setParent(parent);
if (cloneNodeCallback) {
cloneNodeCallback(oldChild, newChild, parent, i);
}
}
}

void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) { void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) {
YGAssertWithNode( YGAssertWithNode(
node, node,
Expand All @@ -388,14 +358,15 @@ void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32
node->getMeasure() == nullptr, node->getMeasure() == nullptr,
"Cannot add child: Nodes with measure functions cannot have children."); "Cannot add child: Nodes with measure functions cannot have children.");


YGCloneChildrenIfNeeded(node); node->cloneChildrenIfNeeded();
node->insertChild(child, index); node->insertChild(child, index);
child->setParent(node); child->setParent(node);
YGNodeMarkDirtyInternal(node); YGNodeMarkDirtyInternal(node);
} }


void YGNodeRemoveChild(const YGNodeRef parent, const YGNodeRef excludedChild) { void YGNodeRemoveChild(const YGNodeRef parent, const YGNodeRef excludedChild) {
// This algorithm is a forked variant from YGCloneChildrenIfNeeded that excludes a child. // This algorithm is a forked variant from cloneChildrenIfNeeded in YGNode
// that excludes a child.
const uint32_t childCount = YGNodeGetChildCount(parent); const uint32_t childCount = YGNodeGetChildCount(parent);


if (childCount == 0) { if (childCount == 0) {
Expand Down Expand Up @@ -1805,7 +1776,7 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node,
static void YGZeroOutLayoutRecursivly(const YGNodeRef node) { static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
memset(&(node->getLayout()), 0, sizeof(YGLayout)); memset(&(node->getLayout()), 0, sizeof(YGLayout));
node->setHasNewLayout(true); node->setHasNewLayout(true);
YGCloneChildrenIfNeeded(node); node->cloneChildrenIfNeeded();
const uint32_t childCount = YGNodeGetChildCount(node); const uint32_t childCount = YGNodeGetChildCount(node);
for (uint32_t i = 0; i < childCount; i++) { for (uint32_t i = 0; i < childCount; i++) {
const YGNodeRef child = node->getChild(i); const YGNodeRef child = node->getChild(i);
Expand Down Expand Up @@ -1993,8 +1964,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
} }


// At this point we know we're going to perform work. Ensure that each child has a mutable copy. // At this point we know we're going to perform work. Ensure that each child has a mutable copy.
YGCloneChildrenIfNeeded(node); node->cloneChildrenIfNeeded();

// Reset layout flags, as they could have changed. // Reset layout flags, as they could have changed.
node->setLayoutHadOverflow(false); node->setLayoutHadOverflow(false);


Expand Down

0 comments on commit 28968e2

Please sign in to comment.