JIT Compile simple cases of :nth-last-child()
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Feb 2015 04:11:42 +0000 (04:11 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Feb 2015 04:11:42 +0000 (04:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=141053

Reviewed by Andreas Kling.

Source/WebCore:

This patch adds the code generator for :nth-last-child(), skipping
any :nth-last-child(An+B of selector list).

The code generator is boring here, nothing fancy.
There is no optimization opportunity here so it is basically the same
speed as the code generated by Clang when the simple selector is alone.

The only reason to JIT compile this is to avoid going to slow-path
for every selector that contain :nth-last-child().

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::addNthChildType):
The code creating the intermediate representation of :nth-child() is exactly
the same as what we need for :nth-last-child(). I extracted the code from addPseudoClassType()
and share it for both simple selectors.

(WebCore::SelectorCompiler::addPseudoClassType):
I fail :nth-last-child(An+B of selector list). Let's add it later.

(WebCore::SelectorCompiler::minimumRegisterRequirements):
Oops, there was a bug with nthChildOfFilters.

(WebCore::SelectorCompiler::hasAnyCombinators):
(WebCore::SelectorCompiler::computeBacktrackingMemoryRequirements):
(WebCore::SelectorCompiler::computeBacktrackingInformation):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
(WebCore::SelectorCompiler::setChildrenAffectedByBackwardPositionalRules):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChild):

LayoutTests:

There was almost no test coverage for :nth-last-child(). I copied the main tests
from :nth-child() and updated the expected results.

This is not ideal because we should have style update tests targetting
backward invalidation... Still better than nothing :)

* fast/selectors/nth-last-child-as-first-simple-selector-style-update-expected.txt: Added.
* fast/selectors/nth-last-child-as-first-simple-selector-style-update.html: Added.
* fast/selectors/nth-last-child-basics-expected.txt: Added.
* fast/selectors/nth-last-child-basics.html: Added.
* fast/selectors/nth-last-child-bounds-expected.txt: Added.
* fast/selectors/nth-last-child-bounds.html: Added.
* fast/selectors/nth-last-child-chained-expected.txt: Added.
* fast/selectors/nth-last-child-chained.html: Added.
* fast/selectors/nth-last-child-on-root-expected.txt: Added.
* fast/selectors/nth-last-child-on-root.html: Added.
* fast/selectors/nth-last-child-style-update-expected.txt: Added.
* fast/selectors/nth-last-child-style-update.html: Added.
* fast/selectors/nth-last-child-with-backtracking-expected.txt: Added.
* fast/selectors/nth-last-child-with-backtracking.html: Added.
* fast/selectors/several-nth-last-child-expected.txt: Added.
* fast/selectors/several-nth-last-child.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179535 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/selectors/nth-last-child-as-first-simple-selector-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-as-first-simple-selector-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-basics-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-basics.html [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-bounds-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-bounds.html [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-chained-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-chained.html [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-on-root-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-on-root.html [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-style-update-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-style-update.html [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-with-backtracking-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/nth-last-child-with-backtracking.html [new file with mode: 0644]
LayoutTests/fast/selectors/several-nth-last-child-expected.txt [new file with mode: 0644]
LayoutTests/fast/selectors/several-nth-last-child.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/cssjit/SelectorCompiler.cpp

index 6821895..09ebcdf 100644 (file)
@@ -1,3 +1,33 @@
+2015-02-02  Benjamin Poulain  <benjamin@webkit.org>
+
+        JIT Compile simple cases of :nth-last-child()
+        https://bugs.webkit.org/show_bug.cgi?id=141053
+
+        Reviewed by Andreas Kling.
+
+        There was almost no test coverage for :nth-last-child(). I copied the main tests
+        from :nth-child() and updated the expected results.
+
+        This is not ideal because we should have style update tests targetting
+        backward invalidation... Still better than nothing :)
+
+        * fast/selectors/nth-last-child-as-first-simple-selector-style-update-expected.txt: Added.
+        * fast/selectors/nth-last-child-as-first-simple-selector-style-update.html: Added.
+        * fast/selectors/nth-last-child-basics-expected.txt: Added.
+        * fast/selectors/nth-last-child-basics.html: Added.
+        * fast/selectors/nth-last-child-bounds-expected.txt: Added.
+        * fast/selectors/nth-last-child-bounds.html: Added.
+        * fast/selectors/nth-last-child-chained-expected.txt: Added.
+        * fast/selectors/nth-last-child-chained.html: Added.
+        * fast/selectors/nth-last-child-on-root-expected.txt: Added.
+        * fast/selectors/nth-last-child-on-root.html: Added.
+        * fast/selectors/nth-last-child-style-update-expected.txt: Added.
+        * fast/selectors/nth-last-child-style-update.html: Added.
+        * fast/selectors/nth-last-child-with-backtracking-expected.txt: Added.
+        * fast/selectors/nth-last-child-with-backtracking.html: Added.
+        * fast/selectors/several-nth-last-child-expected.txt: Added.
+        * fast/selectors/several-nth-last-child.html: Added.
+
 2015-02-02  Gyuyoung Kim  <gyuyoung.kim@samsung.com>
 
         Unreviewed, EFL gardening. Update flakiness tests on W3C SVG 1.1 tests.
diff --git a/LayoutTests/fast/selectors/nth-last-child-as-first-simple-selector-style-update-expected.txt b/LayoutTests/fast/selectors/nth-last-child-as-first-simple-selector-style-update-expected.txt
new file mode 100644 (file)
index 0000000..debab4a
--- /dev/null
@@ -0,0 +1,189 @@
+Test style update of :nth-last-child() when the tree structure is modified. In this case, :nth-last-child() is not the last component of the compound selector, which is a bit less common.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initialy, only the first element should match.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <testnode> on top, we should now match 0 and 1.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <nottestnode> on top, we should now match -1, 0 and 1.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[13]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <nottestnode> on top, we should now match -2, -1, 0 and 1.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[13]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[14]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[15]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <testnode> on top, we should now match -3, -2, -1, 0 and 1.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[12]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[13]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[14]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[15]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[16]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[17]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <nottestnode> on top, we should now match -4, -3, -2, -1, 0 and 1.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[12]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[13]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[14]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[15]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[16]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[17]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[18]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[19]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <nottestnode>, -2 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[12]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[13]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[14]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[15]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[16]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[17]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <testnode>, -4 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[13]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[14]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[15]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <notestnode>, -1 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[13]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <testnode>, -3 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[11]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <testnode>, 0 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[9]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <testnode>, there are only 4 siblings left, nothing can match.
+PASS getComputedStyle(document.querySelectorAll("testnode")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("testnode")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/nth-last-child-as-first-simple-selector-style-update.html b/LayoutTests/fast/selectors/nth-last-child-as-first-simple-selector-style-update.html
new file mode 100644 (file)
index 0000000..2e35c79
--- /dev/null
@@ -0,0 +1,110 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+testnode {
+    background-color: white;
+}
+:nth-last-child(n+5).target {
+    background-color: rgb(1, 2, 3);
+}
+</style>
+</head>
+<body>
+    <div id="with-renderer">
+        <testnode class="element_1 target"></testnode>
+        <testnode class="element_2 target"></testnode>
+        <testnode class="element_3 target"></testnode>
+        <testnode class="element_4 target"></testnode>
+        <testnode class="element_5 target"></testnode>
+    </div>
+    <div id="without-renderer" style="display:none;">
+        <testnode class="element_1 target"></testnode>
+        <testnode class="element_2 target"></testnode>
+        <testnode class="element_3 target"></testnode>
+        <testnode class="element_4 target"></testnode>
+        <testnode class="element_5 target"></testnode>
+    </div>
+</body>
+<script>
+description('Test style update of :nth-last-child() when the tree structure is modified. In this case, :nth-last-child() is not the last component of the compound selector, which is a bit less common.');
+
+function testColor(classesThatShouldMatch) {
+    var alltestnodes = document.querySelectorAll("testnode");
+    for (var i = 0; i < alltestnodes.length; ++i) {
+        var expectMath = classesThatShouldMatch.indexOf(alltestnodes[i].classList[0]) != -1;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll("testnode")[' + i + ']).backgroundColor', expectMath ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    }
+}
+
+function addElementAsFirstChild(tagName, className)
+{
+    var newElement = document.createElement(tagName);
+    newElement.className = className;
+
+    var withRenderer = document.getElementById("with-renderer");
+    withRenderer.insertBefore(newElement, withRenderer.firstChild);
+
+    var withoutRenderer = document.getElementById("without-renderer");
+    withoutRenderer.insertBefore(newElement.cloneNode(), withoutRenderer.firstChild);
+}
+
+function removeElementsOfClass(className)
+{
+    var allElementsToRemove = document.querySelectorAll('.' + className);
+    for (var i = 0; i < allElementsToRemove.length; ++i)
+        allElementsToRemove[i].parentElement.removeChild(allElementsToRemove[i]);
+}
+
+debug("Initialy, only the first element should match.");
+testColor(["element_1"]);
+
+debug("Adding an element &lt;testnode&gt; on top, we should now match 0 and 1.");
+addElementAsFirstChild("testnode", "element_0 target")
+testColor(["element_0", "element_1"]);
+
+// Using nottestnode is interesting because the ':nth-last-child()' part is not matched for those elements.
+debug("Adding an element &lt;nottestnode&gt; on top, we should now match -1, 0 and 1.");
+addElementAsFirstChild("testnode", "element_-1 target")
+testColor(["element_-1", "element_0", "element_1"]);
+
+debug("Adding an element &lt;nottestnode&gt; on top, we should now match -2, -1, 0 and 1.");
+addElementAsFirstChild("testnode", "element_-2 target")
+testColor(["element_-2", "element_-1", "element_0", "element_1"]);
+
+debug("Adding an element &lt;testnode&gt; on top, we should now match -3, -2, -1, 0 and 1.");
+addElementAsFirstChild("testnode", "element_-3 target")
+testColor(["element_-3", "element_-2", "element_-1", "element_0", "element_1"]);
+
+debug("Adding an element &lt;nottestnode&gt; on top, we should now match -4, -3, -2, -1, 0 and 1.");
+addElementAsFirstChild("testnode", "element_-4 target")
+testColor(["element_-4", "element_-3", "element_-2", "element_-1", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;nottestnode&gt;, -2 should no longer match.");
+removeElementsOfClass("element_-2");
+testColor(["element_-4", "element_-3", "element_-1", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;testnode&gt;, -4 should no longer match.");
+removeElementsOfClass("element_-4");
+testColor(["element_-3", "element_-1", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;notestnode&gt;, -1 should no longer match.");
+removeElementsOfClass("element_-1");
+testColor(["element_-3", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;testnode&gt;, -3 should no longer match.");
+removeElementsOfClass("element_-3");
+testColor(["element_0", "element_1"]);
+
+debug("Removing one of the &lt;testnode&gt;, 0 should no longer match.");
+removeElementsOfClass("element_0");
+testColor(["element_1"]);
+
+debug("Removing one of the &lt;testnode&gt;, there are only 4 siblings left, nothing can match.");
+removeElementsOfClass("element_1");
+testColor([]);
+
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/fast/selectors/nth-last-child-basics-expected.txt b/LayoutTests/fast/selectors/nth-last-child-basics-expected.txt
new file mode 100644 (file)
index 0000000..0eb98d3
--- /dev/null
@@ -0,0 +1,664 @@
+Test basic uses cases of :nth-last-child().
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Testing ":nth-last-child(8)"
+PASS document.querySelectorAll('#test-root :nth-last-child(8)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(8)')[0].id is "testcase4"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+6)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+6)').length is 6
+PASS document.querySelectorAll('#test-root :nth-last-child(n+6)')[0].id is "testcase1"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+6)')[1].id is "testcase2"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+6)')[2].id is "testcase3"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+6)')[3].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+6)')[4].id is "testcase5"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+6)')[5].id is "testcase6"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+9)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)').length is 9
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[0].id is "testcase3"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[1].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[2].id is "testcase5"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[3].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[4].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[5].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[6].id is "testcase9"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[7].id is "testcase10"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+9)')[8].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing ":nth-last-child(n+4):nth-last-child(-n+8)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+4):nth-last-child(-n+8)').length is 5
+PASS document.querySelectorAll('#test-root :nth-last-child(n+4):nth-last-child(-n+8)')[0].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+4):nth-last-child(-n+8)')[1].id is "testcase5"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+4):nth-last-child(-n+8)')[2].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+4):nth-last-child(-n+8)')[3].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+4):nth-last-child(-n+8)')[4].id is "testcase8"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+8):nth-last-child(n+4)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+8):nth-last-child(n+4)').length is 5
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+8):nth-last-child(n+4)')[0].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+8):nth-last-child(n+4)')[1].id is "testcase5"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+8):nth-last-child(n+4)')[2].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+8):nth-last-child(n+4)')[3].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+8):nth-last-child(n+4)')[4].id is "testcase8"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+2):nth-last-child(odd):nth-last-child(-n+9)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+2):nth-last-child(odd):nth-last-child(-n+9)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(n+2):nth-last-child(odd):nth-last-child(-n+9)')[0].id is "testcase3"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+2):nth-last-child(odd):nth-last-child(-n+9)')[1].id is "testcase5"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+2):nth-last-child(odd):nth-last-child(-n+9)')[2].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+2):nth-last-child(odd):nth-last-child(-n+9)')[3].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(3n+1):nth-last-child(even)"
+PASS document.querySelectorAll('#test-root :nth-last-child(3n+1):nth-last-child(even)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(3n+1):nth-last-child(even)')[0].id is "testcase2"
+PASS document.querySelectorAll('#test-root :nth-last-child(3n+1):nth-last-child(even)')[1].id is "testcase8"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(even):nth-last-child(3n+1)"
+PASS document.querySelectorAll('#test-root :nth-last-child(even):nth-last-child(3n+1)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(even):nth-last-child(3n+1)')[0].id is "testcase2"
+PASS document.querySelectorAll('#test-root :nth-last-child(even):nth-last-child(3n+1)')[1].id is "testcase8"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(3)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(3)')[0].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(4)"
+PASS document.querySelectorAll('#test-root :nth-last-child(4)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(4)')[0].id is "testcase8"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(3):nth-last-child(4)"
+PASS document.querySelectorAll('#test-root :nth-last-child(3):nth-last-child(4)').length is 0
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(4):nth-last-child(3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(4):nth-last-child(3)').length is 0
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)').length is 9
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[0].id is "testcase1"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[1].id is "testcase2"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[2].id is "testcase3"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[3].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[4].id is "testcase5"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[5].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[6].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[7].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3)')[8].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(2n+2)"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2)').length is 5
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2)')[0].id is "testcase2"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2)')[1].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2)')[2].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2)')[3].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2)')[4].id is "testcase10"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+3):nth-last-child(2n+2)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(2n+2)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(2n+2)')[0].id is "testcase2"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(2n+2)')[1].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(2n+2)')[2].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(2n+2)')[3].id is "testcase8"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(2n+2):nth-last-child(n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2):nth-last-child(n+3)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2):nth-last-child(n+3)')[0].id is "testcase2"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2):nth-last-child(n+3)')[1].id is "testcase4"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2):nth-last-child(n+3)')[2].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(2n+2):nth-last-child(n+3)')[3].id is "testcase8"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+4)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4)')[0].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4)')[1].id is "testcase9"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4)')[2].id is "testcase10"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4)')[3].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing ":nth-last-child(-n+5)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5)').length is 5
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5)')[0].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5)')[1].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5)')[2].id is "testcase9"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5)')[3].id is "testcase10"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5)')[4].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing ":nth-last-child(-n+4):nth-last-child(-n+5)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4):nth-last-child(-n+5)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4):nth-last-child(-n+5)')[0].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4):nth-last-child(-n+5)')[1].id is "testcase9"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4):nth-last-child(-n+5)')[2].id is "testcase10"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+4):nth-last-child(-n+5)')[3].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing ":nth-last-child(-n+5):nth-last-child(-n+4)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5):nth-last-child(-n+4)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5):nth-last-child(-n+4)')[0].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5):nth-last-child(-n+4)')[1].id is "testcase9"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5):nth-last-child(-n+4)')[2].id is "testcase10"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+5):nth-last-child(-n+4)')[3].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing ":nth-last-child(n+3):nth-last-child(-n+6)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6)')[0].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6)')[1].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6)')[2].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6)')[3].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+6):nth-last-child(n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3)').length is 4
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3)')[0].id is "testcase6"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3)')[1].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3)')[2].id is "testcase8"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3)')[3].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+1):nth-last-child(-n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(-n+3)').length is 3
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(-n+3)')[0].id is "testcase9"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(-n+3)')[1].id is "testcase10"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(-n+3)')[2].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing ":nth-last-child(-n+3):nth-last-child(n+1)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(n+1)').length is 3
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(n+1)')[0].id is "testcase9"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(n+1)')[1].id is "testcase10"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(n+1)')[2].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing ":nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(n+1):nth-last-child(-n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(n+1):nth-last-child(-n+3)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(n+1):nth-last-child(-n+3)')[0].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(-n+3):nth-last-child(n+1)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(-n+3):nth-last-child(n+1)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(-n+3):nth-last-child(n+1)')[0].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6)')[0].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6)')[1].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+6):nth-last-child(odd):nth-last-child(n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(odd):nth-last-child(n+3)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(odd):nth-last-child(n+3)')[0].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(odd):nth-last-child(n+3)')[1].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(odd):nth-last-child(n+3):nth-last-child(-n+6)"
+PASS document.querySelectorAll('#test-root :nth-last-child(odd):nth-last-child(n+3):nth-last-child(-n+6)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(odd):nth-last-child(n+3):nth-last-child(-n+6)')[0].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(odd):nth-last-child(n+3):nth-last-child(-n+6)')[1].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+3)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+3)')[0].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+3)')[1].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(odd)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(odd)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(odd)')[0].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(odd)')[1].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(odd)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(odd)').length is 2
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(odd)')[0].id is "testcase7"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(odd)')[1].id is "testcase9"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+1):nth-last-child(even):nth-last-child(-n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(even):nth-last-child(-n+3)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(even):nth-last-child(-n+3)')[0].id is "testcase10"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+3):nth-last-child(even):nth-last-child(n+1)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(even):nth-last-child(n+1)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(even):nth-last-child(n+1)')[0].id is "testcase10"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(even):nth-last-child(n+1):nth-last-child(-n+3)"
+PASS document.querySelectorAll('#test-root :nth-last-child(even):nth-last-child(n+1):nth-last-child(-n+3)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(even):nth-last-child(n+1):nth-last-child(-n+3)')[0].id is "testcase10"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(even):nth-last-child(-n+3):nth-last-child(n+1)"
+PASS document.querySelectorAll('#test-root :nth-last-child(even):nth-last-child(-n+3):nth-last-child(n+1)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(even):nth-last-child(-n+3):nth-last-child(n+1)')[0].id is "testcase10"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(-n+3):nth-last-child(n+1):nth-last-child(even)"
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(n+1):nth-last-child(even)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(-n+3):nth-last-child(n+1):nth-last-child(even)')[0].id is "testcase10"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+1):nth-last-child(-n+3):nth-last-child(even)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(-n+3):nth-last-child(even)').length is 1
+PASS document.querySelectorAll('#test-root :nth-last-child(n+1):nth-last-child(-n+3):nth-last-child(even)')[0].id is "testcase10"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing ":nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+1):nth-last-child(-n+3):nth-last-child(even)"
+PASS document.querySelectorAll('#test-root :nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+1):nth-last-child(-n+3):nth-last-child(even)').length is 0
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[10]).backgroundColor is "rgb(255, 0, 0)"
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/nth-last-child-basics.html b/LayoutTests/fast/selectors/nth-last-child-basics.html
new file mode 100644 (file)
index 0000000..cf5afec
--- /dev/null
@@ -0,0 +1,107 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+#test-root * {
+    background-color: red;
+}
+</style>
+<style id="style">
+</style>
+</head>
+<body>
+    <div style="display:none" id="test-root">
+        <testcase id="testcase1"></testcase>
+        <testcase id="testcase2"></testcase>
+        <testcase id="testcase3"></testcase>
+        <testcase id="testcase4"></testcase>
+        <testcase id="testcase5"></testcase>
+        <testcase id="testcase6"></testcase>
+        <testcase id="testcase7"></testcase>
+        <testcase id="testcase8"></testcase>
+        <testcase id="testcase9"></testcase>
+        <testcase id="testcase10"></testcase>
+        <testcase id="testcase11"></testcase>
+    </div>
+</body>
+<script>
+description('Test basic uses cases of :nth-last-child().');
+
+function testQuerySelector(selector, expectedIds) {
+    shouldBe("document.querySelectorAll('" + selector + "').length", '' + expectedIds.length);
+    for (var i = 0; i < expectedIds.length; ++i)
+        shouldBeEqualToString("document.querySelectorAll('" + selector + "')[" + i + "].id", expectedIds[i]);
+}
+
+function testStyling(selector, expectedIds) {
+    var stylingElement = document.getElementById("style");
+    stylingElement.innerHTML = '' + selector + ' { background-color: rgb(10, 100, 200); }';
+
+    var allTestCases = document.querySelectorAll("#test-root *");
+    for (var i = 0; i < allTestCases.length; ++i) {
+        var expectMatch = expectedIds.indexOf(allTestCases[i].id) >= 0;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll("#test-root *")[' + i + ']).backgroundColor', expectMatch ? 'rgb(10, 100, 200)' : 'rgb(255, 0, 0)');
+    }
+
+    stylingElement.innerHTML = '';
+}
+
+function testSelector(selector, expectedIds) {
+    debug("Testing \"" + selector + "\"");
+    testQuerySelector("#test-root " + selector, expectedIds);
+    testStyling("#test-root " + selector, expectedIds);
+    debug("");
+}
+
+// Test cases presented on http://nthmaster.com/ to have a simple baseline.
+testSelector(":nth-last-child(8)", ["testcase4"]);
+testSelector(":nth-last-child(n+6)", ["testcase1", "testcase2", "testcase3", "testcase4", "testcase5", "testcase6"]);
+testSelector(":nth-last-child(-n+9)", ["testcase3", "testcase4", "testcase5", "testcase6", "testcase7", "testcase8", "testcase9", "testcase10", "testcase11"]);
+testSelector(":nth-last-child(n+4):nth-last-child(-n+8)", ["testcase4", "testcase5", "testcase6", "testcase7", "testcase8"]);
+testSelector(":nth-last-child(-n+8):nth-last-child(n+4)", ["testcase4", "testcase5", "testcase6", "testcase7", "testcase8"]);
+testSelector(":nth-last-child(n+2):nth-last-child(odd):nth-last-child(-n+9)", ["testcase3", "testcase5", "testcase7", "testcase9"]);
+testSelector(":nth-last-child(3n+1):nth-last-child(even)", ["testcase2", "testcase8"]);
+testSelector(":nth-last-child(even):nth-last-child(3n+1)", ["testcase2", "testcase8"]);
+
+// The following was using :nth-last-child() on http://nthmaster.com/. It is adapted here for completness.
+testSelector(":nth-last-child(3)", ["testcase9"]);
+testSelector(":nth-last-child(4)", ["testcase8"]);
+testSelector(":nth-last-child(3):nth-last-child(4)", []);
+testSelector(":nth-last-child(4):nth-last-child(3)", []);
+
+testSelector(":nth-last-child(n+3)", ["testcase1", "testcase2", "testcase3", "testcase4", "testcase5", "testcase6", "testcase7", "testcase8", "testcase9"]);
+testSelector(":nth-last-child(2n+2)", ["testcase2", "testcase4", "testcase6", "testcase8", "testcase10"]);
+testSelector(":nth-last-child(n+3):nth-last-child(2n+2)", ["testcase2", "testcase4", "testcase6", "testcase8"]);
+testSelector(":nth-last-child(2n+2):nth-last-child(n+3)", ["testcase2", "testcase4", "testcase6", "testcase8"]);
+
+testSelector(":nth-last-child(-n+4)", ["testcase8", "testcase9", "testcase10", "testcase11"]);
+testSelector(":nth-last-child(-n+5)", ["testcase7", "testcase8", "testcase9", "testcase10", "testcase11"]);
+testSelector(":nth-last-child(-n+4):nth-last-child(-n+5)", ["testcase8", "testcase9", "testcase10", "testcase11"]);
+testSelector(":nth-last-child(-n+5):nth-last-child(-n+4)", ["testcase8", "testcase9", "testcase10", "testcase11"]);
+
+testSelector(":nth-last-child(n+3):nth-last-child(-n+6)", ["testcase6", "testcase7", "testcase8", "testcase9"]);
+testSelector(":nth-last-child(-n+6):nth-last-child(n+3)", ["testcase6", "testcase7", "testcase8", "testcase9"]);
+testSelector(":nth-last-child(n+1):nth-last-child(-n+3)", ["testcase9", "testcase10", "testcase11"]);
+testSelector(":nth-last-child(-n+3):nth-last-child(n+1)", ["testcase9", "testcase10", "testcase11"]);
+testSelector(":nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(n+1):nth-last-child(-n+3)", ["testcase9"]);
+testSelector(":nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(-n+3):nth-last-child(n+1)", ["testcase9"]);
+
+testSelector(":nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6)", ["testcase7", "testcase9"]);
+testSelector(":nth-last-child(-n+6):nth-last-child(odd):nth-last-child(n+3)", ["testcase7", "testcase9"]);
+testSelector(":nth-last-child(odd):nth-last-child(n+3):nth-last-child(-n+6)", ["testcase7", "testcase9"]);
+testSelector(":nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+3)", ["testcase7", "testcase9"]);
+testSelector(":nth-last-child(n+3):nth-last-child(-n+6):nth-last-child(odd)", ["testcase7", "testcase9"]);
+testSelector(":nth-last-child(-n+6):nth-last-child(n+3):nth-last-child(odd)", ["testcase7", "testcase9"]);
+
+testSelector(":nth-last-child(n+1):nth-last-child(even):nth-last-child(-n+3)", ["testcase10"]);
+testSelector(":nth-last-child(-n+3):nth-last-child(even):nth-last-child(n+1)", ["testcase10"]);
+testSelector(":nth-last-child(even):nth-last-child(n+1):nth-last-child(-n+3)", ["testcase10"]);
+testSelector(":nth-last-child(even):nth-last-child(-n+3):nth-last-child(n+1)", ["testcase10"]);
+testSelector(":nth-last-child(-n+3):nth-last-child(n+1):nth-last-child(even)", ["testcase10"]);
+testSelector(":nth-last-child(n+1):nth-last-child(-n+3):nth-last-child(even)", ["testcase10"]);
+
+testSelector(":nth-last-child(n+3):nth-last-child(odd):nth-last-child(-n+6):nth-last-child(n+1):nth-last-child(-n+3):nth-last-child(even)", []);
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/fast/selectors/nth-last-child-bounds-expected.txt b/LayoutTests/fast/selectors/nth-last-child-bounds-expected.txt
new file mode 100644 (file)
index 0000000..7245966
--- /dev/null
@@ -0,0 +1,35 @@
+Test the boundary values of the :nth-last-child() selector.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll("li:nth-last-child(0n+0)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-0n+0)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(0n-0)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-0n-0)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-0n)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(0)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-0)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-1)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(2147483647n+2147483647)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(2147483647n)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(2147483647)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-2147483648n)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-2147483648)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(2147483647n-2147483648)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-2147483648n+2147483647)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(2147483648n+2147483648)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(2147483648n)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(2147483648)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(3147483647n+3147483647)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(3147483647n)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(3147483647)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-2147483649n-2147483649)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-2147483649n)").length is 0
+PASS document.querySelectorAll("li:nth-last-child(-2147483649)").length is 0
+PASS allItems.length is 20
+PASS coloredCount is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/nth-last-child-bounds.html b/LayoutTests/fast/selectors/nth-last-child-bounds.html
new file mode 100644 (file)
index 0000000..d2fb449
--- /dev/null
@@ -0,0 +1,161 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+/* The element count starts at 1, no count <= 1 can match anything */
+li:nth-last-child(0n+0) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-0n+0) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(0n-0) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-0n-0) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(0n) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-0n) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(0) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-0) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-1) {
+    background-color:rgb(1, 2, 3);
+}
+
+/* IntMax (2147483647) and IntMin (-2147483647). The tree is not big enough to match any of those. */
+li:nth-last-child(2147483647n+2147483647) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(2147483647n) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(2147483647) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-2147483648n-2147483648) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-2147483648n) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-2147483648) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(2147483647n-2147483648) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-2147483648n+2147483647) {
+    background-color:rgb(1, 2, 3);
+}
+
+/* Values too large/small for int32 */
+li:nth-last-child(2147483648n+2147483648) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(2147483648n) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(2147483648) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(3147483647n+3147483647) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(3147483647n) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(3147483647) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-2147483649n-2147483649) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-2147483649n) {
+    background-color:rgb(1, 2, 3);
+}
+li:nth-last-child(-2147483649) {
+    background-color:rgb(1, 2, 3);
+}
+
+</style>
+</head>
+<body>
+<div style="display:none">
+    <ul id=targetTree>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+        <li></li>
+    </ul>
+</div>
+</body>
+<script>
+description('Test the boundary values of the :nth-last-child() selector.');
+
+shouldBe('document.querySelectorAll("li:nth-last-child(0n+0)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-0n+0)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(0n-0)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-0n-0)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-0n)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(0)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-0)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-1)").length', '0');
+
+shouldBe('document.querySelectorAll("li:nth-last-child(2147483647n+2147483647)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(2147483647n)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(2147483647)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-2147483648n)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-2147483648)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(2147483647n-2147483648)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-2147483648n+2147483647)").length', '0');
+
+shouldBe('document.querySelectorAll("li:nth-last-child(2147483648n+2147483648)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(2147483648n)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(2147483648)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(3147483647n+3147483647)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(3147483647n)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(3147483647)").length', '0');
+
+shouldBe('document.querySelectorAll("li:nth-last-child(-2147483649n-2147483649)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-2147483649n)").length', '0');
+shouldBe('document.querySelectorAll("li:nth-last-child(-2147483649)").length', '0');
+
+var allItems = document.querySelectorAll('li');
+var coloredCount = 0;
+for (var i = 0; i < allItems.length; ++i) {
+    if (getComputedStyle(allItems[i]).backgroundColor === 'rgb(1, 2, 3)')
+        coloredCount++;
+}
+
+shouldBe('allItems.length', '20');
+shouldBe('coloredCount', '0');
+
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/fast/selectors/nth-last-child-chained-expected.txt b/LayoutTests/fast/selectors/nth-last-child-chained-expected.txt
new file mode 100644 (file)
index 0000000..f42a1d6
--- /dev/null
@@ -0,0 +1,184 @@
+Test chaining many :nth-last-child() selectors. This verifies register allocation is correct.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Testing ":nth-last-child(-n+21):nth-last-child(odd):nth-last-child(-2n+21):nth-last-child(3n+1):nth-last-child(-3n+22):nth-last-child(4n+1):nth-last-child(-5n+51)"
+PASS document.querySelectorAll('testcase:nth-last-child(-n+21):nth-last-child(odd):nth-last-child(-2n+21):nth-last-child(3n+1):nth-last-child(-3n+22):nth-last-child(4n+1):nth-last-child(-5n+51)').length is 1
+PASS document.querySelectorAll('testcase:nth-last-child(-n+21):nth-last-child(odd):nth-last-child(-2n+21):nth-last-child(3n+1):nth-last-child(-3n+22):nth-last-child(4n+1):nth-last-child(-5n+51)')[0].id is "testcase20"
+PASS getComputedStyle(document.querySelectorAll("testcase")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[10]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[11]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[12]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[13]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[14]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[15]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[16]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[17]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[18]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[19]).backgroundColor is "rgb(10, 100, 200)"
+PASS document.querySelectorAll('div>testcase:nth-last-child(-n+21):nth-last-child(odd):nth-last-child(-2n+21):nth-last-child(3n+1):nth-last-child(-3n+22):nth-last-child(4n+1):nth-last-child(-5n+51)>div>div>div span').length is 1
+
+Testing ":nth-last-child(2n-200):nth-last-child(3n-1):nth-last-child(4n-38):nth-last-child(5n-98)"
+PASS document.querySelectorAll('testcase:nth-last-child(2n-200):nth-last-child(3n-1):nth-last-child(4n-38):nth-last-child(5n-98)').length is 1
+PASS document.querySelectorAll('testcase:nth-last-child(2n-200):nth-last-child(3n-1):nth-last-child(4n-38):nth-last-child(5n-98)')[0].id is "testcase19"
+PASS getComputedStyle(document.querySelectorAll("testcase")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[10]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[11]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[12]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[13]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[14]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[15]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[16]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[17]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[18]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[19]).backgroundColor is "rgb(255, 0, 0)"
+PASS document.querySelectorAll('div>testcase:nth-last-child(2n-200):nth-last-child(3n-1):nth-last-child(4n-38):nth-last-child(5n-98)>div>div>div span').length is 1
+
+Testing ":nth-last-child(even):nth-last-child(3n):nth-last-child(4n-2):nth-last-child(5n+1)"
+PASS document.querySelectorAll('testcase:nth-last-child(even):nth-last-child(3n):nth-last-child(4n-2):nth-last-child(5n+1)').length is 1
+PASS document.querySelectorAll('testcase:nth-last-child(even):nth-last-child(3n):nth-last-child(4n-2):nth-last-child(5n+1)')[0].id is "testcase15"
+PASS getComputedStyle(document.querySelectorAll("testcase")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[10]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[11]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[12]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[13]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[14]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[15]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[16]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[17]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[18]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[19]).backgroundColor is "rgb(255, 0, 0)"
+PASS document.querySelectorAll('div>testcase:nth-last-child(even):nth-last-child(3n):nth-last-child(4n-2):nth-last-child(5n+1)>div>div>div span').length is 1
+
+Testing ":nth-last-child(-n+9000):nth-last-child(-2n+683):nth-last-child(-3n+31):nth-last-child(-4n+47):nth-last-child(-5n+107):nth-last-child(-6n+73):nth-last-child(-7n+70)"
+PASS document.querySelectorAll('testcase:nth-last-child(-n+9000):nth-last-child(-2n+683):nth-last-child(-3n+31):nth-last-child(-4n+47):nth-last-child(-5n+107):nth-last-child(-6n+73):nth-last-child(-7n+70)').length is 1
+PASS document.querySelectorAll('testcase:nth-last-child(-n+9000):nth-last-child(-2n+683):nth-last-child(-3n+31):nth-last-child(-4n+47):nth-last-child(-5n+107):nth-last-child(-6n+73):nth-last-child(-7n+70)')[0].id is "testcase14"
+PASS getComputedStyle(document.querySelectorAll("testcase")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[10]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[11]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[12]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[13]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[14]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[15]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[16]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[17]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[18]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[19]).backgroundColor is "rgb(255, 0, 0)"
+PASS document.querySelectorAll('div>testcase:nth-last-child(-n+9000):nth-last-child(-2n+683):nth-last-child(-3n+31):nth-last-child(-4n+47):nth-last-child(-5n+107):nth-last-child(-6n+73):nth-last-child(-7n+70)>div>div>div span').length is 1
+
+Testing ":nth-last-child(odd):nth-last-child(3n+1):nth-last-child(4n-1):nth-last-child(5n+4)"
+PASS document.querySelectorAll('testcase:nth-last-child(odd):nth-last-child(3n+1):nth-last-child(4n-1):nth-last-child(5n+4)').length is 1
+PASS document.querySelectorAll('testcase:nth-last-child(odd):nth-last-child(3n+1):nth-last-child(4n-1):nth-last-child(5n+4)')[0].id is "testcase2"
+PASS getComputedStyle(document.querySelectorAll("testcase")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[10]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[11]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[12]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[13]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[14]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[15]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[16]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[17]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[18]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[19]).backgroundColor is "rgb(255, 0, 0)"
+PASS document.querySelectorAll('div>testcase:nth-last-child(odd):nth-last-child(3n+1):nth-last-child(4n-1):nth-last-child(5n+4)>div>div>div span').length is 1
+
+Testing ":nth-last-child(-n+1500):nth-last-child(2n+1):nth-last-child(-3n+45):nth-last-child(4n+3):nth-last-child(-5n+1545)"
+PASS document.querySelectorAll('testcase:nth-last-child(-n+1500):nth-last-child(2n+1):nth-last-child(-3n+45):nth-last-child(4n+3):nth-last-child(-5n+1545)').length is 1
+PASS document.querySelectorAll('testcase:nth-last-child(-n+1500):nth-last-child(2n+1):nth-last-child(-3n+45):nth-last-child(4n+3):nth-last-child(-5n+1545)')[0].id is "testcase6"
+PASS getComputedStyle(document.querySelectorAll("testcase")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[5]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[10]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[11]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[12]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[13]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[14]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[15]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[16]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[17]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[18]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[19]).backgroundColor is "rgb(255, 0, 0)"
+PASS document.querySelectorAll('div>testcase:nth-last-child(-n+1500):nth-last-child(2n+1):nth-last-child(-3n+45):nth-last-child(4n+3):nth-last-child(-5n+1545)>div>div>div span').length is 1
+
+Testing ":nth-last-child(n+2):nth-last-child(-n+6000):nth-last-child(n-2):nth-last-child(2n):nth-last-child(-2n+20):nth-last-child(2n+2):nth-last-child(3n+1):nth-last-child(-3n+49):nth-last-child(3n-92):nth-last-child(4n+2):nth-last-child(-4n+50)"
+PASS document.querySelectorAll('testcase:nth-last-child(n+2):nth-last-child(-n+6000):nth-last-child(n-2):nth-last-child(2n):nth-last-child(-2n+20):nth-last-child(2n+2):nth-last-child(3n+1):nth-last-child(-3n+49):nth-last-child(3n-92):nth-last-child(4n+2):nth-last-child(-4n+50)').length is 1
+PASS document.querySelectorAll('testcase:nth-last-child(n+2):nth-last-child(-n+6000):nth-last-child(n-2):nth-last-child(2n):nth-last-child(-2n+20):nth-last-child(2n+2):nth-last-child(3n+1):nth-last-child(-3n+49):nth-last-child(3n-92):nth-last-child(4n+2):nth-last-child(-4n+50)')[0].id is "testcase11"
+PASS getComputedStyle(document.querySelectorAll("testcase")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[4]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[5]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[6]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[7]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[8]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[9]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[10]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[11]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[12]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[13]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[14]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[15]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[16]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[17]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[18]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("testcase")[19]).backgroundColor is "rgb(255, 0, 0)"
+PASS document.querySelectorAll('div>testcase:nth-last-child(n+2):nth-last-child(-n+6000):nth-last-child(n-2):nth-last-child(2n):nth-last-child(-2n+20):nth-last-child(2n+2):nth-last-child(3n+1):nth-last-child(-3n+49):nth-last-child(3n-92):nth-last-child(4n+2):nth-last-child(-4n+50)>div>div>div span').length is 1
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/nth-last-child-chained.html b/LayoutTests/fast/selectors/nth-last-child-chained.html
new file mode 100644 (file)
index 0000000..ba44f4c
--- /dev/null
@@ -0,0 +1,94 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+testcase {
+    background-color: red;
+}
+</style>
+<style id="style">
+</style>
+</head>
+<body>
+    <div style="display:none">
+        <testcase id="testcase1"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase2"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase3"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase4"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase5"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase6"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase7"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase8"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase9"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase10"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase11"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase12"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase13"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase14"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase15"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase16"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase17"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase18"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase19"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+        <testcase id="testcase20"><div><div><div><div><div><div><div><div><span></span></div></div></div></div></div></div></div></div></testcase>
+    </div>
+</body>
+<script>
+description('Test chaining many :nth-last-child() selectors. This verifies register allocation is correct.');
+
+function testQuerySelector(selector, expectedIds) {
+    shouldBe("document.querySelectorAll('" + selector + "').length", '' + expectedIds.length);
+    for (var i = 0; i < expectedIds.length; ++i)
+        shouldBeEqualToString("document.querySelectorAll('" + selector + "')[" + i + "].id", expectedIds[i]);
+}
+
+function testStyling(selector, expectedIds) {
+    var stylingElement = document.getElementById("style");
+    stylingElement.innerHTML = '' + selector + ' { background-color: rgb(10, 100, 200); }';
+
+    var allTestCases = document.querySelectorAll("testcase");
+    for (var i = 0; i < allTestCases.length; ++i) {
+        var expectMatch = expectedIds.indexOf(allTestCases[i].id) >= 0;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll("testcase")[' + i + ']).backgroundColor', expectMatch ? 'rgb(10, 100, 200)' : 'rgb(255, 0, 0)');
+    }
+
+    stylingElement.innerHTML = '';
+}
+
+function testSelector(selector, expectedIds) {
+    debug("Testing \"" + selector + "\"");
+    testQuerySelector("testcase" + selector, expectedIds);
+    testStyling("testcase" + selector, expectedIds);
+
+    // Test the same request with a backtracking register.
+    shouldBe("document.querySelectorAll('div>testcase" + selector + ">div>div>div span').length", '' + expectedIds.length);
+
+    debug("");
+}
+
+// The :nth-last-child() should not completely overlap to ensure all of them are executed.
+
+// All positive B.
+testSelector(":nth-last-child(-n+21):nth-last-child(odd):nth-last-child(-2n+21):nth-last-child(3n+1):nth-last-child(-3n+22):nth-last-child(4n+1):nth-last-child(-5n+51)", ["testcase20"]);
+
+// All negative B.
+testSelector(":nth-last-child(2n-200):nth-last-child(3n-1):nth-last-child(4n-38):nth-last-child(5n-98)", ["testcase19"]);
+
+// All positive A.
+testSelector(":nth-last-child(even):nth-last-child(3n):nth-last-child(4n-2):nth-last-child(5n+1)", ["testcase15"]);
+
+// All negative A.
+testSelector(":nth-last-child(-n+9000):nth-last-child(-2n+683):nth-last-child(-3n+31):nth-last-child(-4n+47):nth-last-child(-5n+107):nth-last-child(-6n+73):nth-last-child(-7n+70)", ["testcase14"]);
+
+// Positive and Negative B.
+testSelector(":nth-last-child(odd):nth-last-child(3n+1):nth-last-child(4n-1):nth-last-child(5n+4)", ["testcase2"]);
+
+// Positive and Negative A.
+testSelector(":nth-last-child(-n+1500):nth-last-child(2n+1):nth-last-child(-3n+45):nth-last-child(4n+3):nth-last-child(-5n+1545)", ["testcase6"]);
+
+// Everything.
+testSelector(":nth-last-child(n+2):nth-last-child(-n+6000):nth-last-child(n-2):nth-last-child(2n):nth-last-child(-2n+20):nth-last-child(2n+2):nth-last-child(3n+1):nth-last-child(-3n+49):nth-last-child(3n-92):nth-last-child(4n+2):nth-last-child(-4n+50)", ["testcase11"]);
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/fast/selectors/nth-last-child-on-root-expected.txt b/LayoutTests/fast/selectors/nth-last-child-on-root-expected.txt
new file mode 100644 (file)
index 0000000..9c76f72
--- /dev/null
@@ -0,0 +1,20 @@
+Verify the nth-last-child() pseudo class matcher always test for the parent element. Some :nth-last-child pseudo selectors can skip counting the siblings, but they should never skip the parent check.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll("html:nth-last-child(1)").length is 0
+PASS document.querySelectorAll("html:nth-last-child(n)").length is 0
+PASS document.querySelectorAll("html:nth-last-child(n+1)").length is 0
+PASS document.querySelectorAll(":root:nth-last-child(1)").length is 0
+PASS document.querySelectorAll(":root:nth-last-child(n)").length is 0
+PASS document.querySelectorAll(":root:nth-last-child(n+1)").length is 0
+PASS getComputedStyle(document.documentElement).backgroundColor is "rgb(255, 255, 255)"
+PASS document.querySelectorAll("svg:root").length is 0
+PASS document.querySelectorAll("svg:nth-last-child(1)").length is 1
+PASS document.querySelectorAll("svg:nth-last-child(n)").length is 1
+PASS getComputedStyle(document.querySelector("svg")).backgroundColor is "rgb(1, 2, 3)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/nth-last-child-on-root.html b/LayoutTests/fast/selectors/nth-last-child-on-root.html
new file mode 100644 (file)
index 0000000..3d69bb6
--- /dev/null
@@ -0,0 +1,60 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+html {
+    background-color:white;
+}
+html:nth-last-child(1) {
+    background-color:rgb(1, 2, 3);
+}
+html:nth-last-child(n) {
+    background-color:rgb(1, 2, 3);
+}
+html:nth-last-child(n+1) {
+    background-color:rgb(1, 2, 3);
+}
+
+:root:nth-last-child(1) {
+    background-color:rgb(1, 2, 3);
+}
+:root:nth-last-child(n) {
+    background-color:rgb(1, 2, 3);
+}
+:root:nth-last-child(n+1) {
+    background-color:rgb(1, 2, 3);
+}
+
+svg:nth-last-child(n) {
+    background-color:rgb(1, 2, 3);
+}
+svg:root {
+    background-color:rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div style="display:none">
+        <svg><g></g></svg>
+    </div>
+</body>
+<script>
+description('Verify the nth-last-child() pseudo class matcher always test for the parent element. Some :nth-last-child pseudo selectors can skip counting the siblings, but they should never skip the parent check.');
+
+shouldBe('document.querySelectorAll("html:nth-last-child(1)").length', '0');
+shouldBe('document.querySelectorAll("html:nth-last-child(n)").length', '0');
+shouldBe('document.querySelectorAll("html:nth-last-child(n+1)").length', '0');
+shouldBe('document.querySelectorAll(":root:nth-last-child(1)").length', '0');
+shouldBe('document.querySelectorAll(":root:nth-last-child(n)").length', '0');
+shouldBe('document.querySelectorAll(":root:nth-last-child(n+1)").length', '0');
+shouldBeEqualToString('getComputedStyle(document.documentElement).backgroundColor', 'rgb(255, 255, 255)');
+
+// This svg document is not the root, ":root" should not match anything, nth-last-child should work.
+shouldBe('document.querySelectorAll("svg:root").length', '0');
+shouldBe('document.querySelectorAll("svg:nth-last-child(1)").length', '1');
+shouldBe('document.querySelectorAll("svg:nth-last-child(n)").length', '1');
+shouldBeEqualToString('getComputedStyle(document.querySelector("svg")).backgroundColor', 'rgb(1, 2, 3)');
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/fast/selectors/nth-last-child-style-update-expected.txt b/LayoutTests/fast/selectors/nth-last-child-style-update-expected.txt
new file mode 100644 (file)
index 0000000..e91d00f
--- /dev/null
@@ -0,0 +1,167 @@
+Test style update of :nth-last-child() when the tree structure is modified.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initialy, only the first can match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <target> on top, we should now match 0 and 1.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <nottarget> on top, we should now match -1, 0, 1.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <nottarget> on top, we should now match -2, -1, 0, 1.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <target> on top, we should now match -3, -2, -1, 0, 1.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[13]).backgroundColor is "rgb(255, 255, 255)"
+Adding an element <nottarget> on top, we should now match -4, -3, -2, -1, 0, 1.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[13]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <nottarget>, -2 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[13]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <target>, -4 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[13]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <notarget>, -1 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[13]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <target>, -3 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[11]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <target>, 0 should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[9]).backgroundColor is "rgb(255, 255, 255)"
+Removing one of the <target>, there are only 4 siblings left, nothing can match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/nth-last-child-style-update.html b/LayoutTests/fast/selectors/nth-last-child-style-update.html
new file mode 100644 (file)
index 0000000..a98da19
--- /dev/null
@@ -0,0 +1,110 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+target {
+    background-color: white;
+}
+target:nth-last-child(n+5) {
+    background-color: rgb(1, 2, 3);
+}
+</style>
+</head>
+<body>
+    <div id="with-renderer">
+        <target class="element_1"></target>
+        <target class="element_2"></target>
+        <target class="element_3"></target>
+        <target class="element_4"></target>
+        <target class="element_5"></target>
+    </div>
+    <div id="without-renderer" style="display:none;">
+        <target class="element_1"></target>
+        <target class="element_2"></target>
+        <target class="element_3"></target>
+        <target class="element_4"></target>
+        <target class="element_5"></target>
+    </div>
+</body>
+<script>
+description('Test style update of :nth-last-child() when the tree structure is modified.');
+
+function testColor(classesThatShouldMatch) {
+    var allTargets = document.querySelectorAll("target");
+    for (var i = 0; i < allTargets.length; ++i) {
+        var expectMath = classesThatShouldMatch.indexOf(allTargets[i].className) != -1;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[' + i + ']).backgroundColor', expectMath ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    }
+}
+
+function addElementAsFirstChild(tagName, className)
+{
+    var newElement = document.createElement(tagName);
+    newElement.className = className;
+
+    var withRenderer = document.getElementById("with-renderer");
+    withRenderer.insertBefore(newElement, withRenderer.firstChild);
+
+    var withoutRenderer = document.getElementById("without-renderer");
+    withoutRenderer.insertBefore(newElement.cloneNode(), withoutRenderer.firstChild);
+}
+
+function removeElementsOfClass(className)
+{
+    var allElementsToRemove = document.querySelectorAll('.' + className);
+    for (var i = 0; i < allElementsToRemove.length; ++i)
+        allElementsToRemove[i].parentElement.removeChild(allElementsToRemove[i]);
+}
+
+debug("Initialy, only the first can match.");
+testColor(["element_1"]);
+
+debug("Adding an element &lt;target&gt; on top, we should now match 0 and 1.");
+addElementAsFirstChild("target", "element_0")
+testColor(["element_0", "element_1"]);
+
+// Using nottarget is interesting because the ':nth-last-child()' part is not matched for those elements.
+debug("Adding an element &lt;nottarget&gt; on top, we should now match -1, 0, 1.");
+addElementAsFirstChild("nottarget", "element_-1")
+testColor(["element_-1", "element_0", "element_1"]);
+
+debug("Adding an element &lt;nottarget&gt; on top, we should now match -2, -1, 0, 1.");
+addElementAsFirstChild("nottarget", "element_-2")
+testColor(["element_-2", "element_-1", "element_0", "element_1"]);
+
+debug("Adding an element &lt;target&gt; on top, we should now match -3, -2, -1, 0, 1.");
+addElementAsFirstChild("target", "element_-3")
+testColor(["element_-3", "element_-2", "element_-1", "element_0", "element_1"]);
+
+debug("Adding an element &lt;nottarget&gt; on top, we should now match -4, -3, -2, -1, 0, 1.");
+addElementAsFirstChild("nottarget", "element_-4")
+testColor(["element_-4", "element_-3", "element_-2", "element_-1", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;nottarget&gt;, -2 should no longer match.");
+removeElementsOfClass("element_-2");
+testColor(["element_-4", "element_-3", "element_-1", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;target&gt;, -4 should no longer match.");
+removeElementsOfClass("element_-4");
+testColor(["element_-3", "element_-1", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;notarget&gt;, -1 should no longer match.");
+removeElementsOfClass("element_-1");
+testColor(["element_-3", "element_0", "element_1"]);
+
+debug("Removing one of the &lt;target&gt;, -3 should no longer match.");
+removeElementsOfClass("element_-3");
+testColor(["element_0", "element_1"]);
+
+debug("Removing one of the &lt;target&gt;, 0 should no longer match.");
+removeElementsOfClass("element_0");
+testColor(["element_1"]);
+
+debug("Removing one of the &lt;target&gt;, there are only 4 siblings left, nothing can match.");
+removeElementsOfClass("element_1");
+testColor([]);
+
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/fast/selectors/nth-last-child-with-backtracking-expected.txt b/LayoutTests/fast/selectors/nth-last-child-with-backtracking-expected.txt
new file mode 100644 (file)
index 0000000..d470ddf
--- /dev/null
@@ -0,0 +1,17 @@
+Test nth-last-child inside deep backtracking.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll("li+li+:nth-last-child(-5n+14)+li+li+li~li+li+li~li").length is 7
+PASS allItems.length is 20
+PASS coloredItems is 7
+PASS document.querySelectorAll("ul>[foo=bar]:nth-last-child(-3n+18)+li+li+li~li+li+li~li>span.first>span.second a").length is 11
+PASS allLinks.length is 20
+PASS backgroundColoredCount is 11
+PASS document.querySelectorAll("ul>:nth-last-child(-3n+3)>*>* a").length is 1
+PASS nonOpaqueCount is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/nth-last-child-with-backtracking.html b/LayoutTests/fast/selectors/nth-last-child-with-backtracking.html
new file mode 100644 (file)
index 0000000..c87e3b8
--- /dev/null
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+li+li+:nth-last-child(-5n+14)+li+li+li~li+li+li~li {
+    color:rgb(4, 5, 6);
+}
+ul>[foo=bar]:nth-last-child(-3n+18)+li+li+li~li+li+li~li>span.first>span.second a {
+    background-color:rgb(1,2,3);
+}
+ul>:nth-last-child(-3n+3)>*>* a {
+    opacity: 0.5;
+}
+</style>
+</head>
+<body>
+<div>
+    <ul style="display:none">
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+        <li foo=bar><span class="first"><span class="second"><span><a href="http://www.webkit.org">WebKit!</a></span></span></span></li>
+    </ul>
+</div>
+</body>
+<script>
+
+description('Test nth-last-child inside deep backtracking.');
+
+// nth-last-child inside two adjacent backtracking chains.
+shouldBe('document.querySelectorAll("li+li+:nth-last-child(-5n+14)+li+li+li~li+li+li~li").length', '7');
+var allItems = document.querySelectorAll('li');
+shouldBe('allItems.length', '20');
+var coloredItems = 0;
+for (var i = 0; i < allItems.length; ++i) {
+    if (getComputedStyle(allItems[i]).color === 'rgb(4, 5, 6)')
+        coloredItems++;
+}
+shouldBe('coloredItems', '7');
+
+// nth-last-child inside two adjacent backtracking chains, inside one descendant backtracking chain.
+shouldBe('document.querySelectorAll("ul>[foo=bar]:nth-last-child(-3n+18)+li+li+li~li+li+li~li>span.first>span.second a").length', '11');
+var allLinks = document.querySelectorAll('a');
+shouldBe('allLinks.length', '20');
+var backgroundColoredCount = 0;
+var nonOpaqueCount = 0;
+for (var i = 0; i < allLinks.length; ++i) {
+    var computedStyle = getComputedStyle(allLinks[i]);
+    if (computedStyle.backgroundColor === 'rgb(1, 2, 3)')
+        backgroundColoredCount++;
+    if (computedStyle.opacity === '0.5')
+        ++nonOpaqueCount;
+}
+shouldBe('backgroundColoredCount', '11');
+
+shouldBe('document.querySelectorAll("ul>:nth-last-child(-3n+3)>*>* a").length', '1');
+shouldBe('nonOpaqueCount', '1');
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/fast/selectors/several-nth-last-child-expected.txt b/LayoutTests/fast/selectors/several-nth-last-child-expected.txt
new file mode 100644 (file)
index 0000000..22a5615
--- /dev/null
@@ -0,0 +1,17 @@
+Verify the nth-last-child() pseudo class does not leak registers.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll("body:nth-last-child(n) div:nth-last-child(n) ul:nth-last-child(n) li:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n)").length is 1
+PASS getComputedStyle(document.getElementById("target")).backgroundColor is "rgb(1, 2, 3)"
+PASS document.querySelectorAll("body:nth-last-child(n+1) div:nth-last-child(n+1) ul:nth-last-child(n+1) li:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1)").length is 1
+PASS getComputedStyle(document.getElementById("target")).color is "rgb(4, 5, 6)"
+PASS document.querySelectorAll("body:nth-last-child(1) div:nth-last-child(1) ul:nth-last-child(1) li:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1)").length is 0
+PASS document.querySelectorAll("body:nth-last-child(2) div:nth-last-child(2) ul:nth-last-child(2) li:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2)").length is 0
+PASS document.querySelectorAll("body:nth-last-child(2n) div:nth-last-child(2n) ul:nth-last-child(2n) li:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n)").length is 0
+PASS document.querySelectorAll("body:nth-last-child(2n+1) div:nth-last-child(2n+1) ul:nth-last-child(2n+1) li:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1)").length is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/selectors/several-nth-last-child.html b/LayoutTests/fast/selectors/several-nth-last-child.html
new file mode 100644 (file)
index 0000000..4071719
--- /dev/null
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+body:nth-last-child(n) div:nth-last-child(n) ul:nth-last-child(n) li:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) {
+    background-color:rgb(1, 2, 3);
+}
+body:nth-last-child(n+1) div:nth-last-child(n+1) ul:nth-last-child(n+1) li:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) {
+    color:rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div style="display:none">
+        <ul>
+            <li><span><span><span><span><span><span id=target></span></span></span></span></span></span></li>
+        </ul>
+    </div>
+</body>
+<script>
+description('Verify the nth-last-child() pseudo class does not leak registers.');
+
+shouldBe('document.querySelectorAll("body:nth-last-child(n) div:nth-last-child(n) ul:nth-last-child(n) li:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n) span:nth-last-child(n)").length', '1');
+shouldBeEqualToString('getComputedStyle(document.getElementById("target")).backgroundColor', 'rgb(1, 2, 3)');
+shouldBe('document.querySelectorAll("body:nth-last-child(n+1) div:nth-last-child(n+1) ul:nth-last-child(n+1) li:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1) span:nth-last-child(n+1)").length', '1');
+shouldBeEqualToString('getComputedStyle(document.getElementById("target")).color', 'rgb(4, 5, 6)');
+
+shouldBe('document.querySelectorAll("body:nth-last-child(1) div:nth-last-child(1) ul:nth-last-child(1) li:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1) span:nth-last-child(1)").length', '0');
+shouldBe('document.querySelectorAll("body:nth-last-child(2) div:nth-last-child(2) ul:nth-last-child(2) li:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2) span:nth-last-child(2)").length', '0');
+shouldBe('document.querySelectorAll("body:nth-last-child(2n) div:nth-last-child(2n) ul:nth-last-child(2n) li:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n) span:nth-last-child(2n)").length', '0');
+shouldBe('document.querySelectorAll("body:nth-last-child(2n+1) div:nth-last-child(2n+1) ul:nth-last-child(2n+1) li:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1) span:nth-last-child(2n+1)").length', '0');
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
index ae303af..8a7af49 100644 (file)
@@ -1,3 +1,39 @@
+2015-02-02  Benjamin Poulain  <benjamin@webkit.org>
+
+        JIT Compile simple cases of :nth-last-child()
+        https://bugs.webkit.org/show_bug.cgi?id=141053
+
+        Reviewed by Andreas Kling.
+
+        This patch adds the code generator for :nth-last-child(), skipping
+        any :nth-last-child(An+B of selector list).
+
+        The code generator is boring here, nothing fancy.
+        There is no optimization opportunity here so it is basically the same
+        speed as the code generated by Clang when the simple selector is alone.
+
+        The only reason to JIT compile this is to avoid going to slow-path
+        for every selector that contain :nth-last-child().
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::addNthChildType):
+        The code creating the intermediate representation of :nth-child() is exactly
+        the same as what we need for :nth-last-child(). I extracted the code from addPseudoClassType()
+        and share it for both simple selectors.
+
+        (WebCore::SelectorCompiler::addPseudoClassType):
+        I fail :nth-last-child(An+B of selector list). Let's add it later.
+
+        (WebCore::SelectorCompiler::minimumRegisterRequirements):
+        Oops, there was a bug with nthChildOfFilters.
+
+        (WebCore::SelectorCompiler::hasAnyCombinators):
+        (WebCore::SelectorCompiler::computeBacktrackingMemoryRequirements):
+        (WebCore::SelectorCompiler::computeBacktrackingInformation):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
+        (WebCore::SelectorCompiler::setChildrenAffectedByBackwardPositionalRules):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementIsNthLastChild):
+
 2015-02-02  Zalan Bujtas  <zalan@apple.com>
 
         Simple line layout: Rename FlowContentsIterator to TextFragmentIterator.
index d1a84f2..95d4b98 100644 (file)
@@ -177,6 +177,8 @@ struct SelectorFragment {
     Vector<AttributeMatchingInfo, 4> attributes;
     Vector<std::pair<int, int>, 2> nthChildFilters;
     Vector<NthChildOfSelectorInfo> nthChildOfFilters;
+    Vector<std::pair<int, int>, 2> nthLastChildFilters;
+    Vector<NthChildOfSelectorInfo> nthLastChildOfFilters;
     SelectorList notFilters;
     Vector<SelectorList> matchesFilters;
     Vector<Vector<SelectorFragment>> anyFilters;
@@ -284,6 +286,7 @@ private:
     void generateElementIsLink(Assembler::JumpList& failureCases);
     void generateElementIsNthChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementIsNthChildOf(Assembler::JumpList& failureCases, const SelectorFragment&);
+    void generateElementIsNthLastChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementMatchesNotPseudoClass(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementMatchesAnyPseudoClass(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementMatchesMatchesPseudoClass(Assembler::JumpList& failureCases, const SelectorFragment&);
@@ -440,6 +443,82 @@ static inline FunctionType addScrollbarPseudoClassType(const CSSSelector& select
     return FunctionType::CannotMatchAnything;
 }
 
+// Handle the forward :nth-child() and backward :nth-last-child().
+static FunctionType addNthChildType(const CSSSelector& selector, SelectorContext selectorContext, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, Vector<std::pair<int, int>, 2>& simpleCases, Vector<NthChildOfSelectorInfo>& filteredCases, unsigned& internalSpecificity)
+{
+    if (!selector.parseNth())
+        return FunctionType::CannotMatchAnything;
+
+    int a = selector.nthA();
+    int b = selector.nthB();
+
+    // The element count is always positive.
+    if (a <= 0 && b < 1)
+        return FunctionType::CannotMatchAnything;
+
+    if (const CSSSelectorList* selectorList = selector.selectorList()) {
+        NthChildOfSelectorInfo nthChildOfSelectorInfo;
+        nthChildOfSelectorInfo.a = a;
+        nthChildOfSelectorInfo.b = b;
+
+        FunctionType globalFunctionType = FunctionType::SimpleSelectorChecker;
+        if (selectorContext != SelectorContext::QuerySelector)
+            globalFunctionType = FunctionType::SelectorCheckerWithCheckingContext;
+
+        unsigned firstFragmentListSpecificity = 0;
+        bool firstFragmentListSpecificitySet = false;
+
+        SelectorFragmentList* selectorFragments = nullptr;
+        for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
+            if (!selectorFragments) {
+                nthChildOfSelectorInfo.selectorList.append(SelectorFragmentList());
+                selectorFragments = &nthChildOfSelectorInfo.selectorList.last();
+            }
+
+            VisitedMode ignoreVisitedMode = VisitedMode::None;
+            FunctionType functionType = constructFragments(subselector, selectorContext, *selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, PseudoElementMatchingBehavior::NeverMatch);
+            ASSERT_WITH_MESSAGE(ignoreVisitedMode == VisitedMode::None, ":visited is disabled in the functional pseudo classes");
+            switch (functionType) {
+            case FunctionType::SimpleSelectorChecker:
+            case FunctionType::SelectorCheckerWithCheckingContext:
+                break;
+            case FunctionType::CannotMatchAnything:
+                continue;
+            case FunctionType::CannotCompile:
+                return FunctionType::CannotCompile;
+            }
+
+            if (firstFragmentListSpecificitySet) {
+                // The CSS JIT does not handle dynamic specificity yet.
+                if (selectorContext == SelectorContext::RuleCollector && selectorFragments->staticSpecificity != firstFragmentListSpecificity)
+                    return FunctionType::CannotCompile;
+            } else {
+                firstFragmentListSpecificitySet = true;
+                firstFragmentListSpecificity = selectorFragments->staticSpecificity;
+            }
+
+            globalFunctionType = mostRestrictiveFunctionType(globalFunctionType, functionType);
+            selectorFragments = nullptr;
+        }
+
+        // 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;
+
+        internalSpecificity = firstFragmentListSpecificity;
+        filteredCases.append(nthChildOfSelectorInfo);
+        return globalFunctionType;
+    }
+    simpleCases.append(std::pair<int, int>(a, b));
+    if (selectorContext == SelectorContext::QuerySelector)
+        return FunctionType::SimpleSelectorChecker;
+    return FunctionType::SelectorCheckerWithCheckingContext;
+}
+
 static inline FunctionType addPseudoClassType(const CSSSelector& selector, SelectorFragment& fragment, unsigned& internalSpecificity, SelectorContext selectorContext, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments, bool visitedMatchEnabled, VisitedMode& visitedMode, PseudoElementMatchingBehavior pseudoElementMatchingBehavior)
 {
     CSSSelector::PseudoClassType type = selector.pseudoClassType();
@@ -538,7 +617,6 @@ static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec
     case CSSSelector::PseudoClassLastOfType:
     case CSSSelector::PseudoClassOnlyOfType:
     case CSSSelector::PseudoClassNthOfType:
-    case CSSSelector::PseudoClassNthLastChild:
     case CSSSelector::PseudoClassNthLastOfType:
     case CSSSelector::PseudoClassDrag:
 #if ENABLE(CSS_SELECTORS_LEVEL4)
@@ -593,79 +671,14 @@ static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec
         return FunctionType::SelectorCheckerWithCheckingContext;
 
     case CSSSelector::PseudoClassNthChild:
-        {
-            if (!selector.parseNth())
-                return FunctionType::CannotMatchAnything;
-
-            int a = selector.nthA();
-            int b = selector.nthB();
-
-            // The element count is always positive.
-            if (a <= 0 && b < 1)
-                return FunctionType::CannotMatchAnything;
+        return addNthChildType(selector, selectorContext, positionInRootFragments, visitedMatchEnabled, fragment.nthChildFilters, fragment.nthChildOfFilters, internalSpecificity);
 
-            if (const CSSSelectorList* selectorList = selector.selectorList()) {
-                NthChildOfSelectorInfo nthChildOfSelectorInfo;
-                nthChildOfSelectorInfo.a = a;
-                nthChildOfSelectorInfo.b = b;
-
-                FunctionType globalFunctionType = FunctionType::SimpleSelectorChecker;
-                if (selectorContext != SelectorContext::QuerySelector)
-                    globalFunctionType = FunctionType::SelectorCheckerWithCheckingContext;
-
-                unsigned firstFragmentListSpecificity = 0;
-                bool firstFragmentListSpecificitySet = false;
-
-                SelectorFragmentList* selectorFragments = nullptr;
-                for (const CSSSelector* subselector = selectorList->first(); subselector; subselector = CSSSelectorList::next(subselector)) {
-                    if (!selectorFragments) {
-                        nthChildOfSelectorInfo.selectorList.append(SelectorFragmentList());
-                        selectorFragments = &nthChildOfSelectorInfo.selectorList.last();
-                    }
-
-                    VisitedMode ignoreVisitedMode = VisitedMode::None;
-                    FunctionType functionType = constructFragments(subselector, selectorContext, *selectorFragments, FragmentsLevel::InFunctionalPseudoType, positionInRootFragments, visitedMatchEnabled, ignoreVisitedMode, PseudoElementMatchingBehavior::NeverMatch);
-                    ASSERT_WITH_MESSAGE(ignoreVisitedMode == VisitedMode::None, ":visited is disabled in the functional pseudo classes");
-                    switch (functionType) {
-                    case FunctionType::SimpleSelectorChecker:
-                    case FunctionType::SelectorCheckerWithCheckingContext:
-                        break;
-                    case FunctionType::CannotMatchAnything:
-                        continue;
-                    case FunctionType::CannotCompile:
-                        return FunctionType::CannotCompile;
-                    }
-
-                    if (firstFragmentListSpecificitySet) {
-                        // The CSS JIT does not handle dynamic specificity yet.
-                        if (selectorContext == SelectorContext::RuleCollector && selectorFragments->staticSpecificity != firstFragmentListSpecificity)
-                            return FunctionType::CannotCompile;
-                    } else {
-                        firstFragmentListSpecificitySet = true;
-                        firstFragmentListSpecificity = selectorFragments->staticSpecificity;
-                    }
-
-                    globalFunctionType = mostRestrictiveFunctionType(globalFunctionType, functionType);
-                    selectorFragments = nullptr;
-                }
-
-                // 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;
-
-                internalSpecificity = firstFragmentListSpecificity;
-                fragment.nthChildOfFilters.append(nthChildOfSelectorInfo);
-                return globalFunctionType;
-            }
-            fragment.nthChildFilters.append(std::pair<int, int>(a, b));
-            if (selectorContext == SelectorContext::QuerySelector)
-                return FunctionType::SimpleSelectorChecker;
-            return FunctionType::SelectorCheckerWithCheckingContext;
-        }
+    case CSSSelector::PseudoClassNthLastChild: {
+        FunctionType functionType = addNthChildType(selector, selectorContext, positionInRootFragments, visitedMatchEnabled, fragment.nthLastChildFilters, fragment.nthLastChildOfFilters, internalSpecificity);
+        if (!fragment.nthLastChildOfFilters.isEmpty())
+            return FunctionType::CannotCompile;
+        return functionType;
+    }
 
     case CSSSelector::PseudoClassNot:
         {
@@ -1081,7 +1094,7 @@ static unsigned minimumRegisterRequirements(const SelectorFragment& selectorFrag
     }
 
 #if CPU(X86_64)
-    if (!selectorFragment.nthChildFilters.isEmpty() || selectorFragment.nthChildOfFilters.isEmpty())
+    if (!selectorFragment.nthChildFilters.isEmpty() || !selectorFragment.nthChildOfFilters.isEmpty() || !selectorFragment.nthLastChildFilters.isEmpty() || !selectorFragment.nthLastChildOfFilters.isEmpty())
         minimum = std::max(minimum, minimumRequiredRegisterCountForNthChildFilter);
 #endif
 
@@ -1126,6 +1139,10 @@ bool hasAnyCombinators(const Vector<SelectorFragment, inlineCapacity>& selectorF
         if (hasAnyCombinators(nthChildOfSelectorInfo.selectorList))
             return true;
     }
+    for (const NthChildOfSelectorInfo& nthLastChildOfSelectorInfo : selectorFragmentList.first().nthLastChildOfFilters) {
+        if (hasAnyCombinators(nthLastChildOfSelectorInfo.selectorList))
+            return true;
+    }
     return false;
 }
 
@@ -1176,6 +1193,9 @@ void computeBacktrackingMemoryRequirements(SelectorFragmentList& selectorFragmen
         for (NthChildOfSelectorInfo& nthChildOfSelectorInfo : selectorFragment.nthChildOfFilters)
             computeBacktrackingMemoryRequirements(nthChildOfSelectorInfo.selectorList, fragmentRegisterRequirements, fragmentStackRequirements, backtrackingRegisterReservedForFragment);
 
+        for (NthChildOfSelectorInfo& nthLastChildOfSelectorInfo : selectorFragment.nthLastChildOfFilters)
+            computeBacktrackingMemoryRequirements(nthLastChildOfSelectorInfo.selectorList, fragmentRegisterRequirements, fragmentStackRequirements, backtrackingRegisterReservedForFragment);
+
         if (selectorFragment.backtrackingFlags & BacktrackingFlag::InChainWithDescendantTail) {
             if (!backtrackingRegisterReserved)
                 ++fragmentRegisterRequirements;
@@ -1621,6 +1641,15 @@ void computeBacktrackingInformation(SelectorFragmentList& selectorFragments, uns
             for (SelectorFragmentList& selectorList : nthChildOfSelectorInfo.selectorList)
                 computeBacktrackingInformation(selectorList, level + 1);
         }
+
+        for (NthChildOfSelectorInfo& nthLastChildOfSelectorInfo : fragment.nthLastChildOfFilters) {
+#if CSS_SELECTOR_JIT_DEBUGGING
+            dataLogF("%*s  Subselectors for %dn+%d:\n", level * 4, "", nthLastChildOfSelectorInfo.a, nthLastChildOfSelectorInfo.b);
+#endif
+
+            for (SelectorFragmentList& selectorList : nthLastChildOfSelectorInfo.selectorList)
+                computeBacktrackingInformation(selectorList, level + 1);
+        }
     }
 }
 
@@ -2498,6 +2527,8 @@ void SelectorCodeGenerator::generateElementMatching(Assembler::JumpList& matchin
         generateElementIsLastChild(matchingPostTagNameFailureCases, fragment);
     if (!fragment.nthChildFilters.isEmpty())
         generateElementIsNthChild(matchingPostTagNameFailureCases, fragment);
+    if (!fragment.nthLastChildFilters.isEmpty())
+        generateElementIsNthLastChild(matchingPostTagNameFailureCases, fragment);
     if (!fragment.nthChildOfFilters.isEmpty())
         generateElementIsNthChildOf(matchingPostTagNameFailureCases, fragment);
     if (!fragment.notFilters.isEmpty())
@@ -3621,6 +3652,65 @@ void SelectorCodeGenerator::generateElementIsNthChildOf(Assembler::JumpList& fai
     }
 }
 
+static void setChildrenAffectedByBackwardPositionalRules(Element* element)
+{
+    element->setChildrenAffectedByBackwardPositionalRules();
+}
+
+void SelectorCodeGenerator::generateElementIsNthLastChild(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
+{
+    Vector<std::pair<int, int>, 32> validSubsetFilters;
+    validSubsetFilters.reserveInitialCapacity(fragment.nthLastChildFilters.size());
+    { // :nth-last-child() must have a parent to match. If there is a parent, do the invalidation marking.
+        LocalRegister parentElement(m_registerAllocator);
+        generateWalkToParentElement(failureCases, parentElement);
+
+        for (const auto& slot : fragment.nthLastChildFilters) {
+            if (nthFilterIsAlwaysSatisified(slot.first, slot.second))
+                continue;
+            validSubsetFilters.uncheckedAppend(slot);
+        }
+        if (validSubsetFilters.isEmpty())
+            return;
+
+        if (m_selectorContext != SelectorContext::QuerySelector) {
+            Assembler::Jump skipMarking;
+            {
+                LocalRegister checkingContext(m_registerAllocator);
+                skipMarking = jumpIfNotResolvingStyle(checkingContext);
+            }
+
+            FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+            functionCall.setFunctionAddress(setChildrenAffectedByBackwardPositionalRules);
+            functionCall.setOneArgument(parentElement);
+            functionCall.call();
+
+            skipMarking.link(&m_assembler);
+        }
+    }
+
+    LocalRegister elementCounter(m_registerAllocator);
+    { // Loop over the following sibling elements and increment the counter.
+        LocalRegister nextSibling(m_registerAllocator);
+        m_assembler.move(elementAddressRegister, nextSibling);
+        // Setup the counter at 1.
+        m_assembler.move(Assembler::TrustedImm32(1), elementCounter);
+
+        Assembler::JumpList noMoreSiblingsCases;
+
+        generateWalkToNextAdjacentElement(noMoreSiblingsCases, nextSibling);
+
+        Assembler::Label loopStart = m_assembler.label();
+        m_assembler.add32(Assembler::TrustedImm32(1), elementCounter);
+        generateWalkToNextAdjacentElement(noMoreSiblingsCases, nextSibling);
+        m_assembler.jump().linkTo(loopStart, &m_assembler);
+        noMoreSiblingsCases.link(&m_assembler);
+    }
+
+    for (const auto& slot : validSubsetFilters)
+        generateNthFilterTest(failureCases, elementCounter, slot.first, slot.second);
+}
+
 void SelectorCodeGenerator::generateElementMatchesNotPseudoClass(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
 {
     Assembler::JumpList localFailureCases;