Style invalidation does not work for adjacent node updates
https://bugs.webkit.org/show_bug.cgi?id=136145
Reviewed by Antti Koivisto.
Source/WebCore:
There were a bunch of cases in which the style would be in an inconsistent
state until the style resolver kicks in for the entire document.
For example, let's take the selector "foo.bar + target". When the class "bar"
changes, the element foo is invalidated. The element target is untouched.
Now, if the style of "target" is accessed, nodeOrItsAncestorNeedsStyleRecalc()
returns false and the old style is accessed.
At some point, when the style of the entire document is resolved, the node
"foo" is styled, and "target" is invalidated.
To fix the issue, this patch adds an extra flag keeping track of subtrees that
have any node needing style recalc: DirectChildNeedsStyleRecalcFlag.
When invalidating the node "foo", its parent is marked with
DirectChildNeedsStyleRecalcFlag to note that one of the child nodes has an invalid style.
When verifying the style state in nodeOrItsAncestorNeedsStyleRecalc(), we check that flag
in addition to the siblings dependencies to find if the node is part of a subtree that may
be invalid due to sibling selectors.
Similarly, in the style resolver, we use the flag to clear the style on all elements
that could potentially be invalid.
This patch removes the changes introduced by r172721
(The style is not updated correctly when the pseudo class :empty is applied on anything but the rightmost element).
That bug was just a special case of what is solved here.
Tests: fast/selectors/attribute-direct-adjacent-style-update.html
fast/selectors/attribute-sibling-style-update.html
fast/selectors/class-direct-adjacent-style-update.html
fast/selectors/class-sibling-style-update.html
fast/selectors/first-child-direct-adjacent-style-update.html
fast/selectors/first-child-sibling-style-update.html
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsEmpty):
(WebCore::SelectorCompiler::setStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/ContainerNode.h:
(WebCore::ContainerNode::directChildNeedsStyleRecalc):
(WebCore::ContainerNode::setDirectChildNeedsStyleRecalc):
Remove the special case for :empty.
* dom/Document.cpp:
(WebCore::nodeOrItsAncestorNeedsStyleRecalc):
* dom/Element.cpp:
(WebCore::checkForEmptyStyleChange):
(WebCore::checkForSiblingStyleChanges):
(WebCore::Element::setStyleOfSiblingsAffectedByEmpty): Deleted.
(WebCore::Element::rareDataStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/Element.h:
(WebCore::Element::styleOfSiblingsAffectedByEmpty): Deleted.
* dom/ElementRareData.h:
(WebCore::ElementRareData::ElementRareData):
(WebCore::ElementRareData::styleOfSiblingsAffectedByEmpty): Deleted.
(WebCore::ElementRareData::setStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/Node.cpp:
(WebCore::markAncestorsWithChildNeedsStyleRecalc):
(WebCore::Node::setNeedsStyleRecalc):
(WebCore::Node::markAncestorsWithChildNeedsStyleRecalc): Deleted.
* dom/Node.h:
(WebCore::Node::clearChildNeedsStyleRecalc):
* style/StyleResolveTree.cpp:
(WebCore::Style::resetStyleForNonRenderedDescendants):
LayoutTests:
Add tests covering the basic cases: classes and attributes.
First-child covers the basic positional updates.
The tests have a version without any indirect adjacent ("~") because the marking
used for those is much more generic and having them hide some bugs.
Some tests are still failing. That is due to the style resolver not handling
direct siblings ("+") correctly when there are multiple of them. I will address
that separately.
* fast/selectors/attribute-direct-adjacent-style-update-expected.txt: Added.
* fast/selectors/attribute-direct-adjacent-style-update.html: Added.
* fast/selectors/attribute-sibling-style-update-expected.txt: Added.
* fast/selectors/attribute-sibling-style-update.html: Added.
* fast/selectors/class-direct-adjacent-style-update-expected.txt: Added.
* fast/selectors/class-direct-adjacent-style-update.html: Added.
* fast/selectors/class-sibling-style-update-expected.txt: Added.
* fast/selectors/class-sibling-style-update.html: Added.
* fast/selectors/first-child-direct-adjacent-style-update.html: Added.
* fast/selectors/first-child-sibling-style-update-expected.txt: Added.
* fast/selectors/first-child-sibling-style-update.html: Added.
* fast/selectors/placeholder-shown-sibling-style-update-expected.txt:
Canonical link: https://commits.webkit.org/154010@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@172880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-08-23 04:30:33 +00:00
|
|
|
Test style update caused by class changes on a sibling. This test does not use any sibling "~" combinator to avoid its more generic marking.
|
|
|
|
|
|
|
|
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
|
|
|
|
|
|
|
|
|
|
|
|
Initial state does not match, the class is not there.
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
Adding the class, the extra rules should match.
|
Fix style invalidation of elements with multiple siblings dependencies
https://bugs.webkit.org/show_bug.cgi?id=136472
Reviewed by Andreas Kling.
Source/WebCore:
Previously, style invalidation of siblings was driven by a pair of flags:
-ChildrenAffectedByDirectAdjacentRules.
-ChildrenAffectedByForwardPositionalRules.
When ChildrenAffectedByDirectAdjacentRules was set, the element after an element
with "needsStyleRecalc" was also recomputed. While this work for pair of elements:
a + b
It does not work for more than that. For example, with
a.propery + b + c
When the state of <a> changes, the style of <b> was updated, which is useless. The style
of <c> was untouched, which is incorrect.
When ChildrenAffectedByForwardPositionalRules, all elements after one with "needsStyleRecalc"
were invalidated. While more correct, it caused avalanche of style recalc and was not a very
useful "optimization".
To fix the correctness issues (e.g. "a + b + c"), I could have gone two ways:
1) Invalidate the parent of a, b, c. The children would always get a correct style
when their parent's style would be resolved.
2) Create invalidation relations to enforce that the right siblings are invalidated.
I have decided for a weak version of (2). The reason is that most DOM trees are very
shallow while being very wide. Invalidating the parent generally causes massive style
recalculation.
To keep things simple for now, there is no explicit dependency list between siblings.
Instead, each element has a pair of flag:
1) The element's style depends on the state of a previous sibling.
2) The element's state affects following siblings.
With the notation "<-" for (1), "->" for (2), the selector "a + b + c" create this kind
of marking:
a + b + c
-> ->
<-
When <a> is invalidated, the style resolver will go through the chain of dependent elements
and invalidate any element that can be affected by a prior invalidation, here <c>.
Overlaps are possible. For example with the two selector, "a + b + c", "b ~ d"
the marking would be
a + b + c + d
-> -> ->
<- <-
A change in <a> would invalidate both <c> and <d>. This is overkill, but the end result
is correct and it is a net improvement over the previous flags.
As usual, the CSS JIT makes an effort at compile time to reduce tree marking. SelectorChecker
marks everything as usual.
Tests: fast/css/direct-adjacent-style-update-optimization.html
fast/css/indirect-adjacent-style-update-optimization.html
fast/css/non-matching-adjacent-style-update.html
fast/selectors/first-of-type-direct-adjacent-style-update.html
fast/selectors/first-of-type-sibling-style-update.html
fast/selectors/id-direct-adjacent-style-update.html
fast/selectors/id-sibling-style-update.html
fast/selectors/nth-child-as-first-simple-selector-style-update.html
fast/selectors/nth-child-direct-adjacent-style-update.html
fast/selectors/nth-child-style-update.html
* css/SelectorChecker.cpp:
(WebCore::isFirstOfType):
(WebCore::countElementsBefore):
(WebCore::countElementsOfTypeBefore):
Counting selectors are not unlike adjacent combinators, they are handled the exact same way.
For example a :nth-child(4) would generate somewhat similar marking as
:first-child + * + * + *
Everything prior to the element with the counter affects the style of the element.
(WebCore::hasScrollbarPseudoElement):
The assertion was incorrect. You can get an scrollbar pseudo ID on an element without scrollbar.
It will never match, but such case is possible.
(WebCore::SelectorChecker::matchRecursively):
(WebCore::SelectorChecker::checkOne):
* css/StyleResolver.cpp:
(WebCore::StyleResolver::canShareStyleWithElement):
Previously, any subtree affected by sibling selectors were unshareable. That was done by checking
for Element::hasFlagsSetDuringStylingOfChildren().
Now that sibling relation are local, they no longer prevent sharing of all children. Instead, we can
test locally for subgroup with sibling relations.
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::isAdjacentRelation):
(WebCore::SelectorCompiler::shouldMarkStyleIsAffectedByPreviousSibling):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::markElementIfResolvingStyle):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild):
(WebCore::SelectorCompiler::SelectorCodeGenerator::markParentElementIfResolvingStyle): Deleted.
* dom/Document.cpp:
(WebCore::nodeOrItsAncestorNeedsStyleRecalc):
* dom/Element.cpp:
(WebCore::checkForSiblingStyleChanges):
(WebCore::Element::hasFlagsSetDuringStylingOfChildren):
(WebCore::Element::setChildrenAffectedByForwardPositionalRules): Deleted.
(WebCore::Element::rareDataChildrenAffectedByForwardPositionalRules): Deleted.
* dom/Element.h:
(WebCore::Element::affectsNextSiblingElementStyle):
(WebCore::Element::setAffectsNextSiblingElementStyle):
(WebCore::Element::setStyleIsAffectedByPreviousSibling):
(WebCore::Element::childrenAffectedByPositionalRules): Deleted.
(WebCore::Element::childrenAffectedByDirectAdjacentRules): Deleted.
(WebCore::Element::childrenAffectedByForwardPositionalRules): Deleted.
(WebCore::Element::setChildrenAffectedByDirectAdjacentRules): Deleted.
(WebCore::Element::setChildrenAffectedByForwardPositionalRules): Deleted.
* dom/ElementRareData.h:
(WebCore::ElementRareData::ElementRareData):
(WebCore::ElementRareData::resetDynamicRestyleObservations):
(WebCore::ElementRareData::childrenAffectedByForwardPositionalRules): Deleted.
(WebCore::ElementRareData::setChildrenAffectedByForwardPositionalRules): Deleted.
* dom/Node.h:
(WebCore::Node::styleIsAffectedByPreviousSibling):
(WebCore::Node::flagAffectsNextSiblingElementStyle):
(WebCore::Node::flagStyleIsAffectedByPreviousSibling):
(WebCore::Node::flagChildrenAffectedByDirectAdjacentRulesFlag): Deleted.
* html/HTMLElement.h:
(WebCore::HTMLElement::isHTMLUnknownElement):
* html/HTMLUnknownElement.h:
* style/StyleResolveTree.cpp:
(WebCore::Style::resetStyleForNonRenderedDescendants):
(WebCore::Style::resolveTree):
LayoutTests:
The test coverage was pretty bad. :(
I tried to cover the most obvious problems.
* fast/css/direct-adjacent-style-update-optimization-expected.txt: Added.
* fast/css/direct-adjacent-style-update-optimization.html: Added.
* fast/css/indirect-adjacent-style-update-optimization-expected.txt: Added.
* fast/css/indirect-adjacent-style-update-optimization.html: Added.
* fast/css/non-matching-adjacent-style-update-expected.txt: Added.
* fast/css/non-matching-adjacent-style-update.html: Added.
* fast/selectors/attribute-direct-adjacent-style-update-expected.txt:
* fast/selectors/class-direct-adjacent-style-update-expected.txt:
* fast/selectors/first-child-direct-adjacent-style-update-expected.txt:
* fast/selectors/first-of-type-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt.
* fast/selectors/first-of-type-direct-adjacent-style-update.html: Added.
* fast/selectors/first-of-type-sibling-style-update-expected.txt: Added.
* fast/selectors/first-of-type-sibling-style-update.html: Added.
* fast/selectors/id-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt.
* fast/selectors/id-direct-adjacent-style-update.html: Added.
* fast/selectors/id-sibling-style-update-expected.txt: Added.
* fast/selectors/id-sibling-style-update.html: Added.
* fast/selectors/nth-child-as-first-simple-selector-style-update-expected.txt: Added.
* fast/selectors/nth-child-as-first-simple-selector-style-update.html: Added.
* fast/selectors/nth-child-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt.
* fast/selectors/nth-child-direct-adjacent-style-update.html: Added.
* fast/selectors/nth-child-style-update-expected.txt: Added.
* fast/selectors/nth-child-style-update.html: Added.
Canonical link: https://commits.webkit.org/154293@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173229 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-09-03 21:30:31 +00:00
|
|
|
PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
|
Style invalidation does not work for adjacent node updates
https://bugs.webkit.org/show_bug.cgi?id=136145
Reviewed by Antti Koivisto.
Source/WebCore:
There were a bunch of cases in which the style would be in an inconsistent
state until the style resolver kicks in for the entire document.
For example, let's take the selector "foo.bar + target". When the class "bar"
changes, the element foo is invalidated. The element target is untouched.
Now, if the style of "target" is accessed, nodeOrItsAncestorNeedsStyleRecalc()
returns false and the old style is accessed.
At some point, when the style of the entire document is resolved, the node
"foo" is styled, and "target" is invalidated.
To fix the issue, this patch adds an extra flag keeping track of subtrees that
have any node needing style recalc: DirectChildNeedsStyleRecalcFlag.
When invalidating the node "foo", its parent is marked with
DirectChildNeedsStyleRecalcFlag to note that one of the child nodes has an invalid style.
When verifying the style state in nodeOrItsAncestorNeedsStyleRecalc(), we check that flag
in addition to the siblings dependencies to find if the node is part of a subtree that may
be invalid due to sibling selectors.
Similarly, in the style resolver, we use the flag to clear the style on all elements
that could potentially be invalid.
This patch removes the changes introduced by r172721
(The style is not updated correctly when the pseudo class :empty is applied on anything but the rightmost element).
That bug was just a special case of what is solved here.
Tests: fast/selectors/attribute-direct-adjacent-style-update.html
fast/selectors/attribute-sibling-style-update.html
fast/selectors/class-direct-adjacent-style-update.html
fast/selectors/class-sibling-style-update.html
fast/selectors/first-child-direct-adjacent-style-update.html
fast/selectors/first-child-sibling-style-update.html
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsEmpty):
(WebCore::SelectorCompiler::setStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/ContainerNode.h:
(WebCore::ContainerNode::directChildNeedsStyleRecalc):
(WebCore::ContainerNode::setDirectChildNeedsStyleRecalc):
Remove the special case for :empty.
* dom/Document.cpp:
(WebCore::nodeOrItsAncestorNeedsStyleRecalc):
* dom/Element.cpp:
(WebCore::checkForEmptyStyleChange):
(WebCore::checkForSiblingStyleChanges):
(WebCore::Element::setStyleOfSiblingsAffectedByEmpty): Deleted.
(WebCore::Element::rareDataStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/Element.h:
(WebCore::Element::styleOfSiblingsAffectedByEmpty): Deleted.
* dom/ElementRareData.h:
(WebCore::ElementRareData::ElementRareData):
(WebCore::ElementRareData::styleOfSiblingsAffectedByEmpty): Deleted.
(WebCore::ElementRareData::setStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/Node.cpp:
(WebCore::markAncestorsWithChildNeedsStyleRecalc):
(WebCore::Node::setNeedsStyleRecalc):
(WebCore::Node::markAncestorsWithChildNeedsStyleRecalc): Deleted.
* dom/Node.h:
(WebCore::Node::clearChildNeedsStyleRecalc):
* style/StyleResolveTree.cpp:
(WebCore::Style::resetStyleForNonRenderedDescendants):
LayoutTests:
Add tests covering the basic cases: classes and attributes.
First-child covers the basic positional updates.
The tests have a version without any indirect adjacent ("~") because the marking
used for those is much more generic and having them hide some bugs.
Some tests are still failing. That is due to the style resolver not handling
direct siblings ("+") correctly when there are multiple of them. I will address
that separately.
* fast/selectors/attribute-direct-adjacent-style-update-expected.txt: Added.
* fast/selectors/attribute-direct-adjacent-style-update.html: Added.
* fast/selectors/attribute-sibling-style-update-expected.txt: Added.
* fast/selectors/attribute-sibling-style-update.html: Added.
* fast/selectors/class-direct-adjacent-style-update-expected.txt: Added.
* fast/selectors/class-direct-adjacent-style-update.html: Added.
* fast/selectors/class-sibling-style-update-expected.txt: Added.
* fast/selectors/class-sibling-style-update.html: Added.
* fast/selectors/first-child-direct-adjacent-style-update.html: Added.
* fast/selectors/first-child-sibling-style-update-expected.txt: Added.
* fast/selectors/first-child-sibling-style-update.html: Added.
* fast/selectors/placeholder-shown-sibling-style-update-expected.txt:
Canonical link: https://commits.webkit.org/154010@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@172880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-08-23 04:30:33 +00:00
|
|
|
PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)"
|
Fix style invalidation of elements with multiple siblings dependencies
https://bugs.webkit.org/show_bug.cgi?id=136472
Reviewed by Andreas Kling.
Source/WebCore:
Previously, style invalidation of siblings was driven by a pair of flags:
-ChildrenAffectedByDirectAdjacentRules.
-ChildrenAffectedByForwardPositionalRules.
When ChildrenAffectedByDirectAdjacentRules was set, the element after an element
with "needsStyleRecalc" was also recomputed. While this work for pair of elements:
a + b
It does not work for more than that. For example, with
a.propery + b + c
When the state of <a> changes, the style of <b> was updated, which is useless. The style
of <c> was untouched, which is incorrect.
When ChildrenAffectedByForwardPositionalRules, all elements after one with "needsStyleRecalc"
were invalidated. While more correct, it caused avalanche of style recalc and was not a very
useful "optimization".
To fix the correctness issues (e.g. "a + b + c"), I could have gone two ways:
1) Invalidate the parent of a, b, c. The children would always get a correct style
when their parent's style would be resolved.
2) Create invalidation relations to enforce that the right siblings are invalidated.
I have decided for a weak version of (2). The reason is that most DOM trees are very
shallow while being very wide. Invalidating the parent generally causes massive style
recalculation.
To keep things simple for now, there is no explicit dependency list between siblings.
Instead, each element has a pair of flag:
1) The element's style depends on the state of a previous sibling.
2) The element's state affects following siblings.
With the notation "<-" for (1), "->" for (2), the selector "a + b + c" create this kind
of marking:
a + b + c
-> ->
<-
When <a> is invalidated, the style resolver will go through the chain of dependent elements
and invalidate any element that can be affected by a prior invalidation, here <c>.
Overlaps are possible. For example with the two selector, "a + b + c", "b ~ d"
the marking would be
a + b + c + d
-> -> ->
<- <-
A change in <a> would invalidate both <c> and <d>. This is overkill, but the end result
is correct and it is a net improvement over the previous flags.
As usual, the CSS JIT makes an effort at compile time to reduce tree marking. SelectorChecker
marks everything as usual.
Tests: fast/css/direct-adjacent-style-update-optimization.html
fast/css/indirect-adjacent-style-update-optimization.html
fast/css/non-matching-adjacent-style-update.html
fast/selectors/first-of-type-direct-adjacent-style-update.html
fast/selectors/first-of-type-sibling-style-update.html
fast/selectors/id-direct-adjacent-style-update.html
fast/selectors/id-sibling-style-update.html
fast/selectors/nth-child-as-first-simple-selector-style-update.html
fast/selectors/nth-child-direct-adjacent-style-update.html
fast/selectors/nth-child-style-update.html
* css/SelectorChecker.cpp:
(WebCore::isFirstOfType):
(WebCore::countElementsBefore):
(WebCore::countElementsOfTypeBefore):
Counting selectors are not unlike adjacent combinators, they are handled the exact same way.
For example a :nth-child(4) would generate somewhat similar marking as
:first-child + * + * + *
Everything prior to the element with the counter affects the style of the element.
(WebCore::hasScrollbarPseudoElement):
The assertion was incorrect. You can get an scrollbar pseudo ID on an element without scrollbar.
It will never match, but such case is possible.
(WebCore::SelectorChecker::matchRecursively):
(WebCore::SelectorChecker::checkOne):
* css/StyleResolver.cpp:
(WebCore::StyleResolver::canShareStyleWithElement):
Previously, any subtree affected by sibling selectors were unshareable. That was done by checking
for Element::hasFlagsSetDuringStylingOfChildren().
Now that sibling relation are local, they no longer prevent sharing of all children. Instead, we can
test locally for subgroup with sibling relations.
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::isAdjacentRelation):
(WebCore::SelectorCompiler::shouldMarkStyleIsAffectedByPreviousSibling):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateSelectorChecker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateDirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateIndirectAdjacentTreeWalker):
(WebCore::SelectorCompiler::SelectorCodeGenerator::markElementIfResolvingStyle):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthChild):
(WebCore::SelectorCompiler::SelectorCodeGenerator::markParentElementIfResolvingStyle): Deleted.
* dom/Document.cpp:
(WebCore::nodeOrItsAncestorNeedsStyleRecalc):
* dom/Element.cpp:
(WebCore::checkForSiblingStyleChanges):
(WebCore::Element::hasFlagsSetDuringStylingOfChildren):
(WebCore::Element::setChildrenAffectedByForwardPositionalRules): Deleted.
(WebCore::Element::rareDataChildrenAffectedByForwardPositionalRules): Deleted.
* dom/Element.h:
(WebCore::Element::affectsNextSiblingElementStyle):
(WebCore::Element::setAffectsNextSiblingElementStyle):
(WebCore::Element::setStyleIsAffectedByPreviousSibling):
(WebCore::Element::childrenAffectedByPositionalRules): Deleted.
(WebCore::Element::childrenAffectedByDirectAdjacentRules): Deleted.
(WebCore::Element::childrenAffectedByForwardPositionalRules): Deleted.
(WebCore::Element::setChildrenAffectedByDirectAdjacentRules): Deleted.
(WebCore::Element::setChildrenAffectedByForwardPositionalRules): Deleted.
* dom/ElementRareData.h:
(WebCore::ElementRareData::ElementRareData):
(WebCore::ElementRareData::resetDynamicRestyleObservations):
(WebCore::ElementRareData::childrenAffectedByForwardPositionalRules): Deleted.
(WebCore::ElementRareData::setChildrenAffectedByForwardPositionalRules): Deleted.
* dom/Node.h:
(WebCore::Node::styleIsAffectedByPreviousSibling):
(WebCore::Node::flagAffectsNextSiblingElementStyle):
(WebCore::Node::flagStyleIsAffectedByPreviousSibling):
(WebCore::Node::flagChildrenAffectedByDirectAdjacentRulesFlag): Deleted.
* html/HTMLElement.h:
(WebCore::HTMLElement::isHTMLUnknownElement):
* html/HTMLUnknownElement.h:
* style/StyleResolveTree.cpp:
(WebCore::Style::resetStyleForNonRenderedDescendants):
(WebCore::Style::resolveTree):
LayoutTests:
The test coverage was pretty bad. :(
I tried to cover the most obvious problems.
* fast/css/direct-adjacent-style-update-optimization-expected.txt: Added.
* fast/css/direct-adjacent-style-update-optimization.html: Added.
* fast/css/indirect-adjacent-style-update-optimization-expected.txt: Added.
* fast/css/indirect-adjacent-style-update-optimization.html: Added.
* fast/css/non-matching-adjacent-style-update-expected.txt: Added.
* fast/css/non-matching-adjacent-style-update.html: Added.
* fast/selectors/attribute-direct-adjacent-style-update-expected.txt:
* fast/selectors/class-direct-adjacent-style-update-expected.txt:
* fast/selectors/first-child-direct-adjacent-style-update-expected.txt:
* fast/selectors/first-of-type-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt.
* fast/selectors/first-of-type-direct-adjacent-style-update.html: Added.
* fast/selectors/first-of-type-sibling-style-update-expected.txt: Added.
* fast/selectors/first-of-type-sibling-style-update.html: Added.
* fast/selectors/id-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt.
* fast/selectors/id-direct-adjacent-style-update.html: Added.
* fast/selectors/id-sibling-style-update-expected.txt: Added.
* fast/selectors/id-sibling-style-update.html: Added.
* fast/selectors/nth-child-as-first-simple-selector-style-update-expected.txt: Added.
* fast/selectors/nth-child-as-first-simple-selector-style-update.html: Added.
* fast/selectors/nth-child-direct-adjacent-style-update-expected.txt: Copied from LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt.
* fast/selectors/nth-child-direct-adjacent-style-update.html: Added.
* fast/selectors/nth-child-style-update-expected.txt: Added.
* fast/selectors/nth-child-style-update.html: Added.
Canonical link: https://commits.webkit.org/154293@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173229 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-09-03 21:30:31 +00:00
|
|
|
PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(4, 5, 6)"
|
Style invalidation does not work for adjacent node updates
https://bugs.webkit.org/show_bug.cgi?id=136145
Reviewed by Antti Koivisto.
Source/WebCore:
There were a bunch of cases in which the style would be in an inconsistent
state until the style resolver kicks in for the entire document.
For example, let's take the selector "foo.bar + target". When the class "bar"
changes, the element foo is invalidated. The element target is untouched.
Now, if the style of "target" is accessed, nodeOrItsAncestorNeedsStyleRecalc()
returns false and the old style is accessed.
At some point, when the style of the entire document is resolved, the node
"foo" is styled, and "target" is invalidated.
To fix the issue, this patch adds an extra flag keeping track of subtrees that
have any node needing style recalc: DirectChildNeedsStyleRecalcFlag.
When invalidating the node "foo", its parent is marked with
DirectChildNeedsStyleRecalcFlag to note that one of the child nodes has an invalid style.
When verifying the style state in nodeOrItsAncestorNeedsStyleRecalc(), we check that flag
in addition to the siblings dependencies to find if the node is part of a subtree that may
be invalid due to sibling selectors.
Similarly, in the style resolver, we use the flag to clear the style on all elements
that could potentially be invalid.
This patch removes the changes introduced by r172721
(The style is not updated correctly when the pseudo class :empty is applied on anything but the rightmost element).
That bug was just a special case of what is solved here.
Tests: fast/selectors/attribute-direct-adjacent-style-update.html
fast/selectors/attribute-sibling-style-update.html
fast/selectors/class-direct-adjacent-style-update.html
fast/selectors/class-sibling-style-update.html
fast/selectors/first-child-direct-adjacent-style-update.html
fast/selectors/first-child-sibling-style-update.html
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsEmpty):
(WebCore::SelectorCompiler::setStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/ContainerNode.h:
(WebCore::ContainerNode::directChildNeedsStyleRecalc):
(WebCore::ContainerNode::setDirectChildNeedsStyleRecalc):
Remove the special case for :empty.
* dom/Document.cpp:
(WebCore::nodeOrItsAncestorNeedsStyleRecalc):
* dom/Element.cpp:
(WebCore::checkForEmptyStyleChange):
(WebCore::checkForSiblingStyleChanges):
(WebCore::Element::setStyleOfSiblingsAffectedByEmpty): Deleted.
(WebCore::Element::rareDataStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/Element.h:
(WebCore::Element::styleOfSiblingsAffectedByEmpty): Deleted.
* dom/ElementRareData.h:
(WebCore::ElementRareData::ElementRareData):
(WebCore::ElementRareData::styleOfSiblingsAffectedByEmpty): Deleted.
(WebCore::ElementRareData::setStyleOfSiblingsAffectedByEmpty): Deleted.
* dom/Node.cpp:
(WebCore::markAncestorsWithChildNeedsStyleRecalc):
(WebCore::Node::setNeedsStyleRecalc):
(WebCore::Node::markAncestorsWithChildNeedsStyleRecalc): Deleted.
* dom/Node.h:
(WebCore::Node::clearChildNeedsStyleRecalc):
* style/StyleResolveTree.cpp:
(WebCore::Style::resetStyleForNonRenderedDescendants):
LayoutTests:
Add tests covering the basic cases: classes and attributes.
First-child covers the basic positional updates.
The tests have a version without any indirect adjacent ("~") because the marking
used for those is much more generic and having them hide some bugs.
Some tests are still failing. That is due to the style resolver not handling
direct siblings ("+") correctly when there are multiple of them. I will address
that separately.
* fast/selectors/attribute-direct-adjacent-style-update-expected.txt: Added.
* fast/selectors/attribute-direct-adjacent-style-update.html: Added.
* fast/selectors/attribute-sibling-style-update-expected.txt: Added.
* fast/selectors/attribute-sibling-style-update.html: Added.
* fast/selectors/class-direct-adjacent-style-update-expected.txt: Added.
* fast/selectors/class-direct-adjacent-style-update.html: Added.
* fast/selectors/class-sibling-style-update-expected.txt: Added.
* fast/selectors/class-sibling-style-update.html: Added.
* fast/selectors/first-child-direct-adjacent-style-update.html: Added.
* fast/selectors/first-child-sibling-style-update-expected.txt: Added.
* fast/selectors/first-child-sibling-style-update.html: Added.
* fast/selectors/placeholder-shown-sibling-style-update-expected.txt:
Canonical link: https://commits.webkit.org/154010@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@172880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2014-08-23 04:30:33 +00:00
|
|
|
PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(4, 5, 6)"
|
|
|
|
Removing the class, we should be back to the original state.
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-with-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-with-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS getComputedStyle(document.getElementById("bar-without-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS getComputedStyle(document.getElementById("baz-without-renderer")).color is "rgb(0, 0, 0)"
|
|
|
|
PASS successfullyParsed is true
|
|
|
|
|
|
|
|
TEST COMPLETE
|
|
|
|
|