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 |