Index: third_party/WebKit/Source/core/dom/ContainerNode.cpp |
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp |
index c84626d91ccac8d02a52fa3d09eb7c94405555da..31f06ca496ca4cb67ae96bd81803cd20ca640bdd 100644 |
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp |
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp |
@@ -407,6 +407,7 @@ void ContainerNode::willRemoveChild(Node& child) |
child.notifyMutationObserversNodeWillDetach(); |
dispatchChildRemovalEvents(child); |
ChildFrameDisconnector(child).disconnect(); |
+ document().styleEngine().willRemoveChild(child); |
if (document() != child.document()) { |
// |child| was moved another document by DOM mutation event handler. |
return; |
@@ -588,7 +589,7 @@ void ContainerNode::removeChildren(SubtreeModificationAction action) |
} |
} |
- ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, ChildrenChangeSourceAPI}; |
+ ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, nullptr, ChildrenChangeSourceAPI}; |
childrenChanged(change); |
} |
@@ -1216,7 +1217,7 @@ void ContainerNode::recalcChildStyle(StyleRecalcChange change) |
} |
} |
-void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Node* nodeBeforeChange, Node* nodeAfterChange) |
+void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Node* changedNode, Node* nodeBeforeChange, Node* nodeAfterChange) |
{ |
if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getStyleChangeType() >= SubtreeStyleChange) |
return; |
@@ -1229,7 +1230,7 @@ void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod |
// |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to. |
// For performance reasons we just mark the parent node as changed, since we don't want to make childrenChanged O(n^2) by crawling all our kids |
// here. recalcStyle will then force a walk of the children when it sees that this has happened. |
- if (((childrenAffectedByForwardPositionalRules() || childrenAffectedByIndirectAdjacentRules()) && nodeAfterChange) |
+ if ((childrenAffectedByForwardPositionalRules() && nodeAfterChange) |
|| (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) { |
setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
return; |
@@ -1278,13 +1279,27 @@ void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod |
lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
} |
- // The + selector. We need to invalidate the first element following the change. It is the only possible element |
- // that could be affected by this DOM change. |
- if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) { |
- Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); |
- for (unsigned i = document().styleEngine().maxDirectAdjacentSelectors(); i && elementAfterChange; --i, elementAfterChange = ElementTraversal::nextSibling(*elementAfterChange)) |
- elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
- } |
+ // For ~ and + combinators, succeeding siblings may need style invalidation |
+ // after an element is inserted or removed. |
+ |
+ if (!nodeAfterChange) |
+ return; |
+ if (changeType != SiblingElementRemoved && changeType != SiblingElementInserted) |
+ return; |
+ if (!childrenAffectedByIndirectAdjacentRules() && !childrenAffectedByDirectAdjacentRules()) |
+ return; |
+ |
+ Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); |
+ if (!elementAfterChange) |
+ return; |
+ Element* elementBeforeChange = nullptr; |
+ if (nodeBeforeChange) |
+ elementBeforeChange = nodeBeforeChange->isElementNode() ? toElement(nodeBeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange); |
+ |
+ if (changeType == SiblingElementInserted) |
+ document().styleEngine().scheduleInvalidationsForInsertedSibling(elementBeforeChange, *toElement(changedNode)); |
+ else |
+ document().styleEngine().scheduleInvalidationsForRemovedSibling(elementBeforeChange, *toElement(changedNode), *elementAfterChange); |
} |
void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* attrName, Element* attributeOwnerElement) |