Add parsing for :dir()
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Nov 2014 00:27:52 +0000 (00:27 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 26 Nov 2014 00:27:52 +0000 (00:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=138932

Patch by Sukolsak Sakshuwong <sukolsak@gmail.com> on 2014-11-25
Reviewed by Benjamin Poulain.

Source/WebCore:

Add support for parsing :dir() pseudo class. The implementation of selector
matching will be in a follow-up patch.

* css/CSSGrammar.y.in:
* css/CSSParser.cpp:
(WebCore::CSSParser::detectFunctionTypeToken):
* css/CSSSelector.cpp:
(WebCore::appendPseudoClassFunctionTail):
(WebCore::CSSSelector::selectorText):
* css/CSSSelector.h:
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne):
* css/SelectorPseudoClassAndCompatibilityElementMap.in:
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::addPseudoClassType):

LayoutTests:

* fast/css/css-selector-text-expected.txt:
* fast/css/css-selector-text.html:
* fast/css/css-set-selector-text-expected.txt:
* fast/css/css-set-selector-text.html:
* fast/selectors/invalid-functional-pseudo-class-expected.txt:
* fast/selectors/invalid-functional-pseudo-class.html:

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

15 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/css-selector-text-expected.txt
LayoutTests/fast/css/css-selector-text.html
LayoutTests/fast/css/css-set-selector-text-expected.txt
LayoutTests/fast/css/css-set-selector-text.html
LayoutTests/fast/selectors/invalid-functional-pseudo-class-expected.txt
LayoutTests/fast/selectors/invalid-functional-pseudo-class.html
Source/WebCore/ChangeLog
Source/WebCore/css/CSSGrammar.y.in
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSSelector.cpp
Source/WebCore/css/CSSSelector.h
Source/WebCore/css/SelectorChecker.cpp
Source/WebCore/css/SelectorPseudoClassAndCompatibilityElementMap.in
Source/WebCore/cssjit/SelectorCompiler.cpp

index b953f04..f14d3e9 100644 (file)
@@ -1,3 +1,17 @@
+2014-11-25  Sukolsak Sakshuwong  <sukolsak@gmail.com>
+
+        Add parsing for :dir()
+        https://bugs.webkit.org/show_bug.cgi?id=138932
+
+        Reviewed by Benjamin Poulain.
+
+        * fast/css/css-selector-text-expected.txt:
+        * fast/css/css-selector-text.html:
+        * fast/css/css-set-selector-text-expected.txt:
+        * fast/css/css-set-selector-text.html:
+        * fast/selectors/invalid-functional-pseudo-class-expected.txt:
+        * fast/selectors/invalid-functional-pseudo-class.html:
+
 2014-11-25  Alejandro G. Castro  <alex@igalia.com>
 
         Unreviewed, upload two missing test files in the commit r174677.
index c36d962..56a83d1 100644 (file)
@@ -330,6 +330,21 @@ PASS parseThenSerializeRule(':role()) { }') threw exception TypeError: undefined
 PASS parseThenSerializeRule(':role(role()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
 PASS parseThenSerializeRule(':role(:role()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
 PASS parseThenSerializeRule(':role(:role(a)) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+
+PASS parseThenSerializeRule(':dir(ltr) { }') is ':dir(ltr) { }'
+PASS parseThenSerializeRule(':dir(rtl) { }') is ':dir(rtl) { }'
+PASS parseThenSerializeRule(':dir(LTR) { }') is ':dir(LTR) { }'
+PASS parseThenSerializeRule(':dir(aBcD) { }') is ':dir(aBcD) { }'
+PASS parseThenSerializeRule(':dir( a    ) { }') is ':dir(a) { }'
+
+PASS parseThenSerializeRule(':dir() { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':dir(42) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':dir(a, b) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':dir(}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':dir()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':dir(dir()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':dir(:dir()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':dir(:dir(ltr)) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 785963b..fbb3897 100644 (file)
@@ -416,6 +416,25 @@ shouldThrow("parseThenSerializeRule(':role(role()) { }')");
 shouldThrow("parseThenSerializeRule(':role(:role()) { }')");
 shouldThrow("parseThenSerializeRule(':role(:role(a)) { }')");
 
+debug('');
+
+testSelectorRoundTrip(":dir(ltr)");
+testSelectorRoundTrip(":dir(rtl)");
+testSelectorRoundTrip(":dir(LTR)");
+testSelectorRoundTrip(":dir(aBcD)");
+shouldBe("parseThenSerializeRule(':dir( a    ) { }')", "':dir(a) { }'");
+
+debug('');
+
+shouldThrow("parseThenSerializeRule(':dir() { }')");
+shouldThrow("parseThenSerializeRule(':dir(42) { }')");
+shouldThrow("parseThenSerializeRule(':dir(a, b) { }')");
+shouldThrow("parseThenSerializeRule(':dir(}) { }')");
+shouldThrow("parseThenSerializeRule(':dir()) { }')");
+shouldThrow("parseThenSerializeRule(':dir(dir()) { }')");
+shouldThrow("parseThenSerializeRule(':dir(:dir()) { }')");
+shouldThrow("parseThenSerializeRule(':dir(:dir(ltr)) { }')");
+
 </script>
 <script src="../../resources/js-test-post.js"></script>
 </body>
index 29101f7..e5cbedb 100644 (file)
@@ -57,6 +57,7 @@ PASS setThenReadSelectorText(':root') is ':root'
 PASS setThenReadSelectorText(':target') is ':target'
 PASS setThenReadSelectorText(':visited') is ':visited'
 
+PASS setThenReadSelectorText(':dir(a)') is ':dir(a)'
 PASS setThenReadSelectorText(':lang(a)') is ':lang(a)'
 PASS setThenReadSelectorText(':not(a)') is ':not(a)'
 PASS setThenReadSelectorText(':role(a)') is ':role(a)'
index e289de7..ea6fefb 100644 (file)
@@ -97,6 +97,7 @@ testSelectorRoundTrip(":visited");
 
 debug('');
 
+testSelectorRoundTrip(":dir(a)");
 testSelectorRoundTrip(":lang(a)");
 testSelectorRoundTrip(":not(a)");
 testSelectorRoundTrip(":role(a)");
index 7ac2bd9..fd6c396 100644 (file)
@@ -57,6 +57,60 @@ PASS document.styleSheets[1].cssRules.length is 0
 PASS document.styleSheets[1].cssRules.length is 0
 PASS document.styleSheets[1].cssRules.length is 0
 PASS document.styleSheets[1].cssRules.length is 0
+PASS document.querySelectorAll(":dir\").length threw exception SyntaxError: Unexpected EOF.
+PASS document.querySelectorAll(":dir\\").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\").length threw exception SyntaxError: Unexpected EOF.
+PASS document.querySelectorAll(":dir\\\\").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\(").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\(").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\(").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\\(").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\ .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\ .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\ .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\\ .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\( .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\( .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\( .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\\( .foo").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\\()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\ .foo)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\ .foo)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\ .foo)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\\ .foo)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\( .foo)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\( .foo)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":dir\\\\( .foo)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
+PASS document.styleSheets[1].cssRules.length is 0
 PASS document.querySelectorAll(":lang\").length threw exception SyntaxError: Unexpected EOF.
 PASS document.querySelectorAll(":lang\\").length threw exception Error: SyntaxError: DOM Exception 12.
 PASS document.querySelectorAll(":lang\\\").length threw exception SyntaxError: Unexpected EOF.
index f07b8d0..d7cf3be 100644 (file)
@@ -60,6 +60,7 @@ function test(functonalPseudoClassName) {
 
 var functionalPseudoClasses = [
     "-webkit-any",
+    "dir",
     "lang",
     "not",
     "nth-child",
index 354edb8..14f021e 100644 (file)
@@ -1,3 +1,26 @@
+2014-11-25  Sukolsak Sakshuwong  <sukolsak@gmail.com>
+
+        Add parsing for :dir()
+        https://bugs.webkit.org/show_bug.cgi?id=138932
+
+        Reviewed by Benjamin Poulain.
+
+        Add support for parsing :dir() pseudo class. The implementation of selector
+        matching will be in a follow-up patch.
+
+        * css/CSSGrammar.y.in:
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::detectFunctionTypeToken):
+        * css/CSSSelector.cpp:
+        (WebCore::appendPseudoClassFunctionTail):
+        (WebCore::CSSSelector::selectorText):
+        * css/CSSSelector.h:
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::checkOne):
+        * css/SelectorPseudoClassAndCompatibilityElementMap.in:
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::addPseudoClassType):
+
 2014-11-25  Anders Carlsson  <andersca@apple.com>
 
         Remove user content handling from PageGroup
index cf41fcb..abd2fe4 100644 (file)
@@ -63,6 +63,7 @@ static inline bool isCSSTokenAString(int yytype)
     case NTHCHILDFUNCTIONS:
     case NTHCHILDSELECTORSEPARATOR:
 #if ENABLE_CSS_SELECTORS_LEVEL4
+    case DIRFUNCTION:
     case LANGFUNCTION:
     case ROLEFUNCTION:
 #endif
@@ -232,6 +233,7 @@ static bool selectorListDoesNotMatchAnyPseudoElement(const Vector<std::unique_pt
 %token <string> NTHCHILDFUNCTIONS
 
 #if ENABLE_CSS_SELECTORS_LEVEL4
+%token <string> DIRFUNCTION
 %token <string> LANGFUNCTION
 %token <string> ROLEFUNCTION
 #endif
@@ -1376,6 +1378,16 @@ pseudo:
     }
 
 #if ENABLE_CSS_SELECTORS_LEVEL4
+    | ':' DIRFUNCTION maybe_space IDENT maybe_space ')' {
+        $$ = nullptr;
+        auto selector = std::make_unique<CSSParserSelector>();
+        selector->setMatch(CSSSelector::PseudoClass);
+        selector->setArgument($4);
+        selector->setPseudoClassValue($2);
+        if (selector->pseudoClassType() == CSSSelector::PseudoClassDir)
+            $$ = selector.release();
+    }
+
     | ':' LANGFUNCTION maybe_space comma_separated_identifiers maybe_space ')' {
         $$ = nullptr;
         if ($4) {
@@ -1873,7 +1885,7 @@ invalid_parentheses_block: opening_parenthesis error_recovery closing_parenthesi
 opening_parenthesis:
     '(' | FUNCTION | CALCFUNCTION | MATCHESFUNCTION | MAXFUNCTION | MINFUNCTION | ANYFUNCTION | NOTFUNCTION
 #if ENABLE_CSS_SELECTORS_LEVEL4
-    | LANGFUNCTION | ROLEFUNCTION
+    | DIRFUNCTION | LANGFUNCTION | ROLEFUNCTION
 #endif
 #if ENABLE_VIDEO_TRACK
     | CUEFUNCTION
index 0f4631c..78ef642 100644 (file)
@@ -10692,6 +10692,12 @@ inline bool CSSParser::detectFunctionTypeToken(int length)
             return true;
         }
 #endif
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+        if (isASCIIAlphaCaselessEqual(name[0], 'd') && isASCIIAlphaCaselessEqual(name[1], 'i') && isASCIIAlphaCaselessEqual(name[2], 'r')) {
+            m_token = DIRFUNCTION;
+            return true;
+        }
+#endif
         return false;
 
     case 4:
index b4cda72..63dfe4c 100644 (file)
@@ -319,6 +319,9 @@ bool CSSSelector::operator==(const CSSSelector& other) const
 static void appendPseudoClassFunctionTail(StringBuilder& str, const CSSSelector* selector)
 {
     switch (selector->pseudoClassType()) {
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+    case CSSSelector::PseudoClassDir:
+#endif
     case CSSSelector::PseudoClassLang:
     case CSSSelector::PseudoClassNthChild:
     case CSSSelector::PseudoClassNthLastChild:
@@ -441,6 +444,12 @@ String CSSSelector::selectorText(const String& rightSide) const
             case CSSSelector::PseudoClassDefault:
                 str.appendLiteral(":default");
                 break;
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+            case CSSSelector::PseudoClassDir:
+                str.appendLiteral(":dir(");
+                appendPseudoClassFunctionTail(str, cs);
+                break;
+#endif
             case CSSSelector::PseudoClassDisabled:
                 str.appendLiteral(":disabled");
                 break;
index 9c155c6..8a0e2e0 100644 (file)
@@ -158,6 +158,7 @@ namespace WebCore {
             PseudoClassPast,
 #endif
 #if ENABLE(CSS_SELECTORS_LEVEL4)
+            PseudoClassDir,
             PseudoClassRole,
 #endif
         };
index be1a220..58af2d6 100644 (file)
@@ -993,6 +993,10 @@ bool SelectorChecker::checkOne(const CheckingContextWithStatus& context, PseudoI
             return false;
 
 #if ENABLE(CSS_SELECTORS_LEVEL4)
+        // FIXME: Implement :dir() selector.
+        case CSSSelector::PseudoClassDir:
+            return false;
+
         // FIXME: Implement :role() selector.
         case CSSSelector::PseudoClassRole:
             return false;
index eb56e22..0e7069e 100644 (file)
@@ -565,6 +565,7 @@ static inline FunctionType addPseudoClassType(const CSSSelector& selector, Selec
     case CSSSelector::PseudoClassNthLastOfType:
     case CSSSelector::PseudoClassDrag:
 #if ENABLE(CSS_SELECTORS_LEVEL4)
+    case CSSSelector::PseudoClassDir:
     case CSSSelector::PseudoClassRole:
 #endif
         return FunctionType::CannotCompile;