Changeset 173229 in webkit
- Timestamp:
- Sep 3, 2014 2:30:31 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 20 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r173227 r173229 1 2014-09-03 Benjamin Poulain <benjamin@webkit.org> 2 3 Fix style invalidation of elements with multiple siblings dependencies 4 https://bugs.webkit.org/show_bug.cgi?id=136472 5 6 Reviewed by Andreas Kling. 7 8 The test coverage was pretty bad. :( 9 I tried to cover the most obvious problems. 10 11 * fast/css/direct-adjacent-style-update-optimization-expected.txt: Added. 12 * fast/css/direct-adjacent-style-update-optimization.html: Added. 13 * fast/css/indirect-adjacent-style-update-optimization-expected.txt: Added. 14 * fast/css/indirect-adjacent-style-update-optimization.html: Added. 15 * fast/css/non-matching-adjacent-style-update-expected.txt: Added. 16 * fast/css/non-matching-adjacent-style-update.html: Added. 17 * fast/selectors/attribute-direct-adjacent-style-update-expected.txt: 18 * fast/selectors/class-direct-adjacent-style-update-expected.txt: 19 * fast/selectors/first-child-direct-adjacent-style-update-expected.txt: 20 * fast/selectors/first-of-type-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt. 21 * fast/selectors/first-of-type-direct-adjacent-style-update.html: Added. 22 * fast/selectors/first-of-type-sibling-style-update-expected.txt: Added. 23 * fast/selectors/first-of-type-sibling-style-update.html: Added. 24 * fast/selectors/id-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt. 25 * fast/selectors/id-direct-adjacent-style-update.html: Added. 26 * fast/selectors/id-sibling-style-update-expected.txt: Added. 27 * fast/selectors/id-sibling-style-update.html: Added. 28 * fast/selectors/nth-child-as-first-simple-selector-style-update-expected.txt: Added. 29 * fast/selectors/nth-child-as-first-simple-selector-style-update.html: Added. 30 * fast/selectors/nth-child-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt. 31 * fast/selectors/nth-child-direct-adjacent-style-update.html: Added. 32 * fast/selectors/nth-child-style-update-expected.txt: Added. 33 * fast/selectors/nth-child-style-update.html: Added. 34 1 35 2014-09-03 Benjamin Poulain <benjamin@webkit.org> 2 36 -
trunk/LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt
r172880 r173229 14 14 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(0, 0, 0)" 15 15 Adding the attribute, the extra rules should match. 16 FAIL getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255). 16 PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(1, 2, 3)" 17 17 PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)" 18 18 PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(1, 2, 3)" 19 19 PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)" 20 20 PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)" 21 FAIL getComputedStyle(document.getElementById("baz-with-renderer")).color should be rgb(4, 5, 6). Was rgb(0, 0, 0). 21 PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(4, 5, 6)" 22 22 PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)" 23 23 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(4, 5, 6)" 24 24 Emptying the attribute, the extra rules should still match. 25 FAIL getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255). 25 PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(1, 2, 3)" 26 26 PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)" 27 27 PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(1, 2, 3)" 28 28 PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)" 29 29 PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)" 30 FAIL getComputedStyle(document.getElementById("baz-with-renderer")).color should be rgb(4, 5, 6). Was rgb(0, 0, 0). 30 PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(4, 5, 6)" 31 31 PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)" 32 32 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(4, 5, 6)" -
trunk/LayoutTests/fast/selectors/class-direct-adjacent-style-update-expected.txt
r172880 r173229 14 14 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(0, 0, 0)" 15 15 Adding the class, the extra rules should match. 16 FAIL getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255). 16 PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(1, 2, 3)" 17 17 PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)" 18 18 PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(1, 2, 3)" 19 19 PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)" 20 20 PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)" 21 FAIL getComputedStyle(document.getElementById("baz-with-renderer")).color should be rgb(4, 5, 6). Was rgb(0, 0, 0). 21 PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(4, 5, 6)" 22 22 PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)" 23 23 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(4, 5, 6)" -
trunk/LayoutTests/fast/selectors/first-child-direct-adjacent-style-update-expected.txt
r172880 r173229 14 14 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(4, 5, 6)" 15 15 Adding an element as first child should clear the style. 16 FAIL getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor should be rgb(255, 255, 255). Was rgb(1, 2, 3). 16 PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(255, 255, 255)" 17 17 PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)" 18 18 PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(255, 255, 255)" 19 19 PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)" 20 20 PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)" 21 FAIL getComputedStyle(document.getElementById("baz-with-renderer")).color should be rgb(0, 0, 0). Was rgb(4, 5, 6). 21 PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(0, 0, 0)" 22 22 PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)" 23 23 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(0, 0, 0)" … … 32 32 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(4, 5, 6)" 33 33 Removing <foo> should clear the style. 34 FAIL getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor should be rgb(255, 255, 255). Was rgb(1, 2, 3). 34 PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(255, 255, 255)" 35 35 PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)" 36 36 PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(255, 255, 255)" 37 37 PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)" 38 38 PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)" 39 FAIL getComputedStyle(document.getElementById("baz-with-renderer")).color should be rgb(0, 0, 0). Was rgb(4, 5, 6). 39 PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(0, 0, 0)" 40 40 PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)" 41 41 PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(0, 0, 0)" -
trunk/Source/WebCore/ChangeLog
r173226 r173229 1 2014-09-03 Benjamin Poulain <benjamin@webkit.org> 2 3 Fix style invalidation of elements with multiple siblings dependencies 4 https://bugs.webkit.org/show_bug.cgi?id=136472 5 6 Reviewed by Andreas Kling. 7 8 Previously, style invalidation of siblings was driven by a pair of flags: 9 -ChildrenAffectedByDirectAdjacentRules. 10 -ChildrenAffectedByForwardPositionalRules. 11 12 When ChildrenAffectedByDirectAdjacentRules was set, the element after an element 13 with "needsStyleRecalc" was also recomputed. While this work for pair of elements: 14 a + b 15 It does not work for more than that. For example, with 16 a.propery + b + c 17 When the state of <a> changes, the style of <b> was updated, which is useless. The style 18 of <c> was untouched, which is incorrect. 19 20 When ChildrenAffectedByForwardPositionalRules, all elements after one with "needsStyleRecalc" 21 were invalidated. While more correct, it caused avalanche of style recalc and was not a very 22 useful "optimization". 23 24 25 To fix the correctness issues (e.g. "a + b + c"), I could have gone two ways: 26 1) Invalidate the parent of a, b, c. The children would always get a correct style 27 when their parent's style would be resolved. 28 2) Create invalidation relations to enforce that the right siblings are invalidated. 29 30 I have decided for a weak version of (2). The reason is that most DOM trees are very 31 shallow while being very wide. Invalidating the parent generally causes massive style 32 recalculation. 33 34 To keep things simple for now, there is no explicit dependency list between siblings. 35 Instead, each element has a pair of flag: 36 1) The element's style depends on the state of a previous sibling. 37 2) The element's state affects following siblings. 38 39 With the notation "<-" for (1), "->" for (2), the selector "a + b + c" create this kind 40 of marking: 41 a + b + c 42 -> -> 43 <- 44 45 When <a> is invalidated, the style resolver will go through the chain of dependent elements 46 and invalidate any element that can be affected by a prior invalidation, here <c>. 47 48 Overlaps are possible. For example with the two selector, "a + b + c", "b ~ d" 49 the marking would be 50 a + b + c + d 51 -> -> -> 52 <- <- 53 54 A change in <a> would invalidate both <c> and <d>. This is overkill, but the end result 55 is correct and it is a net improvement over the previous flags. 56 57 58 As usual, the CSS JIT makes an effort at compile time to reduce tree marking. SelectorChecker 59 marks everything as usual. 60 61 Tests: fast/css/direct-adjacent-style-update-optimization.html 62 fast/css/indirect-adjacent-style-update-optimization.html 63 fast/css/non-matching-adjacent-style-update.html 64 fast/selectors/first-of-type-direct-adjacent-style-update.html 65 fast/selectors/first-of-type-sibling-style-update.html 66 fast/selectors/id-direct-adjacent-style-update.html 67 fast/selectors/id-sibling-style-update.html 68 fast/selectors/nth-child-as-first-simple-selector-style-update.html 69 fast/selectors/nth-child-direct-adjacent-style-update.html 70 fast/selectors/nth-child-style-update.html 71 72 * css/SelectorChecker.cpp: 73 (WebCore::isFirstOfType): 74 (WebCore::countElementsBefore): 75 (WebCore::countElementsOfTypeBefore): 76 Counting selectors are not unlike adjacent combinators, they are handled the exact same way. 77 For example a :nth-child(4) would generate somewhat similar marking as 78 :first-child + * + * + * 79 80 Everything prior to the element with the counter affects the style of the element. 81 82 (WebCore::hasScrollbarPseudoElement): 83 The assertion was incorrect. You can get an scrollbar pseudo ID on an element without scrollbar. 84 It will never match, but such case is possible. 85 86 (WebCore::SelectorChecker::matchRecursively): 87 (WebCore::SelectorChecker::checkOne): 88 * css/StyleResolver.cpp: 89 (WebCore::StyleResolver::canShareStyleWithElement): 90 Previously, any subtree affected by sibling selectors were unshareable. That was done by checking 91 for Element::hasFlagsSetDuringStylingOfChildren(). 92 93 Now that sibling relation are local, they no longer prevent sharing of all children. Instead, we can 94 test locally for subgroup with sibling relations. 95 96 * cssjit/SelectorCompiler.cpp: 97 (WebCore::SelectorCompiler::isAdjacentRelation): 98 (WebCore::SelectorCompiler::shouldMarkStyleIsAffectedByPreviousSibling): 99 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker): 100 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker): 101 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker): 102 (WebCore::SelectorCompiler::SelectorCodeGenerator::markElementIfResolvingStyle): 103 (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild): 104 (WebCore::SelectorCompiler::SelectorCodeGenerator::markParentElementIfResolvingStyle): Deleted. 105 * dom/Document.cpp: 106 (WebCore::nodeOrItsAncestorNeedsStyleRecalc): 107 * dom/Element.cpp: 108 (WebCore::checkForSiblingStyleChanges): 109 (WebCore::Element::hasFlagsSetDuringStylingOfChildren): 110 (WebCore::Element::setChildrenAffectedByForwardPositionalRules): Deleted. 111 (WebCore::Element::rareDataChildrenAffectedByForwardPositionalRules): Deleted. 112 * dom/Element.h: 113 (WebCore::Element::affectsNextSiblingElementStyle): 114 (WebCore::Element::setAffectsNextSiblingElementStyle): 115 (WebCore::Element::setStyleIsAffectedByPreviousSibling): 116 (WebCore::Element::childrenAffectedByPositionalRules): Deleted. 117 (WebCore::Element::childrenAffectedByDirectAdjacentRules): Deleted. 118 (WebCore::Element::childrenAffectedByForwardPositionalRules): Deleted. 119 (WebCore::Element::setChildrenAffectedByDirectAdjacentRules): Deleted. 120 (WebCore::Element::setChildrenAffectedByForwardPositionalRules): Deleted. 121 * dom/ElementRareData.h: 122 (WebCore::ElementRareData::ElementRareData): 123 (WebCore::ElementRareData::resetDynamicRestyleObservations): 124 (WebCore::ElementRareData::childrenAffectedByForwardPositionalRules): Deleted. 125 (WebCore::ElementRareData::setChildrenAffectedByForwardPositionalRules): Deleted. 126 * dom/Node.h: 127 (WebCore::Node::styleIsAffectedByPreviousSibling): 128 (WebCore::Node::flagAffectsNextSiblingElementStyle): 129 (WebCore::Node::flagStyleIsAffectedByPreviousSibling): 130 (WebCore::Node::flagChildrenAffectedByDirectAdjacentRulesFlag): Deleted. 131 * html/HTMLElement.h: 132 (WebCore::HTMLElement::isHTMLUnknownElement): 133 * html/HTMLUnknownElement.h: 134 * style/StyleResolveTree.cpp: 135 (WebCore::Style::resetStyleForNonRenderedDescendants): 136 (WebCore::Style::resolveTree): 137 1 138 2014-09-03 Simon Fraser <simon.fraser@apple.com> 2 139 -
trunk/Source/WebCore/css/SelectorChecker.cpp
r173138 r173229 69 69 } 70 70 71 static inline bool isFirstOfType(const Element* element, const QualifiedName& type) 72 { 73 for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) { 71 static inline bool isFirstOfType(Element* element, const QualifiedName& type, bool isResolvingStyle) 72 { 73 for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) { 74 if (isResolvingStyle) 75 sibling->setAffectsNextSiblingElementStyle(); 74 76 if (sibling->hasTagName(type)) 75 77 return false; … … 87 89 } 88 90 89 static inline int countElementsBefore( const Element* element)91 static inline int countElementsBefore(Element* element, bool isResolvingStyle) 90 92 { 91 93 int count = 0; 92 for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) { 94 for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) { 95 if (isResolvingStyle) 96 sibling->setAffectsNextSiblingElementStyle(); 97 93 98 unsigned index = sibling->childIndex(); 94 99 if (index) { … … 101 106 } 102 107 103 static inline int countElementsOfTypeBefore( const Element* element, const QualifiedName& type)108 static inline int countElementsOfTypeBefore(Element* element, const QualifiedName& type, bool isResolvingStyle) 104 109 { 105 110 int count = 0; 106 for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) { 111 for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) { 112 if (isResolvingStyle) 113 sibling->setAffectsNextSiblingElementStyle(); 114 107 115 if (sibling->hasTagName(type)) 108 116 ++count; … … 153 161 } 154 162 155 inline static bool hasScrollbarPseudoElement( const SelectorChecker::SelectorCheckingContext& context,PseudoId& dynamicPseudo)163 inline static bool hasScrollbarPseudoElement(PseudoId& dynamicPseudo) 156 164 { 157 165 if (dynamicPseudo == SCROLLBAR … … 161 169 || dynamicPseudo == SCROLLBAR_TRACK_PIECE 162 170 || dynamicPseudo == SCROLLBAR_CORNER) { 163 ASSERT_UNUSED(context, context.scrollbar);164 171 return true; 165 172 } … … 267 274 268 275 case CSSSelector::DirectAdjacent: 269 if (context.resolvingMode == Mode::ResolvingStyle) { 270 if (Element* parentElement = context.element->parentElement()) 271 parentElement->setChildrenAffectedByDirectAdjacentRules(); 272 } 273 nextContext.element = context.element->previousElementSibling(); 274 if (!nextContext.element) 275 return SelectorFailsAllSiblings; 276 nextContext.firstSelectorOfTheFragment = nextContext.selector; 277 nextContext.elementStyle = 0; 278 return matchRecursively(nextContext, ignoreDynamicPseudo); 279 276 { 277 if (context.resolvingMode == Mode::ResolvingStyle) 278 context.element->setStyleIsAffectedByPreviousSibling(); 279 280 Element* previousElement = context.element->previousElementSibling(); 281 if (!previousElement) 282 return SelectorFailsAllSiblings; 283 if (context.resolvingMode == Mode::ResolvingStyle) 284 previousElement->setAffectsNextSiblingElementStyle(); 285 nextContext.element = previousElement; 286 nextContext.firstSelectorOfTheFragment = nextContext.selector; 287 nextContext.elementStyle = 0; 288 return matchRecursively(nextContext, ignoreDynamicPseudo); 289 } 280 290 case CSSSelector::IndirectAdjacent: 281 if (context.resolvingMode == Mode::ResolvingStyle) { 282 if (Element* parentElement = context.element->parentElement()) 283 parentElement->setChildrenAffectedByForwardPositionalRules(); 284 } 291 if (context.resolvingMode == Mode::ResolvingStyle) 292 context.element->setStyleIsAffectedByPreviousSibling(); 285 293 nextContext.element = context.element->previousElementSibling(); 286 294 nextContext.firstSelectorOfTheFragment = nextContext.selector; 287 295 nextContext.elementStyle = 0; 288 296 for (; nextContext.element; nextContext.element = nextContext.element->previousElementSibling()) { 297 if (context.resolvingMode == Mode::ResolvingStyle) 298 context.element->setAffectsNextSiblingElementStyle(); 299 289 300 Match match = this->matchRecursively(nextContext, ignoreDynamicPseudo); 290 301 if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) … … 297 308 // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else) 298 309 // to follow the pseudo elements. 299 nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement( context,dynamicPseudo);310 nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(dynamicPseudo); 300 311 nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION; 301 312 if ((context.elementStyle || context.resolvingMode == Mode::CollectingRules) && dynamicPseudo != NOPSEUDO … … 554 565 case CSSSelector::PseudoClassFirstOfType: 555 566 // first-of-type matches the first element of its type 556 if (Element* parentElement = element->parentElement()) { 557 bool result = isFirstOfType(element, element->tagQName()); 567 if (element->parentElement()) { 558 568 if (context.resolvingMode == Mode::ResolvingStyle) 559 parentElement->setChildrenAffectedByForwardPositionalRules(); 560 return result; 569 element->setStyleIsAffectedByPreviousSibling(); 570 571 return isFirstOfType(element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle); 561 572 } 562 573 break; … … 604 615 if (Element* parentElement = element->parentElement()) { 605 616 if (context.resolvingMode == Mode::ResolvingStyle) { 606 parentElement->setChildrenAffectedByForwardPositionalRules();617 element->setStyleIsAffectedByPreviousSibling(); 607 618 parentElement->setChildrenAffectedByBackwardPositionalRules(); 608 619 } 609 620 if (!parentElement->isFinishedParsingChildren()) 610 621 return false; 611 return isFirstOfType(element, element->tagQName() ) && isLastOfType(element, element->tagQName());622 return isFirstOfType(element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle) && isLastOfType(element, element->tagQName()); 612 623 } 613 624 break; … … 626 637 if (!selector->parseNth()) 627 638 break; 628 if (Element* parentElement = element->parentElement()) { 629 int count = 1 + countElementsBefore(element); 639 if (element->parentElement()) { 640 if (context.resolvingMode == Mode::ResolvingStyle) 641 element->setStyleIsAffectedByPreviousSibling(); 642 643 int count = 1 + countElementsBefore(element, context.resolvingMode == Mode::ResolvingStyle); 630 644 if (context.resolvingMode == Mode::ResolvingStyle) { 631 645 RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle(); … … 633 647 if (childStyle) 634 648 childStyle->setUnique(); 635 parentElement->setChildrenAffectedByForwardPositionalRules();636 649 } 637 650 … … 643 656 if (!selector->parseNth()) 644 657 break; 645 if (Element* parentElement = element->parentElement()) { 646 int count = 1 + countElementsOfTypeBefore(element, element->tagQName());658 659 if (element->parentElement()) { 647 660 if (context.resolvingMode == Mode::ResolvingStyle) 648 parentElement->setChildrenAffectedByForwardPositionalRules(); 649 661 element->setStyleIsAffectedByPreviousSibling(); 662 663 int count = 1 + countElementsOfTypeBefore(element, element->tagQName(), context.resolvingMode == Mode::ResolvingStyle); 650 664 if (selector->matchNth(count)) 651 665 return true; -
trunk/Source/WebCore/css/StyleResolver.cpp
r173217 r173229 625 625 if (element->additionalPresentationAttributeStyle() != state.styledElement()->additionalPresentationAttributeStyle()) 626 626 return false; 627 if (element->affectsNextSiblingElementStyle() || element->styleIsAffectedByPreviousSibling()) 628 return false; 627 629 628 630 if (element->hasID() && m_ruleSets.features().idsInRules.contains(element->idForStyleResolution().impl())) -
trunk/Source/WebCore/cssjit/SelectorCompiler.cpp
r172933 r173229 225 225 void generateDirectAdjacentTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment&); 226 226 void generateIndirectAdjacentTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment&); 227 void markParentElementIfResolvingStyle(int32_t);228 void markParentElementIfResolvingStyle(JSC::FunctionPtr);229 227 230 228 void linkFailures(Assembler::JumpList& globalFailureCases, BacktrackingAction, Assembler::JumpList& localFailureCases); … … 274 272 void generateRequestedPseudoElementEqualsToSelectorPseudoElement(Assembler::JumpList& failureCases, const SelectorFragment&, Assembler::RegisterID checkingContext); 275 273 void generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(Assembler::JumpList& failureCases, const SelectorFragment&); 274 void markElementIfResolvingStyle(Assembler::RegisterID, int32_t); 276 275 Assembler::JumpList jumpIfNoPreviousAdjacentElement(); 277 276 Assembler::JumpList jumpIfNoNextAdjacentElement(); … … 1340 1339 } 1341 1340 1341 static bool isAdjacentRelation(FragmentRelation relation) 1342 { 1343 return relation == FragmentRelation::DirectAdjacent || relation == FragmentRelation::IndirectAdjacent; 1344 } 1345 1346 static bool shouldMarkStyleIsAffectedByPreviousSibling(const SelectorFragment& fragment) 1347 { 1348 return isAdjacentRelation(fragment.relationToLeftFragment) && !isAdjacentRelation(fragment.relationToRightFragment); 1349 } 1350 1342 1351 void SelectorCodeGenerator::generateSelectorChecker() 1343 1352 { … … 1402 1411 break; 1403 1412 } 1413 if (shouldMarkStyleIsAffectedByPreviousSibling(fragment)) 1414 markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling()); 1404 1415 generateBacktrackingTailsIfNeeded(failureCases, fragment); 1405 1416 } … … 1561 1572 void SelectorCodeGenerator::generateDirectAdjacentTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment& fragment) 1562 1573 { 1563 markParentElementIfResolvingStyle(Node::flagChildrenAffectedByDirectAdjacentRulesFlag());1564 1565 1574 generateWalkToPreviousAdjacent(failureCases, fragment); 1575 markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle()); 1566 1576 1567 1577 Assembler::JumpList matchingTagNameFailureCases; … … 1579 1589 void SelectorCodeGenerator::generateIndirectAdjacentTreeWalker(Assembler::JumpList& failureCases, const SelectorFragment& fragment) 1580 1590 { 1581 markParentElementIfResolvingStyle(Element::setChildrenAffectedByForwardPositionalRules);1582 1583 1591 Assembler::Label loopStart(m_assembler.label()); 1584 1592 … … 1587 1595 1588 1596 generateWalkToPreviousAdjacent(failureCases, fragment); 1597 markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle()); 1589 1598 1590 1599 if (fragment.backtrackingFlags & BacktrackingFlag::IndirectAdjacentEntryPoint) … … 1828 1837 } 1829 1838 1830 void SelectorCodeGenerator::mark ParentElementIfResolvingStyle(int32_t nodeFlag)1839 void SelectorCodeGenerator::markElementIfResolvingStyle(Assembler::RegisterID element, int32_t nodeFlag) 1831 1840 { 1832 1841 if (m_selectorContext == SelectorContext::QuerySelector) … … 1839 1848 } 1840 1849 1841 LocalRegister parentElement(m_registerAllocator); 1842 generateWalkToParentElement(skipMarking, parentElement); 1843 1844 setNodeFlag(m_assembler, parentElement, nodeFlag); 1850 setNodeFlag(m_assembler, element, nodeFlag); 1845 1851 1846 1852 skipMarking.link(&m_assembler); 1847 1853 } 1848 1849 void SelectorCodeGenerator::markParentElementIfResolvingStyle(JSC::FunctionPtr markingFunction)1850 {1851 if (m_selectorContext == SelectorContext::QuerySelector)1852 return;1853 1854 // if (checkingContext.resolvingMode == ResolvingStyle) {1855 // Element* parent = element->parentNode();1856 // markingFunction(parent);1857 // }1858 1859 Assembler::JumpList skipMarking;1860 {1861 LocalRegister checkingContext(m_registerAllocator);1862 skipMarking.append(jumpIfNotResolvingStyle(checkingContext));1863 }1864 1865 // Get the parent element in a temporary register.1866 Assembler::RegisterID parentElement = m_registerAllocator.allocateRegister();1867 generateWalkToParentElement(skipMarking, parentElement);1868 1869 // Return the register parentElement just before the function call since we don't need it to be preserved1870 // on the stack.1871 m_registerAllocator.deallocateRegister(parentElement);1872 1873 // Invoke the marking function on the parent element.1874 FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);1875 functionCall.setFunctionAddress(markingFunction);1876 functionCall.setOneArgument(parentElement);1877 functionCall.call();1878 1879 skipMarking.link(&m_assembler);1880 }1881 1882 1854 1883 1855 void SelectorCodeGenerator::linkFailures(Assembler::JumpList& globalFailureCases, BacktrackingAction backtrackingAction, Assembler::JumpList& localFailureCases) … … 2944 2916 void SelectorCodeGenerator::generateElementIsNthChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment) 2945 2917 { 2946 Assembler::RegisterID parentElement = m_registerAllocator.allocateRegister(); 2947 generateWalkToParentElement(failureCases, parentElement); 2918 { 2919 LocalRegister parentElement(m_registerAllocator); 2920 generateWalkToParentElement(failureCases, parentElement); 2921 } 2948 2922 2949 2923 Vector<std::pair<int, int>, 32> validSubsetFilters; … … 2958 2932 validSubsetFilters.uncheckedAppend(slot); 2959 2933 } 2960 if (validSubsetFilters.isEmpty()) { 2961 m_registerAllocator.deallocateRegister(parentElement); 2934 if (validSubsetFilters.isEmpty()) 2962 2935 return; 2963 } 2964 if ( m_selectorContext == SelectorContext::QuerySelector)2965 m _registerAllocator.deallocateRegister(parentElement);2936 2937 if (!isAdjacentRelation(fragment.relationToRightFragment)) 2938 markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling()); 2966 2939 2967 2940 // Setup the counter at 1. … … 2981 2954 Assembler::JumpList noCachedChildIndexCases; 2982 2955 generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling); 2956 markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle()); 2983 2957 noCachedChildIndexCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(previousSibling, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagHasRareData()))); 2984 2958 { … … 2996 2970 Assembler::Label loopStart = m_assembler.label(); 2997 2971 generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling); 2972 markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle()); 2998 2973 m_assembler.add32(Assembler::TrustedImm32(1), elementCounter); 2999 2974 m_assembler.jump().linkTo(loopStart, &m_assembler); … … 3005 2980 LocalRegister checkingContext(m_registerAllocator); 3006 2981 Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext); 3007 3008 m_registerAllocator.deallocateRegister(parentElement);3009 FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);3010 functionCall.setFunctionAddress(Element::setChildrenAffectedByForwardPositionalRules);3011 functionCall.setOneArgument(parentElement);3012 functionCall.call();3013 2982 3014 2983 if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) { -
trunk/Source/WebCore/dom/Document.cpp
r173066 r173229 6155 6155 return true; 6156 6156 6157 for (const Element* ancestor = node.parentOrShadowHostElement(); ancestor; ancestor = ancestor->parentOrShadowHostElement()) { 6157 const Node* currentNode = &node; 6158 const Element* ancestor = currentNode->parentOrShadowHostElement(); 6159 while (ancestor) { 6158 6160 if (ancestor->needsStyleRecalc()) 6159 6161 return true; 6160 6162 6161 if (ancestor->directChildNeedsStyleRecalc() && (ancestor->childrenAffectedByDirectAdjacentRules() || ancestor->childrenAffectedByForwardPositionalRules()))6163 if (ancestor->directChildNeedsStyleRecalc() && currentNode->styleIsAffectedByPreviousSibling()) 6162 6164 return true; 6165 6166 currentNode = ancestor; 6167 ancestor = currentNode->parentOrShadowHostElement(); 6163 6168 } 6164 6169 return false; -
trunk/Source/WebCore/dom/Element.cpp
r173012 r173229 1541 1541 // :empty selector. 1542 1542 checkForEmptyStyleChange(*parent); 1543 1544 if (parent-> needsStyleRecalc() && parent->childrenAffectedByPositionalRules())1543 1544 if (parent->styleChangeType() >= FullStyleChange) 1545 1545 return; 1546 1546 … … 1589 1589 } 1590 1590 1591 // The + selector. We need to invalidate the first element following the insertion point. It is the only possible element 1592 // that could be affected by this DOM change. 1593 if (parent->childrenAffectedByDirectAdjacentRules() && elementAfterChange) 1594 elementAfterChange->setNeedsStyleRecalc(); 1595 1596 // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type. 1591 if (elementAfterChange) { 1592 if (elementAfterChange->styleIsAffectedByPreviousSibling()) 1593 elementAfterChange->setNeedsStyleRecalc(); 1594 else if (elementAfterChange->affectsNextSiblingElementStyle()) { 1595 Element* elementToInvalidate = elementAfterChange; 1596 do { 1597 elementToInvalidate = elementToInvalidate->nextElementSibling(); 1598 } while (elementToInvalidate && !elementToInvalidate->styleIsAffectedByPreviousSibling()); 1599 1600 if (elementToInvalidate) 1601 elementToInvalidate->setNeedsStyleRecalc(); 1602 } 1603 } 1604 1597 1605 // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type. 1598 1606 // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the … … 1601 1609 // 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 1602 1610 // here. recalcStyle will then force a walk of the children when it sees that this has happened. 1603 if (parent->childrenAffectedByForwardPositionalRules() && elementAfterChange)1604 parent->setNeedsStyleRecalc();1605 1611 if (parent->childrenAffectedByBackwardPositionalRules() && elementBeforeChange) 1606 1612 parent->setNeedsStyleRecalc(); … … 2109 2115 } 2110 2116 2111 void Element::setChildrenAffectedByForwardPositionalRules(Element* element)2112 {2113 element->ensureElementRareData().setChildrenAffectedByForwardPositionalRules(true);2114 }2115 2116 2117 void Element::setChildrenAffectedByBackwardPositionalRules() 2117 2118 { … … 2129 2130 bool Element::hasFlagsSetDuringStylingOfChildren() const 2130 2131 { 2131 if (childrenAffectedByHover() || childrenAffectedByFirstChildRules() || childrenAffectedByLastChildRules() || childrenAffectedByDirectAdjacentRules())2132 if (childrenAffectedByHover() || childrenAffectedByFirstChildRules() || childrenAffectedByLastChildRules()) 2132 2133 return true; 2133 2134 … … 2136 2137 return rareDataChildrenAffectedByActive() 2137 2138 || rareDataChildrenAffectedByDrag() 2138 || rareDataChildrenAffectedByForwardPositionalRules()2139 2139 || rareDataChildrenAffectedByBackwardPositionalRules(); 2140 2140 } … … 2156 2156 ASSERT(hasRareData()); 2157 2157 return elementRareData()->childrenAffectedByDrag(); 2158 }2159 2160 bool Element::rareDataChildrenAffectedByForwardPositionalRules() const2161 {2162 ASSERT(hasRareData());2163 return elementRareData()->childrenAffectedByForwardPositionalRules();2164 2158 } 2165 2159 -
trunk/Source/WebCore/dom/Element.h
r173176 r173229 361 361 bool childrenAffectedByActive() const { return hasRareData() && rareDataChildrenAffectedByActive(); } 362 362 bool childrenAffectedByDrag() const { return hasRareData() && rareDataChildrenAffectedByDrag(); } 363 bool childrenAffectedByPositionalRules() const { return hasRareData() && (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); }364 363 bool childrenAffectedByFirstChildRules() const { return getFlag(ChildrenAffectedByFirstChildRulesFlag); } 365 364 bool childrenAffectedByLastChildRules() const { return getFlag(ChildrenAffectedByLastChildRulesFlag); } 366 bool childrenAffectedByDirectAdjacentRules() const { return getFlag(ChildrenAffectedByDirectAdjacentRulesFlag); }367 bool childrenAffectedByForwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByForwardPositionalRules(); }368 365 bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() && rareDataChildrenAffectedByBackwardPositionalRules(); } 366 bool affectsNextSiblingElementStyle() const { return getFlag(AffectsNextSiblingElementStyle); } 369 367 unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; } 370 368 … … 377 375 void setChildrenAffectedByFirstChildRules() { setFlag(ChildrenAffectedByFirstChildRulesFlag); } 378 376 void setChildrenAffectedByLastChildRules() { setFlag(ChildrenAffectedByLastChildRulesFlag); } 379 void setChildrenAffectedByDirectAdjacentRules() { setFlag(ChildrenAffectedByDirectAdjacentRulesFlag); }380 static void setChildrenAffectedByForwardPositionalRules(Element*);381 void setChildrenAffectedByForwardPositionalRules() { setChildrenAffectedByForwardPositionalRules(this); }382 377 void setChildrenAffectedByBackwardPositionalRules(); 378 void setAffectsNextSiblingElementStyle() { setFlag(AffectsNextSiblingElementStyle); } 379 void setStyleIsAffectedByPreviousSibling() { setFlag(StyleIsAffectedByPreviousSibling); } 383 380 void setChildIndex(unsigned); 384 381 … … 651 648 bool rareDataChildrenAffectedByDrag() const; 652 649 bool rareDataChildrenAffectedByLastChildRules() const; 653 bool rareDataChildrenAffectedByForwardPositionalRules() const;654 650 bool rareDataChildrenAffectedByBackwardPositionalRules() const; 655 651 unsigned rareDataChildIndex() const; -
trunk/Source/WebCore/dom/ElementRareData.h
r172880 r173229 76 76 bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; } 77 77 void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; } 78 bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }79 void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; }80 78 bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; } 81 79 void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; } … … 133 131 // *-child-of-type, we will just give up and re-evaluate whenever children change at all. 134 132 unsigned m_childrenAffectedByLastChildRules : 1; 135 unsigned m_childrenAffectedByForwardPositionalRules : 1;136 133 unsigned m_childrenAffectedByBackwardPositionalRules : 1; 137 134 … … 174 171 , m_childrenAffectedByDrag(false) 175 172 , m_childrenAffectedByLastChildRules(false) 176 , m_childrenAffectedByForwardPositionalRules(false)177 173 , m_childrenAffectedByBackwardPositionalRules(false) 178 174 , m_regionOversetState(RegionUndefined) … … 212 208 setChildrenAffectedByDrag(false); 213 209 setChildrenAffectedByLastChildRules(false); 214 setChildrenAffectedByForwardPositionalRules(false);215 210 setChildrenAffectedByBackwardPositionalRules(false); 216 211 } -
trunk/Source/WebCore/dom/Node.h
r173047 r173229 326 326 StyleChangeType styleChangeType() const { return static_cast<StyleChangeType>(m_nodeFlags & StyleChangeMask); } 327 327 bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); } 328 bool styleIsAffectedByPreviousSibling() const { return getFlag(StyleIsAffectedByPreviousSibling); } 328 329 bool isLink() const { return getFlag(IsLinkFlag); } 329 330 bool isEditingText() const { return getFlag(IsEditingTextFlag); } … … 579 580 static int32_t flagChildrenAffectedByFirstChildRulesFlag() { return ChildrenAffectedByFirstChildRulesFlag; } 580 581 static int32_t flagChildrenAffectedByLastChildRulesFlag() { return ChildrenAffectedByLastChildRulesFlag; } 581 static int32_t flagChildrenAffectedByDirectAdjacentRulesFlag() { return ChildrenAffectedByDirectAdjacentRulesFlag; } 582 583 static int32_t flagAffectsNextSiblingElementStyle() { return AffectsNextSiblingElementStyle; } 584 static int32_t flagStyleIsAffectedByPreviousSibling() { return StyleIsAffectedByPreviousSibling; } 582 585 #endif // ENABLE(CSS_SELECTOR_JIT) 583 586 … … 613 616 ChildrenAffectedByFirstChildRulesFlag = 1 << 25, 614 617 ChildrenAffectedByLastChildRulesFlag = 1 << 26, 615 ChildrenAffectedBy DirectAdjacentRulesFlag = 1 << 27,616 ChildrenAffectedByHoverRulesFlag = 1 << 28, 617 DirectChildNeedsStyleRecalcFlag = 1 << 2 9,618 619 S elfOrAncestorHasDirAutoFlag = 1 << 30,620 621 IsHTMLUnknownElementFlag = 1 << 31,618 ChildrenAffectedByHoverRulesFlag = 1 << 27, 619 620 DirectChildNeedsStyleRecalcFlag = 1 << 28, 621 AffectsNextSiblingElementStyle = 1 << 29, 622 StyleIsAffectedByPreviousSibling = 1 << 30, 623 624 SelfOrAncestorHasDirAutoFlag = 1 << 31, 622 625 623 626 DefaultNodeFlags = IsParsingChildrenFinishedFlag … … 643 646 CreateInsertionPoint = CreateHTMLElement | NeedsNodeRenderingTraversalSlowPathFlag, 644 647 CreateEditingText = CreateText | IsEditingTextFlag, 645 CreateMathMLElement = CreateStyledElement | IsMathMLFlag, 646 CreateHTMLUnknownElement = CreateHTMLElement | IsHTMLUnknownElementFlag, 648 CreateMathMLElement = CreateStyledElement | IsMathMLFlag 647 649 }; 648 650 Node(Document&, ConstructionType); -
trunk/Source/WebCore/html/HTMLElement.h
r172862 r173229 89 89 TextDirection directionalityIfhasDirAutoAttribute(bool& isAuto) const; 90 90 91 bool isHTMLUnknownElement() const { return getFlag(IsHTMLUnknownElementFlag); }91 virtual bool isHTMLUnknownElement() const { return false; } 92 92 virtual bool isTextControlInnerTextElement() const { return false; } 93 93 -
trunk/Source/WebCore/html/HTMLUnknownElement.h
r166841 r173229 42 42 } 43 43 44 virtual bool isHTMLUnknownElement() const override { return true; } 45 44 46 private: 45 47 HTMLUnknownElement(const QualifiedName& tagName, Document& document) 46 : HTMLElement(tagName, document, CreateHTML UnknownElement)48 : HTMLElement(tagName, document, CreateHTMLElement) 47 49 { 48 50 } -
trunk/Source/WebCore/style/StyleResolveTree.cpp
r172985 r173229 553 553 { 554 554 ASSERT(!current.renderer()); 555 bool shouldInvalidateDirectChildren = current.directChildNeedsStyleRecalc() && (current.childrenAffectedByDirectAdjacentRules() || current.childrenAffectedByForwardPositionalRules());555 bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false; 556 556 for (auto& child : childrenOfType<Element>(current)) { 557 557 ASSERT(!child.renderer()); 558 if (shouldInvalidateDirectChildren || child.needsStyleRecalc()) { 558 if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) { 559 if (child.styleIsAffectedByPreviousSibling()) 560 child.setNeedsStyleRecalc(); 561 elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle(); 562 } 563 564 if (child.needsStyleRecalc()) { 559 565 child.resetComputedStyle(); 560 566 child.clearNeedsStyleRecalc(); 561 } 567 elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle(); 568 } 569 562 570 if (child.childNeedsStyleRecalc()) { 563 571 resetStyleForNonRenderedDescendants(child); … … 898 906 } 899 907 900 bool hasDirectAdjacentRules = current.childrenAffectedByDirectAdjacentRules();901 bool hasIndirectAdjacentRules = current.childrenAffectedByForwardPositionalRules();902 903 908 #if PLATFORM(IOS) 904 909 CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(¤t, current.renderStyle()); … … 926 931 updateBeforeOrAfterPseudoElement(current, change, BEFORE, childRenderTreePosition); 927 932 928 // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar. 929 // For now we will just worry about the common case, since it's a lot trickier to get the second case right 930 // without doing way too much re-resolution. 931 bool forceCheckOfNextElementSibling = false; 932 bool forceCheckOfAnyElementSibling = false; 933 bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false; 933 934 for (Node* child = current.firstChild(); child; child = child->nextSibling()) { 934 935 if (RenderObject* childRenderer = child->renderer()) … … 940 941 if (!child->isElementNode()) 941 942 continue; 943 942 944 Element* childElement = toElement(child); 943 bool childRulesChanged = childElement->needsStyleRecalc() && childElement->styleChangeType() == FullStyleChange; 944 if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling)) 945 childElement->setNeedsStyleRecalc(); 945 if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) { 946 if (childElement->styleIsAffectedByPreviousSibling()) 947 childElement->setNeedsStyleRecalc(); 948 elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement->affectsNextSiblingElementStyle(); 949 } else if (childElement->styleChangeType() >= FullStyleChange) 950 elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement->affectsNextSiblingElementStyle(); 946 951 if (change >= Inherit || childElement->childNeedsStyleRecalc() || childElement->needsStyleRecalc()) { 947 952 parentPusher.push(); 948 953 resolveTree(*childElement, renderer->style(), childRenderTreePosition, change); 949 954 } 950 forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;951 forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);952 955 } 953 956
Note: See TracChangeset
for help on using the changeset viewer.