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 Peter Kelly (pmk@post.com) | 4 * (C) 2001 Peter Kelly (pmk@post.com) |
| 5 * (C) 2001 Dirk Mueller (mueller@kde.org) | 5 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 6 * (C) 2007 David Smith (catfish.man@gmail.com) | 6 * (C) 2007 David Smith (catfish.man@gmail.com) |
| 7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. | 7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. |
| 8 * (C) 2007 Eric Seidel (eric@webkit.org) | 8 * (C) 2007 Eric Seidel (eric@webkit.org) |
| 9 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| (...skipping 1496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1507 document().styleResolver()->invalidateMatchedPropertiesCache(); | 1507 document().styleResolver()->invalidateMatchedPropertiesCache(); |
| 1508 return Force; | 1508 return Force; |
| 1509 } | 1509 } |
| 1510 | 1510 |
| 1511 if (styleChangeType() >= SubtreeStyleChange) | 1511 if (styleChangeType() >= SubtreeStyleChange) |
| 1512 return Force; | 1512 return Force; |
| 1513 | 1513 |
| 1514 return max(localChange, change); | 1514 return max(localChange, change); |
| 1515 } | 1515 } |
| 1516 | 1516 |
| 1517 static const int maxWhitespaceChildrenToDefer = 10; | |
| 1518 typedef Vector<Text*, maxWhitespaceChildrenToDefer> DeferredWhitespaceChildren; | |
| 1519 | |
| 1520 static inline void recalcWhitespaceChildrenStyle(DeferredWhitespaceChildren& whi tespaceChildren, StyleRecalcChange change) | |
| 1521 { | |
| 1522 for (int i = whitespaceChildren.size() - 1; i >= 0; --i) | |
| 1523 whitespaceChildren[i]->recalcTextStyle(change); | |
| 1524 } | |
| 1525 | |
| 1517 void Element::recalcChildStyle(StyleRecalcChange change) | 1526 void Element::recalcChildStyle(StyleRecalcChange change) |
| 1518 { | 1527 { |
| 1519 ASSERT(document().inStyleRecalc()); | 1528 ASSERT(document().inStyleRecalc()); |
| 1520 | 1529 |
| 1521 StyleResolverParentPusher parentPusher(this); | 1530 StyleResolverParentPusher parentPusher(this); |
| 1522 | 1531 |
| 1523 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadow Root()) { | 1532 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadow Root()) { |
| 1524 if (shouldRecalcStyle(change, root)) { | 1533 if (shouldRecalcStyle(change, root)) { |
| 1525 parentPusher.push(); | 1534 parentPusher.push(); |
| 1526 root->recalcStyle(change); | 1535 root->recalcStyle(change); |
| 1527 } | 1536 } |
| 1528 } | 1537 } |
| 1529 | 1538 |
| 1530 if (shouldRecalcStyle(change, this)) | 1539 if (shouldRecalcStyle(change, this)) |
| 1531 updatePseudoElement(BEFORE, change); | 1540 updatePseudoElement(BEFORE, change); |
| 1532 | 1541 |
| 1533 // FIXME: This check is good enough for :hover + foo, but it is not good eno ugh for :hover + foo + bar. | 1542 // FIXME: This check is good enough for :hover + foo, but it is not good eno ugh for :hover + foo + bar. |
| 1534 // For now we will just worry about the common case, since it's a lot tricki er to get the second case right | 1543 // For now we will just worry about the common case, since it's a lot tricki er to get the second case right |
| 1535 // without doing way too much re-resolution. | 1544 // without doing way too much re-resolution. |
| 1536 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules(); | 1545 bool hasDirectAdjacentRules = childrenAffectedByDirectAdjacentRules(); |
| 1537 bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules(); | 1546 bool hasIndirectAdjacentRules = childrenAffectedByForwardPositionalRules(); |
| 1538 bool forceCheckOfNextElementSibling = false; | 1547 bool forceCheckOfNextElementSibling = false; |
| 1539 bool forceCheckOfAnyElementSibling = false; | 1548 bool forceCheckOfAnyElementSibling = false; |
| 1540 bool forceReattachOfAnyWhitespaceSibling = false; | 1549 if (hasDirectAdjacentRules || hasIndirectAdjacentRules) { |
| 1541 for (Node* child = firstChild(); child; child = child->nextSibling()) { | 1550 for (Node* child = firstChild(); child; child = child->nextSibling()) { |
| 1551 if (!child->isElementNode()) | |
| 1552 continue; | |
| 1553 Element* element = toElement(child); | |
| 1554 bool childRulesChanged = element->needsStyleRecalc() && element->sty leChangeType() >= SubtreeStyleChange; | |
| 1555 if (forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling) | |
| 1556 element->setNeedsStyleRecalc(); | |
| 1557 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjac entRules; | |
| 1558 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (ch ildRulesChanged && hasIndirectAdjacentRules); | |
| 1559 } | |
| 1560 } | |
| 1561 // This loop is deliberately backwards because we use insertBefore in the re ndering tree, and want to avoid | |
| 1562 // a potentially n^2 loop to find the insertion point while resolving style. Having us start from the last | |
| 1563 // child and work our way back means in the common case, we'll find the inse rtion point in O(1) time. | |
| 1564 // Reversing this loop can lead to non-deterministic results in our code to optimize out empty whitespace | |
| 1565 // RenderTexts. We try to put off recalcing their style until the end to avo id this issue. | |
| 1566 // See crbug.com/288225 | |
| 1567 DeferredWhitespaceChildren whitespaceChildren; | |
| 1568 for (Node* child = lastChild(); child; child = child->previousSibling()) { | |
| 1542 bool didReattach = false; | 1569 bool didReattach = false; |
| 1543 | 1570 |
| 1544 if (child->renderer()) | |
| 1545 forceReattachOfAnyWhitespaceSibling = false; | |
| 1546 | |
| 1547 if (child->isTextNode()) { | 1571 if (child->isTextNode()) { |
| 1548 if (forceReattachOfAnyWhitespaceSibling && toText(child)->containsOn lyWhitespace()) | 1572 Text* textChild = toText(child); |
| 1549 child->reattach(); | 1573 if (textChild->containsOnlyWhitespace()) { |
|
esprehn
2013/09/30 22:55:34
This also makes us do the string scan for whitespa
| |
| 1550 else | 1574 if (whitespaceChildren.size() == maxWhitespaceChildrenToDefer) { |
| 1575 recalcWhitespaceChildrenStyle(whitespaceChildren, change); | |
| 1576 whitespaceChildren.clear(); | |
| 1577 } | |
| 1578 whitespaceChildren.append(textChild); | |
| 1579 } else { | |
| 1551 didReattach = toText(child)->recalcTextStyle(change); | 1580 didReattach = toText(child)->recalcTextStyle(change); |
| 1581 } | |
| 1552 } else if (child->isElementNode()) { | 1582 } else if (child->isElementNode()) { |
| 1553 Element* element = toElement(child); | 1583 Element* element = toElement(child); |
| 1554 | |
| 1555 bool childRulesChanged = element->needsStyleRecalc() && element->sty leChangeType() >= SubtreeStyleChange; | |
| 1556 | |
| 1557 if (forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling) | |
| 1558 element->setNeedsStyleRecalc(); | |
| 1559 | |
| 1560 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjac entRules; | |
| 1561 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (ch ildRulesChanged && hasIndirectAdjacentRules); | |
| 1562 | |
| 1563 if (shouldRecalcStyle(change, element)) { | 1584 if (shouldRecalcStyle(change, element)) { |
| 1564 parentPusher.push(); | 1585 parentPusher.push(); |
| 1565 didReattach = element->recalcStyle(change); | 1586 didReattach = element->recalcStyle(change); |
| 1566 } else if (document().styleResolver()->supportsStyleSharing(element) ) { | 1587 } else if (document().styleResolver()->supportsStyleSharing(element) ) { |
| 1567 document().styleResolver()->addToStyleSharingList(element); | 1588 document().styleResolver()->addToStyleSharingList(element); |
| 1568 } | 1589 } |
| 1569 } | 1590 } |
| 1570 | 1591 |
| 1571 forceReattachOfAnyWhitespaceSibling = didReattach || forceReattachOfAnyW hitespaceSibling; | 1592 if (didReattach) |
| 1593 child->reattachWhitespaceSiblings(); | |
| 1572 } | 1594 } |
| 1573 | 1595 |
| 1596 recalcWhitespaceChildrenStyle(whitespaceChildren, change); | |
| 1597 | |
| 1574 if (shouldRecalcStyle(change, this)) { | 1598 if (shouldRecalcStyle(change, this)) { |
| 1575 updatePseudoElement(AFTER, change); | 1599 updatePseudoElement(AFTER, change); |
| 1576 updatePseudoElement(BACKDROP, change); | 1600 updatePseudoElement(BACKDROP, change); |
| 1577 } | 1601 } |
| 1578 } | 1602 } |
| 1579 | 1603 |
| 1580 ElementShadow* Element::shadow() const | 1604 ElementShadow* Element::shadow() const |
| 1581 { | 1605 { |
| 1582 return hasRareData() ? elementRareData()->shadow() : 0; | 1606 return hasRareData() ? elementRareData()->shadow() : 0; |
| 1583 } | 1607 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1733 | 1757 |
| 1734 // We also have to handle node removal. The parser callback case is sim ilar to node removal as well in that we need to change the last child | 1758 // We also have to handle node removal. The parser callback case is sim ilar to node removal as well in that we need to change the last child |
| 1735 // to match now. | 1759 // to match now. |
| 1736 if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && (!newLastChildStyle || !newLastChi ldStyle->lastChildState())) | 1760 if ((childCountDelta < 0 || finishedParsingCallback) && newLastChild == lastElementBeforeInsertion && newLastChild && (!newLastChildStyle || !newLastChi ldStyle->lastChildState())) |
| 1737 newLastChild->setNeedsStyleRecalc(); | 1761 newLastChild->setNeedsStyleRecalc(); |
| 1738 } | 1762 } |
| 1739 | 1763 |
| 1740 // The + selector. We need to invalidate the first element following the in sertion point. It is the only possible element | 1764 // The + selector. We need to invalidate the first element following the in sertion point. It is the only possible element |
| 1741 // that could be affected by this DOM change. | 1765 // that could be affected by this DOM change. |
| 1742 if (e->childrenAffectedByDirectAdjacentRules() && afterChange) { | 1766 if (e->childrenAffectedByDirectAdjacentRules() && afterChange) { |
| 1743 if (Node* firstElementAfterInsertion = afterChange->nextElementSibling() ) | 1767 if (Node* firstElementAfterInsertion = afterChange->isElementNode() ? af terChange : afterChange->nextElementSibling()) |
| 1744 firstElementAfterInsertion->setNeedsStyleRecalc(); | 1768 firstElementAfterInsertion->setNeedsStyleRecalc(); |
| 1745 } | 1769 } |
| 1746 } | 1770 } |
| 1747 | 1771 |
| 1748 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* af terChange, int childCountDelta) | 1772 void Element::childrenChanged(bool changedByParser, Node* beforeChange, Node* af terChange, int childCountDelta) |
| 1749 { | 1773 { |
| 1750 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, c hildCountDelta); | 1774 ContainerNode::childrenChanged(changedByParser, beforeChange, afterChange, c hildCountDelta); |
| 1751 if (changedByParser) | 1775 if (changedByParser) |
| 1752 checkForEmptyStyleChange(this, renderStyle()); | 1776 checkForEmptyStyleChange(this, renderStyle()); |
| 1753 else | 1777 else |
| (...skipping 1888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3642 return 0; | 3666 return 0; |
| 3643 } | 3667 } |
| 3644 | 3668 |
| 3645 Attribute* UniqueElementData::attributeItem(unsigned index) | 3669 Attribute* UniqueElementData::attributeItem(unsigned index) |
| 3646 { | 3670 { |
| 3647 ASSERT_WITH_SECURITY_IMPLICATION(index < length()); | 3671 ASSERT_WITH_SECURITY_IMPLICATION(index < length()); |
| 3648 return &m_attributeVector.at(index); | 3672 return &m_attributeVector.at(index); |
| 3649 } | 3673 } |
| 3650 | 3674 |
| 3651 } // namespace WebCore | 3675 } // namespace WebCore |
| OLD | NEW |