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

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

Issue 2059163002: Schedule sibling invalidation sets for sibling insert/remove. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 6 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 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 return child; 400 return child;
401 } 401 }
402 402
403 void ContainerNode::willRemoveChild(Node& child) 403 void ContainerNode::willRemoveChild(Node& child)
404 { 404 {
405 DCHECK_EQ(child.parentNode(), this); 405 DCHECK_EQ(child.parentNode(), this);
406 ChildListMutationScope(*this).willRemoveChild(child); 406 ChildListMutationScope(*this).willRemoveChild(child);
407 child.notifyMutationObserversNodeWillDetach(); 407 child.notifyMutationObserversNodeWillDetach();
408 dispatchChildRemovalEvents(child); 408 dispatchChildRemovalEvents(child);
409 ChildFrameDisconnector(child).disconnect(); 409 ChildFrameDisconnector(child).disconnect();
410 document().styleEngine().willRemoveChild(child);
410 if (document() != child.document()) { 411 if (document() != child.document()) {
411 // |child| was moved another document by DOM mutation event handler. 412 // |child| was moved another document by DOM mutation event handler.
412 return; 413 return;
413 } 414 }
414 415
415 // |nodeWillBeRemoved()| must be run after |ChildFrameDisconnector|, because 416 // |nodeWillBeRemoved()| must be run after |ChildFrameDisconnector|, because
416 // |ChildFrameDisconnector| can run script which may cause state that is to 417 // |ChildFrameDisconnector| can run script which may cause state that is to
417 // be invalidated by removing the node. 418 // be invalidated by removing the node.
418 ScriptForbiddenScope scriptForbiddenScope; 419 ScriptForbiddenScope scriptForbiddenScope;
419 EventDispatchForbiddenScope assertNoEventDispatch; 420 EventDispatchForbiddenScope assertNoEventDispatch;
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 { 582 {
582 EventDispatchForbiddenScope assertNoEventDispatch; 583 EventDispatchForbiddenScope assertNoEventDispatch;
583 ScriptForbiddenScope forbidScript; 584 ScriptForbiddenScope forbidScript;
584 585
585 while (Node* child = m_firstChild) { 586 while (Node* child = m_firstChild) {
586 removeBetween(0, child->nextSibling(), *child); 587 removeBetween(0, child->nextSibling(), *child);
587 notifyNodeRemoved(*child); 588 notifyNodeRemoved(*child);
588 } 589 }
589 } 590 }
590 591
591 ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, ChildrenC hangeSourceAPI}; 592 ChildrenChange change = {AllChildrenRemoved, nullptr, nullptr, nullptr, ChildrenChangeSourceAPI};
592 childrenChanged(change); 593 childrenChanged(change);
593 } 594 }
594 595
595 if (action == DispatchSubtreeModifiedEvent) 596 if (action == DispatchSubtreeModifiedEvent)
596 dispatchSubtreeModifiedEvent(); 597 dispatchSubtreeModifiedEvent();
597 } 598 }
598 599
599 Node* ContainerNode::appendChild(Node* newChild, ExceptionState& exceptionState) 600 Node* ContainerNode::appendChild(Node* newChild, ExceptionState& exceptionState)
600 { 601 {
601 602
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 if (element->shouldCallRecalcStyle(change)) 1210 if (element->shouldCallRecalcStyle(change))
1210 element->recalcStyle(change, lastTextNode); 1211 element->recalcStyle(change, lastTextNode);
1211 else if (element->supportsStyleSharing()) 1212 else if (element->supportsStyleSharing())
1212 styleResolver.addToStyleSharingList(*element); 1213 styleResolver.addToStyleSharingList(*element);
1213 if (element->layoutObject()) 1214 if (element->layoutObject())
1214 lastTextNode = nullptr; 1215 lastTextNode = nullptr;
1215 } 1216 }
1216 } 1217 }
1217 } 1218 }
1218 1219
1219 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod e* nodeBeforeChange, Node* nodeAfterChange) 1220 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod e* changedNode, Node* nodeBeforeChange, Node* nodeAfterChange)
1220 { 1221 {
1221 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getSt yleChangeType() >= SubtreeStyleChange) 1222 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getSt yleChangeType() >= SubtreeStyleChange)
1222 return; 1223 return;
1223 1224
1224 // Forward positional selectors include nth-child, nth-of-type, first-of-typ e and only-of-type. 1225 // 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. 1226 // 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. 1227 // 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, 1228 // 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. 1229 // 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. 1230 // |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 1231 // 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. 1232 // here. recalcStyle will then force a walk of the children when it sees tha t this has happened.
1232 if (((childrenAffectedByForwardPositionalRules() || childrenAffectedByIndire ctAdjacentRules()) && nodeAfterChange) 1233 if ((childrenAffectedByForwardPositionalRules() && nodeAfterChange)
1233 || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) { 1234 || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) {
1234 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre ate(StyleChangeReason::SiblingSelector)); 1235 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre ate(StyleChangeReason::SiblingSelector));
1235 return; 1236 return;
1236 } 1237 }
1237 1238
1238 // :first-child. In the parser callback case, we don't have to check anythin g, since we were right the first time. 1239 // :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. 1240 // 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. 1241 // |afterChange| is 0 in the parser case, so it works out that we'll skip th is block.
1241 if (childrenAffectedByFirstChildRules() && nodeAfterChange) { 1242 if (childrenAffectedByFirstChildRules() && nodeAfterChange) {
1242 DCHECK_NE(changeType, FinishedParsingChildren); 1243 DCHECK_NE(changeType, FinishedParsingChildren);
(...skipping 28 matching lines...) Expand all
1271 && (!nodeAfterChange || !nodeAfterChange->isElementNode()) && elemen tBeforeChange->affectedByLastChildRules()) { 1272 && (!nodeAfterChange || !nodeAfterChange->isElementNode()) && elemen tBeforeChange->affectedByLastChildRules()) {
1272 elementBeforeChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCh angeReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1273 elementBeforeChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCh angeReasonForTracing::create(StyleChangeReason::SiblingSelector));
1273 } 1274 }
1274 1275
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 // 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. 1277 // to match now.
1277 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las tChildElement->affectedByLastChildRules()) 1278 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las tChildElement->affectedByLastChildRules())
1278 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang eReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1279 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang eReasonForTracing::create(StyleChangeReason::SiblingSelector));
1279 } 1280 }
1280 1281
1281 // The + selector. We need to invalidate the first element following the cha nge. It is the only possible element 1282 // For ~ and + combinators, succeeding siblings may need style invalidation
1282 // that could be affected by this DOM change. 1283 // after an element is inserted or removed.
1283 if (childrenAffectedByDirectAdjacentRules() && nodeAfterChange) { 1284
1284 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); 1285 if (!nodeAfterChange)
1285 for (unsigned i = document().styleEngine().maxDirectAdjacentSelectors(); i && elementAfterChange; --i, elementAfterChange = ElementTraversal::nextSiblin g(*elementAfterChange)) 1286 return;
1286 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); 1287 if (changeType != SiblingElementRemoved && changeType != SiblingElementInser ted)
1287 } 1288 return;
1289 if (!childrenAffectedByIndirectAdjacentRules() && !childrenAffectedByDirectA djacentRules())
1290 return;
1291
1292 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(n odeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange);
1293 if (!elementAfterChange)
1294 return;
1295 Element* elementBeforeChange = nullptr;
1296 if (nodeBeforeChange)
1297 elementBeforeChange = nodeBeforeChange->isElementNode() ? toElement(node BeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange);
1298
1299 if (changeType == SiblingElementInserted)
1300 document().styleEngine().scheduleInvalidationsForInsertedSibling(element BeforeChange, *toElement(changedNode));
1301 else
1302 document().styleEngine().scheduleInvalidationsForRemovedSibling(elementB eforeChange, *toElement(changedNode), *elementAfterChange);
1288 } 1303 }
1289 1304
1290 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att rName, Element* attributeOwnerElement) 1305 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att rName, Element* attributeOwnerElement)
1291 { 1306 {
1292 if (hasRareData() && (!attrName || isAttributeNode())) { 1307 if (hasRareData() && (!attrName || isAttributeNode())) {
1293 if (NodeListsNodeData* lists = rareData()->nodeLists()) { 1308 if (NodeListsNodeData* lists = rareData()->nodeLists()) {
1294 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) 1309 if (ChildNodeList* childNodeList = lists->childNodeList(*this))
1295 childNodeList->invalidateCache(); 1310 childNodeList->invalidateCache();
1296 } 1311 }
1297 } 1312 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 return true; 1400 return true;
1386 1401
1387 if (node->isElementNode() && toElement(node)->shadow()) 1402 if (node->isElementNode() && toElement(node)->shadow())
1388 return true; 1403 return true;
1389 1404
1390 return false; 1405 return false;
1391 } 1406 }
1392 #endif 1407 #endif
1393 1408
1394 } // namespace blink 1409 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698