Style invalidation does not work for adjacent node updates
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 23 Aug 2014 04:30:33 +0000 (04:30 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 23 Aug 2014 04:30:33 +0000 (04:30 +0000)
commit3bfd8105e3c1081821d89a7a96cc67ec22688893
tree7ca34df0005f3f823c14f7ee1511d6046cd39bf6
parent752905d82c766b3ca50f9377b99197efd309f5f4
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:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@172880 268f45cc-cd09-0410-ab3c-d52691b4dbfc
25 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/attribute-direct-adjacent-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/attribute-sibling-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/attribute-sibling-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/class-direct-adjacent-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/class-direct-adjacent-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/class-sibling-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/class-sibling-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/first-child-direct-adjacent-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/first-child-direct-adjacent-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/first-child-sibling-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/first-child-sibling-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/placeholder-shown-sibling-style-update-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/css/SelectorChecker.cpp
Source/WebCore/cssjit/SelectorCompiler.cpp
Source/WebCore/dom/ContainerNode.h
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/ElementRareData.h
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/style/StyleResolveTree.cpp