Title: [172220] trunk
Revision
172220
Author
[email protected]
Date
2014-08-07 11:55:50 -0700 (Thu, 07 Aug 2014)

Log Message

Compile scrollbar pseudoclass css selectors.
https://bugs.webkit.org/show_bug.cgi?id=135242

Reviewed by Benjamin Poulain.

Source/WebCore:

Tests: scrollbars/corner-resizer-window-inactive.html
       scrollbars/scrollbar-selectors.html

* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::ruleMatches):
Changed assertion because there are pseudo-elements selectors that return CannotCompileAnything now, which
make SimpleSelectorCheckers.
Add scrollbar, scrollbarPart, and document to the CheckingContext and compile scrollbar pseudo-element selectors.
* css/SelectorChecker.cpp:
(WebCore::hasScrollbarPseudoElement):
Added.  Logic moved from matchRecursively to be easier to read and to add assertions.
context.scrollbar is always non-null when dynamicPseudo is SCROLLBAR_CORNER.
(WebCore::SelectorChecker::matchRecursively):
Moved logic to hasScrollbarPseudoElement.
(WebCore::SelectorChecker::checkOne):
checkScrollbarPseudoClass accesses the document through the element now.
(WebCore::SelectorChecker::checkScrollbarPseudoClass):
* css/SelectorChecker.h:
(WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext):
* css/SelectorCheckerTestFunctions.h:
(WebCore::scrollbarMatchesEnabledPseudoClass):
(WebCore::scrollbarMatchesDisabledPseudoClass):
(WebCore::scrollbarMatchesHoverPseudoClass):
(WebCore::scrollbarMatchesActivePseudoClass):
(WebCore::scrollbarMatchesHorizontalPseudoClass):
(WebCore::scrollbarMatchesVerticalPseudoClass):
(WebCore::scrollbarMatchesDecrementPseudoClass):
(WebCore::scrollbarMatchesIncrementPseudoClass):
(WebCore::scrollbarMatchesStartPseudoClass):
(WebCore::scrollbarMatchesEndPseudoClass):
(WebCore::scrollbarMatchesDoubleButtonPseudoClass):
(WebCore::scrollbarMatchesSingleButtonPseudoClass):
(WebCore::scrollbarMatchesNoButtonPseudoClass):
(WebCore::scrollbarMatchesCornerPresentPseudoClass):
Move scrollbar selector logic from SelectorChecker.cpp to SelectorCheckerTestFunctions.h
For window-inactive pseudo classes, we now access the document through the element instead of as a separate parameter.
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorFragment::appendUnoptimizedPseudoClassWithContext):
(WebCore::SelectorCompiler::addScrollbarPseudoClassType):
(WebCore::SelectorCompiler::addPseudoClassType):
(WebCore::SelectorCompiler::isScrollbarPseudoElement):
(WebCore::SelectorCompiler::constructFragments):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
Call functions for unoptimized pseudo classes that require a context.
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateContextFunctionCallTest):
Added.  Similar to generateElementFunctionCallTest, but the CheckingContext pointer is stored on the stack instead of a dedicated register.
* cssjit/SelectorCompiler.h:
Added scrollbar, scrollbarPart, and document to the CheckingContext.
(WebCore::SelectorCompiler::CheckingContext::document):
Added method to access the document in a way that is syntactically equal to SelectorCheckingContext.
This way, the template functions in SelectorCheckerTestFunctions.h can be compiled with both context types,
but the context types store the document differently.

LayoutTests:

* platform/wk2/TestExpectations:
Don't run corner-resizer-window-inactive-expected in WK2 because testRunner.setWindowIsKey doesn't work with WK2.
* scrollbars/corner-resizer-window-inactive-expected.html: Added.
* scrollbars/corner-resizer-window-inactive.html: Added.
* scrollbars/scrollbar-selectors-expected.txt: Added.
* scrollbars/scrollbar-selectors.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (172219 => 172220)


--- trunk/LayoutTests/ChangeLog	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/LayoutTests/ChangeLog	2014-08-07 18:55:50 UTC (rev 172220)
@@ -1,3 +1,17 @@
+2014-08-07  Alex Christensen  <[email protected]>
+
+        Compile scrollbar pseudoclass css selectors.
+        https://bugs.webkit.org/show_bug.cgi?id=135242
+
+        Reviewed by Benjamin Poulain.
+
+        * platform/wk2/TestExpectations:
+        Don't run corner-resizer-window-inactive-expected in WK2 because testRunner.setWindowIsKey doesn't work with WK2.
+        * scrollbars/corner-resizer-window-inactive-expected.html: Added.
+        * scrollbars/corner-resizer-window-inactive.html: Added.
+        * scrollbars/scrollbar-selectors-expected.txt: Added.
+        * scrollbars/scrollbar-selectors.html: Added.
+
 2014-08-07  Zalan Bujtas  <[email protected]>
 
         border-radius on html does not render properly.

Modified: trunk/LayoutTests/platform/wk2/TestExpectations (172219 => 172220)


--- trunk/LayoutTests/platform/wk2/TestExpectations	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/LayoutTests/platform/wk2/TestExpectations	2014-08-07 18:55:50 UTC (rev 172220)
@@ -213,6 +213,7 @@
 fast/selectors/querySelector-window-inactive.html
 fast/selectors/selection-window-inactive.html
 fast/dom/Window/window-focus-self.html
+scrollbars/corner-resizer-window-inactive.html
 
 # css3-conditionals support is not yet enabled.
 webkit.org/b/86146 css3/supports.html

Added: trunk/LayoutTests/scrollbars/corner-resizer-window-inactive-expected.html (0 => 172220)


--- trunk/LayoutTests/scrollbars/corner-resizer-window-inactive-expected.html	                        (rev 0)
+++ trunk/LayoutTests/scrollbars/corner-resizer-window-inactive-expected.html	2014-08-07 18:55:50 UTC (rev 172220)
@@ -0,0 +1,48 @@
+<head>
+<style>
+body > div {
+    padding: 10px;
+    margin: 20px;
+    border: 1px solid lightgray;
+    width: 125px;
+    height: 100px;
+}
+
+::-webkit-scrollbar {
+    width: 13px;
+    height: 13px;
+    background-color: blue;
+}
+
+::-webkit-resizer {
+    background-color: green;
+}
+
+::-webkit-scrollbar-corner {
+    background-color: green;
+}
+
+</style>
+</head>
+<body>
+The scrollbar corner (bottom right) should be green when the window is inactive.
+<div style="overflow: auto; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+The resizer (bottom right) should be green when the window is inactive.
+<div style="overflow: auto; resize: both; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>

Added: trunk/LayoutTests/scrollbars/corner-resizer-window-inactive.html (0 => 172220)


--- trunk/LayoutTests/scrollbars/corner-resizer-window-inactive.html	                        (rev 0)
+++ trunk/LayoutTests/scrollbars/corner-resizer-window-inactive.html	2014-08-07 18:55:50 UTC (rev 172220)
@@ -0,0 +1,61 @@
+<head>
+<style>
+body > div {
+    padding: 10px;
+    margin: 20px;
+    border: 1px solid lightgray;
+    width: 125px;
+    height: 100px;
+}
+
+::-webkit-scrollbar {
+    width: 13px;
+    height: 13px;
+    background-color: blue;
+}
+
+::-webkit-resizer {
+    background-color: white;
+}
+
+::-webkit-resizer:window-inactive {
+    background-color: green;
+}
+
+::-webkit-scrollbar-corner {
+    background-color: white;
+}
+
+::-webkit-scrollbar-corner:window-inactive {
+    background-color: green;
+}
+
+</style>
+</head>
+<body>
+The scrollbar corner (bottom right) should be green when the window is inactive.
+<div style="overflow: auto; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+The resizer (bottom right) should be green when the window is inactive.
+<div style="overflow: auto; resize: both; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<script>
+if (window.testRunner)
+    window.testRunner.setWindowIsKey(false);
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/scrollbars/scrollbar-selectors-expected.txt (0 => 172220)


--- trunk/LayoutTests/scrollbars/scrollbar-selectors-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/scrollbars/scrollbar-selectors-expected.txt	2014-08-07 18:55:50 UTC (rev 172220)
@@ -0,0 +1,9 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderText {#text} at (0,0) size 448x18
+        text run at (0,0) width 272: "This test runs many scrollbar selector tests. "
+        text run at (272,0) width 176: "It passes if it does not crash."
+      RenderText {#text} at (0,0) size 0x0

Added: trunk/LayoutTests/scrollbars/scrollbar-selectors.html (0 => 172220)


--- trunk/LayoutTests/scrollbars/scrollbar-selectors.html	                        (rev 0)
+++ trunk/LayoutTests/scrollbars/scrollbar-selectors.html	2014-08-07 18:55:50 UTC (rev 172220)
@@ -0,0 +1,254 @@
+<head>
+<style>
+body > div {
+    padding: 10px;
+    margin: 20px;
+    display: inline-block;
+    border: 1px solid lightgray;
+    -webkit-box-sizing: border-box;
+    vertical-align: top;
+    font-family: Verdana, sans-serif;
+    font-size: 12px;
+    -webkit-user-select: text;
+    width: 125px;
+    height: 100px;
+}
+</style>
+</head>
+
+<body>
+This test runs many scrollbar selector tests.  It passes if it does not crash.
+<div style="overflow: scroll">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+
+<div style="overflow: auto">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+
+<div style="overflow: auto; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<div style="overflow: scroll; resize: both">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+
+<div style="overflow: auto; resize: both">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+
+<div style="overflow: auto; resize: both; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<div style="overflow-x: hidden; overflow-y: scroll">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+
+<div style="overflow-x: scroll; overflow-y: hidden; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+</div>
+</div>
+
+<div style="overflow-x: hidden; overflow-y: scroll; resize: both">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+
+<div style="overflow-x: scroll; overflow-y: hidden; resize: both; padding: 0">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+</div>
+</div>
+
+<div style="overflow: scroll; padding: 0" class="single">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<div style="overflow: scroll; padding: 0" class="double-end">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<div style="overflow: scroll; padding: 0" class="double-start">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<div style="overflow: scroll; padding: 0" class="double-both">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<div style="overflow: scroll; padding: 0" class="none">
+<div style="width: 400px; padding: 10px">
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Morbi et nisi ut est venenatis viverra. Aenean pede orci, blandit quis, faucibus quis, egestas ut, mi. Pellentesque enim purus, venenatis dignissim, tincidunt a, ullamcorper eget, nibh. Nullam ut sem adipiscing orci vehicula interdum. Proin a enim. Phasellus sollicitudin, magna vitae vestibulum facilisis, tellus nunc iaculis arcu, in molestie sem velit tempus est. In eleifend velit at sem adipiscing sodales. Nunc sapien felis, aliquam et, volutpat rhoncus, condimentum ut, tortor. Integer est. Quisque viverra. Praesent sed arcu. Maecenas id lorem a leo lobortis condimentum.
+<br><br>
+Cras commodo rutrum augue. Vivamus iaculis. Nullam est. Maecenas consequat. Sed id dui. Vivamus a nisl. Donec pretium sapien. Proin et ligula et ligula placerat pulvinar. Aliquam erat volutpat. Proin id est. Suspendisse cursus, magna at hendrerit consequat, mauris est imperdiet neque, a ultrices arcu urna non nunc. Quisque tellus. Nulla nulla justo, vehicula nec, pellentesque eu, iaculis et, ligula. Praesent mattis ante vel sem. Suspendisse porta rhoncus urna. Phasellus felis. Praesent viverra convallis libero. Maecenas non augue. Donec hendrerit lectus id enim.
+<br><br>
+Nulla ligula dui, euismod et, sodales quis, sollicitudin quis, elit. In adipiscing est sed enim. Fusce at massa vitae metus semper hendrerit. Integer vitae urna. Nulla eget ligula. Etiam libero. Maecenas nisi nibh, convallis a, feugiat vitae, pulvinar et, mi. Curabitur arcu pede, adipiscing sed, egestas nec, commodo in, elit. Nulla facilisi. Proin varius pede et dui lacinia dapibus. Morbi nec augue. Proin imperdiet lacus eu tellus.
+</div>
+</div>
+
+<script>
+var pseudoElements = 
+[
+    "-webkit-scrollbar", 
+    "-webkit-scrollbar-button", 
+    "-webkit-scrollbar-track", 
+    "-webkit-scrollbar-track-piece", 
+    "-webkit-scrollbar-thumb", 
+    "-webkit-scrollbar-corner", 
+    "-webkit-resizer",
+    "invalidPseudoElement"
+];
+
+function toColor(n) {
+    var hex = "0123456789ABCDEF";
+    // Multiplying by 7 just makes the colors more diverse.
+    return "#"
+        + hex.substr(n * 7 >> 00 & 0x0F, 1)
+        + hex.substr(n * 7 >> 04 & 0x0F, 1)
+        + hex.substr(n * 7 >> 08 & 0x0F, 1)
+        + hex.substr(n * 7 >> 12 & 0x0F, 1)
+        + hex.substr(n * 7 >> 16 & 0x0F, 1)
+        + hex.substr(n * 7 >> 20 & 0x0F, 1);
+}
+
+function getPseudoClasses(n, pseudoClasses) {
+    var pseudoClassString = "";
+    for (var i = 0; i < pseudoClasses.length; i++)
+        if (n & (1 << i))
+            pseudoClassString += ":" + pseudoClasses[i];
+    return pseudoClassString;
+}
+
+function appendStyle(css) {
+    var style = document.createElement('style');
+    style.type = 'text/css';
+    style.appendChild(document.createTextNode(css));
+    document.head.appendChild(style);
+    
+    var divs = document.querySelectorAll("div");
+    for (var i = 0; i < divs.length; i++) {
+        // Redraw each div
+        divs[i].style.display = "none";
+        divs[i].style.display = "inline-block";
+        // Switch whether window-inactive works.
+        if (window.testRunner) {
+            window.testRunner.setWindowIsKey(false);
+            window.testRunner.setWindowIsKey(true);
+        }
+    }
+}
+
+function testPseudoClasses(pseudoClasses) {
+    // Generate css with every pseudo element having every possible combination of pseudo class.
+    var css = "";
+    var color = 0;
+    for (pseudoElement of pseudoElements)
+        for (var i = 0; i < 1 << pseudoClasses.length; i++)
+            css += "::" + pseudoElement + getPseudoClasses(i, pseudoClasses) + " { background-color: " + toColor(color++) + "; }";
+    appendStyle(css);
+}
+
+var pseudoClasses1 = 
+[
+    "disabled",
+    "enabled",
+    "horizontal",
+    "active",
+    "hover",
+    "vertical",
+    "decrement",
+    "increment",
+    "visited", // This is not a valid scrollbar pseudo class, but it is a valid pseudo class.
+    "invalidPseudoClass"
+];
+var pseudoClasses2 = 
+[
+    "start",
+    "end",
+    "double-button",
+    "single-button",
+    "no-button",
+    "corner-present",
+    "window-inactive",
+    "visited", // This is not a valid scrollbar pseudo class, but it is a valid pseudo class.
+    "invalidPseudoClass"
+];
+
+// Testing all combinations of pseudo classes would generate 2^17 combinations, which times out.
+// This is not quite comprehensive, but tests 2^10 + 2^9 combinations in a fraction of the time.
+testPseudoClasses(pseudoClasses1);
+testPseudoClasses(pseudoClasses2);
+
+// This tests various other unexpected things.
+appendStyle("::-webkit-scrollbar:start:start:start:start:start:start:start:start:start { color: red; }");
+appendStyle("::-webkit-scrollbar:invalid:invalid:invalid:invalid:invalid:invalid:invalid:invalid:invalid { color: red; }");
+appendStyle("::-webkit-scrollbar:visited:visited:visited:visited:visited:visited:visited:visited:visited { color: red; }");
+appendStyle("::-not-a-valid-pseudo-element::start:start:start:start:start:start:start:start:start { color: red; }");
+appendStyle("div:start { color: red; }");
+
+var divs = document.querySelectorAll("div");
+for (var i = 0; i < divs.length; i++)
+    divs[i].outerHTML = "";
+</script>

Modified: trunk/Source/WebCore/ChangeLog (172219 => 172220)


--- trunk/Source/WebCore/ChangeLog	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/Source/WebCore/ChangeLog	2014-08-07 18:55:50 UTC (rev 172220)
@@ -1,3 +1,63 @@
+2014-08-07  Alex Christensen  <[email protected]>
+
+        Compile scrollbar pseudoclass css selectors.
+        https://bugs.webkit.org/show_bug.cgi?id=135242
+
+        Reviewed by Benjamin Poulain.
+
+        Tests: scrollbars/corner-resizer-window-inactive.html
+               scrollbars/scrollbar-selectors.html
+
+        * css/ElementRuleCollector.cpp:
+        (WebCore::ElementRuleCollector::ruleMatches):
+        Changed assertion because there are pseudo-elements selectors that return CannotCompileAnything now, which
+        make SimpleSelectorCheckers.
+        Add scrollbar, scrollbarPart, and document to the CheckingContext and compile scrollbar pseudo-element selectors.
+        * css/SelectorChecker.cpp:
+        (WebCore::hasScrollbarPseudoElement):
+        Added.  Logic moved from matchRecursively to be easier to read and to add assertions.
+        context.scrollbar is always non-null when dynamicPseudo is SCROLLBAR_CORNER.
+        (WebCore::SelectorChecker::matchRecursively):
+        Moved logic to hasScrollbarPseudoElement.
+        (WebCore::SelectorChecker::checkOne):
+        checkScrollbarPseudoClass accesses the document through the element now.
+        (WebCore::SelectorChecker::checkScrollbarPseudoClass):
+        * css/SelectorChecker.h:
+        (WebCore::SelectorChecker::SelectorCheckingContext::SelectorCheckingContext):
+        * css/SelectorCheckerTestFunctions.h:
+        (WebCore::scrollbarMatchesEnabledPseudoClass):
+        (WebCore::scrollbarMatchesDisabledPseudoClass):
+        (WebCore::scrollbarMatchesHoverPseudoClass):
+        (WebCore::scrollbarMatchesActivePseudoClass):
+        (WebCore::scrollbarMatchesHorizontalPseudoClass):
+        (WebCore::scrollbarMatchesVerticalPseudoClass):
+        (WebCore::scrollbarMatchesDecrementPseudoClass):
+        (WebCore::scrollbarMatchesIncrementPseudoClass):
+        (WebCore::scrollbarMatchesStartPseudoClass):
+        (WebCore::scrollbarMatchesEndPseudoClass):
+        (WebCore::scrollbarMatchesDoubleButtonPseudoClass):
+        (WebCore::scrollbarMatchesSingleButtonPseudoClass):
+        (WebCore::scrollbarMatchesNoButtonPseudoClass):
+        (WebCore::scrollbarMatchesCornerPresentPseudoClass):
+        Move scrollbar selector logic from SelectorChecker.cpp to SelectorCheckerTestFunctions.h
+        For window-inactive pseudo classes, we now access the document through the element instead of as a separate parameter.
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorFragment::appendUnoptimizedPseudoClassWithContext):
+        (WebCore::SelectorCompiler::addScrollbarPseudoClassType):
+        (WebCore::SelectorCompiler::addPseudoClassType):
+        (WebCore::SelectorCompiler::isScrollbarPseudoElement):
+        (WebCore::SelectorCompiler::constructFragments):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
+        Call functions for unoptimized pseudo classes that require a context.
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateContextFunctionCallTest):
+        Added.  Similar to generateElementFunctionCallTest, but the CheckingContext pointer is stored on the stack instead of a dedicated register.
+        * cssjit/SelectorCompiler.h:
+        Added scrollbar, scrollbarPart, and document to the CheckingContext.
+        (WebCore::SelectorCompiler::CheckingContext::document):
+        Added method to access the document in a way that is syntactically equal to SelectorCheckingContext.
+        This way, the template functions in SelectorCheckerTestFunctions.h can be compiled with both context types,
+        but the context types store the document differently.
+
 2014-08-07  Daniel Bates  <[email protected]>
 
         Sometimes Gmail cannot load messages, particularly on refresh ("...the application ran into an unexpected error...")

Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (172219 => 172220)


--- trunk/Source/WebCore/css/ElementRuleCollector.cpp	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp	2014-08-07 18:55:50 UTC (rev 172220)
@@ -297,8 +297,8 @@
 
     if (compiledSelectorChecker) {
         if (ruleData.compilationStatus() == SelectorCompilationStatus::SimpleSelectorChecker) {
-            ASSERT_WITH_MESSAGE(m_pseudoStyleRequest.pseudoId == NOPSEUDO, "When matching pseudo elements, we should never compile a selector checker without context. ElementRuleCollector::collectMatchingRulesForList() should filter out useless rules for pseudo elements.");
             SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, ruleData.compilationStatus());
+            ASSERT_WITH_MESSAGE(!selectorChecker(&m_element) || m_pseudoStyleRequest.pseudoId == NOPSEUDO, "When matching pseudo elements, we should never compile a selector checker without context unless it cannot match anything.");
 #if CSS_SELECTOR_JIT_PROFILING
             ruleData.compiledSelectorUsed();
 #endif
@@ -306,18 +306,17 @@
         }
         ASSERT(ruleData.compilationStatus() == SelectorCompilationStatus::SelectorCheckerWithCheckingContext);
 
-        // FIXME: Currently a compiled selector doesn't support scrollbar / selection's exceptional case.
-        if (!m_pseudoStyleRequest.scrollbar) {
-            SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::selectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, ruleData.compilationStatus());
-            SelectorCompiler::CheckingContext context;
-            context.elementStyle = m_style;
-            context.resolvingMode = m_mode;
-            context.pseudoId = m_pseudoStyleRequest.pseudoId;
+        SelectorCompiler::SelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::selectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, ruleData.compilationStatus());
+        SelectorCompiler::CheckingContext context;
+        context.elementStyle = m_style;
+        context.resolvingMode = m_mode;
+        context.pseudoId = m_pseudoStyleRequest.pseudoId;
+        context.scrollbar = m_pseudoStyleRequest.scrollbar;
+        context.scrollbarPart = m_pseudoStyleRequest.scrollbarPart;
 #if CSS_SELECTOR_JIT_PROFILING
-            ruleData.compiledSelectorUsed();
+        ruleData.compiledSelectorUsed();
 #endif
-            return selectorChecker(&m_element, &context);
-        }
+        return selectorChecker(&m_element, &context);
     }
 #endif // ENABLE(CSS_SELECTOR_JIT)
 

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (172219 => 172220)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2014-08-07 18:55:50 UTC (rev 172220)
@@ -48,10 +48,7 @@
 #include "NodeRenderStyle.h"
 #include "Page.h"
 #include "RenderElement.h"
-#include "RenderScrollbar.h"
 #include "RenderStyle.h"
-#include "ScrollableArea.h"
-#include "ScrollbarTheme.h"
 #include "SelectorCheckerTestFunctions.h"
 #include "ShadowRoot.h"
 #include "StyledElement.h"
@@ -155,6 +152,23 @@
     return true;
 }
 
+inline static bool hasScrollbarPseudoElement(const SelectorChecker::SelectorCheckingContext& context, PseudoId& dynamicPseudo)
+{
+    if (dynamicPseudo == SCROLLBAR
+        || dynamicPseudo == SCROLLBAR_THUMB
+        || dynamicPseudo == SCROLLBAR_BUTTON
+        || dynamicPseudo == SCROLLBAR_TRACK
+        || dynamicPseudo == SCROLLBAR_TRACK_PIECE
+        || dynamicPseudo == SCROLLBAR_CORNER) {
+        ASSERT(context.scrollbar);
+        return true;
+    }
+    
+    // RESIZER does not always have a scrollbar but it is a scrollbar-like pseudo element
+    // because it can have more than one pseudo element.
+    return dynamicPseudo == RESIZER;
+}
+    
 // Recursive check of selectors and combinators
 // It can return 4 different values:
 // * SelectorMatches          - the selector matches the element e
@@ -272,7 +286,7 @@
         // a selector is invalid if something follows a pseudo-element
         // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
         // to follow the pseudo elements.
-        nextContext.hasScrollbarPseudo = dynamicPseudo != NOPSEUDO && (context.scrollbar || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER);
+        nextContext.hasScrollbarPseudo = hasScrollbarPseudoElement(context, dynamicPseudo);
         nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION;
         if ((context.elementStyle || m_mode == Mode::CollectingRules) && dynamicPseudo != NOPSEUDO
             && !nextContext.hasSelectionPseudo
@@ -482,8 +496,8 @@
             }
         } else if (context.hasScrollbarPseudo) {
             // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
-            // (since there are no elements involved).
-            return checkScrollbarPseudoClass(context, &element->document(), selector);
+            // (since there are no elements involved except with window-inactive).
+            return checkScrollbarPseudoClass(context, selector);
         }
 
         // Normal element pseudo class checking.
@@ -810,83 +824,41 @@
     return true;
 }
 
-bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& context, Document* document, const CSSSelector* selector) const
+bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& context, const CSSSelector* selector) const
 {
     ASSERT(selector->m_match == CSSSelector::PseudoClass);
 
-    RenderScrollbar* scrollbar = context.scrollbar;
-    ScrollbarPart part = context.scrollbarPart;
-
-    // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventually :window-inactive should become a real
-    // pseudo class and just apply to everything.
-    if (selector->pseudoClassType() == CSSSelector::PseudoClassWindowInactive)
-        return !document->page()->focusController().isActive();
-
-    if (!scrollbar)
-        return false;
-
     switch (selector->pseudoClassType()) {
+    case CSSSelector::PseudoClassWindowInactive:
+        return isWindowInactive(context.element);
     case CSSSelector::PseudoClassEnabled:
-        return scrollbar->enabled();
+        return scrollbarMatchesEnabledPseudoClass(context);
     case CSSSelector::PseudoClassDisabled:
-        return !scrollbar->enabled();
+        return scrollbarMatchesDisabledPseudoClass(context);
     case CSSSelector::PseudoClassHover:
-        {
-            ScrollbarPart hoveredPart = scrollbar->hoveredPart();
-            if (part == ScrollbarBGPart)
-                return hoveredPart != NoPart;
-            if (part == TrackBGPart)
-                return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
-            return part == hoveredPart;
-        }
+        return scrollbarMatchesHoverPseudoClass(context);
     case CSSSelector::PseudoClassActive:
-        {
-            ScrollbarPart pressedPart = scrollbar->pressedPart();
-            if (part == ScrollbarBGPart)
-                return pressedPart != NoPart;
-            if (part == TrackBGPart)
-                return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
-            return part == pressedPart;
-        }
+        return scrollbarMatchesActivePseudoClass(context);
     case CSSSelector::PseudoClassHorizontal:
-        return scrollbar->orientation() == HorizontalScrollbar;
+        return scrollbarMatchesHorizontalPseudoClass(context);
     case CSSSelector::PseudoClassVertical:
-        return scrollbar->orientation() == VerticalScrollbar;
+        return scrollbarMatchesVerticalPseudoClass(context);
     case CSSSelector::PseudoClassDecrement:
-        return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
+        return scrollbarMatchesDecrementPseudoClass(context);
     case CSSSelector::PseudoClassIncrement:
-        return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
+        return scrollbarMatchesIncrementPseudoClass(context);
     case CSSSelector::PseudoClassStart:
-        return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
+        return scrollbarMatchesStartPseudoClass(context);
     case CSSSelector::PseudoClassEnd:
-        return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
+        return scrollbarMatchesEndPseudoClass(context);
     case CSSSelector::PseudoClassDoubleButton:
-        {
-            ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
-            if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
-                return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
-            if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
-                return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
-            return false;
-        }
+        return scrollbarMatchesDoubleButtonPseudoClass(context);
     case CSSSelector::PseudoClassSingleButton:
-        {
-            ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
-            if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
-                return buttonsPlacement == ScrollbarButtonsSingle;
-            return false;
-        }
+        return scrollbarMatchesSingleButtonPseudoClass(context);
     case CSSSelector::PseudoClassNoButton:
-        {
-            ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
-            if (part == BackTrackPart)
-                return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
-            if (part == ForwardTrackPart)
-                return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
-            return false;
-        }
+        return scrollbarMatchesNoButtonPseudoClass(context);
     case CSSSelector::PseudoClassCornerPresent:
-        return scrollbar->scrollableArea()->isScrollCornerVisible();
+        return scrollbarMatchesCornerPresentPseudoClass(context);
     default:
         return false;
     }

Modified: trunk/Source/WebCore/css/SelectorChecker.h (172219 => 172220)


--- trunk/Source/WebCore/css/SelectorChecker.h	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/Source/WebCore/css/SelectorChecker.h	2014-08-07 18:55:50 UTC (rev 172220)
@@ -58,11 +58,11 @@
         SelectorCheckingContext(const CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType)
             : selector(selector)
             , element(element)
-            , scope(0)
+            , scope(nullptr)
             , visitedMatchType(visitedMatchType)
             , pseudoId(NOPSEUDO)
-            , elementStyle(0)
-            , scrollbar(0)
+            , elementStyle(nullptr)
+            , scrollbar(nullptr)
             , firstSelectorOfTheFragment(selector)
             , scrollbarPart(NoPart)
             , inFunctionalPseudoClass(false)
@@ -98,7 +98,7 @@
     Match matchRecursively(const SelectorCheckingContext&, PseudoId&) const;
     bool checkOne(const SelectorCheckingContext&) const;
 
-    bool checkScrollbarPseudoClass(const SelectorCheckingContext&, Document*, const CSSSelector*) const;
+    bool checkScrollbarPseudoClass(const SelectorCheckingContext&, const CSSSelector*) const;
 
     bool m_strictParsing;
     bool m_documentIsHTML;

Modified: trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h (172219 => 172220)


--- trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2014-08-07 18:55:50 UTC (rev 172220)
@@ -31,6 +31,9 @@
 #include "HTMLAreaElement.h"
 #include "HTMLInputElement.h"
 #include "HTMLOptionElement.h"
+#include "RenderScrollbar.h"
+#include "ScrollableArea.h"
+#include "ScrollbarTheme.h"
 #include <wtf/Compiler.h>
 
 #if ENABLE(VIDEO_TRACK)
@@ -160,7 +163,124 @@
 {
     return element->shouldAppearIndeterminate();
 }
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesEnabledPseudoClass(const ContextType& context)
+{
+    return context.scrollbar && context.scrollbar->enabled();
+}
 
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesDisabledPseudoClass(const ContextType& context)
+{
+    return context.scrollbar && !context.scrollbar->enabled();
+}
+
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesHoverPseudoClass(const ContextType& context)
+{
+    if (!context.scrollbar)
+        return false;
+    ScrollbarPart hoveredPart = context.scrollbar->hoveredPart();
+    if (context.scrollbarPart == ScrollbarBGPart)
+        return hoveredPart != NoPart;
+    if (context.scrollbarPart == TrackBGPart)
+        return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
+    return context.scrollbarPart == hoveredPart;
+}
+
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesActivePseudoClass(const ContextType& context)
+{
+    if (!context.scrollbar)
+        return false;
+    ScrollbarPart pressedPart = context.scrollbar->pressedPart();
+    if (context.scrollbarPart == ScrollbarBGPart)
+        return pressedPart != NoPart;
+    if (context.scrollbarPart == TrackBGPart)
+        return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
+    return context.scrollbarPart == pressedPart;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesHorizontalPseudoClass(const ContextType& context)
+{
+    return context.scrollbar && context.scrollbar->orientation() == HorizontalScrollbar;
+}
+
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesVerticalPseudoClass(const ContextType& context)
+{
+    return context.scrollbar && context.scrollbar->orientation() == VerticalScrollbar;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesDecrementPseudoClass(const ContextType& context)
+{
+    return context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == BackTrackPart;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesIncrementPseudoClass(const ContextType& context)
+{
+    return context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesStartPseudoClass(const ContextType& context)
+{
+    return context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == BackTrackPart;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesEndPseudoClass(const ContextType& context)
+{
+    return context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesDoubleButtonPseudoClass(const ContextType& context)
+{
+    if (!context.scrollbar)
+        return false;
+    ScrollbarButtonsPlacement buttonsPlacement = context.scrollbar->theme()->buttonsPlacement();
+    if (context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == ForwardButtonStartPart || context.scrollbarPart == BackTrackPart)
+        return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
+    if (context.scrollbarPart == BackButtonEndPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == ForwardTrackPart)
+        return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
+    return false;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesSingleButtonPseudoClass(const ContextType& context)
+{
+    if (!context.scrollbar)
+        return false;
+    ScrollbarButtonsPlacement buttonsPlacement = context.scrollbar->theme()->buttonsPlacement();
+    if (context.scrollbarPart == BackButtonStartPart || context.scrollbarPart == ForwardButtonEndPart || context.scrollbarPart == BackTrackPart || context.scrollbarPart == ForwardTrackPart)
+        return buttonsPlacement == ScrollbarButtonsSingle;
+    return false;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesNoButtonPseudoClass(const ContextType& context)
+{
+    if (!context.scrollbar)
+        return false;
+    ScrollbarButtonsPlacement buttonsPlacement = context.scrollbar->theme()->buttonsPlacement();
+    if (context.scrollbarPart == BackTrackPart)
+        return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
+    if (context.scrollbarPart == ForwardTrackPart)
+        return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
+    return false;
+}
+    
+template <typename ContextType>
+ALWAYS_INLINE bool scrollbarMatchesCornerPresentPseudoClass(const ContextType& context)
+{
+    return context.scrollbar && context.scrollbar->scrollableArea()->isScrollCornerVisible();
+}
+
 #if ENABLE(FULLSCREEN_API)
 ALWAYS_INLINE bool matchesFullScreenPseudoClass(const Element* element)
 {

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (172219 => 172220)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-08-07 18:55:50 UTC (rev 172220)
@@ -157,12 +157,15 @@
     unsigned tagNameNotMatchedBacktrackingStartWidthFromIndirectAdjacent;
     unsigned widthFromIndirectAdjacent;
 
+    FunctionType appendUnoptimizedPseudoClassWithContext(bool (*matcher)(const CheckingContext&));
+    
     const QualifiedName* tagName;
     const AtomicString* id;
     const AtomicString* langFilter;
     Vector<const AtomicStringImpl*, 32> classNames;
     HashSet<unsigned> pseudoClasses;
     Vector<JSC::FunctionPtr, 32> unoptimizedPseudoClasses;
+    Vector<JSC::FunctionPtr, 32> unoptimizedPseudoClassesWithContext;
     Vector<AttributeMatchingInfo, 32> attributes;
     Vector<std::pair<int, int>, 32> nthChildFilters;
     Vector<SelectorFragment> notFilters;
@@ -233,6 +236,7 @@
     void generateElementMatching(Assembler::JumpList& matchingTagNameFailureCases, Assembler::JumpList& matchingPostTagNameFailureCases, const SelectorFragment&);
     void generateElementDataMatching(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementFunctionCallTest(Assembler::JumpList& failureCases, JSC::FunctionPtr);
+    void generateContextFunctionCallTest(Assembler::JumpList& failureCases, JSC::FunctionPtr);
     void generateElementIsActive(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementIsFirstChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementIsHovered(Assembler::JumpList& failureCases, const SelectorFragment&);
@@ -354,6 +358,52 @@
     return fragment.relationToRightFragment == FragmentRelation::Rightmost && fragment.positionInRootFragments == FragmentPositionInRootFragments::Rightmost;
 }
 
+FunctionType SelectorFragment::appendUnoptimizedPseudoClassWithContext(bool (*matcher)(const CheckingContext&))
+{
+    unoptimizedPseudoClassesWithContext.append(JSC::FunctionPtr(matcher));
+    return FunctionType::SelectorCheckerWithCheckingContext;
+}
+
+static inline FunctionType addScrollbarPseudoClassType(const CSSSelector& selector, SelectorFragment& fragment)
+{
+    switch (selector.pseudoClassType()) {
+    case CSSSelector::PseudoClassWindowInactive:
+        fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr(isWindowInactive));
+        return FunctionType::SimpleSelectorChecker;
+    case CSSSelector::PseudoClassDisabled:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDisabledPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassEnabled:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesEnabledPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassHorizontal:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesHorizontalPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassVertical:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesVerticalPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassDecrement:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDecrementPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassIncrement:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesIncrementPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassStart:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesStartPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassEnd:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesEndPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassDoubleButton:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesDoubleButtonPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassSingleButton:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesSingleButtonPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassNoButton:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesNoButtonPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassCornerPresent:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesCornerPresentPseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassActive:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesActivePseudoClass<CheckingContext>);
+    case CSSSelector::PseudoClassHover:
+        return fragment.appendUnoptimizedPseudoClassWithContext(scrollbarMatchesHoverPseudoClass<CheckingContext>);
+    default:
+        return FunctionType::CannotMatchAnything;
+    }
+    return FunctionType::CannotMatchAnything;
+}
+
 static inline FunctionType addPseudoClassType(const CSSSelector& selector, SelectorFragment& fragment, SelectorContext selectorContext, FragmentPositionInRootFragments positionInRootFragments)
 {
     CSSSelector::PseudoClassType type = selector.pseudoClassType();
@@ -431,6 +481,19 @@
         return FunctionType::SimpleSelectorChecker;
 #endif
 
+    // These pseudo-classes only have meaning with scrollbars.
+    case CSSSelector::PseudoClassHorizontal:
+    case CSSSelector::PseudoClassVertical:
+    case CSSSelector::PseudoClassDecrement:
+    case CSSSelector::PseudoClassIncrement:
+    case CSSSelector::PseudoClassStart:
+    case CSSSelector::PseudoClassEnd:
+    case CSSSelector::PseudoClassDoubleButton:
+    case CSSSelector::PseudoClassSingleButton:
+    case CSSSelector::PseudoClassNoButton:
+    case CSSSelector::PseudoClassCornerPresent:
+        return FunctionType::CannotMatchAnything;
+
     // FIXME: Compile these pseudoclasses, too!
     case CSSSelector::PseudoClassEmpty:
     case CSSSelector::PseudoClassFirstOfType:
@@ -443,16 +506,6 @@
     case CSSSelector::PseudoClassDrag:
     case CSSSelector::PseudoClassFullPageMedia:
     case CSSSelector::PseudoClassScope:
-    case CSSSelector::PseudoClassCornerPresent:
-    case CSSSelector::PseudoClassDecrement:
-    case CSSSelector::PseudoClassIncrement:
-    case CSSSelector::PseudoClassHorizontal:
-    case CSSSelector::PseudoClassVertical:
-    case CSSSelector::PseudoClassStart:
-    case CSSSelector::PseudoClassEnd:
-    case CSSSelector::PseudoClassDoubleButton:
-    case CSSSelector::PseudoClassSingleButton:
-    case CSSSelector::PseudoClassNoButton:
         return FunctionType::CannotCompile;
 
     // Optimized pseudo selectors.
@@ -612,6 +665,11 @@
     return pseudoClassType == CSSSelector::PseudoClassHover || pseudoClassType == CSSSelector::PseudoClassActive;
 }
 
+static bool isScrollbarPseudoElement(CSSSelector::PseudoElementType type)
+{
+    return type >= CSSSelector::PseudoElementScrollbar && type <= CSSSelector::PseudoElementScrollbarTrackPiece;
+}
+
 static FunctionType constructFragments(const CSSSelector* rootSelector, SelectorContext selectorContext, SelectorFragmentList& selectorFragments, FragmentsLevel fragmentLevel, FragmentPositionInRootFragments positionInRootFragments)
 {
     SelectorFragment fragment;
@@ -623,10 +681,11 @@
         // A selector is invalid if something follows a pseudo-element.
         // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
         // to follow the pseudo elements.
-        // FIXME: Currently, CSS JIT doesn't support scrollbar and selection's exceptional cases.
-        // So all selectors following a pseudo-element is treated as invalid.
-        if (relation == CSSSelector::SubSelector && fragment.pseudoElementSelector)
-            return FunctionType::CannotCompile;
+        if (relation == CSSSelector::SubSelector
+            && fragment.pseudoElementSelector
+            && !isScrollbarPseudoElement(fragment.pseudoElementSelector->pseudoElementType())) {
+            return FunctionType::CannotMatchAnything;
+        }
 
         switch (selector->m_match) {
         case CSSSelector::Tag:
@@ -653,8 +712,10 @@
             FragmentPositionInRootFragments subPosition = positionInRootFragments;
             if (relationToPreviousFragment != FragmentRelation::Rightmost)
                 subPosition = FragmentPositionInRootFragments::NotRightmost;
-
-            functionType = mostRestrictiveFunctionType(functionType, addPseudoClassType(*selector, fragment, selectorContext, subPosition));
+            if (fragment.pseudoElementSelector && isScrollbarPseudoElement(fragment.pseudoElementSelector->pseudoElementType()))
+                functionType = mostRestrictiveFunctionType(functionType, addScrollbarPseudoClassType(*selector, fragment));
+            else
+                functionType = mostRestrictiveFunctionType(functionType, addPseudoClassType(*selector, fragment, selectorContext, subPosition));
             if (!pseudoClassOnlyMatchesLinksInQuirksMode(*selector))
                 fragment._onlyMatchesLinksInQuirksMode_ = false;
             if (functionType == FunctionType::CannotCompile || functionType == FunctionType::CannotMatchAnything)
@@ -678,9 +739,18 @@
             case CSSSelector::PseudoElementBefore:
             case CSSSelector::PseudoElementFirstLetter:
             case CSSSelector::PseudoElementFirstLine:
+            case CSSSelector::PseudoElementScrollbar:
+            case CSSSelector::PseudoElementScrollbarButton:
+            case CSSSelector::PseudoElementScrollbarCorner:
+            case CSSSelector::PseudoElementScrollbarThumb:
+            case CSSSelector::PseudoElementScrollbarTrack:
+            case CSSSelector::PseudoElementScrollbarTrackPiece:
                 fragment.pseudoElementSelector = selector;
                 break;
-            // FIXME: Support SCROLLBAR, RESIZER, SELECTION etc.
+            case CSSSelector::PseudoElementUnknown:
+                ASSERT_NOT_REACHED();
+                return FunctionType::CannotMatchAnything;
+            // FIXME: Support RESIZER, SELECTION etc.
             default:
                 return FunctionType::CannotCompile;
             }
@@ -1872,6 +1942,9 @@
     for (unsigned i = 0; i < fragment.unoptimizedPseudoClasses.size(); ++i)
         generateElementFunctionCallTest(matchingPostTagNameFailureCases, fragment.unoptimizedPseudoClasses[i]);
 
+    for (unsigned i = 0; i < fragment.unoptimizedPseudoClassesWithContext.size(); ++i)
+        generateContextFunctionCallTest(matchingPostTagNameFailureCases, fragment.unoptimizedPseudoClassesWithContext[i]);
+
     generateElementDataMatching(matchingPostTagNameFailureCases, fragment);
 
     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassActive))
@@ -2308,7 +2381,19 @@
     functionCall.setOneArgument(elementAddress);
     failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
 }
+    
+void SelectorCodeGenerator::generateContextFunctionCallTest(Assembler::JumpList& failureCases, JSC::FunctionPtr testFunction)
+{
+    Assembler::RegisterID checkingContext = m_registerAllocator.allocateRegister();
+    loadCheckingContext(checkingContext);
+    m_registerAllocator.deallocateRegister(checkingContext);
 
+    FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+    functionCall.setFunctionAddress(testFunction);
+    functionCall.setOneArgument(checkingContext);
+    failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
+}
+
 static void setFirstChildState(Element* element)
 {
     if (RenderStyle* style = element->renderStyle())

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.h (172219 => 172220)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.h	2014-08-07 18:46:43 UTC (rev 172219)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.h	2014-08-07 18:55:50 UTC (rev 172220)
@@ -73,6 +73,8 @@
     SelectorChecker::Mode resolvingMode;
     RenderStyle* elementStyle;
     PseudoId pseudoId;
+    RenderScrollbar* scrollbar;
+    ScrollbarPart scrollbarPart;
 };
 
 enum class SelectorContext {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to