Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |