Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -596,11 +596,20 @@ YogaLayoutableShadowNode& YogaLayoutableShadowNode::cloneChildInPlace(
void YogaLayoutableShadowNode::setSize(Size size) const {
ensureUnsealed();

auto width = yoga::StyleSizeLength::points(size.width);
auto height = yoga::StyleSizeLength::points(size.height);

// Component descriptors call this from `adopt`, which runs on every clone.
// Dirtying the node when nothing changed would make every commit that clones
// it re-run layout over the whole tree.
auto style = yogaNode_.style();
style.setDimension(
yoga::Dimension::Width, yoga::StyleSizeLength::points(size.width));
style.setDimension(
yoga::Dimension::Height, yoga::StyleSizeLength::points(size.height));
if (width == style.dimension(yoga::Dimension::Width) &&
height == style.dimension(yoga::Dimension::Height)) {
return;
}

style.setDimension(yoga::Dimension::Width, width);
style.setDimension(yoga::Dimension::Height, height);
yogaNode_.setStyle(style);
yogaNode_.setDirty(true);
}
Expand Down Expand Up @@ -635,6 +644,10 @@ void YogaLayoutableShadowNode::setPositionType(
ensureUnsealed();

auto style = yogaNode_.style();
if (style.positionType() == yoga::scopedEnum(positionType)) {
return;
}

style.setPositionType(yoga::scopedEnum(positionType));
yogaNode_.setStyle(style);
yogaNode_.setDirty(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,63 @@ TEST_F(YogaDirtyFlagTest, showingHiddenNodeMustDirtyItAndLayOutItsChildren) {
EXPECT_EQ(child->getLayoutMetrics().frame.size.width, 42);
}

TEST_F(YogaDirtyFlagTest, settingUnchangedSizeMustNotDirtyYogaNode) {
/*
* Component descriptors call `setSize` from `adopt`, which runs on every
* clone. Setting the size a node already has must *not* dirty its Yoga node,
* otherwise every commit that clones it re-runs layout.
*/
auto setSize = [](const ShadowNode& oldShadowNode) {
auto newShadowNode = oldShadowNode.clone({});
static_cast<YogaLayoutableShadowNode&>(*newShadowNode)
.setSize({.width = 100, .height = 200});
return newShadowNode;
};

auto sizedRootShadowNode =
rootShadowNode_->cloneTree(innerShadowNode_->getFamily(), setSize);

/*
* Changing the size *must* dirty the Yoga node.
*/
EXPECT_TRUE(
static_cast<RootShadowNode&>(*sizedRootShadowNode).layoutIfNeeded());

auto newRootShadowNode =
sizedRootShadowNode->cloneTree(innerShadowNode_->getFamily(), setSize);

EXPECT_FALSE(
static_cast<RootShadowNode&>(*newRootShadowNode).layoutIfNeeded());
}

TEST_F(YogaDirtyFlagTest, settingUnchangedPositionTypeMustNotDirtyYogaNode) {
/*
* Setting the position type a node already has must *not* dirty its Yoga
* node.
*/
auto setPositionType = [](const ShadowNode& oldShadowNode) {
auto newShadowNode = oldShadowNode.clone({});
static_cast<YogaLayoutableShadowNode&>(*newShadowNode)
.setPositionType(YGPositionTypeAbsolute);
return newShadowNode;
};

auto absoluteRootShadowNode = rootShadowNode_->cloneTree(
innerShadowNode_->getFamily(), setPositionType);

/*
* Changing the position type *must* dirty the Yoga node.
*/
EXPECT_TRUE(
static_cast<RootShadowNode&>(*absoluteRootShadowNode).layoutIfNeeded());

auto newRootShadowNode = absoluteRootShadowNode->cloneTree(
innerShadowNode_->getFamily(), setPositionType);

EXPECT_FALSE(
static_cast<RootShadowNode&>(*newRootShadowNode).layoutIfNeeded());
}

TEST_F(YogaDirtyFlagTest, clonedPropsPreserveAspectRatio) {
ContextContainer contextContainer{};
PropsParserContext parserContext{-1, contextContainer};
Expand Down
Loading