<!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>[178150] 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/178150">178150</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2015-01-08 17:50:41 -0800 (Thu, 08 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make better use of the stack when compiling selectors
https://bugs.webkit.org/show_bug.cgi?id=139615
rdar://problem/19226482

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2015-01-08
Reviewed by Andreas Kling.

Source/WebCore:

Selectors used to be only on one level. To avoid memory allocations, we were allocating
a lot of stack upfront and we were using that to create all the intermediary objects
used by the code generator.

Then, selectors became multilevel. We now support arbitrary nesting of selector lists.

We did not adapt any of the structures and the creation of the intermediary object is recursive.
This resulted in over 1k of stack allocation at every level, quickly accumulating to unreasonable
numbers.

This patch fixes this problem by making each stack frame of the recursion much lighter.
We no longer allocate the big objects (SelectorFragment and SelectorFragmentList) on the stack.

In each case where we would have used a Stack allocated SelectorFragment or SelectorFragmentList,
we now allocate the memory directly into the target vector.

In the cases where the object should not be on the vector, we simply remove it. Those are uncommon
cases so that should not be too bad.

Tests: fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html
       fast/selectors/not-selector-list-ending-with-never-matching-selectors.html
       fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html
       fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html

* cssjit/SelectorCompiler.cpp:
SelectorFragmentList is also used for nested lists. Keeping 32 SelectorFragment preallocated
for each nested list is way too big.

(WebCore::SelectorCompiler::addPseudoClassType):
There are three cases of nested selector lists supported by the compiler: :matches(), :not()
and :nth-child(). For those 3 cases, use the target vector memory instead of the stack.

(WebCore::SelectorCompiler::constructFragmentsInternal):
(WebCore::SelectorCompiler::constructFragments):
Make sure we do not modify the input list on failure since it may be reused.

(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatchesSelectorList):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatchesMatchesPseudoClass):
I changed the handling of :nth-child(An+B of selectorList) to not generate empty filters.
With that we can generalize the assertion to generateElementMatchesSelectorList() and simplify
the flow of selector lists a bit.

LayoutTests:

Those tests are checking the tail behavior of the various loop, just in case.

* fast/selectors/matches-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
* fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html: Added.
* fast/selectors/not-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
* fast/selectors/not-selector-list-ending-with-never-matching-selectors.html: Added.
* fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
* fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html: Added.
* fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
* fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssjitSelectorCompilercpp">trunk/Source/WebCore/cssjit/SelectorCompiler.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastselectorsmatchesselectorlistendingwithnevermatchingselectorsexpectedtxt">trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsmatchesselectorlistendingwithnevermatchingselectorshtml">trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnotselectorlistendingwithnevermatchingselectorsexpectedtxt">trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnotselectorlistendingwithnevermatchingselectorshtml">trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchildofselectorlistendingwithnevermatchingselectorsexpectedtxt">trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthchildofselectorlistendingwithnevermatchingselectorshtml">trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthlastchildofselectorlistendingwithnevermatchingselectorsexpectedtxt">trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastselectorsnthlastchildofselectorlistendingwithnevermatchingselectorshtml">trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (178149 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-01-09 01:42:10 UTC (rev 178149)
+++ trunk/LayoutTests/ChangeLog        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2015-01-08  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        Make better use of the stack when compiling selectors
+        https://bugs.webkit.org/show_bug.cgi?id=139615
+        rdar://problem/19226482
+
+        Reviewed by Andreas Kling.
+
+        Those tests are checking the tail behavior of the various loop, just in case.
+
+        * fast/selectors/matches-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
+        * fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html: Added.
+        * fast/selectors/not-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
+        * fast/selectors/not-selector-list-ending-with-never-matching-selectors.html: Added.
+        * fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
+        * fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html: Added.
+        * fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors-expected.txt: Added.
+        * fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html: Added.
+
</ins><span class="cx"> 2015-01-08  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Further twek the results for kerning and ligature related failures:
</span></span></pre></div>
<a id="trunkLayoutTestsfastselectorsmatchesselectorlistendingwithnevermatchingselectorsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors-expected.txt (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors-expected.txt        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+Test :matches() with a selector list ending with selector that can never match.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Testing &quot;testcase:matches(.bar, :not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:matches(.bar, :not(*))').length is 1
+PASS document.querySelectorAll('#test-root testcase:matches(.bar, :not(*))')[0].id is &quot;testcase1&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;testcase:matches(.bazoo, *:not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:matches(.bazoo, *:not(*))').length is 1
+PASS document.querySelectorAll('#test-root testcase:matches(.bazoo, *:not(*))')[0].id is &quot;testcase2&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;testcase:matches(.baz, #foo#bar)&quot;
+PASS document.querySelectorAll('#test-root testcase:matches(.baz, #foo#bar)').length is 1
+PASS document.querySelectorAll('#test-root testcase:matches(.baz, #foo#bar)')[0].id is &quot;testcase3&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+
+Testing &quot;testcase:matches(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:matches(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))').length is 1
+PASS document.querySelectorAll('#test-root testcase:matches(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase1&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;testcase:matches(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:matches(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))').length is 1
+PASS document.querySelectorAll('#test-root testcase:matches(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase2&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsmatchesselectorlistendingwithnevermatchingselectorshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,56 @@
</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;
+#test-root * {
+    background-color: red;
+}
+&lt;/style&gt;
+&lt;style id=&quot;style&quot;&gt;
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div style=&quot;display:none&quot; id=&quot;test-root&quot;&gt;
+        &lt;testcase id=&quot;testcase1&quot; class=&quot;bar&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcase id=&quot;testcase2&quot; class=&quot;bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcase id=&quot;testcase3&quot; class=&quot;baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test :matches() with a selector list ending with selector that can never match.');
+
+function testQuerySelector(selector, expectedIds) {
+    shouldBe(&quot;document.querySelectorAll('&quot; + selector + &quot;').length&quot;, '' + expectedIds.length);
+    for (var i = 0; i &lt; expectedIds.length; ++i)
+        shouldBeEqualToString(&quot;document.querySelectorAll('&quot; + selector + &quot;')[&quot; + i + &quot;].id&quot;, expectedIds[i]);
+}
+
+function testStyling(selector, expectedIds) {
+    var stylingElement = document.getElementById(&quot;style&quot;);
+    stylingElement.innerHTML = '' + selector + ' { background-color: rgb(10, 100, 200); }';
+
+    var allTestCases = document.querySelectorAll(&quot;#test-root *&quot;);
+    for (var i = 0; i &lt; allTestCases.length; ++i) {
+        var expectMatch = expectedIds.indexOf(allTestCases[i].id) &gt;= 0;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[' + i + ']).backgroundColor', expectMatch ? 'rgb(10, 100, 200)' : 'rgb(255, 0, 0)');
+    }
+
+    stylingElement.innerHTML = '';
+}
+
+function testSelector(selector, expectedIds) {
+    debug(&quot;Testing \&quot;&quot; + selector + &quot;\&quot;&quot;);
+    testQuerySelector(&quot;#test-root &quot; + selector, expectedIds);
+    testStyling(&quot;#test-root &quot; + selector, expectedIds);
+    debug(&quot;&quot;);
+}
+
+testSelector(&quot;testcase:matches(.bar, :not(*))&quot;, [&quot;testcase1&quot;]);
+testSelector(&quot;testcase:matches(.bazoo, *:not(*))&quot;, [&quot;testcase2&quot;]);
+testSelector(&quot;testcase:matches(.baz, #foo#bar)&quot;, [&quot;testcase3&quot;]);
+testSelector(&quot;testcase:matches(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase1&quot;]);
+testSelector(&quot;testcase:matches(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase2&quot;]);
+&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="trunkLayoutTestsfastselectorsnotselectorlistendingwithnevermatchingselectorsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors-expected.txt (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors-expected.txt        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+Test :not() with a selector list ending with selector that can never match.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Testing &quot;testcase:not(.bar, :not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bar, :not(*))').length is 2
+PASS document.querySelectorAll('#test-root testcase:not(.bar, :not(*))')[0].id is &quot;testcase2&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bar, :not(*))')[1].id is &quot;testcase3&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+
+Testing &quot;testcase:not(.bazoo, *:not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bazoo, *:not(*))').length is 2
+PASS document.querySelectorAll('#test-root testcase:not(.bazoo, *:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bazoo, *:not(*))')[1].id is &quot;testcase3&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+
+Testing &quot;testcase:not(.baz, #foo#bar)&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.baz, #foo#bar)').length is 2
+PASS document.querySelectorAll('#test-root testcase:not(.baz, #foo#bar)')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.baz, #foo#bar)')[1].id is &quot;testcase2&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;testcase:not(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))').length is 2
+PASS document.querySelectorAll('#test-root testcase:not(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase2&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))')[1].id is &quot;testcase3&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+
+Testing &quot;testcase:not(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))').length is 2
+PASS document.querySelectorAll('#test-root testcase:not(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root testcase:not(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[1].id is &quot;testcase3&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnotselectorlistendingwithnevermatchingselectorshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors.html (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/not-selector-list-ending-with-never-matching-selectors.html        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,56 @@
</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;
+#test-root * {
+    background-color: red;
+}
+&lt;/style&gt;
+&lt;style id=&quot;style&quot;&gt;
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div style=&quot;display:none&quot; id=&quot;test-root&quot;&gt;
+        &lt;testcase id=&quot;testcase1&quot; class=&quot;bar&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcase id=&quot;testcase2&quot; class=&quot;bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcase id=&quot;testcase3&quot; class=&quot;baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Test :not() with a selector list ending with selector that can never match.');
+
+function testQuerySelector(selector, expectedIds) {
+    shouldBe(&quot;document.querySelectorAll('&quot; + selector + &quot;').length&quot;, '' + expectedIds.length);
+    for (var i = 0; i &lt; expectedIds.length; ++i)
+        shouldBeEqualToString(&quot;document.querySelectorAll('&quot; + selector + &quot;')[&quot; + i + &quot;].id&quot;, expectedIds[i]);
+}
+
+function testStyling(selector, expectedIds) {
+    var stylingElement = document.getElementById(&quot;style&quot;);
+    stylingElement.innerHTML = '' + selector + ' { background-color: rgb(10, 100, 200); }';
+
+    var allTestCases = document.querySelectorAll(&quot;#test-root *&quot;);
+    for (var i = 0; i &lt; allTestCases.length; ++i) {
+        var expectMatch = expectedIds.indexOf(allTestCases[i].id) &gt;= 0;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[' + i + ']).backgroundColor', expectMatch ? 'rgb(10, 100, 200)' : 'rgb(255, 0, 0)');
+    }
+
+    stylingElement.innerHTML = '';
+}
+
+function testSelector(selector, expectedIds) {
+    debug(&quot;Testing \&quot;&quot; + selector + &quot;\&quot;&quot;);
+    testQuerySelector(&quot;#test-root &quot; + selector, expectedIds);
+    testStyling(&quot;#test-root &quot; + selector, expectedIds);
+    debug(&quot;&quot;);
+}
+
+testSelector(&quot;testcase:not(.bar, :not(*))&quot;, [&quot;testcase2&quot;, &quot;testcase3&quot;]);
+testSelector(&quot;testcase:not(.bazoo, *:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase3&quot;]);
+testSelector(&quot;testcase:not(.baz, #foo#bar)&quot;, [&quot;testcase1&quot;, &quot;testcase2&quot;]);
+testSelector(&quot;testcase:not(.bar, #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase2&quot;, &quot;testcase3&quot;]);
+testSelector(&quot;testcase:not(.bazoo, #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase3&quot;]);
+&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="trunkLayoutTestsfastselectorsnthchildofselectorlistendingwithnevermatchingselectorsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors-expected.txt (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors-expected.txt        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,209 @@
</span><ins>+Check the basic features of the &quot;:nth-child(An+B of selectorList)&quot; with a selector which ending with selectors that never match.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Testing &quot;:nth-child(n+1 of testcaseA[attribute3], :not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], :not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-child(n+1 of testcaseA[attribute3], *:not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], *:not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-child(n+1 of testcaseA[attribute3], #foo#bar)&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)').length is 7
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar)')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthchildofselectorlistendingwithnevermatchingselectorshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,83 @@
</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;
+#test-root * {
+    background-color: red;
+}
+&lt;/style&gt;
+&lt;style id=&quot;style&quot;&gt;
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div style=&quot;display:none&quot; id=&quot;test-root&quot;&gt;
+        &lt;testcaseA id=&quot;testcase1&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase2&quot; class=&quot;bar baz bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase3&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase4&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase5&quot; class=&quot;foo baz bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase6&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase7&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase8&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase9&quot; class=&quot;foo bar bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase10&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase11&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase12&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase13&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase14&quot; class=&quot;foo bar baz&quot; attribute2=&quot;value2&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase15&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase16&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase17&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase18&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase19&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase20&quot; class=&quot;bar baz bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase21&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase22&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase23&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase24&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase25&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase26&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase27&quot; class=&quot;foo baz bazoo&quot; attribute2=&quot;value2&quot;&gt;&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase28&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase29&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase30&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot;&gt;Not empty&lt;/testcaseB&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Check the basic features of the &quot;:nth-child(An+B of selectorList)&quot; with a selector which ending with selectors that never match.');
+
+function testQuerySelector(selector, expectedIds) {
+    shouldBe(&quot;document.querySelectorAll('&quot; + selector + &quot;').length&quot;, '' + expectedIds.length);
+    for (var i = 0; i &lt; expectedIds.length; ++i)
+        shouldBeEqualToString(&quot;document.querySelectorAll('&quot; + selector + &quot;')[&quot; + i + &quot;].id&quot;, expectedIds[i]);
+}
+
+function testStyling(selector, expectedIds) {
+    var stylingElement = document.getElementById(&quot;style&quot;);
+    stylingElement.innerHTML = '' + selector + ' { background-color: rgb(10, 100, 200); }';
+
+    var allTestCases = document.querySelectorAll(&quot;#test-root *&quot;);
+    for (var i = 0; i &lt; allTestCases.length; ++i) {
+        var expectMatch = expectedIds.indexOf(allTestCases[i].id) &gt;= 0;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[' + i + ']).backgroundColor', expectMatch ? 'rgb(10, 100, 200)' : 'rgb(255, 0, 0)');
+    }
+
+    stylingElement.innerHTML = '';
+}
+
+function testSelector(selector, expectedIds) {
+    debug(&quot;Testing \&quot;&quot; + selector + &quot;\&quot;&quot;);
+    testQuerySelector(&quot;#test-root &quot; + selector, expectedIds);
+    testStyling(&quot;#test-root &quot; + selector, expectedIds);
+    debug(&quot;&quot;);
+}
+
+testSelector(&quot;:nth-child(n+1 of testcaseA[attribute3], :not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-child(n+1 of testcaseA[attribute3], *:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-child(n+1 of testcaseA[attribute3], #foo#bar)&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+&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="trunkLayoutTestsfastselectorsnthlastchildofselectorlistendingwithnevermatchingselectorsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors-expected.txt (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors-expected.txt        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,209 @@
</span><ins>+Check the basic features of the &quot;:nth-last-child(An+B of selectorList)&quot; with a selector which ending with selectors that never match.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Testing &quot;:nth-last-child(n+1 of testcaseA[attribute3], :not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], :not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-last-child(n+1 of testcaseA[attribute3], *:not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], *:not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)').length is 7
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+Testing &quot;:nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))').length is 7
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[0].id is &quot;testcase1&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[1].id is &quot;testcase5&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[2].id is &quot;testcase9&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[3].id is &quot;testcase13&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[4].id is &quot;testcase17&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[5].id is &quot;testcase21&quot;
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))')[6].id is &quot;testcase25&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[0]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[1]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[2]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[3]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[4]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[5]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[6]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[7]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[8]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[9]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[10]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[11]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[12]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[13]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[14]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[15]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[16]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[17]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[18]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[19]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[20]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[21]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[22]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[23]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[24]).backgroundColor is &quot;rgb(10, 100, 200)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[25]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[26]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[27]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[28]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+PASS getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[29]).backgroundColor is &quot;rgb(255, 0, 0)&quot;
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastselectorsnthlastchildofselectorlistendingwithnevermatchingselectorshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html (0 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html                                (rev 0)
+++ trunk/LayoutTests/fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -0,0 +1,83 @@
</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;
+#test-root * {
+    background-color: red;
+}
+&lt;/style&gt;
+&lt;style id=&quot;style&quot;&gt;
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+    &lt;div style=&quot;display:none&quot; id=&quot;test-root&quot;&gt;
+        &lt;testcaseA id=&quot;testcase1&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase2&quot; class=&quot;bar baz bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase3&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase4&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase5&quot; class=&quot;foo baz bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase6&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase7&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase8&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase9&quot; class=&quot;foo bar bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase10&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase11&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase12&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase13&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase14&quot; class=&quot;foo bar baz&quot; attribute2=&quot;value2&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase15&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase16&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase17&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase18&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase19&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase20&quot; class=&quot;bar baz bazoo&quot; attribute2=&quot;value2&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase21&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase22&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase23&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase24&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase25&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase26&quot; attribute1=&quot;value1&quot; class=&quot;bar baz bazoo&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase27&quot; class=&quot;foo baz bazoo&quot; attribute2=&quot;value2&quot;&gt;&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase28&quot; attribute1=&quot;value1&quot; class=&quot;foo baz bazoo&quot; attribute3=&quot;value3&quot;&gt;Not empty&lt;/testcaseB&gt;
+        &lt;testcaseA id=&quot;testcase29&quot; attribute1=&quot;value1&quot; class=&quot;foo bar bazoo&quot;&gt;Not empty&lt;/testcaseA&gt;
+        &lt;testcaseB id=&quot;testcase30&quot; attribute1=&quot;value1&quot; class=&quot;foo bar baz&quot;&gt;Not empty&lt;/testcaseB&gt;
+    &lt;/div&gt;
+&lt;/body&gt;
+&lt;script&gt;
+description('Check the basic features of the &quot;:nth-last-child(An+B of selectorList)&quot; with a selector which ending with selectors that never match.');
+
+function testQuerySelector(selector, expectedIds) {
+    shouldBe(&quot;document.querySelectorAll('&quot; + selector + &quot;').length&quot;, '' + expectedIds.length);
+    for (var i = 0; i &lt; expectedIds.length; ++i)
+        shouldBeEqualToString(&quot;document.querySelectorAll('&quot; + selector + &quot;')[&quot; + i + &quot;].id&quot;, expectedIds[i]);
+}
+
+function testStyling(selector, expectedIds) {
+    var stylingElement = document.getElementById(&quot;style&quot;);
+    stylingElement.innerHTML = '' + selector + ' { background-color: rgb(10, 100, 200); }';
+
+    var allTestCases = document.querySelectorAll(&quot;#test-root *&quot;);
+    for (var i = 0; i &lt; allTestCases.length; ++i) {
+        var expectMatch = expectedIds.indexOf(allTestCases[i].id) &gt;= 0;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll(&quot;#test-root *&quot;)[' + i + ']).backgroundColor', expectMatch ? 'rgb(10, 100, 200)' : 'rgb(255, 0, 0)');
+    }
+
+    stylingElement.innerHTML = '';
+}
+
+function testSelector(selector, expectedIds) {
+    debug(&quot;Testing \&quot;&quot; + selector + &quot;\&quot;&quot;);
+    testQuerySelector(&quot;#test-root &quot; + selector, expectedIds);
+    testStyling(&quot;#test-root &quot; + selector, expectedIds);
+    debug(&quot;&quot;);
+}
+
+testSelector(&quot;:nth-last-child(n+1 of testcaseA[attribute3], :not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-last-child(n+1 of testcaseA[attribute3], *:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-last-child(n+1 of testcaseA[attribute3], #foo#bar)&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+testSelector(&quot;:nth-last-child(n+1 of testcaseA[attribute3], #foo#bar, :not(*), *:not(*), foo:not(*), #foo#bar, :not(*), *:not(*), foo:not(*))&quot;, [&quot;testcase1&quot;, &quot;testcase5&quot;, &quot;testcase9&quot;, &quot;testcase13&quot;, &quot;testcase17&quot;, &quot;testcase21&quot;, &quot;testcase25&quot;]);
+&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 (178149 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-09 01:42:10 UTC (rev 178149)
+++ trunk/Source/WebCore/ChangeLog        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -1,3 +1,53 @@
</span><ins>+2015-01-08  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        Make better use of the stack when compiling selectors
+        https://bugs.webkit.org/show_bug.cgi?id=139615
+        rdar://problem/19226482
+
+        Reviewed by Andreas Kling.
+
+        Selectors used to be only on one level. To avoid memory allocations, we were allocating
+        a lot of stack upfront and we were using that to create all the intermediary objects
+        used by the code generator.
+
+        Then, selectors became multilevel. We now support arbitrary nesting of selector lists.
+
+        We did not adapt any of the structures and the creation of the intermediary object is recursive.
+        This resulted in over 1k of stack allocation at every level, quickly accumulating to unreasonable
+        numbers.
+
+        This patch fixes this problem by making each stack frame of the recursion much lighter.
+        We no longer allocate the big objects (SelectorFragment and SelectorFragmentList) on the stack.
+
+        In each case where we would have used a Stack allocated SelectorFragment or SelectorFragmentList,
+        we now allocate the memory directly into the target vector.
+
+        In the cases where the object should not be on the vector, we simply remove it. Those are uncommon
+        cases so that should not be too bad.
+
+        Tests: fast/selectors/matches-selector-list-ending-with-never-matching-selectors.html
+               fast/selectors/not-selector-list-ending-with-never-matching-selectors.html
+               fast/selectors/nth-child-of-selector-list-ending-with-never-matching-selectors.html
+               fast/selectors/nth-last-child-of-selector-list-ending-with-never-matching-selectors.html
+
+        * cssjit/SelectorCompiler.cpp:
+        SelectorFragmentList is also used for nested lists. Keeping 32 SelectorFragment preallocated
+        for each nested list is way too big.
+
+        (WebCore::SelectorCompiler::addPseudoClassType):
+        There are three cases of nested selector lists supported by the compiler: :matches(), :not()
+        and :nth-child(). For those 3 cases, use the target vector memory instead of the stack.
+
+        (WebCore::SelectorCompiler::constructFragmentsInternal):
+        (WebCore::SelectorCompiler::constructFragments):
+        Make sure we do not modify the input list on failure since it may be reused.
+
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatchesSelectorList):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatchesMatchesPseudoClass):
+        I changed the handling of :nth-child(An+B of selectorList) to not generate empty filters.
+        With that we can generalize the assertion to generateElementMatchesSelectorList() and simplify
+        the flow of selector lists a bit.
+
</ins><span class="cx"> 2015-01-08  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move '-webkit-font-feature-settings' CSS property to the new StyleBuilder
</span></span></pre></div>
<a id="trunkSourceWebCorecssjitSelectorCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (178149 => 178150)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2015-01-09 01:42:10 UTC (rev 178149)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp        2015-01-09 01:50:41 UTC (rev 178150)
</span><span class="lines">@@ -214,7 +214,7 @@
</span><span class="cx">     bool onlyMatchesLinksInQuirksMode;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-class SelectorFragmentList : public Vector&lt;SelectorFragment, 32&gt; {
</del><ins>+class SelectorFragmentList : public Vector&lt;SelectorFragment, 4&gt; {
</ins><span class="cx"> public:
</span><span class="cx">     unsigned registerRequirements = std::numeric_limits&lt;unsigned&gt;::max();
</span><span class="cx">     unsigned stackRequirements = std::numeric_limits&lt;unsigned&gt;::max();
</span><span class="lines">@@ -639,15 +639,19 @@
</span><span class="cx">                 unsigned firstFragmentListSpecificity = 0;
</span><span class="cx">                 bool firstFragmentListSpecificitySet = false;
</span><span class="cx"> 
</span><ins>+                SelectorFragmentList* selectorFragments = nullptr;
</ins><span class="cx">                 for (const CSSSelector* subselector = selectorList-&gt;first(); subselector; subselector = CSSSelectorList::next(subselector)) {
</span><del>-                    SelectorFragmentList selectorFragments;
</del><ins>+                    if (!selectorFragments) {
+                        nthChildOfSelectorInfo.selectorList.append(SelectorFragmentList());
+                        selectorFragments = &amp;nthChildOfSelectorInfo.selectorList.last();
+                    }
+
</ins><span class="cx">                     VisitedMode ignoreVisitedMode = VisitedMode::None;
</span><del>-                    FunctionType functionType = constructFragments(subselector, selectorContext, selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, PseudoElementMatchingBehavior::NeverMatch);
</del><ins>+                    FunctionType functionType = constructFragments(subselector, selectorContext, *selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, PseudoElementMatchingBehavior::NeverMatch);
</ins><span class="cx">                     ASSERT_WITH_MESSAGE(ignoreVisitedMode == VisitedMode::None, &quot;:visited is disabled in the functional pseudo classes&quot;);
</span><span class="cx">                     switch (functionType) {
</span><span class="cx">                     case FunctionType::SimpleSelectorChecker:
</span><span class="cx">                     case FunctionType::SelectorCheckerWithCheckingContext:
</span><del>-                        nthChildOfSelectorInfo.selectorList.append(selectorFragments);
</del><span class="cx">                         break;
</span><span class="cx">                     case FunctionType::CannotMatchAnything:
</span><span class="cx">                         continue;
</span><span class="lines">@@ -657,15 +661,25 @@
</span><span class="cx"> 
</span><span class="cx">                     if (firstFragmentListSpecificitySet) {
</span><span class="cx">                         // The CSS JIT does not handle dynamic specificity yet.
</span><del>-                        if (selectorContext == SelectorContext::RuleCollector &amp;&amp; selectorFragments.staticSpecificity != firstFragmentListSpecificity)
</del><ins>+                        if (selectorContext == SelectorContext::RuleCollector &amp;&amp; selectorFragments-&gt;staticSpecificity != firstFragmentListSpecificity)
</ins><span class="cx">                             return FunctionType::CannotCompile;
</span><span class="cx">                     } else {
</span><span class="cx">                         firstFragmentListSpecificitySet = true;
</span><del>-                        firstFragmentListSpecificity = selectorFragments.staticSpecificity;
</del><ins>+                        firstFragmentListSpecificity = selectorFragments-&gt;staticSpecificity;
</ins><span class="cx">                     }
</span><span class="cx"> 
</span><span class="cx">                     globalFunctionType = mostRestrictiveFunctionType(globalFunctionType, functionType);
</span><ins>+                    selectorFragments = nullptr;
</ins><span class="cx">                 }
</span><ins>+
+                // If there is still a SelectorFragmentList open, the last Fragment(s) cannot match anything,
+                // we have one FragmentList too many in our selector list.
+                if (selectorFragments)
+                    nthChildOfSelectorInfo.selectorList.removeLast();
+
+                if (nthChildOfSelectorInfo.selectorList.isEmpty())
+                    return FunctionType::CannotMatchAnything;
+
</ins><span class="cx">                 internalSpecificity = firstFragmentListSpecificity;
</span><span class="cx">                 fragment.nthChildOfFilters.append(nthChildOfSelectorInfo);
</span><span class="cx">                 return globalFunctionType;
</span><span class="lines">@@ -685,10 +699,15 @@
</span><span class="cx">                 return FunctionType::CannotMatchAnything;
</span><span class="cx"> 
</span><span class="cx">             FunctionType functionType = FunctionType::SimpleSelectorChecker;
</span><ins>+            SelectorFragmentList* selectorFragments = nullptr;
</ins><span class="cx">             for (const CSSSelector* subselector = selectorList-&gt;first(); subselector; subselector = CSSSelectorList::next(subselector)) {
</span><del>-                SelectorFragmentList selectorFragments;
</del><ins>+                if (!selectorFragments) {
+                    fragment.notFilters.append(SelectorFragmentList());
+                    selectorFragments = &amp;fragment.notFilters.last();
+                }
+
</ins><span class="cx">                 VisitedMode ignoreVisitedMode = VisitedMode::None;
</span><del>-                FunctionType localFunctionType = constructFragments(subselector, selectorContext, selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, PseudoElementMatchingBehavior::NeverMatch);
</del><ins>+                FunctionType localFunctionType = constructFragments(subselector, selectorContext, *selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, PseudoElementMatchingBehavior::NeverMatch);
</ins><span class="cx">                 ASSERT_WITH_MESSAGE(ignoreVisitedMode == VisitedMode::None, &quot;:visited is disabled in the functional pseudo classes&quot;);
</span><span class="cx"> 
</span><span class="cx">                 // Since this is not pseudo class filter, CannotMatchAnything implies this filter always passes.
</span><span class="lines">@@ -699,9 +718,14 @@
</span><span class="cx">                     return FunctionType::CannotCompile;
</span><span class="cx"> 
</span><span class="cx">                 functionType = mostRestrictiveFunctionType(functionType, localFunctionType);
</span><del>-                fragment.notFilters.append(selectorFragments);
</del><ins>+                selectorFragments = nullptr;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            // If there is still a SelectorFragmentList open, the last Fragment(s) cannot match anything,
+            // we have one FragmentList too many in our selector list.
+            if (selectorFragments)
+                fragment.notFilters.removeLast();
+
</ins><span class="cx">             return functionType;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -774,10 +798,15 @@
</span><span class="cx">             FunctionType functionType = FunctionType::SimpleSelectorChecker;
</span><span class="cx">             unsigned firstFragmentListSpecificity = 0;
</span><span class="cx">             bool firstFragmentListSpecificitySet = false;
</span><ins>+            SelectorFragmentList* selectorFragments = nullptr;
</ins><span class="cx">             for (const CSSSelector* subselector = selectorList-&gt;first(); subselector; subselector = CSSSelectorList::next(subselector)) {
</span><del>-                SelectorFragmentList selectorFragments;
</del><ins>+                if (!selectorFragments) {
+                    matchesList.append(SelectorFragmentList());
+                    selectorFragments = &amp;matchesList.last();
+                }
+
</ins><span class="cx">                 VisitedMode ignoreVisitedMode = VisitedMode::None;
</span><del>-                FunctionType localFunctionType = constructFragments(subselector, selectorContext, selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, pseudoElementMatchingBehavior);
</del><ins>+                FunctionType localFunctionType = constructFragments(subselector, selectorContext, *selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, pseudoElementMatchingBehavior);
</ins><span class="cx">                 ASSERT_WITH_MESSAGE(ignoreVisitedMode == VisitedMode::None, &quot;:visited is disabled in the functional pseudo classes&quot;);
</span><span class="cx"> 
</span><span class="cx">                 // Since this fragment never matches against the element, don't insert it to matchesList.
</span><span class="lines">@@ -788,22 +817,27 @@
</span><span class="cx">                     return FunctionType::CannotCompile;
</span><span class="cx"> 
</span><span class="cx">                 // FIXME: Currently pseudo elements inside :matches are supported in non-JIT code.
</span><del>-                if (selectorFragments.first().pseudoElementSelector)
</del><ins>+                if (selectorFragments-&gt;first().pseudoElementSelector)
</ins><span class="cx">                     return FunctionType::CannotCompile;
</span><span class="cx"> 
</span><span class="cx">                 if (firstFragmentListSpecificitySet) {
</span><span class="cx">                     // The CSS JIT does not handle dynamic specificity yet.
</span><del>-                    if (selectorContext == SelectorContext::RuleCollector &amp;&amp; selectorFragments.staticSpecificity != firstFragmentListSpecificity)
</del><ins>+                    if (selectorContext == SelectorContext::RuleCollector &amp;&amp; selectorFragments-&gt;staticSpecificity != firstFragmentListSpecificity)
</ins><span class="cx">                         return FunctionType::CannotCompile;
</span><span class="cx">                 } else {
</span><span class="cx">                     firstFragmentListSpecificitySet = true;
</span><del>-                    firstFragmentListSpecificity = selectorFragments.staticSpecificity;
</del><ins>+                    firstFragmentListSpecificity = selectorFragments-&gt;staticSpecificity;
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 functionType = mostRestrictiveFunctionType(functionType, localFunctionType);
</span><del>-                matchesList.append(selectorFragments);
</del><ins>+                selectorFragments = nullptr;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            // If there is still a SelectorFragmentList open, the last Fragment(s) cannot match anything,
+            // we have one FragmentList too many in our selector list.
+            if (selectorFragments)
+                matchesList.removeLast();
+
</ins><span class="cx">             // Since all selector list in :matches() cannot match anything, the whole :matches() filter cannot match anything.
</span><span class="cx">             if (matchesList.isEmpty())
</span><span class="cx">                 return FunctionType::CannotMatchAnything;
</span><span class="lines">@@ -857,61 +891,66 @@
</span><span class="cx">     return type &gt;= CSSSelector::PseudoElementScrollbar &amp;&amp; type &lt;= CSSSelector::PseudoElementScrollbarTrackPiece;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static FunctionType constructFragments(const CSSSelector* rootSelector, SelectorContext selectorContext, SelectorFragmentList&amp; selectorFragments, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, VisitedMode&amp; visitedMode, PseudoElementMatchingBehavior pseudoElementMatchingBehavior)
</del><ins>+static FunctionType constructFragmentsInternal(const CSSSelector* rootSelector, SelectorContext selectorContext, SelectorFragmentList&amp; selectorFragments, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, VisitedMode&amp; visitedMode, PseudoElementMatchingBehavior pseudoElementMatchingBehavior)
</ins><span class="cx"> {
</span><del>-    SelectorFragment fragment;
</del><span class="cx">     FragmentRelation relationToPreviousFragment = FragmentRelation::Rightmost;
</span><span class="cx">     FunctionType functionType = FunctionType::SimpleSelectorChecker;
</span><ins>+    SelectorFragment* fragment = nullptr;
</ins><span class="cx">     unsigned specificity = 0;
</span><span class="cx">     for (const CSSSelector* selector = rootSelector; selector; selector = selector-&gt;tagHistory()) {
</span><ins>+        if (!fragment) {
+            selectorFragments.append(SelectorFragment());
+            fragment = &amp;selectorFragments.last();
+        }
+
</ins><span class="cx">         specificity = CSSSelector::addSpecificities(specificity, selector-&gt;simpleSelectorSpecificity());
</span><span class="cx"> 
</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>-        if (fragment.pseudoElementSelector &amp;&amp; !isScrollbarPseudoElement(fragment.pseudoElementSelector-&gt;pseudoElementType()))
</del><ins>+        if (fragment-&gt;pseudoElementSelector &amp;&amp; !isScrollbarPseudoElement(fragment-&gt;pseudoElementSelector-&gt;pseudoElementType()))
</ins><span class="cx">             return FunctionType::CannotMatchAnything;
</span><span class="cx"> 
</span><span class="cx">         switch (selector-&gt;match()) {
</span><span class="cx">         case CSSSelector::Tag:
</span><del>-            ASSERT(!fragment.tagName);
-            fragment.tagName = &amp;(selector-&gt;tagQName());
-            if (*fragment.tagName != anyQName())
-                fragment.onlyMatchesLinksInQuirksMode = false;
</del><ins>+            ASSERT(!fragment-&gt;tagName);
+            fragment-&gt;tagName = &amp;(selector-&gt;tagQName());
+            if (*fragment-&gt;tagName != anyQName())
+                fragment-&gt;onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             break;
</span><span class="cx">         case CSSSelector::Id: {
</span><span class="cx">             const AtomicString&amp; id = selector-&gt;value();
</span><del>-            if (fragment.id) {
-                if (id != *fragment.id)
</del><ins>+            if (fragment-&gt;id) {
+                if (id != *fragment-&gt;id)
</ins><span class="cx">                     return FunctionType::CannotMatchAnything;
</span><span class="cx">             } else
</span><del>-                fragment.id = &amp;(selector-&gt;value());
-            fragment.onlyMatchesLinksInQuirksMode = false;
</del><ins>+                fragment-&gt;id = &amp;(selector-&gt;value());
+            fragment-&gt;onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case CSSSelector::Class:
</span><del>-            fragment.classNames.append(selector-&gt;value().impl());
-            fragment.onlyMatchesLinksInQuirksMode = false;
</del><ins>+            fragment-&gt;classNames.append(selector-&gt;value().impl());
+            fragment-&gt;onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PseudoClass: {
</span><span class="cx">             FragmentPositionInRootFragments subPosition = positionInRootFragments;
</span><span class="cx">             if (relationToPreviousFragment != FragmentRelation::Rightmost)
</span><span class="cx">                 subPosition = FragmentPositionInRootFragments::NotRightmost;
</span><del>-            if (fragment.pseudoElementSelector &amp;&amp; isScrollbarPseudoElement(fragment.pseudoElementSelector-&gt;pseudoElementType()))
-                functionType = mostRestrictiveFunctionType(functionType, addScrollbarPseudoClassType(*selector, fragment));
</del><ins>+            if (fragment-&gt;pseudoElementSelector &amp;&amp; isScrollbarPseudoElement(fragment-&gt;pseudoElementSelector-&gt;pseudoElementType()))
+                functionType = mostRestrictiveFunctionType(functionType, addScrollbarPseudoClassType(*selector, *fragment));
</ins><span class="cx">             else {
</span><span class="cx">                 unsigned internalSpecificity = 0;
</span><del>-                functionType = mostRestrictiveFunctionType(functionType, addPseudoClassType(*selector, fragment, internalSpecificity, selectorContext, fragmentLevel, subPosition, visitedMatchEnabled, visitedMode, pseudoElementMatchingBehavior));
</del><ins>+                functionType = mostRestrictiveFunctionType(functionType, addPseudoClassType(*selector, *fragment, internalSpecificity, selectorContext, fragmentLevel, subPosition, visitedMatchEnabled, visitedMode, pseudoElementMatchingBehavior));
</ins><span class="cx">                 specificity = CSSSelector::addSpecificities(specificity, internalSpecificity);
</span><span class="cx">             }
</span><span class="cx">             if (!pseudoClassOnlyMatchesLinksInQuirksMode(*selector))
</span><del>-                fragment.onlyMatchesLinksInQuirksMode = false;
</del><ins>+                fragment-&gt;onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             if (functionType == FunctionType::CannotCompile || functionType == FunctionType::CannotMatchAnything)
</span><span class="cx">                 return functionType;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case CSSSelector::PseudoElement: {
</span><del>-            fragment.onlyMatchesLinksInQuirksMode = false;
</del><ins>+            fragment-&gt;onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx"> 
</span><span class="cx">             // In the QuerySelector context, PseudoElement selectors always fail.
</span><span class="cx">             if (selectorContext == SelectorContext::QuerySelector)
</span><span class="lines">@@ -928,8 +967,8 @@
</span><span class="cx">             case CSSSelector::PseudoElementScrollbarThumb:
</span><span class="cx">             case CSSSelector::PseudoElementScrollbarTrack:
</span><span class="cx">             case CSSSelector::PseudoElementScrollbarTrackPiece:
</span><del>-                ASSERT(!fragment.pseudoElementSelector);
-                fragment.pseudoElementSelector = selector;
</del><ins>+                ASSERT(!fragment-&gt;pseudoElementSelector);
+                fragment-&gt;pseudoElementSelector = selector;
</ins><span class="cx">                 break;
</span><span class="cx">             case CSSSelector::PseudoElementUnknown:
</span><span class="cx">                 ASSERT_NOT_REACHED();
</span><span class="lines">@@ -958,16 +997,16 @@
</span><span class="cx">             FALLTHROUGH;
</span><span class="cx">         case CSSSelector::Exact:
</span><span class="cx">         case CSSSelector::Hyphen:
</span><del>-            fragment.onlyMatchesLinksInQuirksMode = false;
-            fragment.attributes.append(AttributeMatchingInfo(selector, HTMLDocument::isCaseSensitiveAttribute(selector-&gt;attribute())));
</del><ins>+            fragment-&gt;onlyMatchesLinksInQuirksMode = false;
+            fragment-&gt;attributes.append(AttributeMatchingInfo(selector, HTMLDocument::isCaseSensitiveAttribute(selector-&gt;attribute())));
</ins><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case CSSSelector::Set:
</span><del>-            fragment.onlyMatchesLinksInQuirksMode = false;
-            fragment.attributes.append(AttributeMatchingInfo(selector, true));
</del><ins>+            fragment-&gt;onlyMatchesLinksInQuirksMode = false;
+            fragment-&gt;attributes.append(AttributeMatchingInfo(selector, true));
</ins><span class="cx">             break;
</span><span class="cx">         case CSSSelector::PagePseudoClass:
</span><del>-            fragment.onlyMatchesLinksInQuirksMode = false;
</del><ins>+            fragment-&gt;onlyMatchesLinksInQuirksMode = false;
</ins><span class="cx">             // Pseudo page class are only relevant for style resolution, they are ignored for matching.
</span><span class="cx">             break;
</span><span class="cx">         case CSSSelector::Unknown:
</span><span class="lines">@@ -995,22 +1034,34 @@
</span><span class="cx">         // Virtual pseudo element is only effective in the rightmost fragment.
</span><span class="cx">         pseudoElementMatchingBehavior = PseudoElementMatchingBehavior::NeverMatch;
</span><span class="cx"> 
</span><del>-        fragment.relationToLeftFragment = fragmentRelationForSelectorRelation(relation);
-        fragment.relationToRightFragment = relationToPreviousFragment;
-        fragment.positionInRootFragments = positionInRootFragments;
-        relationToPreviousFragment = fragment.relationToLeftFragment;
</del><ins>+        fragment-&gt;relationToLeftFragment = fragmentRelationForSelectorRelation(relation);
+        fragment-&gt;relationToRightFragment = relationToPreviousFragment;
+        fragment-&gt;positionInRootFragments = positionInRootFragments;
+        relationToPreviousFragment = fragment-&gt;relationToLeftFragment;
</ins><span class="cx"> 
</span><span class="cx">         if (fragmentLevel != FragmentsLevel::Root)
</span><del>-            fragment.onlyMatchesLinksInQuirksMode = false;
-        selectorFragments.append(fragment);
-        fragment = SelectorFragment();
</del><ins>+            fragment-&gt;onlyMatchesLinksInQuirksMode = false;
+
+        fragment = nullptr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ASSERT(!fragment);
+
</ins><span class="cx">     selectorFragments.staticSpecificity = specificity;
</span><span class="cx"> 
</span><span class="cx">     return functionType;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static FunctionType constructFragments(const CSSSelector* rootSelector, SelectorContext selectorContext, SelectorFragmentList&amp; selectorFragments, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, VisitedMode&amp; visitedMode, PseudoElementMatchingBehavior pseudoElementMatchingBehavior)
+{
+    ASSERT(selectorFragments.isEmpty());
+
+    FunctionType functionType = constructFragmentsInternal(rootSelector, selectorContext, selectorFragments, fragmentLevel, positionInRootFragments, visitedMatchEnabled, visitedMode, pseudoElementMatchingBehavior);
+    if (functionType != FunctionType::SimpleSelectorChecker &amp;&amp; functionType != FunctionType::SelectorCheckerWithCheckingContext)
+        selectorFragments.clear();
+    return functionType;
+}
+
</ins><span class="cx"> static inline bool attributeNameTestingRequiresNamespaceRegister(const CSSSelector&amp; attributeSelector)
</span><span class="cx"> {
</span><span class="cx">     return attributeSelector.attribute().prefix() != starAtom &amp;&amp; !attributeSelector.attribute().namespaceURI().isNull();
</span><span class="lines">@@ -1803,6 +1854,8 @@
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateElementMatchesSelectorList(Assembler::JumpList&amp; failingCases, Assembler::RegisterID elementToMatch, const SelectorList&amp; selectorList)
</span><span class="cx"> {
</span><ins>+    ASSERT(!selectorList.isEmpty());
+
</ins><span class="cx">     RegisterVector registersToSave;
</span><span class="cx"> 
</span><span class="cx">     // The contract is that existing registers are preserved. Two special cases are elementToMatch and elementAddressRegister
</span><span class="lines">@@ -3590,10 +3643,8 @@
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateElementMatchesMatchesPseudoClass(Assembler::JumpList&amp; failureCases, const SelectorFragment&amp; fragment)
</span><span class="cx"> {
</span><del>-    for (const SelectorList&amp; matchesList : fragment.matchesFilters) {
-        ASSERT(!matchesList.isEmpty());
</del><ins>+    for (const SelectorList&amp; matchesList : fragment.matchesFilters)
</ins><span class="cx">         generateElementMatchesSelectorList(failureCases, elementAddressRegister, matchesList);
</span><del>-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SelectorCodeGenerator::generateElementHasPseudoElement(Assembler::JumpList&amp;, const SelectorFragment&amp; fragment)
</span></span></pre>
</div>
</div>

</body>
</html>