diff --git a/tests/YGDirtyMarkingTest.cpp b/tests/YGDirtyMarkingTest.cpp index 9e098a4561..f0d22312ee 100644 --- a/tests/YGDirtyMarkingTest.cpp +++ b/tests/YGDirtyMarkingTest.cpp @@ -339,3 +339,29 @@ TEST(YogaTest, dirty_parent_when_subtree_freed_recursive) { EXPECT_TRUE(YGNodeIsDirty(root)); YGNodeFree(root); } + +TEST(YogaTest, dirty_propagation_through_child_set_to_display_contents) { + YGNodeRef root = YGNodeNew(); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + YGNodeRef child = YGNodeNew(); + YGNodeInsertChild(root, child, 0); + + YGNodeRef grandchild = YGNodeNew(); + YGNodeStyleSetWidth(grandchild, 10); + YGNodeStyleSetHeight(grandchild, 10); + YGNodeInsertChild(child, grandchild, 0); + + YGNodeStyleSetDisplay(child, YGDisplayContents); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + EXPECT_FALSE(YGNodeIsDirty(child)); + + YGNodeStyleSetWidth(grandchild, 20); + EXPECT_TRUE(YGNodeIsDirty(root)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(grandchild)); + + YGNodeFreeRecursive(root); +} diff --git a/yoga/YGNodeStyle.cpp b/yoga/YGNodeStyle.cpp index e43a38e64e..86da8ddf20 100644 --- a/yoga/YGNodeStyle.cpp +++ b/yoga/YGNodeStyle.cpp @@ -152,7 +152,16 @@ YGOverflow YGNodeStyleGetOverflow(const YGNodeConstRef node) { } void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { + const bool wasContents = + resolveRef(node)->style().display() == Display::Contents; updateStyle<&Style::display, &Style::setDisplay>(node, scopedEnum(display)); + + // The owner caches how many of its children use display: contents, so it + // has to be recomputed when an attached child switches to or from it. + auto owner = resolveRef(node)->getOwner(); + if (owner != nullptr && wasContents != (display == YGDisplayContents)) { + owner->setChildren(owner->getChildren()); + } } YGDisplay YGNodeStyleGetDisplay(const YGNodeConstRef node) {