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

Side by Side Diff: third_party/WebKit/Source/core/dom/ContainerNode.cpp

Issue 2089063005: Schedule sibling invalidation sets for sibling insert/remove. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Corrected DCHECK Created 4 years, 5 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved. 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 { 581 {
582 EventDispatchForbiddenScope assertNoEventDispatch; 582 EventDispatchForbiddenScope assertNoEventDispatch;
583 ScriptForbiddenScope forbidScript; 583 ScriptForbiddenScope forbidScript;
584 584
585 while (Node* child = m_firstChild) { 585 while (Node* child = m_firstChild) {
586 removeBetween(0, child->nextSibling(), *child); 586 removeBetween(0, child->nextSibling(), *child);
587 notifyNodeRemoved(*child); 587 notifyNodeRemoved(*child);
588 } 588 }
589 } 589 }
590 590
591 ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, ChildrenC hangeSourceAPI}; 591 ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, nullptr, ChildrenChangeSourceAPI};
592 childrenChanged(change); 592 childrenChanged(change);
593 } 593 }
594 594
595 if (action == DispatchSubtreeModifiedEvent) 595 if (action == DispatchSubtreeModifiedEvent)
596 dispatchSubtreeModifiedEvent(); 596 dispatchSubtreeModifiedEvent();
597 } 597 }
598 598
599 Node* ContainerNode::appendChild(Node* newChild, ExceptionState& exceptionState) 599 Node* ContainerNode::appendChild(Node* newChild, ExceptionState& exceptionState)
600 { 600 {
601 601
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 if (element->shouldCallRecalcStyle(change)) 1209 if (element->shouldCallRecalcStyle(change))
1210 element->recalcStyle(change, lastTextNode); 1210 element->recalcStyle(change, lastTextNode);
1211 else if (element->supportsStyleSharing()) 1211 else if (element->supportsStyleSharing())
1212 styleResolver.addToStyleSharingList(*element); 1212 styleResolver.addToStyleSharingList(*element);
1213 if (element->layoutObject()) 1213 if (element->layoutObject())
1214 lastTextNode = nullptr; 1214 lastTextNode = nullptr;
1215 } 1215 }
1216 } 1216 }
1217 } 1217 }
1218 1218
1219 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod e* nodeBeforeChange, Node* nodeAfterChange) 1219 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod e* changedNode, Node* nodeBeforeChange, Node* nodeAfterChange)
1220 { 1220 {
1221 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getSt yleChangeType() >= SubtreeStyleChange) 1221 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getSt yleChangeType() >= SubtreeStyleChange)
1222 return; 1222 return;
1223 1223
1224 // Forward positional selectors include nth-child, nth-of-type, first-of-typ e and only-of-type. 1224 // Forward positional selectors include nth-child, nth-of-type, first-of-typ e and only-of-type.
1225 // The indirect adjacent selector is the ~ selector. 1225 // The indirect adjacent selector is the ~ selector.
1226 // Backward positional selectors include nth-last-child, nth-last-of-type, l ast-of-type and only-of-type. 1226 // Backward positional selectors include nth-last-child, nth-last-of-type, l ast-of-type and only-of-type.
1227 // We have to invalidate everything following the insertion point in the for ward and indirect adjacent case, 1227 // We have to invalidate everything following the insertion point in the for ward and indirect adjacent case,
1228 // and everything before the insertion point in the backward case. 1228 // and everything before the insertion point in the backward case.
1229 // |afterChange| is 0 in the parser callback case, so we won't do any work f or the forward case if we don't have to. 1229 // |afterChange| is 0 in the parser callback case, so we won't do any work f or the forward case if we don't have to.
1230 // 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 1230 // 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
1231 // here. recalcStyle will then force a walk of the children when it sees tha t this has happened. 1231 // here. recalcStyle will then force a walk of the children when it sees tha t this has happened.
1232 if (((childrenAffectedByForwardPositionalRules() || childrenAffectedByIndire ctAdjacentRules()) && nodeAfterChange) 1232 if ((childrenAffectedByForwardPositionalRules() && nodeAfterChange)
1233 || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) { 1233 || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) {
1234 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre ate(StyleChangeReason::SiblingSelector)); 1234 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre ate(StyleChangeReason::SiblingSelector));
esprehn 2016/06/29 04:52:08 We need to figure out how to kill all of these Sub
rune 2016/06/29 07:44:21 crbug.com/624277
1235 return; 1235 return;
1236 } 1236 }
1237 1237
1238 // :first-child. In the parser callback case, we don't have to check anythin g, since we were right the first time. 1238 // :first-child. In the parser callback case, we don't have to check anythin g, since we were right the first time.
1239 // In the DOM case, we only need to do something if |afterChange| is not 0. 1239 // In the DOM case, we only need to do something if |afterChange| is not 0.
1240 // |afterChange| is 0 in the parser case, so it works out that we'll skip th is block. 1240 // |afterChange| is 0 in the parser case, so it works out that we'll skip th is block.
1241 if (childrenAffectedByFirstChildRules() && nodeAfterChange) { 1241 if (childrenAffectedByFirstChildRules() && nodeAfterChange) {
1242 DCHECK_NE(changeType, FinishedParsingChildren); 1242 DCHECK_NE(changeType, FinishedParsingChildren);
1243 // Find our new first child element. 1243 // Find our new first child element.
1244 Element* firstChildElement = ElementTraversal::firstChild(*this); 1244 Element* firstChildElement = ElementTraversal::firstChild(*this);
1245 1245
1246 // Find the first element after the change. 1246 // Find the first element after the change.
1247 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); 1247 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange);
1248 1248
1249 // This is the element insertion as first child element case. 1249 // This is the element insertion as first child element case.
1250 if (changeType == SiblingElementInserted && elementAfterChange && firstC hildElement != elementAfterChange 1250 if (changeType == SiblingElementInserted && elementAfterChange && firstC hildElement != elementAfterChange
1251 && (!nodeBeforeChange || !nodeBeforeChange->isElementNode()) && elem entAfterChange->affectedByFirstChildRules()) { 1251 && (!nodeBeforeChange || !nodeBeforeChange->isElementNode()) && elem entAfterChange->affectedByFirstChildRules()) {
1252 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1252 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha ngeReasonForTracing::create(StyleChangeReason::SiblingSelector));
esprehn 2016/06/29 04:52:08 ex. we should use invalidation sets for the :first
rune 2016/06/29 07:44:21 Acknowledged.
1253 } 1253 }
1254 1254
1255 // This is the first child element removal case. 1255 // This is the first child element removal case.
1256 if (changeType == SiblingElementRemoved && firstChildElement == elementA fterChange && firstChildElement && firstChildElement->affectedByFirstChildRules( )) 1256 if (changeType == SiblingElementRemoved && firstChildElement == elementA fterChange && firstChildElement && firstChildElement->affectedByFirstChildRules( ))
1257 firstChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChan geReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1257 firstChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChan geReasonForTracing::create(StyleChangeReason::SiblingSelector));
1258 } 1258 }
1259 1259
1260 // :last-child. In the parser callback case, we don't have to check anything , since we were right the first time. 1260 // :last-child. In the parser callback case, we don't have to check anything , since we were right the first time.
1261 // In the DOM case, we only need to do something if |afterChange| is not 0. 1261 // In the DOM case, we only need to do something if |afterChange| is not 0.
1262 if (childrenAffectedByLastChildRules() && nodeBeforeChange) { 1262 if (childrenAffectedByLastChildRules() && nodeBeforeChange) {
1263 // Find our new last child element. 1263 // Find our new last child element.
1264 Element* lastChildElement = ElementTraversal::lastChild(*this); 1264 Element* lastChildElement = ElementTraversal::lastChild(*this);
1265 1265
1266 // Find the last element before the change. 1266 // Find the last element before the change.
1267 Element* elementBeforeChange = nodeBeforeChange->isElementNode() ? toEle ment(nodeBeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange); 1267 Element* elementBeforeChange = nodeBeforeChange->isElementNode() ? toEle ment(nodeBeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange);
1268 1268
1269 // This is the element insertion as last child element case. 1269 // This is the element insertion as last child element case.
1270 if (changeType == SiblingElementInserted && elementBeforeChange && lastC hildElement != elementBeforeChange 1270 if (changeType == SiblingElementInserted && elementBeforeChange && lastC hildElement != elementBeforeChange
1271 && (!nodeAfterChange || !nodeAfterChange->isElementNode()) && elemen tBeforeChange->affectedByLastChildRules()) { 1271 && (!nodeAfterChange || !nodeAfterChange->isElementNode()) && elemen tBeforeChange->affectedByLastChildRules()) {
1272 elementBeforeChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCh angeReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1272 elementBeforeChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCh angeReasonForTracing::create(StyleChangeReason::SiblingSelector));
1273 } 1273 }
1274 1274
1275 // 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 1275 // 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
1276 // to match now. 1276 // to match now.
1277 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las tChildElement->affectedByLastChildRules()) 1277 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las tChildElement->affectedByLastChildRules())
1278 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang eReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1278 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang eReasonForTracing::create(StyleChangeReason::SiblingSelector));
1279 } 1279 }
1280 1280
1281 // The + selector. We need to invalidate the first element following the cha nge. It is the only possible element 1281 // For ~ and + combinators, succeeding siblings may need style invalidation
1282 // that could be affected by this DOM change. 1282 // after an element is inserted or removed.
1283 if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) { 1283
1284 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); 1284 if (!nodeAfterChange)
1285 for (unsigned i = document().styleEngine().maxDirectAdjacentSelectors(); i && elementAfterChange; --i, elementAfterChange = ElementTraversal::nextSiblin g(*elementAfterChange)) 1285 return;
1286 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1286 if (changeType != SiblingElementRemoved && changeType != SiblingElementInser ted)
1287 } 1287 return;
1288 if (!childrenAffectedByIndirectAdjacentRules() && !childrenAffectedByDirectA djacentRules())
1289 return;
1290
1291 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(n odeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange);
1292 if (!elementAfterChange)
1293 return;
1294 Element* elementBeforeChange = nullptr;
1295 if (nodeBeforeChange)
1296 elementBeforeChange = nodeBeforeChange->isElementNode() ? toElement(node BeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange);
1297
1298 if (changeType == SiblingElementInserted)
1299 document().styleEngine().scheduleInvalidationsForInsertedSibling(element BeforeChange, *toElement(changedNode));
1300 else
1301 document().styleEngine().scheduleInvalidationsForRemovedSibling(elementB eforeChange, *toElement(changedNode), *elementAfterChange);
1288 } 1302 }
1289 1303
1290 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att rName, Element* attributeOwnerElement) 1304 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att rName, Element* attributeOwnerElement)
1291 { 1305 {
1292 if (hasRareData() && (!attrName || isAttributeNode())) { 1306 if (hasRareData() && (!attrName || isAttributeNode())) {
1293 if (NodeListsNodeData* lists = rareData()->nodeLists()) { 1307 if (NodeListsNodeData* lists = rareData()->nodeLists()) {
1294 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) 1308 if (ChildNodeList* childNodeList = lists->childNodeList(*this))
1295 childNodeList->invalidateCache(); 1309 childNodeList->invalidateCache();
1296 } 1310 }
1297 } 1311 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 return true; 1399 return true;
1386 1400
1387 if (node->isElementNode() && toElement(node)->shadow()) 1401 if (node->isElementNode() && toElement(node)->shadow())
1388 return true; 1402 return true;
1389 1403
1390 return false; 1404 return false;
1391 } 1405 }
1392 #endif 1406 #endif
1393 1407
1394 } // namespace blink 1408 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698