| 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 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 if (element->shouldCallRecalcStyle(change)) | 1241 if (element->shouldCallRecalcStyle(change)) |
| 1242 element->recalcStyle(change, lastTextNode); | 1242 element->recalcStyle(change, lastTextNode); |
| 1243 else if (element->supportsStyleSharing()) | 1243 else if (element->supportsStyleSharing()) |
| 1244 styleResolver.addToStyleSharingList(*element); | 1244 styleResolver.addToStyleSharingList(*element); |
| 1245 if (element->layoutObject()) | 1245 if (element->layoutObject()) |
| 1246 lastTextNode = nullptr; | 1246 lastTextNode = nullptr; |
| 1247 } | 1247 } |
| 1248 } | 1248 } |
| 1249 } | 1249 } |
| 1250 | 1250 |
| 1251 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Ele
ment* changedElement, Node* nodeBeforeChange, Node* nodeAfterChange) | 1251 void ContainerNode::checkForSiblingStyleChanges(SiblingCheckType changeType, Nod
e* changedNode, Node* nodeBeforeChange, Node* nodeAfterChange) |
| 1252 { | 1252 { |
| 1253 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getSt
yleChangeType() >= SubtreeStyleChange) | 1253 if (!inActiveDocument() || document().hasPendingForcedStyleRecalc() || getSt
yleChangeType() >= SubtreeStyleChange) |
| 1254 return; | 1254 return; |
| 1255 | 1255 |
| 1256 if (!hasRestyleFlag(ChildrenAffectedByStructuralRules)) | 1256 // Forward positional selectors include nth-child, nth-of-type, first-of-typ
e and only-of-type. |
| 1257 // The indirect adjacent selector is the ~ selector. |
| 1258 // Backward positional selectors include nth-last-child, nth-last-of-type, l
ast-of-type and only-of-type. |
| 1259 // We have to invalidate everything following the insertion point in the for
ward and indirect adjacent case, |
| 1260 // and everything before the insertion point in the backward case. |
| 1261 // |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. |
| 1262 // 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 |
| 1263 // here. recalcStyle will then force a walk of the children when it sees tha
t this has happened. |
| 1264 if ((childrenAffectedByForwardPositionalRules() && nodeAfterChange) |
| 1265 || (childrenAffectedByBackwardPositionalRules() && nodeBeforeChange)) { |
| 1266 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::cre
ate(StyleChangeReason::SiblingSelector)); |
| 1257 return; | 1267 return; |
| 1258 | |
| 1259 Element* elementAfterChange = !nodeAfterChange || nodeAfterChange->isElement
Node() ? toElement(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterCh
ange); | |
| 1260 Element* elementBeforeChange = !nodeBeforeChange || nodeBeforeChange->isElem
entNode() ? toElement(nodeBeforeChange) : ElementTraversal::previousSibling(*nod
eBeforeChange); | |
| 1261 | |
| 1262 // TODO(rune@opera.com): move this code into StyleEngine and collect the | |
| 1263 // various invalidation sets into a single InvalidationLists object and | |
| 1264 // schedule with a single scheduleInvalidationSetsForNode for efficiency. | |
| 1265 | |
| 1266 // Forward positional selectors include :nth-child, :nth-of-type, | |
| 1267 // :first-of-type, and only-of-type. Backward positional selectors include | |
| 1268 // :nth-last-child, :nth-last-of-type, :last-of-type, and :only-of-type. | |
| 1269 if ((childrenAffectedByForwardPositionalRules() && elementAfterChange) | |
| 1270 || (childrenAffectedByBackwardPositionalRules() && elementBeforeChange))
{ | |
| 1271 document().styleEngine().scheduleNthPseudoInvalidations(*this); | |
| 1272 } | 1268 } |
| 1273 | 1269 |
| 1274 if (childrenAffectedByFirstChildRules() && !elementBeforeChange && elementAf
terChange && elementAfterChange->affectedByFirstChildRules()) { | 1270 // :first-child. In the parser callback case, we don't have to check anythin
g, since we were right the first time. |
| 1271 // In the DOM case, we only need to do something if |afterChange| is not 0. |
| 1272 // |afterChange| is 0 in the parser case, so it works out that we'll skip th
is block. |
| 1273 if (childrenAffectedByFirstChildRules() && nodeAfterChange) { |
| 1275 DCHECK_NE(changeType, FinishedParsingChildren); | 1274 DCHECK_NE(changeType, FinishedParsingChildren); |
| 1276 elementAfterChange->pseudoStateChanged(CSSSelector::PseudoFirstChild); | 1275 // Find our new first child element. |
| 1277 elementAfterChange->pseudoStateChanged(CSSSelector::PseudoOnlyChild); | 1276 Element* firstChildElement = ElementTraversal::firstChild(*this); |
| 1277 |
| 1278 // Find the first element after the change. |
| 1279 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toEleme
nt(nodeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); |
| 1280 |
| 1281 // This is the element insertion as first child element case. |
| 1282 if (changeType == SiblingElementInserted && elementAfterChange && firstC
hildElement != elementAfterChange |
| 1283 && (!nodeBeforeChange || !nodeBeforeChange->isElementNode()) && elem
entAfterChange->affectedByFirstChildRules()) { |
| 1284 elementAfterChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCha
ngeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
| 1285 } |
| 1286 |
| 1287 // This is the first child element removal case. |
| 1288 if (changeType == SiblingElementRemoved && firstChildElement == elementA
fterChange && firstChildElement && firstChildElement->affectedByFirstChildRules(
)) |
| 1289 firstChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChan
geReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
| 1278 } | 1290 } |
| 1279 | 1291 |
| 1280 if (childrenAffectedByLastChildRules() && !elementAfterChange && elementBefo
reChange && elementBeforeChange->affectedByLastChildRules()) { | 1292 // :last-child. In the parser callback case, we don't have to check anything
, since we were right the first time. |
| 1281 elementBeforeChange->pseudoStateChanged(CSSSelector::PseudoLastChild); | 1293 // In the DOM case, we only need to do something if |afterChange| is not 0. |
| 1282 elementBeforeChange->pseudoStateChanged(CSSSelector::PseudoOnlyChild); | 1294 if (childrenAffectedByLastChildRules() && nodeBeforeChange) { |
| 1295 // Find our new last child element. |
| 1296 Element* lastChildElement = ElementTraversal::lastChild(*this); |
| 1297 |
| 1298 // Find the last element before the change. |
| 1299 Element* elementBeforeChange = nodeBeforeChange->isElementNode() ? toEle
ment(nodeBeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange); |
| 1300 |
| 1301 // This is the element insertion as last child element case. |
| 1302 if (changeType == SiblingElementInserted && elementBeforeChange && lastC
hildElement != elementBeforeChange |
| 1303 && (!nodeAfterChange || !nodeAfterChange->isElementNode()) && elemen
tBeforeChange->affectedByLastChildRules()) { |
| 1304 elementBeforeChange->setNeedsStyleRecalc(SubtreeStyleChange, StyleCh
angeReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
| 1305 } |
| 1306 |
| 1307 // 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 |
| 1308 // to match now. |
| 1309 if ((changeType == SiblingElementRemoved || changeType == FinishedParsin
gChildren) && lastChildElement == elementBeforeChange && lastChildElement && las
tChildElement->affectedByLastChildRules()) |
| 1310 lastChildElement->setNeedsStyleRecalc(SubtreeStyleChange, StyleChang
eReasonForTracing::create(StyleChangeReason::SiblingSelector)); |
| 1283 } | 1311 } |
| 1284 | 1312 |
| 1285 // For ~ and + combinators, succeeding siblings may need style invalidation | 1313 // For ~ and + combinators, succeeding siblings may need style invalidation |
| 1286 // after an element is inserted or removed. | 1314 // after an element is inserted or removed. |
| 1287 | 1315 |
| 1288 if (!elementAfterChange) | 1316 if (!nodeAfterChange) |
| 1289 return; | 1317 return; |
| 1290 | 1318 if (changeType != SiblingElementRemoved && changeType != SiblingElementInser
ted) |
| 1319 return; |
| 1291 if (!childrenAffectedByIndirectAdjacentRules() && !childrenAffectedByDirectA
djacentRules()) | 1320 if (!childrenAffectedByIndirectAdjacentRules() && !childrenAffectedByDirectA
djacentRules()) |
| 1292 return; | 1321 return; |
| 1293 | 1322 |
| 1294 if (changeType == SiblingElementInserted) { | 1323 Element* elementAfterChange = nodeAfterChange->isElementNode() ? toElement(n
odeAfterChange) : ElementTraversal::nextSibling(*nodeAfterChange); |
| 1295 document().styleEngine().scheduleInvalidationsForInsertedSibling(element
BeforeChange, *changedElement); | 1324 if (!elementAfterChange) |
| 1296 return; | 1325 return; |
| 1297 } | 1326 Element* elementBeforeChange = nullptr; |
| 1327 if (nodeBeforeChange) |
| 1328 elementBeforeChange = nodeBeforeChange->isElementNode() ? toElement(node
BeforeChange) : ElementTraversal::previousSibling(*nodeBeforeChange); |
| 1298 | 1329 |
| 1299 DCHECK(changeType == SiblingElementRemoved); | 1330 if (changeType == SiblingElementInserted) |
| 1300 document().styleEngine().scheduleInvalidationsForRemovedSibling(elementBefor
eChange, *changedElement, *elementAfterChange); | 1331 document().styleEngine().scheduleInvalidationsForInsertedSibling(element
BeforeChange, *toElement(changedNode)); |
| 1332 else |
| 1333 document().styleEngine().scheduleInvalidationsForRemovedSibling(elementB
eforeChange, *toElement(changedNode), *elementAfterChange); |
| 1301 } | 1334 } |
| 1302 | 1335 |
| 1303 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att
rName, Element* attributeOwnerElement) | 1336 void ContainerNode::invalidateNodeListCachesInAncestors(const QualifiedName* att
rName, Element* attributeOwnerElement) |
| 1304 { | 1337 { |
| 1305 if (hasRareData() && (!attrName || isAttributeNode())) { | 1338 if (hasRareData() && (!attrName || isAttributeNode())) { |
| 1306 if (NodeListsNodeData* lists = rareData()->nodeLists()) { | 1339 if (NodeListsNodeData* lists = rareData()->nodeLists()) { |
| 1307 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) | 1340 if (ChildNodeList* childNodeList = lists->childNodeList(*this)) |
| 1308 childNodeList->invalidateCache(); | 1341 childNodeList->invalidateCache(); |
| 1309 } | 1342 } |
| 1310 } | 1343 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 return true; | 1431 return true; |
| 1399 | 1432 |
| 1400 if (node->isElementNode() && toElement(node)->shadow()) | 1433 if (node->isElementNode() && toElement(node)->shadow()) |
| 1401 return true; | 1434 return true; |
| 1402 | 1435 |
| 1403 return false; | 1436 return false; |
| 1404 } | 1437 } |
| 1405 #endif | 1438 #endif |
| 1406 | 1439 |
| 1407 } // namespace blink | 1440 } // namespace blink |
| OLD | NEW |