Commit 2721c154 authored by Rune Lillesveen's avatar Rune Lillesveen Committed by Commit Bot

Update child-style-dirty chain on slot re-assignment.

With flat tree style recalc enabled, we need to update the new flat
tree ancestors with ChildNeedsStyleRecalc() when the slot assignment
changes. SetNeedsStyleRecalc() will only do that if the node was clean.
Otherwise it assumes the child-dirty bits are already marked. If we are
already dirty, call MarkAncestorsWithChildNeedsStyleRecalc() to update
the child-dirty chain on FlatTreeParentChanged().

Also, added an early return for disconnected elements.

Bug: 972752
Change-Id: I5bc76ee70eb310f2d2bc1765dcfcd15e4883f0d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1893060Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712157}
parent 2414bc8b
......@@ -3209,6 +3209,8 @@ bool Node::HasMediaControlAncestor() const {
}
void Node::FlatTreeParentChanged() {
if (!isConnected())
return;
// TODO(futhark): Replace with DCHECK(IsSlotable()) when Shadow DOM V0 support
// is removed.
if (!IsElementNode() && !IsTextNode()) {
......@@ -3218,6 +3220,14 @@ void Node::FlatTreeParentChanged() {
// The node changed the flat tree position by being slotted to a new slot or
// slotted for the first time. We need to recalc style since the inheritance
// parent may have changed.
if (NeedsStyleRecalc() &&
RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) {
// For flat tree style recalc, the ancestor chain may have changed. We need
// make sure that the child-dirty flags are updated, but the
// SetNeedsStyleRecalc() call below will skip
// MarkAncestorsWithChildNeedsStyleRecalc() if the node was already dirty.
MarkAncestorsWithChildNeedsStyleRecalc();
}
SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::Create(
style_change_reason::kFlatTreeChange));
......
......@@ -405,4 +405,30 @@ TEST_F(NodeTest, SkipForceReattachDisplayNone) {
EXPECT_FALSE(span->GetForceReattachLayoutTree());
}
TEST_F(NodeTest, UpdateChildDirtyAncestorsOnSlotAssignment) {
ScopedFlatTreeStyleRecalcForTest scope(true);
SetBodyContent("<div id=host><span></span></div>");
Element* host = GetDocument().getElementById("host");
ShadowRoot& shadow_root =
host->AttachShadowRootInternal(ShadowRootType::kOpen);
shadow_root.SetInnerHTMLFromString(
"<div><slot></slot></div><div id='child-dirty'><slot "
"name='target'></slot></div>");
UpdateAllLifecyclePhasesForTest();
EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
auto* span = To<Element>(host->firstChild());
auto* ancestor = shadow_root.getElementById("child-dirty");
// Make sure the span is dirty before the re-assignment.
span->setAttribute("style", "color:green");
EXPECT_FALSE(ancestor->ChildNeedsStyleRecalc());
// Re-assign to second slot.
span->setAttribute(html_names::kSlotAttr, "target");
GetDocument().GetSlotAssignmentEngine().RecalcSlotAssignments();
EXPECT_TRUE(ancestor->ChildNeedsStyleRecalc());
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment