Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Unified Diff: third_party/WebKit/Source/core/dom/ContainerNode.cpp

Issue 2254443002: CL for perf tryjob on win (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/dom/ContainerNode.h ('k') | third_party/WebKit/Source/core/dom/Element.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 d948b388f951a9e755aad04c8b9da44f09f8c28c..cd2427da8b25ea8a9f7c1e4940409dfefdebac75 100644
--- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp
+++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -1248,56 +1248,89 @@ void ContainerNode::recalcDescendantStyles(StyleRecalcChange change)
}
}
-void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Element* changedElement, Node* nodeBeforeChange, Node* nodeAfterChange)
+void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Node* changedNode, Node* nodeBeforeChange, Node* nodeAfterChange)
{
if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getStyleChangeType() >= SubtreeStyleChange)
return;
- if (!hasRestyleFlag(ChildrenAffectedByStructuralRules))
+ // Forward positional selectors include nth-child, nth-of-type, first-of-type and only-of-type.
+ // The indirect adjacent selector is the ~ selector.
+ // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
+ // We have to invalidate everything following the insertion point in the forward and indirect adjacent case,
+ // and everything before the insertion point in the backward case.
+ // |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() && nodeAfterChange)
+ || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) {
+ setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector));
return;
+ }
- Element* elementAfterChange = !nodeAfterChange || nodeAfterChange->isElementNode() ? toElement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange);
- Element* elementBeforeChange = !nodeBeforeChange || nodeBeforeChange->isElementNode() ? toElement(nodeBeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange);
+ // :first-child. In the parser callback case, we don't have to check anything, since we were right the first time.
+ // In the DOM case, we only need to do something if |afterChange| is not 0.
+ // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
+ if (childrenAffectedByFirstChildRules() && nodeAfterChange) {
+ DCHECK_NE(changeType, FinishedParsingChildren);
+ // Find our new first child element.
+ Element* firstChildElement = ElementTraversal::firstChild(*this);
- // TODO(rune@opera.com): move this code into StyleEngine and collect the
- // various invalidation sets into a single InvalidationLists object and
- // schedule with a single scheduleInvalidationSetsForNode for efficiency.
+ // Find the first element after the change.
+ Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange);
- // Forward positional selectors include :nth-child, :nth-of-type,
- // :first-of-type, and only-of-type. Backward positional selectors include
- // :nth-last-child, :nth-last-of-type, :last-of-type, and :only-of-type.
- if ((childrenAffectedByForwardPositionalRules() && elementAfterChange)
- || (childrenAffectedByBackwardPositionalRules() && elementBeforeChange)) {
- document().styleEngine().scheduleNthPseudoInvalidations(*this);
- }
+ // This is the element insertion as first child element case.
+ if (changeType == SiblingElementInserted && elementAfterChange && firstChildElement != elementAfterChange
+ && (!nodeBeforeChange || !nodeBeforeChange->isElementNode()) && elementAfterChange->affectedByFirstChildRules()) {
+ elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector));
+ }
- if (childrenAffectedByFirstChildRules() && !elementBeforeChange && elementAfterChange && elementAfterChange->affectedByFirstChildRules()) {
- DCHECK_NE(changeType, FinishedParsingChildren);
- elementAfterChange->pseudoStateChanged(CSSSelector::PseudoFirstChild);
- elementAfterChange->pseudoStateChanged(CSSSelector::PseudoOnlyChild);
+ // This is the first child element removal case.
+ if (changeType == SiblingElementRemoved && firstChildElement == elementAfterChange && firstChildElement && firstChildElement->affectedByFirstChildRules())
+ firstChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector));
}
- if (childrenAffectedByLastChildRules() && !elementAfterChange && elementBeforeChange && elementBeforeChange->affectedByLastChildRules()) {
- elementBeforeChange->pseudoStateChanged(CSSSelector::PseudoLastChild);
- elementBeforeChange->pseudoStateChanged(CSSSelector::PseudoOnlyChild);
+ // :last-child. In the parser callback case, we don't have to check anything, since we were right the first time.
+ // In the DOM case, we only need to do something if |afterChange| is not 0.
+ if (childrenAffectedByLastChildRules() && nodeBeforeChange) {
+ // Find our new last child element.
+ Element* lastChildElement = ElementTraversal::lastChild(*this);
+
+ // Find the last element before the change.
+ Element* elementBeforeChange = nodeBeforeChange->isElementNode() ? toElement(nodeBeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange);
+
+ // This is the element insertion as last child element case.
+ if (changeType == SiblingElementInserted && elementBeforeChange && lastChildElement != elementBeforeChange
+ && (!nodeAfterChange || !nodeAfterChange->isElementNode()) && elementBeforeChange->affectedByLastChildRules()) {
+ elementBeforeChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector));
+ }
+
+ // This is the last child element removal case. The parser callback case is similar to node removal as well in that we need to change the last child
+ // to match now.
+ if ((changeType == SiblingElementRemoved || changeType == FinishedParsingChildren) && lastChildElement == elementBeforeChange && lastChildElement && lastChildElement->affectedByLastChildRules())
+ lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::SiblingSelector));
}
// For ~ and + combinators, succeeding siblings may need style invalidation
// after an element is inserted or removed.
- if (!elementAfterChange)
+ if (!nodeAfterChange)
+ return;
+ if (changeType != SiblingElementRemoved && changeType != SiblingElementInserted)
return;
-
if (!childrenAffectedByIndirectAdjacentRules() && !childrenAffectedByDirectAdjacentRules())
return;
- if (changeType == SiblingElementInserted) {
- document().styleEngine().scheduleInvalidationsForInsertedSibling(elementBeforeChange, *changedElement);
+ 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);
- DCHECK(changeType == SiblingElementRemoved);
- document().styleEngine().scheduleInvalidationsForRemovedSibling(elementBeforeChange, *changedElement, *elementAfterChange);
+ 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)
« no previous file with comments | « third_party/WebKit/Source/core/dom/ContainerNode.h ('k') | third_party/WebKit/Source/core/dom/Element.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698