<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[173229] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/173229">173229</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-09-03 14:30:31 -0700 (Wed, 03 Sep 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>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 &quot;needsStyleRecalc&quot; 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 &lt;a&gt; changes, the style of &lt;b&gt; was updated, which is useless. The style
of &lt;c&gt; was untouched, which is incorrect.

When ChildrenAffectedByForwardPositionalRules, all elements after one with &quot;needsStyleRecalc&quot;
were invalidated. While more correct, it caused avalanche of style recalc and was not a very
useful &quot;optimization&quot;.

 
To fix the correctness issues (e.g. &quot;a + b + c&quot;), 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 &quot;&lt;-&quot; for (1), &quot;-&gt;&quot; for (2), the selector &quot;a + b + c&quot; create this kind
of marking:
    a  +  b  +  c
    -&gt;    -&gt;
               &lt;-

When &lt;a&gt; 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 &lt;c&gt;.

Overlaps are possible. For example with the two selector, &quot;a + b + c&quot;, &quot;b ~ d&quot;
the marking would be
    a  +  b  +  c  +  d
    -&gt;    -&gt;    -&gt;
               &lt;-    &lt;-

A change in &lt;a&gt; would invalidate both &lt;c&gt; and &lt;d&gt;. 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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastselectorsattributedirectadjacentstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsclassdirectadjacentstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/class-direct-adjacent-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsfirstchilddirectadjacentstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/first-child-direct-adjacent-style-update-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssSelectorCheckercpp">trunk/Source/WebCore/css/SelectorChecker.cpp</a></li>
<li><a href="#trunkSourceWebCorecssStyleResolvercpp">trunk/Source/WebCore/css/StyleResolver.cpp</a></li>
<li><a href="#trunkSourceWebCorecssjitSelectorCompilercpp">trunk/Source/WebCore/cssjit/SelectorCompiler.cpp</a></li>
<li><a href="#trunkSourceWebCoredomDocumentcpp">trunk/Source/WebCore/dom/Document.cpp</a></li>
<li><a href="#trunkSourceWebCoredomElementcpp">trunk/Source/WebCore/dom/Element.cpp</a></li>
<li><a href="#trunkSourceWebCoredomElementh">trunk/Source/WebCore/dom/Element.h</a></li>
<li><a href="#trunkSourceWebCoredomElementRareDatah">trunk/Source/WebCore/dom/ElementRareData.h</a></li>
<li><a href="#trunkSourceWebCoredomNodeh">trunk/Source/WebCore/dom/Node.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLElementh">trunk/Source/WebCore/html/HTMLElement.h</a></li>
<li><a href="#trunkSourceWebCorehtmlHTMLUnknownElementh">trunk/Source/WebCore/html/HTMLUnknownElement.h</a></li>
<li><a href="#trunkSourceWebCorestyleStyleResolveTreecpp">trunk/Source/WebCore/style/StyleResolveTree.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcssdirectadjacentstyleupdateoptimizationexpectedtxt">trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcssdirectadjacentstyleupdateoptimizationhtml">trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization.html</a></li>
<li><a href="#trunkLayoutTestsfastcssindirectadjacentstyleupdateoptimizationexpectedtxt">trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcssindirectadjacentstyleupdateoptimizationhtml">trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization.html</a></li>
<li><a href="#trunkLayoutTestsfastcssnonmatchingadjacentstyleupdateexpectedtxt">trunk/LayoutTests/fast/css/non-matching-adjacent-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcssnonmatchingadjacentstyleupdatehtml">trunk/LayoutTests/fast/css/non-matching-adjacent-style-update.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsfirstoftypedirectadjacentstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsfirstoftypedirectadjacentstyleupdatehtml">trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsfirstoftypesiblingstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsfirstoftypesiblingstyleupdatehtml">trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsiddirectadjacentstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsiddirectadjacentstyleupdatehtml">trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsidsiblingstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/id-sibling-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsidsiblingstyleupdatehtml">trunk/LayoutTests/fast/selectors/id-sibling-style-update.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchildasfirstsimpleselectorstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchildasfirstsimpleselectorstyleupdatehtml">trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchilddirectadjacentstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchilddirectadjacentstyleupdatehtml">trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchildstyleupdateexpectedtxt">trunk/LayoutTests/fast/selectors/nth-child-style-update-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchildstyleupdatehtml">trunk/LayoutTests/fast/selectors/nth-child-style-update.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/LayoutTests/ChangeLog        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -1,5 +1,39 @@
</span><span class="cx"> 2014-09-03  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
</span><span class="cx"> 
</span><ins>+        Fix style invalidation of elements with multiple siblings dependencies
+        https://bugs.webkit.org/show_bug.cgi?id=136472
+
+        Reviewed by Andreas Kling.
+
+        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.
+
+2014-09-03  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
</ins><span class="cx">         Add a test case for Element.matches() with :scope
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=136475
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsfastcssdirectadjacentstyleupdateoptimizationexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+This test checks the style invalidation does not dirty elements that cannot be affected by the changes.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initially, we should have a match. After getting the style, nothing should require a style recalc.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[8]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[9]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS elementsWithTagnameNeedsStyleRecalc([]) is true
+Let's remove the class &quot;property&quot;.
+Source should require a style recalc.
+PASS elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;]) is true
+We should no longer have a match. Let's add back the class &quot;property&quot;. Then we get the style of everything except &lt;source&gt; and &lt;target&gt;. Since none of the style touched above are related to the dirty elements, &lt;source&gt; should still require a style recalc.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[8]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[9]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;]) is true
+We should match again now that property is back.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[8]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[9]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing the &lt;source&gt; should invalidate the &lt;target&gt;, and nothing else.
+PASS elementsWithTagnameNeedsStyleRecalc([&quot;TARGET&quot;]) is true
+We should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcssdirectadjacentstyleupdateoptimizationhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization.html                                (rev 0)
+++ trunk/LayoutTests/fast/css/direct-adjacent-style-update-optimization.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,99 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: rgb(255, 254, 253);
+}
+source.property + intermediary + target {
+    background-color: rgb(1, 2, 3);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div class=&quot;test-case&quot;&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;source class=&quot;foo property bar&quot;&gt;&lt;/source&gt;
+        &lt;intermediary&gt;&lt;/intermediary&gt;
+        &lt;target&gt;&lt;/target&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+    &lt;/div&gt;
+    &lt;div class=&quot;test-case&quot; style=&quot;display:none;&quot;&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;source class=&quot;foo property bar&quot;&gt;&lt;/source&gt;
+        &lt;intermediary&gt;&lt;/intermediary&gt;
+        &lt;target&gt;&lt;/target&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('This test checks the style invalidation does not dirty elements that cannot be affected by the changes.');
+
+function testColor(expectedMatch)
+{
+    var others = document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;);
+    for (var i = 0; i &lt; others.length; ++i)
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[' + i + ']).backgroundColor', 'rgb(255, 254, 253)');
+    var targets = document.querySelectorAll(&quot;target&quot;);
+    for (var i = 0; i &lt; targets.length; ++i)
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;target&quot;)[' + i + ']).backgroundColor', expectedMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 254, 253)');
+}
+
+function elementsWithTagnameNeedsStyleRecalc(expectedTagnameNeedingStyleRecalc)
+{
+    // We cannot modify the DOM here or we could cause a style recalculation.
+    var allContent = document.querySelectorAll(&quot;.test-case, .test-case *&quot;);
+    for (var i = 0; i &lt; allContent.length; ++i) {
+        var expected = expectedTagnameNeedingStyleRecalc.indexOf(allContent[i].tagName) &gt;= 0;
+        if (internals.nodeNeedsStyleRecalc(allContent[i]) != expected) {
+            debug(&quot;Expected &amp;lt;&quot; + allContent[i].tagName + &quot;&amp;gt; to be &quot; + expected + &quot;, it wasn't :(&quot;);
+            return false;
+        }
+    }
+    return true;
+}
+
+debug(&quot;Initially, we should have a match. After getting the style, nothing should require a style recalc.&quot;);
+testColor(true);
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([])');
+
+debug(&quot;Let's remove the class \&quot;property\&quot;.&quot;);
+var allSources = document.querySelectorAll(&quot;source&quot;);
+for (var i = 0; i &lt; allSources.length; ++i)
+    allSources[i].classList.remove(&quot;property&quot;);
+
+debug(&quot;Source should require a style recalc.&quot;);
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;])');
+
+debug(&quot;We should no longer have a match. Let's add back the class \&quot;property\&quot;. Then we get the style of everything except &amp;lt;source&amp;gt; and &amp;lt;target&amp;gt;. Since none of the style touched above are related to the dirty elements, &amp;lt;source&amp;gt; should still require a style recalc.&quot;);
+
+// This should clear the dirty style.
+testColor(false);
+
+// Add the class without touching anything else
+var allSources = document.querySelectorAll(&quot;source&quot;);
+for (var i = 0; i &lt; allSources.length; ++i)
+    allSources[i].classList.add(&quot;property&quot;);
+
+var others = document.querySelectorAll(&quot;.test-case, .test-case :not(target):not(source)&quot;);
+for (var i = 0; i &lt; others.length; ++i) {
+    if (getComputedStyle(others[i]).backgroundColor != 'rgb(255, 254, 253)')
+        debug(&quot;Something horribly wrong is happening.&quot;);
+}
+
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;])');
+
+debug(&quot;We should match again now that property is back.&quot;);
+testColor(true);
+
+debug(&quot;Removing the &amp;lt;source&amp;gt; should invalidate the &amp;lt;target&amp;gt;, and nothing else.&quot;);
+for (var i = 0; i &lt; allSources.length; ++i)
+    allSources[i].parentElement.removeChild(allSources[i]);
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([&quot;TARGET&quot;])');
+
+debug(&quot;We should no longer match.&quot;);
+testColor(false);
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcssindirectadjacentstyleupdateoptimizationexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+This test checks the style invalidation does not dirty elements that cannot be affected by the changes.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initially, we should have a match. After getting the style, nothing should require a style recalc.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[8]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[9]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS elementsWithTagnameNeedsStyleRecalc([]) is true
+Let's remove the class &quot;property&quot;.
+Source should require a style recalc.
+PASS elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;]) is true
+We should no longer have a match. Let's add back the class &quot;property&quot;. Then we get the style of everything except &lt;source&gt; and &lt;target&gt;. Since none of the style touched above are related to the dirty elements, &lt;source&gt; should still require a style recalc.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[8]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[9]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;]) is true
+We should match again now that property is back.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[8]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[9]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing the &lt;source&gt; should invalidate the &lt;target&gt;, and nothing else.
+PASS elementsWithTagnameNeedsStyleRecalc([&quot;TARGET&quot;]) is true
+We should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcssindirectadjacentstyleupdateoptimizationhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization.html                                (rev 0)
+++ trunk/LayoutTests/fast/css/indirect-adjacent-style-update-optimization.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,99 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: rgb(255, 254, 253);
+}
+source.property ~ target {
+    background-color: rgb(1, 2, 3);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div class=&quot;test-case&quot;&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;source class=&quot;foo property bar&quot;&gt;&lt;/source&gt;
+        &lt;intermediary&gt;&lt;/intermediary&gt;
+        &lt;target&gt;&lt;/target&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+    &lt;/div&gt;
+    &lt;div class=&quot;test-case&quot; style=&quot;display:none;&quot;&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;source class=&quot;foo property bar&quot;&gt;&lt;/source&gt;
+        &lt;intermediary&gt;&lt;/intermediary&gt;
+        &lt;target&gt;&lt;/target&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('This test checks the style invalidation does not dirty elements that cannot be affected by the changes.');
+
+function testColor(expectedMatch)
+{
+    var others = document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;);
+    for (var i = 0; i &lt; others.length; ++i)
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;.test-case, .test-case :not(target)&quot;)[' + i + ']).backgroundColor', 'rgb(255, 254, 253)');
+    var targets = document.querySelectorAll(&quot;target&quot;);
+    for (var i = 0; i &lt; targets.length; ++i)
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;target&quot;)[' + i + ']).backgroundColor', expectedMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 254, 253)');
+}
+
+function elementsWithTagnameNeedsStyleRecalc(expectedTagnameNeedingStyleRecalc)
+{
+    // We cannot modify the DOM here or we could cause a style recalculation.
+    var allContent = document.querySelectorAll(&quot;.test-case, .test-case *&quot;);
+    for (var i = 0; i &lt; allContent.length; ++i) {
+        var expected = expectedTagnameNeedingStyleRecalc.indexOf(allContent[i].tagName) &gt;= 0;
+        if (internals.nodeNeedsStyleRecalc(allContent[i]) != expected) {
+            debug(&quot;Expected &amp;lt;&quot; + allContent[i].tagName + &quot;&amp;gt; to be &quot; + expected + &quot;, it wasn't :(&quot;);
+            return false;
+        }
+    }
+    return true;
+}
+
+debug(&quot;Initially, we should have a match. After getting the style, nothing should require a style recalc.&quot;);
+testColor(true);
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([])');
+
+debug(&quot;Let's remove the class \&quot;property\&quot;.&quot;);
+var allSources = document.querySelectorAll(&quot;source&quot;);
+for (var i = 0; i &lt; allSources.length; ++i)
+    allSources[i].classList.remove(&quot;property&quot;);
+
+debug(&quot;Source should require a style recalc.&quot;);
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;])');
+
+debug(&quot;We should no longer have a match. Let's add back the class \&quot;property\&quot;. Then we get the style of everything except &amp;lt;source&amp;gt; and &amp;lt;target&amp;gt;. Since none of the style touched above are related to the dirty elements, &amp;lt;source&amp;gt; should still require a style recalc.&quot;);
+
+// This should clear the dirty style.
+testColor(false);
+
+// Add the class without touching anything else
+var allSources = document.querySelectorAll(&quot;source&quot;);
+for (var i = 0; i &lt; allSources.length; ++i)
+    allSources[i].classList.add(&quot;property&quot;);
+
+var others = document.querySelectorAll(&quot;.test-case, .test-case :not(target):not(source)&quot;);
+for (var i = 0; i &lt; others.length; ++i) {
+    if (getComputedStyle(others[i]).backgroundColor != 'rgb(255, 254, 253)')
+        debug(&quot;Something horribly wrong is happening.&quot;);
+}
+
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([&quot;SOURCE&quot;])');
+
+debug(&quot;We should match again now that property is back.&quot;);
+testColor(true);
+
+debug(&quot;Removing the &amp;lt;source&amp;gt; should invalidate the &amp;lt;target&amp;gt;, and nothing else.&quot;);
+for (var i = 0; i &lt; allSources.length; ++i)
+    allSources[i].parentElement.removeChild(allSources[i]);
+shouldBeTrue('elementsWithTagnameNeedsStyleRecalc([&quot;TARGET&quot;])');
+
+debug(&quot;We should no longer match.&quot;);
+testColor(false);
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcssnonmatchingadjacentstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/non-matching-adjacent-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/non-matching-adjacent-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/css/non-matching-adjacent-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+Selectors' sibling combinators (&quot;+&quot; or &quot;~&quot;) create style update relation between elements. This test the case were such relation exists and is removed. This test relies on WebCore's internals.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initially, the direct adjacent relation is satisfied and we have a match.
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+We remove &lt;bar&gt;, there is nothing matching the rightmost compound selector.
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[0]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[1]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[2]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[3]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[4]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[5]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[6]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[7]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[8]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[9]) is false
+PASS document.getElementById(&quot;bar-with-renderer&quot;) is null
+PASS document.getElementById(&quot;bar-without-renderer&quot;) is null
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+Now we change a property of &lt;foo&gt;. Doing that can invalidate foo, but not the other elements.
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[0]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[1]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[2]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[3]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[4]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[5]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[6]) is false
+PASS internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[7]) is false
+PASS document.getElementById(&quot;bar-with-renderer&quot;) is null
+PASS document.getElementById(&quot;bar-without-renderer&quot;) is null
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[0]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[1]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[2]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[3]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[4]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[5]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[6]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[7]).backgroundColor is &quot;rgb(255, 254, 253)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcssnonmatchingadjacentstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/non-matching-adjacent-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/non-matching-adjacent-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/css/non-matching-adjacent-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: rgb(255, 254, 253);
+}
+foo.property+padding+padding+padding+bar {
+    background-color: rgb(1, 2, 3);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div class=&quot;test-case&quot;&gt;
+        &lt;foo class=&quot;foo property bar&quot;&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-with-renderer&quot;&gt;&lt;/bar&gt;
+    &lt;/div&gt;
+    &lt;div class=&quot;test-case&quot; style=&quot;display:none;&quot;&gt;
+        &lt;foo class=&quot;foo property bar&quot;&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-without-renderer&quot;&gt;&lt;/bar&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Selectors\' sibling combinators (&quot;+&quot; or &quot;~&quot;) create style update relation between elements. This test the case were such relation exists and is removed. This test relies on WebCore\'s internals.');
+
+function testUnrelatedElementsAreUnchanged()
+{
+    var others = document.querySelectorAll(&quot;foo, padding&quot;);
+    for (var i = 0; i &lt; others.length; ++i)
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;foo, padding&quot;)[' + i + ']).backgroundColor', 'rgb(255, 254, 253)');
+}
+
+debug(&quot;Initially, the direct adjacent relation is satisfied and we have a match.&quot;);
+testUnrelatedElementsAreUnchanged();
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor', 'rgb(1, 2, 3)');
+shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor', 'rgb(1, 2, 3)');
+
+
+debug(&quot;We remove &amp;lt;bar&amp;gt;, there is nothing matching the rightmost compound selector.&quot;);
+var barWithRenderer = document.getElementById(&quot;bar-with-renderer&quot;);
+barWithRenderer.parentElement.removeChild(barWithRenderer);
+var barWithoutRenderer = document.getElementById(&quot;bar-without-renderer&quot;);
+barWithoutRenderer.parentElement.removeChild(barWithoutRenderer);
+
+// No element should be dirty after the removal. This is testing the invalidation optimization, not correctness.
+if (window.internals) {
+    var allContent = document.querySelectorAll(&quot;.test-case, .test-case *&quot;);
+    for (var i = 0; i &lt; allContent.length; ++i)
+        shouldBeFalse('internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case *&quot;)[' + i + '])');
+}
+
+shouldBeNull('document.getElementById(&quot;bar-with-renderer&quot;)');
+shouldBeNull('document.getElementById(&quot;bar-without-renderer&quot;)');
+testUnrelatedElementsAreUnchanged();
+
+
+debug(&quot;Now we change a property of &amp;lt;foo&amp;gt;. Doing that can invalidate foo, but not the other elements.&quot;);
+
+var allFoos = document.querySelectorAll(&quot;foo&quot;);
+for (var i = 0; i &lt; allFoos.length; ++i)
+    allFoos[i].classList.remove(&quot;property&quot;);
+
+// No element should be dirty after the removal. This is testing the invalidation optimization, not correctness.
+if (window.internals) {
+    var allContent = document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;);
+    for (var i = 0; i &lt; allContent.length; ++i)
+    shouldBeFalse('internals.nodeNeedsStyleRecalc(document.querySelectorAll(&quot;.test-case, .test-case :not(foo)&quot;)[' + i + '])');
+}
+
+shouldBeNull('document.getElementById(&quot;bar-with-renderer&quot;)');
+shouldBeNull('document.getElementById(&quot;bar-without-renderer&quot;)');
+testUnrelatedElementsAreUnchanged();
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsattributedirectadjacentstyleupdateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/LayoutTests/fast/selectors/attribute-direct-adjacent-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -13,21 +13,21 @@
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> Adding the attribute, the extra rules should match.
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color should be rgb(4, 5, 6). Was rgb(0, 0, 0).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> Emptying the attribute, the extra rules should still match.
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color should be rgb(4, 5, 6). Was rgb(0, 0, 0).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> Removing the attribute, we should not longer match.
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsclassdirectadjacentstyleupdateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/selectors/class-direct-adjacent-style-update-expected.txt (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/class-direct-adjacent-style-update-expected.txt        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/LayoutTests/fast/selectors/class-direct-adjacent-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -13,12 +13,12 @@
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> Adding the class, the extra rules should match.
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color should be rgb(4, 5, 6). Was rgb(0, 0, 0).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> Removing the class, we should be back to the original state.
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsfirstchilddirectadjacentstyleupdateexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/selectors/first-child-direct-adjacent-style-update-expected.txt (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/first-child-direct-adjacent-style-update-expected.txt        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/LayoutTests/fast/selectors/first-child-direct-adjacent-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -13,12 +13,12 @@
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> Adding an element as first child should clear the style.
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor should be rgb(255, 255, 255). Was rgb(1, 2, 3).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color should be rgb(0, 0, 0). Was rgb(4, 5, 6).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> Removing that first element put back the style.
</span><span class="lines">@@ -31,12 +31,12 @@
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
</span><span class="cx"> Removing &lt;foo&gt; should clear the style.
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor should be rgb(255, 255, 255). Was rgb(1, 2, 3).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><del>-FAIL getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color should be rgb(0, 0, 0). Was rgb(4, 5, 6).
</del><ins>+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</ins><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
</span><span class="cx"> PASS successfullyParsed is true
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsfirstoftypedirectadjacentstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+Test style update caused by tree changes with the selector :first-of-type. This test does not use any sibling &quot;~&quot; combinator to avoid its more generic marking.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initialy, &lt;foo&gt; is the first of its type, the style should match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+Adding a few elements that are not &lt;foo&gt; do not invalidate the :first-of-type.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+Adding a second &lt;foo&gt;. This should breat the rules because the new foo does not match &quot;+ padding&quot;.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+Adding a few elements that are not &lt;foo&gt;, we should still not match because of the previously added &lt;foo&gt;.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+Removing the &lt;foo&gt; blocking foo:first-of-type+padding.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsfirstoftypedirectadjacentstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/first-of-type-direct-adjacent-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+    min-width: 0px;
+}
+foo:first-of-type+padding+padding+padding+bar {
+    background-color: rgb(1, 2, 3);
+}
+foo:first-of-type+padding+padding+padding+bar baz {
+    color: rgb(4, 5, 6);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-with-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-with-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+    &lt;div style=&quot;display:none;&quot;&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-without-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-without-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test style update caused by tree changes with the selector :first-of-type. This test does not use any sibling &quot;~&quot; combinator to avoid its more generic marking.');
+
+function testColor(expectMatch) {
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+}
+
+function addElementAsFirstChild(tagName, className)
+{
+    var allFoos = document.querySelectorAll(&quot;foo&quot;);
+    for (var i = 0; i &lt; allFoos.length; ++i) {
+        var newElement = document.createElement(tagName);
+        newElement.className = className;
+        allFoos[i].parentElement.insertBefore(newElement, allFoos[i]);
+    }
+}
+
+debug(&quot;Initialy, &amp;lt;foo&amp;gt; is the first of its type, the style should match.&quot;);
+testColor(true);
+
+debug(&quot;Adding a few elements that are not &amp;lt;foo&amp;gt; do not invalidate the :first-of-type.&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+testColor(true);
+
+debug(&quot;Adding a second &amp;lt;foo&amp;gt;. This should breat the rules because the new foo does not match \&quot;+ padding\&quot;.&quot;);
+addElementAsFirstChild(&quot;foo&quot;, &quot;extra-foo&quot;);
+testColor(false);
+
+debug(&quot;Adding a few elements that are not &amp;lt;foo&amp;gt;, we should still not match because of the previously added &amp;lt;foo&amp;gt;.&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+testColor(false);
+
+debug(&quot;Removing the &amp;lt;foo&amp;gt; blocking foo:first-of-type+padding.&quot;);
+var extraFoos = document.querySelectorAll(&quot;.extra-foo&quot;);
+for (var i = 0; i &lt; extraFoos.length; ++i)
+    extraFoos[i].parentElement.removeChild(extraFoos[i]);
+testColor(true);
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsfirstoftypesiblingstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,94 @@
</span><ins>+Test style update caused by tree changes with the selector :first-of-type.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initialy, &lt;foo&gt; is the first of its type, the style should match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;1px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;1px&quot;
+Adding a few elements that are not &lt;foo&gt; do not invalidate the :first-of-type.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;1px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;1px&quot;
+Adding a second &lt;foo&gt;. This should breat the rules because the new foo does not match &quot;+ padding&quot;.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;0px&quot;
+Adding a few elements that are not &lt;foo&gt;, we should still not match because of the previously added &lt;foo&gt;.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;0px&quot;
+Removing the &lt;foo&gt; blocking foo:first-of-type+padding.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;1px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;1px&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsfirstoftypesiblingstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/first-of-type-sibling-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,109 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+    min-width: 0px;
+}
+foo:first-of-type+padding+padding+padding+bar {
+    background-color: rgb(1, 2, 3);
+}
+foo:first-of-type+padding~bar {
+    fill-opacity: 0.5;
+}
+foo:first-of-type+padding+padding+padding+bar baz {
+    color: rgb(4, 5, 6);
+}
+foo:first-of-type+padding~bar baz {
+    min-width: 1px;
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-with-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-with-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+    &lt;div style=&quot;display:none;&quot;&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-without-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-without-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test style update caused by tree changes with the selector :first-of-type.');
+
+function testColor(expectMatch) {
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity', expectMatch ? '0.5' : '1');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity', '1');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity', expectMatch ? '0.5' : '1');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity', '1');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth', '0px');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth', expectMatch ? '1px': '0px');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth', '0px');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth', expectMatch ? '1px': '0px');
+}
+
+function addElementAsFirstChild(tagName, className)
+{
+    var allFoos = document.querySelectorAll(&quot;foo&quot;);
+    for (var i = 0; i &lt; allFoos.length; ++i) {
+        var newElement = document.createElement(tagName);
+        newElement.className = className;
+        allFoos[i].parentElement.insertBefore(newElement, allFoos[i]);
+    }
+}
+
+debug(&quot;Initialy, &amp;lt;foo&amp;gt; is the first of its type, the style should match.&quot;);
+testColor(true);
+
+debug(&quot;Adding a few elements that are not &amp;lt;foo&amp;gt; do not invalidate the :first-of-type.&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+testColor(true);
+
+debug(&quot;Adding a second &amp;lt;foo&amp;gt;. This should breat the rules because the new foo does not match \&quot;+ padding\&quot;.&quot;);
+addElementAsFirstChild(&quot;foo&quot;, &quot;extra-foo&quot;);
+testColor(false);
+
+debug(&quot;Adding a few elements that are not &amp;lt;foo&amp;gt;, we should still not match because of the previously added &amp;lt;foo&amp;gt;.&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+addElementAsFirstChild(&quot;notfoo&quot;);
+testColor(false);
+
+debug(&quot;Removing the &amp;lt;foo&amp;gt; blocking foo:first-of-type+padding.&quot;);
+var extraFoos = document.querySelectorAll(&quot;.extra-foo&quot;);
+for (var i = 0; i &lt; extraFoos.length; ++i)
+    extraFoos[i].parentElement.removeChild(extraFoos[i]);
+testColor(true);
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsiddirectadjacentstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+Test style update caused by id changes on a direct adjacent. This test does not use any sibling &quot;~&quot; combinator to avoid its more generic marking.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initial state does not match, there is no id defined.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+Adding the id, we should have a match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+Removing the id, we should not longer match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+Setting the id to a different value, we should not match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsiddirectadjacentstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-direct-adjacent-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: white;
+    color: black;
+}
+#webkit+padding+padding+padding+bar {
+    background-color: rgb(1, 2, 3);
+}
+#webkit+padding+padding+padding+bar baz {
+    color: rgb(4, 5, 6);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-with-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-with-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+    &lt;div style=&quot;display:none;&quot;&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-without-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-without-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test style update caused by id changes on a direct adjacent. This test does not use any sibling &quot;~&quot; combinator to avoid its more generic marking.');
+
+function testColor(expectMatch) {
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+}
+
+// Attributes are covered in a separate test, here we only use the id property.
+function setId(value) {
+    var allFoos = document.querySelectorAll(&quot;foo&quot;);
+    for (var i = 0; i &lt; allFoos.length; ++i)
+        allFoos[i].id =value;
+}
+
+debug(&quot;Initial state does not match, there is no id defined.&quot;);
+testColor(false);
+
+debug(&quot;Adding the id, we should have a match.&quot;);
+setId(&quot;webkit&quot;);
+testColor(true);
+
+debug(&quot;Removing the id, we should not longer match.&quot;);
+setId(&quot;&quot;);
+testColor(false);
+
+debug(&quot;Setting the id to a different value, we should not match.&quot;);
+setId(&quot;notwebkit&quot;);
+testColor(false);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsidsiblingstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/id-sibling-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/id-sibling-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-sibling-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+Test style update caused by id changes on a sibling.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initial state does not match, there is no id defined.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;0px&quot;
+Adding the id, we should have a match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;0.5&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;1px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;1px&quot;
+Removing the id, we should not longer match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;0px&quot;
+Setting the id to a different value, we should not match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity is &quot;1&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth is &quot;0px&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsidsiblingstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/id-sibling-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/id-sibling-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/id-sibling-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+    min-width: 0px;
+}
+#webkit+padding+padding+padding+bar {
+    background-color: rgb(1, 2, 3);
+}
+#webkit~bar {
+    fill-opacity: 0.5;
+}
+#webkit+padding+padding+padding+bar baz {
+    color: rgb(4, 5, 6);
+}
+#webkit~bar baz {
+    min-width: 1px;
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-with-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-with-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+    &lt;div style=&quot;display:none;&quot;&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-without-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-without-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test style update caused by id changes on a sibling.');
+
+function testColor(expectMatch) {
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).fillOpacity', expectMatch ? '0.5' : '1');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).fillOpacity', '1');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).fillOpacity', expectMatch ? '0.5' : '1');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).fillOpacity', '1');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).minWidth', '0px');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).minWidth', expectMatch ? '1px': '0px');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).minWidth', '0px');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).minWidth', expectMatch ? '1px': '0px');
+}
+
+// Attributes are covered in a separate test, here we only use the id property.
+function setId(value) {
+    var allFoos = document.querySelectorAll(&quot;foo&quot;);
+    for (var i = 0; i &lt; allFoos.length; ++i)
+    allFoos[i].id =value;
+}
+
+debug(&quot;Initial state does not match, there is no id defined.&quot;);
+testColor(false);
+
+debug(&quot;Adding the id, we should have a match.&quot;);
+setId(&quot;webkit&quot;);
+testColor(true);
+
+debug(&quot;Removing the id, we should not longer match.&quot;);
+setId(&quot;&quot;);
+testColor(false);
+
+debug(&quot;Setting the id to a different value, we should not match.&quot;);
+setId(&quot;notwebkit&quot;);
+testColor(false);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthchildasfirstsimpleselectorstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,189 @@
</span><ins>+Test style update of :nth-child() when the tree structure is modified. In this case, :nth-child() is not the last component of the compound selector, which is a bit less common.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initialy, &lt;foo&gt; is the first of its type, the style should match.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;testnode&gt; on top, we should now match 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;nottestnode&gt; on top, we should now match 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;nottestnode&gt; on top, we should now match 2, 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[14]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[15]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;testnode&gt; on top, we should now match 1, 2, 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[12]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[14]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[15]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[16]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[17]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;nottestnode&gt; on top, we should now match 0, 1, 2, 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[12]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[13]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[14]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[15]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[16]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[17]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[18]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[19]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;nottestnode&gt;, 0 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[12]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[14]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[15]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[16]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[17]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;testnode&gt;, 1 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[14]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[15]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;notestnode&gt;, 2 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;testnode&gt;, 3 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;testnode&gt;, 4 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;testnode&gt;, there are only 4 siblings left, nothing can match.
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[4]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[5]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthchildasfirstsimpleselectorstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-as-first-simple-selector-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,110 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+testnode {
+    background-color: white;
+}
+:nth-child(n+5).target {
+    background-color: rgb(1, 2, 3);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=&quot;with-renderer&quot;&gt;
+        &lt;testnode class=&quot;element_1 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_2 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_3 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_4 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_5 target&quot;&gt;&lt;/testnode&gt;
+    &lt;/div&gt;
+    &lt;div id=&quot;without-renderer&quot; style=&quot;display:none;&quot;&gt;
+        &lt;testnode class=&quot;element_1 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_2 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_3 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_4 target&quot;&gt;&lt;/testnode&gt;
+        &lt;testnode class=&quot;element_5 target&quot;&gt;&lt;/testnode&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test style update of :nth-child() when the tree structure is modified. In this case, :nth-child() is not the last component of the compound selector, which is a bit less common.');
+
+function testColor(classesThatShouldMatch) {
+    var alltestnodes = document.querySelectorAll(&quot;testnode&quot;);
+    for (var i = 0; i &lt; alltestnodes.length; ++i) {
+        var expectMath = classesThatShouldMatch.indexOf(alltestnodes[i].classList[0]) != -1;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;testnode&quot;)[' + i + ']).backgroundColor', expectMath ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    }
+}
+
+function addElementAsFirstChild(tagName, className)
+{
+    var newElement = document.createElement(tagName);
+    newElement.className = className;
+
+    var withRenderer = document.getElementById(&quot;with-renderer&quot;);
+    withRenderer.insertBefore(newElement, withRenderer.firstChild);
+
+    var withoutRenderer = document.getElementById(&quot;without-renderer&quot;);
+    withoutRenderer.insertBefore(newElement.cloneNode(), withoutRenderer.firstChild);
+}
+
+function removeElementsOfClass(className)
+{
+    var allElementsToRemove = document.querySelectorAll('.' + className);
+    for (var i = 0; i &lt; allElementsToRemove.length; ++i)
+        allElementsToRemove[i].parentElement.removeChild(allElementsToRemove[i]);
+}
+
+debug(&quot;Initialy, &amp;lt;foo&amp;gt; is the first of its type, the style should match.&quot;);
+testColor([&quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;testnode&amp;gt; on top, we should now match 4 and 5.&quot;);
+addElementAsFirstChild(&quot;testnode&quot;, &quot;element_0 target&quot;)
+testColor([&quot;element_4&quot;, &quot;element_5&quot;]);
+
+// Using nottestnode is interesting because the ':nth-child()' part is not matched for those elements.
+debug(&quot;Adding an element &amp;lt;nottestnode&amp;gt; on top, we should now match 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;testnode&quot;, &quot;element_-1 target&quot;)
+testColor([&quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;nottestnode&amp;gt; on top, we should now match 2, 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;testnode&quot;, &quot;element_-2 target&quot;)
+testColor([&quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;testnode&amp;gt; on top, we should now match 1, 2, 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;testnode&quot;, &quot;element_-3 target&quot;)
+testColor([&quot;element_1&quot;, &quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;nottestnode&amp;gt; on top, we should now match 0, 1, 2, 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;testnode&quot;, &quot;element_-4 target&quot;)
+testColor([&quot;element_0&quot;, &quot;element_1&quot;, &quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;nottestnode&amp;gt;, 0 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-2&quot;);
+testColor([&quot;element_1&quot;, &quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;testnode&amp;gt;, 1 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-4&quot;);
+testColor([&quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;notestnode&amp;gt;, 2 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-1&quot;);
+testColor([&quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;testnode&amp;gt;, 3 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-3&quot;);
+testColor([&quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;testnode&amp;gt;, 4 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_0&quot;);
+testColor([&quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;testnode&amp;gt;, there are only 4 siblings left, nothing can match.&quot;);
+removeElementsOfClass(&quot;element_1&quot;);
+testColor([]);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthchilddirectadjacentstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+Test style update caused by :nth-child() changes on a direct adjacent. This test does not use any sibling &quot;~&quot; combinator to avoid its more generic marking.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initially, &lt;foo&gt; is the third child and does not match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+Adding one element before moves &lt;foo&gt; to the fourth position, we should have a match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+Adding one more element before moves &lt;foo&gt; to the fifth position, we should no longer match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+Removing one element, we should be back to 4 and have a match.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(4, 5, 6)&quot;
+Removing one more element, we should be back to the initial state.
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color is &quot;rgb(0, 0, 0)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthchilddirectadjacentstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-direct-adjacent-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+* {
+    background-color: white;
+    color: black;
+}
+:nth-child(4)+padding+padding+padding+bar {
+    background-color: rgb(1, 2, 3);
+}
+:nth-child(4)+padding+padding+padding+bar baz {
+    color: rgb(4, 5, 6);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=&quot;with-renderer&quot;&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-with-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-with-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+    &lt;div id=&quot;without-renderer&quot; style=&quot;display:none;&quot;&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;foo&gt;&lt;/foo&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;padding&gt;&lt;/padding&gt;
+        &lt;bar id=&quot;bar-without-renderer&quot;&gt;
+            &lt;baz id=&quot;baz-without-renderer&quot;&gt;&lt;/baz&gt;
+        &lt;/bar&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test style update caused by :nth-child() changes on a direct adjacent. This test does not use any sibling &quot;~&quot; combinator to avoid its more generic marking.');
+
+function testColor(expectMatch) {
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).backgroundColor', 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-with-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-with-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;bar-without-renderer&quot;)).color', 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById(&quot;baz-without-renderer&quot;)).color', expectMatch ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+}
+
+function addElementAsFirstChild(tagName, className)
+{
+    var newElement = document.createElement(tagName);
+    newElement.className = className;
+
+    var withRenderer = document.getElementById(&quot;with-renderer&quot;);
+    withRenderer.insertBefore(newElement, withRenderer.firstChild);
+
+    var withoutRenderer = document.getElementById(&quot;without-renderer&quot;);
+    withoutRenderer.insertBefore(newElement.cloneNode(), withoutRenderer.firstChild);
+}
+
+function removeElementsOfClass(className)
+{
+    var allElementsToRemove = document.querySelectorAll('.' + className);
+    for (var i = 0; i &lt; allElementsToRemove.length; ++i)
+    allElementsToRemove[i].parentElement.removeChild(allElementsToRemove[i]);
+}
+
+debug(&quot;Initially, &amp;lt;foo&amp;gt; is the third child and does not match.&quot;);
+testColor(false);
+
+debug(&quot;Adding one element before moves &amp;lt;foo&amp;gt; to the fourth position, we should have a match.&quot;);
+addElementAsFirstChild(&quot;padding&quot;, &quot;padding1&quot;)
+testColor(true);
+
+debug(&quot;Adding one more element before moves &amp;lt;foo&amp;gt; to the fifth position, we should no longer match.&quot;);
+addElementAsFirstChild(&quot;padding&quot;, &quot;padding2&quot;)
+testColor(false);
+
+debug(&quot;Removing one element, we should be back to 4 and have a match.&quot;);
+removeElementsOfClass(&quot;padding1&quot;);
+testColor(true);
+
+debug(&quot;Removing one more element, we should be back to the initial state.&quot;);
+removeElementsOfClass(&quot;padding2&quot;);
+testColor(false);
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthchildstyleupdateexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-style-update-expected.txt (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-style-update-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-style-update-expected.txt        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,167 @@
</span><ins>+Test style update of :nth-child() when the tree structure is modified.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Initialy, &lt;foo&gt; is the first of its type, the style should match.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;target&gt; on top, we should now match 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;nottarget&gt; on top, we should now match 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;nottarget&gt; on top, we should now match 2, 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;target&gt; on top, we should now match 1, 2, 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Adding an element &lt;nottarget&gt; on top, we should now match 0, 1, 2, 3, 4 and 5.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;nottarget&gt;, 0 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;target&gt;, 1 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;notarget&gt;, 2 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[12]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[13]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;target&gt;, 3 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[10]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[11]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;target&gt;, 4 should no longer match.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[8]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[9]).backgroundColor is &quot;rgb(1, 2, 3)&quot;
+Removing one of the &lt;target&gt;, there are only 4 siblings left, nothing can match.
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[0]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[1]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[2]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[3]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[4]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[5]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[6]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;target&quot;)[7]).backgroundColor is &quot;rgb(255, 255, 255)&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthchildstyleupdatehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-style-update.html (0 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-style-update.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-style-update.html        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -0,0 +1,110 @@
</span><ins>+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;style&gt;
+target {
+    background-color: white;
+}
+target:nth-child(n+5) {
+    background-color: rgb(1, 2, 3);
+}
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div id=&quot;with-renderer&quot;&gt;
+        &lt;target class=&quot;element_1&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_2&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_3&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_4&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_5&quot;&gt;&lt;/target&gt;
+    &lt;/div&gt;
+    &lt;div id=&quot;without-renderer&quot; style=&quot;display:none;&quot;&gt;
+        &lt;target class=&quot;element_1&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_2&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_3&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_4&quot;&gt;&lt;/target&gt;
+        &lt;target class=&quot;element_5&quot;&gt;&lt;/target&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test style update of :nth-child() when the tree structure is modified.');
+
+function testColor(classesThatShouldMatch) {
+    var allTargets = document.querySelectorAll(&quot;target&quot;);
+    for (var i = 0; i &lt; allTargets.length; ++i) {
+        var expectMath = classesThatShouldMatch.indexOf(allTargets[i].className) != -1;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;target&quot;)[' + i + ']).backgroundColor', expectMath ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    }
+}
+
+function addElementAsFirstChild(tagName, className)
+{
+    var newElement = document.createElement(tagName);
+    newElement.className = className;
+
+    var withRenderer = document.getElementById(&quot;with-renderer&quot;);
+    withRenderer.insertBefore(newElement, withRenderer.firstChild);
+
+    var withoutRenderer = document.getElementById(&quot;without-renderer&quot;);
+    withoutRenderer.insertBefore(newElement.cloneNode(), withoutRenderer.firstChild);
+}
+
+function removeElementsOfClass(className)
+{
+    var allElementsToRemove = document.querySelectorAll('.' + className);
+    for (var i = 0; i &lt; allElementsToRemove.length; ++i)
+        allElementsToRemove[i].parentElement.removeChild(allElementsToRemove[i]);
+}
+
+debug(&quot;Initialy, &amp;lt;foo&amp;gt; is the first of its type, the style should match.&quot;);
+testColor([&quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;target&amp;gt; on top, we should now match 4 and 5.&quot;);
+addElementAsFirstChild(&quot;target&quot;, &quot;element_0&quot;)
+testColor([&quot;element_4&quot;, &quot;element_5&quot;]);
+
+// Using nottarget is interesting because the ':nth-child()' part is not matched for those elements.
+debug(&quot;Adding an element &amp;lt;nottarget&amp;gt; on top, we should now match 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;nottarget&quot;, &quot;element_-1&quot;)
+testColor([&quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;nottarget&amp;gt; on top, we should now match 2, 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;nottarget&quot;, &quot;element_-2&quot;)
+testColor([&quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;target&amp;gt; on top, we should now match 1, 2, 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;target&quot;, &quot;element_-3&quot;)
+testColor([&quot;element_1&quot;, &quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Adding an element &amp;lt;nottarget&amp;gt; on top, we should now match 0, 1, 2, 3, 4 and 5.&quot;);
+addElementAsFirstChild(&quot;nottarget&quot;, &quot;element_-4&quot;)
+testColor([&quot;element_0&quot;, &quot;element_1&quot;, &quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;nottarget&amp;gt;, 0 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-2&quot;);
+testColor([&quot;element_1&quot;, &quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;target&amp;gt;, 1 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-4&quot;);
+testColor([&quot;element_2&quot;, &quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;notarget&amp;gt;, 2 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-1&quot;);
+testColor([&quot;element_3&quot;, &quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;target&amp;gt;, 3 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_-3&quot;);
+testColor([&quot;element_4&quot;, &quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;target&amp;gt;, 4 should no longer match.&quot;);
+removeElementsOfClass(&quot;element_0&quot;);
+testColor([&quot;element_5&quot;]);
+
+debug(&quot;Removing one of the &amp;lt;target&amp;gt;, there are only 4 siblings left, nothing can match.&quot;);
+removeElementsOfClass(&quot;element_1&quot;);
+testColor([]);
+
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/ChangeLog        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -1,3 +1,140 @@
</span><ins>+2014-09-03  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Fix style invalidation of elements with multiple siblings dependencies
+        https://bugs.webkit.org/show_bug.cgi?id=136472
+
+        Reviewed by Andreas Kling.
+
+        Previously, style invalidation of siblings was driven by a pair of flags:
+        -ChildrenAffectedByDirectAdjacentRules.
+        -ChildrenAffectedByForwardPositionalRules.
+
+        When ChildrenAffectedByDirectAdjacentRules was set, the element after an element
+        with &quot;needsStyleRecalc&quot; 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 &lt;a&gt; changes, the style of &lt;b&gt; was updated, which is useless. The style
+        of &lt;c&gt; was untouched, which is incorrect.
+
+        When ChildrenAffectedByForwardPositionalRules, all elements after one with &quot;needsStyleRecalc&quot;
+        were invalidated. While more correct, it caused avalanche of style recalc and was not a very
+        useful &quot;optimization&quot;.
+

+        To fix the correctness issues (e.g. &quot;a + b + c&quot;), 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 &quot;&lt;-&quot; for (1), &quot;-&gt;&quot; for (2), the selector &quot;a + b + c&quot; create this kind
+        of marking:
+            a  +  b  +  c
+            -&gt;    -&gt;
+                       &lt;-
+
+        When &lt;a&gt; 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 &lt;c&gt;.
+
+        Overlaps are possible. For example with the two selector, &quot;a + b + c&quot;, &quot;b ~ d&quot;
+        the marking would be
+            a  +  b  +  c  +  d
+            -&gt;    -&gt;    -&gt;
+                       &lt;-    &lt;-
+
+        A change in &lt;a&gt; would invalidate both &lt;c&gt; and &lt;d&gt;. 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):
+
</ins><span class="cx"> 2014-09-03  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Dump SimpleLineLayout info in showRenderTree() output
</span></span></pre></div>
<a id="trunkSourceWebCorecssSelectorCheckercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/SelectorChecker.cpp        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -68,9 +68,11 @@
</span><span class="cx">     return !ElementTraversal::nextSibling(element);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline bool isFirstOfType(const Element* element, const QualifiedName&amp; type)
</del><ins>+static inline bool isFirstOfType(Element* element, const QualifiedName&amp; type, bool isResolvingStyle)
</ins><span class="cx"> {
</span><del>-    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) {
</del><ins>+    for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) {
+        if (isResolvingStyle)
+            sibling-&gt;setAffectsNextSiblingElementStyle();
</ins><span class="cx">         if (sibling-&gt;hasTagName(type))
</span><span class="cx">             return false;
</span><span class="cx">     }
</span><span class="lines">@@ -86,10 +88,13 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline int countElementsBefore(const Element* element)
</del><ins>+static inline int countElementsBefore(Element* element, bool isResolvingStyle)
</ins><span class="cx"> {
</span><span class="cx">     int count = 0;
</span><del>-    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) {
</del><ins>+    for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) {
+        if (isResolvingStyle)
+            sibling-&gt;setAffectsNextSiblingElementStyle();
+
</ins><span class="cx">         unsigned index = sibling-&gt;childIndex();
</span><span class="cx">         if (index) {
</span><span class="cx">             count += index;
</span><span class="lines">@@ -100,10 +105,13 @@
</span><span class="cx">     return count;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static inline int countElementsOfTypeBefore(const Element* element, const QualifiedName&amp; type)
</del><ins>+static inline int countElementsOfTypeBefore(Element* element, const QualifiedName&amp; type, bool isResolvingStyle)
</ins><span class="cx"> {
</span><span class="cx">     int count = 0;
</span><del>-    for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) {
</del><ins>+    for (Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(sibling)) {
+        if (isResolvingStyle)
+            sibling-&gt;setAffectsNextSiblingElementStyle();
+
</ins><span class="cx">         if (sibling-&gt;hasTagName(type))
</span><span class="cx">             ++count;
</span><span class="cx">     }
</span><span class="lines">@@ -152,7 +160,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline static bool hasScrollbarPseudoElement(const SelectorChecker::SelectorCheckingContext&amp; context, PseudoId&amp; dynamicPseudo)
</del><ins>+inline static bool hasScrollbarPseudoElement(PseudoId&amp; dynamicPseudo)
</ins><span class="cx"> {
</span><span class="cx">     if (dynamicPseudo == SCROLLBAR
</span><span class="cx">         || dynamicPseudo == SCROLLBAR_THUMB
</span><span class="lines">@@ -160,7 +168,6 @@
</span><span class="cx">         || dynamicPseudo == SCROLLBAR_TRACK
</span><span class="cx">         || dynamicPseudo == SCROLLBAR_TRACK_PIECE
</span><span class="cx">         || dynamicPseudo == SCROLLBAR_CORNER) {
</span><del>-        ASSERT_UNUSED(context, context.scrollbar);
</del><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -266,26 +273,30 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">     case CSSSelector::DirectAdjacent:
</span><del>-        if (context.resolvingMode == Mode::ResolvingStyle) {
-            if (Element* parentElement = context.element-&gt;parentElement())
-                parentElement-&gt;setChildrenAffectedByDirectAdjacentRules();
</del><ins>+        {
+            if (context.resolvingMode == Mode::ResolvingStyle)
+                context.element-&gt;setStyleIsAffectedByPreviousSibling();
+
+            Element* previousElement = context.element-&gt;previousElementSibling();
+            if (!previousElement)
+                return SelectorFailsAllSiblings;
+            if (context.resolvingMode == Mode::ResolvingStyle)
+                previousElement-&gt;setAffectsNextSiblingElementStyle();
+            nextContext.element = previousElement;
+            nextContext.firstSelectorOfTheFragment = nextContext.selector;
+            nextContext.elementStyle = 0;
+            return matchRecursively(nextContext, ignoreDynamicPseudo);
</ins><span class="cx">         }
</span><del>-        nextContext.element = context.element-&gt;previousElementSibling();
-        if (!nextContext.element)
-            return SelectorFailsAllSiblings;
-        nextContext.firstSelectorOfTheFragment = nextContext.selector;
-        nextContext.elementStyle = 0;
-        return matchRecursively(nextContext, ignoreDynamicPseudo);
-
</del><span class="cx">     case CSSSelector::IndirectAdjacent:
</span><del>-        if (context.resolvingMode == Mode::ResolvingStyle) {
-            if (Element* parentElement = context.element-&gt;parentElement())
-                parentElement-&gt;setChildrenAffectedByForwardPositionalRules();
-        }
</del><ins>+        if (context.resolvingMode == Mode::ResolvingStyle)
+            context.element-&gt;setStyleIsAffectedByPreviousSibling();
</ins><span class="cx">         nextContext.element = context.element-&gt;previousElementSibling();
</span><span class="cx">         nextContext.firstSelectorOfTheFragment = nextContext.selector;
</span><span class="cx">         nextContext.elementStyle = 0;
</span><span class="cx">         for (; nextContext.element; nextContext.element = nextContext.element-&gt;previousElementSibling()) {
</span><ins>+            if (context.resolvingMode == Mode::ResolvingStyle)
+                context.element-&gt;setAffectsNextSiblingElementStyle();
+
</ins><span class="cx">             Match match = this-&gt;matchRecursively(nextContext, ignoreDynamicPseudo);
</span><span class="cx">             if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely)
</span><span class="cx">                 return match;
</span><span class="lines">@@ -296,7 +307,7 @@
</span><span class="cx">         // a selector is invalid if something follows a pseudo-element
</span><span class="cx">         // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
</span><span class="cx">         // to follow the pseudo elements.
</span><del>-        nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(context, dynamicPseudo);
</del><ins>+        nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(dynamicPseudo);
</ins><span class="cx">         nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION;
</span><span class="cx">         if ((context.elementStyle || context.resolvingMode == Mode::CollectingRules) &amp;&amp; dynamicPseudo != NOPSEUDO
</span><span class="cx">             &amp;&amp; !nextContext.hasSelectionPseudo
</span><span class="lines">@@ -553,11 +564,11 @@
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassFirstOfType:
</span><span class="cx">             // first-of-type matches the first element of its type
</span><del>-            if (Element* parentElement = element-&gt;parentElement()) {
-                bool result = isFirstOfType(element, element-&gt;tagQName());
</del><ins>+            if (element-&gt;parentElement()) {
</ins><span class="cx">                 if (context.resolvingMode == Mode::ResolvingStyle)
</span><del>-                    parentElement-&gt;setChildrenAffectedByForwardPositionalRules();
-                return result;
</del><ins>+                    element-&gt;setStyleIsAffectedByPreviousSibling();
+
+                return isFirstOfType(element, element-&gt;tagQName(), context.resolvingMode == Mode::ResolvingStyle);
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClassLastChild:
</span><span class="lines">@@ -603,12 +614,12 @@
</span><span class="cx">             // FIXME: This selector is very slow.
</span><span class="cx">             if (Element* parentElement = element-&gt;parentElement()) {
</span><span class="cx">                 if (context.resolvingMode == Mode::ResolvingStyle) {
</span><del>-                    parentElement-&gt;setChildrenAffectedByForwardPositionalRules();
</del><ins>+                    element-&gt;setStyleIsAffectedByPreviousSibling();
</ins><span class="cx">                     parentElement-&gt;setChildrenAffectedByBackwardPositionalRules();
</span><span class="cx">                 }
</span><span class="cx">                 if (!parentElement-&gt;isFinishedParsingChildren())
</span><span class="cx">                     return false;
</span><del>-                return isFirstOfType(element, element-&gt;tagQName()) &amp;&amp; isLastOfType(element, element-&gt;tagQName());
</del><ins>+                return isFirstOfType(element, element-&gt;tagQName(), context.resolvingMode == Mode::ResolvingStyle) &amp;&amp; isLastOfType(element, element-&gt;tagQName());
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx"> #if ENABLE(CSS_SELECTORS_LEVEL4)
</span><span class="lines">@@ -625,14 +636,16 @@
</span><span class="cx">         case CSSSelector::PseudoClassNthChild:
</span><span class="cx">             if (!selector-&gt;parseNth())
</span><span class="cx">                 break;
</span><del>-            if (Element* parentElement = element-&gt;parentElement()) {
-                int count = 1 + countElementsBefore(element);
</del><ins>+            if (element-&gt;parentElement()) {
+                if (context.resolvingMode == Mode::ResolvingStyle)
+                    element-&gt;setStyleIsAffectedByPreviousSibling();
+
+                int count = 1 + countElementsBefore(element, context.resolvingMode == Mode::ResolvingStyle);
</ins><span class="cx">                 if (context.resolvingMode == Mode::ResolvingStyle) {
</span><span class="cx">                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element-&gt;renderStyle();
</span><span class="cx">                     element-&gt;setChildIndex(count);
</span><span class="cx">                     if (childStyle)
</span><span class="cx">                         childStyle-&gt;setUnique();
</span><del>-                    parentElement-&gt;setChildrenAffectedByForwardPositionalRules();
</del><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 if (selector-&gt;matchNth(count))
</span><span class="lines">@@ -642,11 +655,12 @@
</span><span class="cx">         case CSSSelector::PseudoClassNthOfType:
</span><span class="cx">             if (!selector-&gt;parseNth())
</span><span class="cx">                 break;
</span><del>-            if (Element* parentElement = element-&gt;parentElement()) {
-                int count = 1 + countElementsOfTypeBefore(element, element-&gt;tagQName());
</del><ins>+
+            if (element-&gt;parentElement()) {
</ins><span class="cx">                 if (context.resolvingMode == Mode::ResolvingStyle)
</span><del>-                    parentElement-&gt;setChildrenAffectedByForwardPositionalRules();
</del><ins>+                    element-&gt;setStyleIsAffectedByPreviousSibling();
</ins><span class="cx"> 
</span><ins>+                int count = 1 + countElementsOfTypeBefore(element, element-&gt;tagQName(), context.resolvingMode == Mode::ResolvingStyle);
</ins><span class="cx">                 if (selector-&gt;matchNth(count))
</span><span class="cx">                     return true;
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceWebCorecssStyleResolvercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/StyleResolver.cpp (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/StyleResolver.cpp        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/css/StyleResolver.cpp        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -624,6 +624,8 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (element-&gt;additionalPresentationAttributeStyle() != state.styledElement()-&gt;additionalPresentationAttributeStyle())
</span><span class="cx">         return false;
</span><ins>+    if (element-&gt;affectsNextSiblingElementStyle() || element-&gt;styleIsAffectedByPreviousSibling())
+        return false;
</ins><span class="cx"> 
</span><span class="cx">     if (element-&gt;hasID() &amp;&amp; m_ruleSets.features().idsInRules.contains(element-&gt;idForStyleResolution().impl()))
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -224,8 +224,6 @@
</span><span class="cx">     void generateWalkToPreviousAdjacent(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><span class="cx">     void generateDirectAdjacentTreeWalker(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><span class="cx">     void generateIndirectAdjacentTreeWalker(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><del>-    void markParentElementIfResolvingStyle(int32_t);
-    void markParentElementIfResolvingStyle(JSC::FunctionPtr);
</del><span class="cx"> 
</span><span class="cx">     void linkFailures(Assembler::JumpList&amp; globalFailureCases, BacktrackingAction, Assembler::JumpList&amp; localFailureCases);
</span><span class="cx">     void generateAdjacentBacktrackingTail();
</span><span class="lines">@@ -273,6 +271,7 @@
</span><span class="cx">     void generateMarkPseudoStyleForPseudoElement(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><span class="cx">     void generateRequestedPseudoElementEqualsToSelectorPseudoElement(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;, Assembler::RegisterID checkingContext);
</span><span class="cx">     void generateSpecialFailureInQuirksModeForActiveAndHoverIfNeeded(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp;);
</span><ins>+    void markElementIfResolvingStyle(Assembler::RegisterID, int32_t);
</ins><span class="cx">     Assembler::JumpList jumpIfNoPreviousAdjacentElement();
</span><span class="cx">     Assembler::JumpList jumpIfNoNextAdjacentElement();
</span><span class="cx">     Assembler::Jump jumpIfNotResolvingStyle(Assembler::RegisterID checkingContextRegister);
</span><span class="lines">@@ -1339,6 +1338,16 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool isAdjacentRelation(FragmentRelation relation)
+{
+    return relation == FragmentRelation::DirectAdjacent || relation == FragmentRelation::IndirectAdjacent;
+}
+
+static bool shouldMarkStyleIsAffectedByPreviousSibling(const SelectorFragment&amp; fragment)
+{
+    return isAdjacentRelation(fragment.relationToLeftFragment) &amp;&amp; !isAdjacentRelation(fragment.relationToRightFragment);
+}
+
</ins><span class="cx"> void SelectorCodeGenerator::generateSelectorChecker()
</span><span class="cx"> {
</span><span class="cx">     StackAllocator::StackReferenceVector calleeSavedRegisterStackReferences;
</span><span class="lines">@@ -1401,6 +1410,8 @@
</span><span class="cx">             generateIndirectAdjacentTreeWalker(failureCases, fragment);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        if (shouldMarkStyleIsAffectedByPreviousSibling(fragment))
+            markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
</ins><span class="cx">         generateBacktrackingTailsIfNeeded(failureCases, fragment);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1560,9 +1571,8 @@
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateDirectAdjacentTreeWalker(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><del>-    markParentElementIfResolvingStyle(Node::flagChildrenAffectedByDirectAdjacentRulesFlag());
-
</del><span class="cx">     generateWalkToPreviousAdjacent(failureCases, fragment);
</span><ins>+    markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle());
</ins><span class="cx"> 
</span><span class="cx">     Assembler::JumpList matchingTagNameFailureCases;
</span><span class="cx">     Assembler::JumpList matchingPostTagNameFailureCases;
</span><span class="lines">@@ -1578,14 +1588,13 @@
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateIndirectAdjacentTreeWalker(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><del>-    markParentElementIfResolvingStyle(Element::setChildrenAffectedByForwardPositionalRules);
-
</del><span class="cx">     Assembler::Label loopStart(m_assembler.label());
</span><span class="cx"> 
</span><span class="cx">     if (fragment.backtrackingFlags &amp; BacktrackingFlag::IndirectAdjacentEntryPoint)
</span><span class="cx">         m_indirectAdjacentTreeWalkerBacktrackingPoint = m_assembler.label();
</span><span class="cx"> 
</span><span class="cx">     generateWalkToPreviousAdjacent(failureCases, fragment);
</span><ins>+    markElementIfResolvingStyle(elementAddressRegister, Node::flagAffectsNextSiblingElementStyle());
</ins><span class="cx"> 
</span><span class="cx">     if (fragment.backtrackingFlags &amp; BacktrackingFlag::IndirectAdjacentEntryPoint)
</span><span class="cx">         m_indirectAdjacentEntryPoint = m_assembler.label();
</span><span class="lines">@@ -1827,7 +1836,7 @@
</span><span class="cx">     assembler.or32(Assembler::TrustedImm32(flag), Assembler::Address(elementAddress, Node::nodeFlagsMemoryOffset()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SelectorCodeGenerator::markParentElementIfResolvingStyle(int32_t nodeFlag)
</del><ins>+void SelectorCodeGenerator::markElementIfResolvingStyle(Assembler::RegisterID element, int32_t nodeFlag)
</ins><span class="cx"> {
</span><span class="cx">     if (m_selectorContext == SelectorContext::QuerySelector)
</span><span class="cx">         return;
</span><span class="lines">@@ -1838,48 +1847,11 @@
</span><span class="cx">         skipMarking.append(jumpIfNotResolvingStyle(checkingContext));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    LocalRegister parentElement(m_registerAllocator);
-    generateWalkToParentElement(skipMarking, parentElement);
</del><ins>+    setNodeFlag(m_assembler, element, nodeFlag);
</ins><span class="cx"> 
</span><del>-    setNodeFlag(m_assembler, parentElement, nodeFlag);
-
</del><span class="cx">     skipMarking.link(&amp;m_assembler);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SelectorCodeGenerator::markParentElementIfResolvingStyle(JSC::FunctionPtr markingFunction)
-{
-    if (m_selectorContext == SelectorContext::QuerySelector)
-        return;
-
-    //     if (checkingContext.resolvingMode == ResolvingStyle) {
-    //         Element* parent = element-&gt;parentNode();
-    //         markingFunction(parent);
-    //     }
-
-    Assembler::JumpList skipMarking;
-    {
-        LocalRegister checkingContext(m_registerAllocator);
-        skipMarking.append(jumpIfNotResolvingStyle(checkingContext));
-    }
-
-    // Get the parent element in a temporary register.
-    Assembler::RegisterID parentElement = m_registerAllocator.allocateRegister();
-    generateWalkToParentElement(skipMarking, parentElement);
-
-    // Return the register parentElement just before the function call since we don't need it to be preserved
-    // on the stack.
-    m_registerAllocator.deallocateRegister(parentElement);
-
-    // Invoke the marking function on the parent element.
-    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-    functionCall.setFunctionAddress(markingFunction);
-    functionCall.setOneArgument(parentElement);
-    functionCall.call();
-
-    skipMarking.link(&amp;m_assembler);
-}
-
-
</del><span class="cx"> void SelectorCodeGenerator::linkFailures(Assembler::JumpList&amp; globalFailureCases, BacktrackingAction backtrackingAction, Assembler::JumpList&amp; localFailureCases)
</span><span class="cx"> {
</span><span class="cx">     switch (backtrackingAction) {
</span><span class="lines">@@ -2943,8 +2915,10 @@
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateElementIsNthChild(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><del>-    Assembler::RegisterID parentElement = m_registerAllocator.allocateRegister();
-    generateWalkToParentElement(failureCases, parentElement);
</del><ins>+    {
+        LocalRegister parentElement(m_registerAllocator);
+        generateWalkToParentElement(failureCases, parentElement);
+    }
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;std::pair&lt;int, int&gt;, 32&gt; validSubsetFilters;
</span><span class="cx">     validSubsetFilters.reserveInitialCapacity(fragment.nthChildFilters.size());
</span><span class="lines">@@ -2957,13 +2931,12 @@
</span><span class="cx">             continue;
</span><span class="cx">         validSubsetFilters.uncheckedAppend(slot);
</span><span class="cx">     }
</span><del>-    if (validSubsetFilters.isEmpty()) {
-        m_registerAllocator.deallocateRegister(parentElement);
</del><ins>+    if (validSubsetFilters.isEmpty())
</ins><span class="cx">         return;
</span><del>-    }
-    if (m_selectorContext == SelectorContext::QuerySelector)
-        m_registerAllocator.deallocateRegister(parentElement);
</del><span class="cx"> 
</span><ins>+    if (!isAdjacentRelation(fragment.relationToRightFragment))
+        markElementIfResolvingStyle(elementAddressRegister, Node::flagStyleIsAffectedByPreviousSibling());
+
</ins><span class="cx">     // Setup the counter at 1.
</span><span class="cx">     LocalRegisterWithPreference elementCounter(m_registerAllocator, JSC::GPRInfo::argumentGPR1);
</span><span class="cx">     m_assembler.move(Assembler::TrustedImm32(1), elementCounter);
</span><span class="lines">@@ -2980,6 +2953,7 @@
</span><span class="cx"> 
</span><span class="cx">         Assembler::JumpList noCachedChildIndexCases;
</span><span class="cx">         generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
</span><ins>+        markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
</ins><span class="cx">         noCachedChildIndexCases.append(m_assembler.branchTest32(Assembler::Zero, Assembler::Address(previousSibling, Node::nodeFlagsMemoryOffset()), Assembler::TrustedImm32(Node::flagHasRareData())));
</span><span class="cx">         {
</span><span class="cx">             LocalRegister elementRareData(m_registerAllocator);
</span><span class="lines">@@ -2995,6 +2969,7 @@
</span><span class="cx"> 
</span><span class="cx">         Assembler::Label loopStart = m_assembler.label();
</span><span class="cx">         generateWalkToPreviousAdjacentElement(noMoreSiblingsCases, previousSibling);
</span><ins>+        markElementIfResolvingStyle(previousSibling, Node::flagAffectsNextSiblingElementStyle());
</ins><span class="cx">         m_assembler.add32(Assembler::TrustedImm32(1), elementCounter);
</span><span class="cx">         m_assembler.jump().linkTo(loopStart, &amp;m_assembler);
</span><span class="cx">         noMoreSiblingsCases.link(&amp;m_assembler);
</span><span class="lines">@@ -3005,12 +2980,6 @@
</span><span class="cx">         LocalRegister checkingContext(m_registerAllocator);
</span><span class="cx">         Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
</span><span class="cx"> 
</span><del>-        m_registerAllocator.deallocateRegister(parentElement);
-        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(Element::setChildrenAffectedByForwardPositionalRules);
-        functionCall.setOneArgument(parentElement);
-        functionCall.call();
-
</del><span class="cx">         if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
</span><span class="cx">             addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagIsUnique());
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomDocumentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Document.cpp (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Document.cpp        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/dom/Document.cpp        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -6154,12 +6154,17 @@
</span><span class="cx">     if (node.needsStyleRecalc())
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    for (const Element* ancestor = node.parentOrShadowHostElement(); ancestor; ancestor = ancestor-&gt;parentOrShadowHostElement()) {
</del><ins>+    const Node* currentNode = &amp;node;
+    const Element* ancestor = currentNode-&gt;parentOrShadowHostElement();
+    while (ancestor) {
</ins><span class="cx">         if (ancestor-&gt;needsStyleRecalc())
</span><span class="cx">             return true;
</span><span class="cx"> 
</span><del>-        if (ancestor-&gt;directChildNeedsStyleRecalc() &amp;&amp; (ancestor-&gt;childrenAffectedByDirectAdjacentRules() || ancestor-&gt;childrenAffectedByForwardPositionalRules()))
</del><ins>+        if (ancestor-&gt;directChildNeedsStyleRecalc() &amp;&amp; currentNode-&gt;styleIsAffectedByPreviousSibling())
</ins><span class="cx">             return true;
</span><ins>+
+        currentNode = ancestor;
+        ancestor = currentNode-&gt;parentOrShadowHostElement();
</ins><span class="cx">     }
</span><span class="cx">     return false;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.cpp (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.cpp        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/dom/Element.cpp        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -1540,8 +1540,8 @@
</span><span class="cx"> {
</span><span class="cx">     // :empty selector.
</span><span class="cx">     checkForEmptyStyleChange(*parent);
</span><del>-    
-    if (parent-&gt;needsStyleRecalc() &amp;&amp; parent-&gt;childrenAffectedByPositionalRules())
</del><ins>+
+    if (parent-&gt;styleChangeType() &gt;= FullStyleChange)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
</span><span class="lines">@@ -1588,20 +1588,26 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // The + selector.  We need to invalidate the first element following the insertion point.  It is the only possible element
-    // that could be affected by this DOM change.
-    if (parent-&gt;childrenAffectedByDirectAdjacentRules() &amp;&amp; elementAfterChange)
-        elementAfterChange-&gt;setNeedsStyleRecalc();
</del><ins>+    if (elementAfterChange) {
+        if (elementAfterChange-&gt;styleIsAffectedByPreviousSibling())
+            elementAfterChange-&gt;setNeedsStyleRecalc();
+        else if (elementAfterChange-&gt;affectsNextSiblingElementStyle()) {
+            Element* elementToInvalidate = elementAfterChange;
+            do {
+                elementToInvalidate = elementToInvalidate-&gt;nextElementSibling();
+            } while (elementToInvalidate &amp;&amp; !elementToInvalidate-&gt;styleIsAffectedByPreviousSibling());
</ins><span class="cx"> 
</span><del>-    // Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
</del><ins>+            if (elementToInvalidate)
+                elementToInvalidate-&gt;setNeedsStyleRecalc();
+        }
+    }
+
</ins><span class="cx">     // Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
</span><span class="cx">     // We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
</span><span class="cx">     // backward case.
</span><span class="cx">     // |afterChange| is 0 in the parser callback case, so we won't do any work for the forward case if we don't have to.
</span><span class="cx">     // 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
</span><span class="cx">     // here.  recalcStyle will then force a walk of the children when it sees that this has happened.
</span><del>-    if (parent-&gt;childrenAffectedByForwardPositionalRules() &amp;&amp; elementAfterChange)
-        parent-&gt;setNeedsStyleRecalc();
</del><span class="cx">     if (parent-&gt;childrenAffectedByBackwardPositionalRules() &amp;&amp; elementBeforeChange)
</span><span class="cx">         parent-&gt;setNeedsStyleRecalc();
</span><span class="cx"> }
</span><span class="lines">@@ -2108,11 +2114,6 @@
</span><span class="cx">     ensureElementRareData().setChildrenAffectedByDrag(true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Element::setChildrenAffectedByForwardPositionalRules(Element* element)
-{
-    element-&gt;ensureElementRareData().setChildrenAffectedByForwardPositionalRules(true);
-}
-
</del><span class="cx"> void Element::setChildrenAffectedByBackwardPositionalRules()
</span><span class="cx"> {
</span><span class="cx">     ensureElementRareData().setChildrenAffectedByBackwardPositionalRules(true);
</span><span class="lines">@@ -2128,14 +2129,13 @@
</span><span class="cx"> 
</span><span class="cx"> bool Element::hasFlagsSetDuringStylingOfChildren() const
</span><span class="cx"> {
</span><del>-    if (childrenAffectedByHover() || childrenAffectedByFirstChildRules() || childrenAffectedByLastChildRules() || childrenAffectedByDirectAdjacentRules())
</del><ins>+    if (childrenAffectedByHover() || childrenAffectedByFirstChildRules() || childrenAffectedByLastChildRules())
</ins><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="cx">     if (!hasRareData())
</span><span class="cx">         return false;
</span><span class="cx">     return rareDataChildrenAffectedByActive()
</span><span class="cx">         || rareDataChildrenAffectedByDrag()
</span><del>-        || rareDataChildrenAffectedByForwardPositionalRules()
</del><span class="cx">         || rareDataChildrenAffectedByBackwardPositionalRules();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2157,12 +2157,6 @@
</span><span class="cx">     return elementRareData()-&gt;childrenAffectedByDrag();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Element::rareDataChildrenAffectedByForwardPositionalRules() const
-{
-    ASSERT(hasRareData());
-    return elementRareData()-&gt;childrenAffectedByForwardPositionalRules();
-}
-
</del><span class="cx"> bool Element::rareDataChildrenAffectedByBackwardPositionalRules() const
</span><span class="cx"> {
</span><span class="cx">     ASSERT(hasRareData());
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.h (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.h        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/dom/Element.h        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -360,12 +360,10 @@
</span><span class="cx">     bool childrenAffectedByHover() const { return getFlag(ChildrenAffectedByHoverRulesFlag); }
</span><span class="cx">     bool childrenAffectedByActive() const { return hasRareData() &amp;&amp; rareDataChildrenAffectedByActive(); }
</span><span class="cx">     bool childrenAffectedByDrag() const { return hasRareData() &amp;&amp; rareDataChildrenAffectedByDrag(); }
</span><del>-    bool childrenAffectedByPositionalRules() const { return hasRareData() &amp;&amp; (rareDataChildrenAffectedByForwardPositionalRules() || rareDataChildrenAffectedByBackwardPositionalRules()); }
</del><span class="cx">     bool childrenAffectedByFirstChildRules() const { return getFlag(ChildrenAffectedByFirstChildRulesFlag); }
</span><span class="cx">     bool childrenAffectedByLastChildRules() const { return getFlag(ChildrenAffectedByLastChildRulesFlag); }
</span><del>-    bool childrenAffectedByDirectAdjacentRules() const { return getFlag(ChildrenAffectedByDirectAdjacentRulesFlag); }
-    bool childrenAffectedByForwardPositionalRules() const { return hasRareData() &amp;&amp; rareDataChildrenAffectedByForwardPositionalRules(); }
</del><span class="cx">     bool childrenAffectedByBackwardPositionalRules() const { return hasRareData() &amp;&amp; rareDataChildrenAffectedByBackwardPositionalRules(); }
</span><ins>+    bool affectsNextSiblingElementStyle() const { return getFlag(AffectsNextSiblingElementStyle); }
</ins><span class="cx">     unsigned childIndex() const { return hasRareData() ? rareDataChildIndex() : 0; }
</span><span class="cx"> 
</span><span class="cx">     bool hasFlagsSetDuringStylingOfChildren() const;
</span><span class="lines">@@ -376,10 +374,9 @@
</span><span class="cx">     void setChildrenAffectedByDrag();
</span><span class="cx">     void setChildrenAffectedByFirstChildRules() { setFlag(ChildrenAffectedByFirstChildRulesFlag); }
</span><span class="cx">     void setChildrenAffectedByLastChildRules() { setFlag(ChildrenAffectedByLastChildRulesFlag); }
</span><del>-    void setChildrenAffectedByDirectAdjacentRules() { setFlag(ChildrenAffectedByDirectAdjacentRulesFlag); }
-    static void setChildrenAffectedByForwardPositionalRules(Element*);
-    void setChildrenAffectedByForwardPositionalRules() { setChildrenAffectedByForwardPositionalRules(this); }
</del><span class="cx">     void setChildrenAffectedByBackwardPositionalRules();
</span><ins>+    void setAffectsNextSiblingElementStyle() { setFlag(AffectsNextSiblingElementStyle); }
+    void setStyleIsAffectedByPreviousSibling() { setFlag(StyleIsAffectedByPreviousSibling); }
</ins><span class="cx">     void setChildIndex(unsigned);
</span><span class="cx"> 
</span><span class="cx">     void setRegionOversetState(RegionOversetState);
</span><span class="lines">@@ -650,7 +647,6 @@
</span><span class="cx">     bool rareDataChildrenAffectedByActive() const;
</span><span class="cx">     bool rareDataChildrenAffectedByDrag() const;
</span><span class="cx">     bool rareDataChildrenAffectedByLastChildRules() const;
</span><del>-    bool rareDataChildrenAffectedByForwardPositionalRules() const;
</del><span class="cx">     bool rareDataChildrenAffectedByBackwardPositionalRules() const;
</span><span class="cx">     unsigned rareDataChildIndex() const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementRareDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/ElementRareData.h (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/ElementRareData.h        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/dom/ElementRareData.h        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -75,8 +75,6 @@
</span><span class="cx"> 
</span><span class="cx">     bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; }
</span><span class="cx">     void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; }
</span><del>-    bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }
-    void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; }
</del><span class="cx">     bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
</span><span class="cx">     void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; }
</span><span class="cx"> 
</span><span class="lines">@@ -132,7 +130,6 @@
</span><span class="cx">     // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
</span><span class="cx">     // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
</span><span class="cx">     unsigned m_childrenAffectedByLastChildRules : 1;
</span><del>-    unsigned m_childrenAffectedByForwardPositionalRules : 1;
</del><span class="cx">     unsigned m_childrenAffectedByBackwardPositionalRules : 1;
</span><span class="cx"> 
</span><span class="cx">     RegionOversetState m_regionOversetState;
</span><span class="lines">@@ -173,7 +170,6 @@
</span><span class="cx">     , m_childrenAffectedByActive(false)
</span><span class="cx">     , m_childrenAffectedByDrag(false)
</span><span class="cx">     , m_childrenAffectedByLastChildRules(false)
</span><del>-    , m_childrenAffectedByForwardPositionalRules(false)
</del><span class="cx">     , m_childrenAffectedByBackwardPositionalRules(false)
</span><span class="cx">     , m_regionOversetState(RegionUndefined)
</span><span class="cx">     , m_minimumSizeForResizing(defaultMinimumSizeForResizing())
</span><span class="lines">@@ -211,7 +207,6 @@
</span><span class="cx">     setChildrenAffectedByActive(false);
</span><span class="cx">     setChildrenAffectedByDrag(false);
</span><span class="cx">     setChildrenAffectedByLastChildRules(false);
</span><del>-    setChildrenAffectedByForwardPositionalRules(false);
</del><span class="cx">     setChildrenAffectedByBackwardPositionalRules(false);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoredomNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Node.h (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Node.h        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/dom/Node.h        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -325,6 +325,7 @@
</span><span class="cx">     bool needsStyleRecalc() const { return styleChangeType() != NoStyleChange; }
</span><span class="cx">     StyleChangeType styleChangeType() const { return static_cast&lt;StyleChangeType&gt;(m_nodeFlags &amp; StyleChangeMask); }
</span><span class="cx">     bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
</span><ins>+    bool styleIsAffectedByPreviousSibling() const { return getFlag(StyleIsAffectedByPreviousSibling); }
</ins><span class="cx">     bool isLink() const { return getFlag(IsLinkFlag); }
</span><span class="cx">     bool isEditingText() const { return getFlag(IsEditingTextFlag); }
</span><span class="cx"> 
</span><span class="lines">@@ -578,7 +579,9 @@
</span><span class="cx">     static int32_t flagIsParsingChildrenFinished() { return IsParsingChildrenFinishedFlag; }
</span><span class="cx">     static int32_t flagChildrenAffectedByFirstChildRulesFlag() { return ChildrenAffectedByFirstChildRulesFlag; }
</span><span class="cx">     static int32_t flagChildrenAffectedByLastChildRulesFlag() { return ChildrenAffectedByLastChildRulesFlag; }
</span><del>-    static int32_t flagChildrenAffectedByDirectAdjacentRulesFlag() { return ChildrenAffectedByDirectAdjacentRulesFlag; }
</del><ins>+
+    static int32_t flagAffectsNextSiblingElementStyle() { return AffectsNextSiblingElementStyle; }
+    static int32_t flagStyleIsAffectedByPreviousSibling() { return StyleIsAffectedByPreviousSibling; }
</ins><span class="cx"> #endif // ENABLE(CSS_SELECTOR_JIT)
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="lines">@@ -612,13 +615,13 @@
</span><span class="cx"> 
</span><span class="cx">         ChildrenAffectedByFirstChildRulesFlag = 1 &lt;&lt; 25,
</span><span class="cx">         ChildrenAffectedByLastChildRulesFlag = 1 &lt;&lt; 26,
</span><del>-        ChildrenAffectedByDirectAdjacentRulesFlag = 1 &lt;&lt; 27,
-        ChildrenAffectedByHoverRulesFlag = 1 &lt;&lt; 28,
-        DirectChildNeedsStyleRecalcFlag = 1 &lt;&lt; 29,
</del><ins>+        ChildrenAffectedByHoverRulesFlag = 1 &lt;&lt; 27,
</ins><span class="cx"> 
</span><del>-        SelfOrAncestorHasDirAutoFlag = 1 &lt;&lt; 30,
</del><ins>+        DirectChildNeedsStyleRecalcFlag = 1 &lt;&lt; 28,
+        AffectsNextSiblingElementStyle = 1 &lt;&lt; 29,
+        StyleIsAffectedByPreviousSibling = 1 &lt;&lt; 30,
</ins><span class="cx"> 
</span><del>-        IsHTMLUnknownElementFlag = 1 &lt;&lt; 31,
</del><ins>+        SelfOrAncestorHasDirAutoFlag = 1 &lt;&lt; 31,
</ins><span class="cx"> 
</span><span class="cx">         DefaultNodeFlags = IsParsingChildrenFinishedFlag
</span><span class="cx">     };
</span><span class="lines">@@ -642,8 +645,7 @@
</span><span class="cx">         CreateDocument = CreateContainer | InDocumentFlag,
</span><span class="cx">         CreateInsertionPoint = CreateHTMLElement | NeedsNodeRenderingTraversalSlowPathFlag,
</span><span class="cx">         CreateEditingText = CreateText | IsEditingTextFlag,
</span><del>-        CreateMathMLElement = CreateStyledElement | IsMathMLFlag,
-        CreateHTMLUnknownElement = CreateHTMLElement | IsHTMLUnknownElementFlag,
</del><ins>+        CreateMathMLElement = CreateStyledElement | IsMathMLFlag
</ins><span class="cx">     };
</span><span class="cx">     Node(Document&amp;, ConstructionType);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLElement.h (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLElement.h        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/html/HTMLElement.h        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -88,7 +88,7 @@
</span><span class="cx">     bool hasDirectionAuto() const;
</span><span class="cx">     TextDirection directionalityIfhasDirAutoAttribute(bool&amp; isAuto) const;
</span><span class="cx"> 
</span><del>-    bool isHTMLUnknownElement() const { return getFlag(IsHTMLUnknownElementFlag); }
</del><ins>+    virtual bool isHTMLUnknownElement() const { return false; }
</ins><span class="cx">     virtual bool isTextControlInnerTextElement() const { return false; }
</span><span class="cx"> 
</span><span class="cx">     virtual bool willRespondToMouseMoveEvents() override;
</span></span></pre></div>
<a id="trunkSourceWebCorehtmlHTMLUnknownElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/html/HTMLUnknownElement.h (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/html/HTMLUnknownElement.h        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/html/HTMLUnknownElement.h        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -41,9 +41,11 @@
</span><span class="cx">         return adoptRef(new HTMLUnknownElement(tagName, document));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    virtual bool isHTMLUnknownElement() const override { return true; }
+
</ins><span class="cx"> private:
</span><span class="cx">     HTMLUnknownElement(const QualifiedName&amp; tagName, Document&amp; document)
</span><del>-        : HTMLElement(tagName, document, CreateHTMLUnknownElement)
</del><ins>+        : HTMLElement(tagName, document, CreateHTMLElement)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorestyleStyleResolveTreecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/style/StyleResolveTree.cpp (173228 => 173229)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/style/StyleResolveTree.cpp        2014-09-03 21:29:52 UTC (rev 173228)
+++ trunk/Source/WebCore/style/StyleResolveTree.cpp        2014-09-03 21:30:31 UTC (rev 173229)
</span><span class="lines">@@ -552,13 +552,21 @@
</span><span class="cx"> static void resetStyleForNonRenderedDescendants(Element&amp; current)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!current.renderer());
</span><del>-    bool shouldInvalidateDirectChildren = current.directChildNeedsStyleRecalc() &amp;&amp; (current.childrenAffectedByDirectAdjacentRules() || current.childrenAffectedByForwardPositionalRules());
</del><ins>+    bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
</ins><span class="cx">     for (auto&amp; child : childrenOfType&lt;Element&gt;(current)) {
</span><span class="cx">         ASSERT(!child.renderer());
</span><del>-        if (shouldInvalidateDirectChildren || child.needsStyleRecalc()) {
</del><ins>+        if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
+            if (child.styleIsAffectedByPreviousSibling())
+                child.setNeedsStyleRecalc();
+            elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle();
+        }
+
+        if (child.needsStyleRecalc()) {
</ins><span class="cx">             child.resetComputedStyle();
</span><span class="cx">             child.clearNeedsStyleRecalc();
</span><ins>+            elementNeedingStyleRecalcAffectsNextSiblingElementStyle = child.affectsNextSiblingElementStyle();
</ins><span class="cx">         }
</span><ins>+
</ins><span class="cx">         if (child.childNeedsStyleRecalc()) {
</span><span class="cx">             resetStyleForNonRenderedDescendants(child);
</span><span class="cx">             child.clearChildNeedsStyleRecalc();
</span><span class="lines">@@ -897,9 +905,6 @@
</span><span class="cx">             return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool hasDirectAdjacentRules = current.childrenAffectedByDirectAdjacentRules();
-    bool hasIndirectAdjacentRules = current.childrenAffectedByForwardPositionalRules();
-
</del><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     CheckForVisibilityChangeOnRecalcStyle checkForVisibilityChange(&amp;current, current.renderStyle());
</span><span class="cx"> #endif
</span><span class="lines">@@ -925,11 +930,7 @@
</span><span class="cx">         RenderTreePosition childRenderTreePosition(*renderer);
</span><span class="cx">         updateBeforeOrAfterPseudoElement(current, change, BEFORE, childRenderTreePosition);
</span><span class="cx"> 
</span><del>-        // FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
-        // For now we will just worry about the common case, since it's a lot trickier to get the second case right
-        // without doing way too much re-resolution.
-        bool forceCheckOfNextElementSibling = false;
-        bool forceCheckOfAnyElementSibling = false;
</del><ins>+        bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
</ins><span class="cx">         for (Node* child = current.firstChild(); child; child = child-&gt;nextSibling()) {
</span><span class="cx">             if (RenderObject* childRenderer = child-&gt;renderer())
</span><span class="cx">                 childRenderTreePosition.invalidateNextSibling(*childRenderer);
</span><span class="lines">@@ -939,16 +940,18 @@
</span><span class="cx">             }
</span><span class="cx">             if (!child-&gt;isElementNode())
</span><span class="cx">                 continue;
</span><ins>+
</ins><span class="cx">             Element* childElement = toElement(child);
</span><del>-            bool childRulesChanged = childElement-&gt;needsStyleRecalc() &amp;&amp; childElement-&gt;styleChangeType() == FullStyleChange;
-            if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
-                childElement-&gt;setNeedsStyleRecalc();
</del><ins>+            if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
+                if (childElement-&gt;styleIsAffectedByPreviousSibling())
+                    childElement-&gt;setNeedsStyleRecalc();
+                elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement-&gt;affectsNextSiblingElementStyle();
+            } else if (childElement-&gt;styleChangeType() &gt;= FullStyleChange)
+                elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement-&gt;affectsNextSiblingElementStyle();
</ins><span class="cx">             if (change &gt;= Inherit || childElement-&gt;childNeedsStyleRecalc() || childElement-&gt;needsStyleRecalc()) {
</span><span class="cx">                 parentPusher.push();
</span><span class="cx">                 resolveTree(*childElement, renderer-&gt;style(), childRenderTreePosition, change);
</span><span class="cx">             }
</span><del>-            forceCheckOfNextElementSibling = childRulesChanged &amp;&amp; hasDirectAdjacentRules;
-            forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged &amp;&amp; hasIndirectAdjacentRules);
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         updateBeforeOrAfterPseudoElement(current, change, AFTER, childRenderTreePosition);
</span></span></pre>
</div>
</div>

</body>
</html>