Title: [175446] trunk
Revision
175446
Author
[email protected]
Date
2014-10-31 20:06:27 -0700 (Fri, 31 Oct 2014)

Log Message

Add initial parsing functionality of :lang pseudo class in Selectors Level 4.
https://bugs.webkit.org/show_bug.cgi?id=138170

Patch by Dhi Aurrahman <[email protected]> on 2014-10-31
Reviewed by Benjamin Poulain.

Source/WebCore:

Add initial parsing functionality of :lang pseudo class in Selectors Level 4,
as specified in [1].

It parses comma-separated list of string arguments. Currently, it throws error
on arguments with "*" (e.g. :lang(zh, *-hant)).

Add additional test file fast/selectors/lang-invalid.html along side the
fast/css/css-selector-text.html.

[1] http://dev.w3.org/csswg/selectors4/#the-lang-pseudo

Test: fast/selectors/lang-invalid.html

* css/CSSGrammar.y.in:
* css/CSSParser.cpp:
(WebCore::CSSParser::detectFunctionTypeToken):
* css/CSSParserValues.cpp:
(WebCore::CSSParserSelector::setArgumentList):
* css/CSSParserValues.h:
* css/CSSSelector.cpp:
(WebCore::appendArgumentList):
(WebCore::CSSSelector::selectorText):
(WebCore::CSSSelector::setArgumentList):
* css/CSSSelector.h:
(WebCore::CSSSelector::argumentList):
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne):
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::addPseudoClassType):

LayoutTests:

Add tests for comma-separated list arguments for :lang

* fast/css/css-selector-text-expected.txt: Updated.
* fast/css/css-selector-text.html: Updated.
* fast/selectors/lang-invalid-expected.txt: Added.
* fast/selectors/lang-invalid.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (175445 => 175446)


--- trunk/LayoutTests/ChangeLog	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/LayoutTests/ChangeLog	2014-11-01 03:06:27 UTC (rev 175446)
@@ -1,3 +1,17 @@
+2014-10-31  Dhi Aurrahman  <[email protected]>
+
+        Add initial parsing functionality of :lang pseudo class in Selectors Level 4.
+        https://bugs.webkit.org/show_bug.cgi?id=138170
+
+        Reviewed by Benjamin Poulain.
+
+        Add tests for comma-separated list arguments for :lang
+
+        * fast/css/css-selector-text-expected.txt: Updated.
+        * fast/css/css-selector-text.html: Updated.
+        * fast/selectors/lang-invalid-expected.txt: Added.
+        * fast/selectors/lang-invalid.html: Added.
+
 2014-10-31  Benjamin Poulain  <[email protected]>
 
         Pseudo classes with an escaped parenthesis generate invalid rules

Modified: trunk/LayoutTests/fast/css/css-selector-text-expected.txt (175445 => 175446)


--- trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2014-11-01 03:06:27 UTC (rev 175446)
@@ -48,6 +48,13 @@
 PASS parseThenSerializeRule(':visited { }') is ':visited { }'
 
 PASS parseThenSerializeRule(':lang(a) { }') is ':lang(a) { }'
+PASS parseThenSerializeRule(':lang(a, b, c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(fr, de, en, id) { }') is ':lang(fr, de, en, id) { }'
+PASS parseThenSerializeRule(':lang(fr, fr-ca, fr-be) { }') is ':lang(fr, fr-ca, fr-be) { }'
+PASS parseThenSerializeRule(':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996) { }') is ':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996) { }'
+PASS parseThenSerializeRule(':lang(de-CH, it-CH, fr-CH, rm-CH) { }') is ':lang(de-CH, it-CH, fr-CH, rm-CH) { }'
+PASS parseThenSerializeRule(':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996, de-CH, it-CH, fr-CH, rm-CH) { }') is ':lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996, de-CH, it-CH, fr-CH, rm-CH) { }'
+
 PASS parseThenSerializeRule(':not(a) { }') is ':not(a) { }'
 PASS parseThenSerializeRule(':-webkit-any(a,b,p) { }') is ':-webkit-any(a,b,p) { }'
 
@@ -245,6 +252,40 @@
 PASS parseThenSerializeRule(':not(a.class1.class2.class3:hover   ) { }') is ':not(a.class1.class2.class3:hover) { }'
 PASS parseThenSerializeRule(':not(:matches(single    ),:matches(a,b    ,p),:matches(#alice,                   #bob,#chris)) { }') is ':not(:matches(single), :matches(a, b, p), :matches(#alice, #bob, #chris)) { }'
 
+PASS parseThenSerializeRule(':lang(a    ) { }') is ':lang(a) { }'
+PASS parseThenSerializeRule(':lang(    a) { }') is ':lang(a) { }'
+PASS parseThenSerializeRule(':lang(a,    b,    c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(    a, b ,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(  a  ,  b  ,  c  ) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(    a  ,b,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(    a  ,b  ,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(    a  ,b  ,c  ) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(a,b    ,c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(a,b,    c) { }') is ':lang(a, b, c) { }'
+PASS parseThenSerializeRule(':lang(a,b,    c    ) { }') is ':lang(a, b, c) { }'
+
+PASS parseThenSerializeRule(':lang() { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(12, b, c) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(a, 12, c) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(a, b, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(a, 12, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(12, b, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(12, 12, 12) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(lang()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(:lang()) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(:lang(id)) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(:lang(en, br)) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(<0_0>) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(99) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(88) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(00) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang({) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang({}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(]) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang([) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang([]) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(@media screen {}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/css/css-selector-text.html (175445 => 175446)


--- trunk/LayoutTests/fast/css/css-selector-text.html	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/LayoutTests/fast/css/css-selector-text.html	2014-11-01 03:06:27 UTC (rev 175446)
@@ -81,6 +81,15 @@
 debug('');
 
 testSelectorRoundTrip(":lang(a)");
+testSelectorRoundTrip(":lang(a, b, c)");
+testSelectorRoundTrip(":lang(fr, de, en, id)");
+testSelectorRoundTrip(":lang(fr, fr-ca, fr-be)");
+testSelectorRoundTrip(":lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996)");
+testSelectorRoundTrip(":lang(de-CH, it-CH, fr-CH, rm-CH)");
+testSelectorRoundTrip(":lang(de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996, de-CH, it-CH, fr-CH, rm-CH)");
+
+debug('');
+
 testSelectorRoundTrip(":not(a)");
 testSelectorRoundTrip(":-webkit-any(a,b,p)");
 
@@ -316,6 +325,43 @@
 
 debug('');
 
+shouldBe("parseThenSerializeRule(':lang(a    ) { }')", "':lang(a) { }'");
+shouldBe("parseThenSerializeRule(':lang(    a) { }')", "':lang(a) { }'");
+shouldBe("parseThenSerializeRule(':lang(a,    b,    c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(    a, b ,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(  a  ,  b  ,  c  ) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(    a  ,b,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(    a  ,b  ,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(    a  ,b  ,c  ) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(a,b    ,c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(a,b,    c) { }')", "':lang(a, b, c) { }'");
+shouldBe("parseThenSerializeRule(':lang(a,b,    c    ) { }')", "':lang(a, b, c) { }'");
+
+debug('');
+
+shouldThrow("parseThenSerializeRule(':lang() { }')");
+shouldThrow("parseThenSerializeRule(':lang(12, b, c) { }')");
+shouldThrow("parseThenSerializeRule(':lang(a, 12, c) { }')");
+shouldThrow("parseThenSerializeRule(':lang(a, b, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(a, 12, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(12, b, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(12, 12, 12) { }')");
+shouldThrow("parseThenSerializeRule(':lang(lang()) { }')");
+shouldThrow("parseThenSerializeRule(':lang(:lang()) { }')");
+shouldThrow("parseThenSerializeRule(':lang(:lang(id)) { }')");
+shouldThrow("parseThenSerializeRule(':lang(:lang(en, br)) { }')");
+shouldThrow("parseThenSerializeRule(':lang(<0_0>) { }')");
+shouldThrow("parseThenSerializeRule(':lang(99) { }')");
+shouldThrow("parseThenSerializeRule(':lang(88) { }')");
+shouldThrow("parseThenSerializeRule(':lang(00) { }')");
+shouldThrow("parseThenSerializeRule(':lang(}) { }')");
+shouldThrow("parseThenSerializeRule(':lang({) { }')");
+shouldThrow("parseThenSerializeRule(':lang({}) { }')");
+shouldThrow("parseThenSerializeRule(':lang(]) { }')");
+shouldThrow("parseThenSerializeRule(':lang([) { }')");
+shouldThrow("parseThenSerializeRule(':lang([]) { }')");
+shouldThrow("parseThenSerializeRule(':lang(@media screen {}) { }')");
+
 </script>
 <script src=""
 </body>

Added: trunk/LayoutTests/fast/selectors/lang-invalid-expected.txt (0 => 175446)


--- trunk/LayoutTests/fast/selectors/lang-invalid-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/lang-invalid-expected.txt	2014-11-01 03:06:27 UTC (rev 175446)
@@ -0,0 +1,39 @@
+Verify invalid :lang() selectors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll(":lang()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(lang()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(:lang(id)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(:lang(en, br)").length threw exception Error: SyntaxError: DOM Exception 12.
+
+PASS document.querySelectorAll(":lang(<0_0>)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(9)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(99)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(999)").length threw exception Error: SyntaxError: DOM Exception 12.
+
+PASS document.querySelectorAll(":lang(})").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang({)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang({}")).length threw exception SyntaxError: Unexpected token ')'.
+PASS document.querySelectorAll(":lang(()").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang())").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(()")).length threw exception SyntaxError: Unexpected token ')'.
+PASS document.querySelectorAll(":lang(])").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang([)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang([])").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(@media screen {})").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(@font-face {})").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(:)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(;)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(.)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(+)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(-)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(=)").length threw exception Error: SyntaxError: DOM Exception 12.
+PASS document.querySelectorAll(":lang(&&)").length threw exception Error: SyntaxError: DOM Exception 12.
+
+PASS getComputedStyle(document.getElementById("target1")).color is "rgb(0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/lang-invalid.html (0 => 175446)


--- trunk/LayoutTests/fast/selectors/lang-invalid.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/lang-invalid.html	2014-11-01 03:06:27 UTC (rev 175446)
@@ -0,0 +1,68 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+* {
+    color: rgb(0, 0, 0);
+}
+:lang() {
+    color: rgb(1, 2, 3);
+}
+
+:lang() * {
+    color: rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div style="display:none">
+        <a>
+            <b>
+                <c id="target1"></c>
+            </b>
+        </a>
+    </div>
+</body>
+<script>
+description('Verify invalid :lang() selectors.');
+
+shouldThrow('document.querySelectorAll(":lang()").length');
+shouldThrow('document.querySelectorAll(":lang(lang()").length');
+shouldThrow('document.querySelectorAll(":lang(:lang(id)").length');
+shouldThrow('document.querySelectorAll(":lang(:lang(en, br)").length');
+
+debug('')
+
+shouldThrow('document.querySelectorAll(":lang(<0_0>)").length');
+shouldThrow('document.querySelectorAll(":lang(9)").length');
+shouldThrow('document.querySelectorAll(":lang(99)").length');
+shouldThrow('document.querySelectorAll(":lang(999)").length');
+
+debug('')
+
+shouldThrow('document.querySelectorAll(":lang(})").length');
+shouldThrow('document.querySelectorAll(":lang({)").length');
+shouldThrow('document.querySelectorAll(":lang({}")).length');
+shouldThrow('document.querySelectorAll(":lang(()").length');
+shouldThrow('document.querySelectorAll(":lang())").length');
+shouldThrow('document.querySelectorAll(":lang(()")).length');
+shouldThrow('document.querySelectorAll(":lang(])").length');
+shouldThrow('document.querySelectorAll(":lang([)").length');
+shouldThrow('document.querySelectorAll(":lang([])").length');
+shouldThrow('document.querySelectorAll(":lang(@media screen {})").length');
+shouldThrow('document.querySelectorAll(":lang(@font-face {})").length');
+shouldThrow('document.querySelectorAll(":lang(:)").length');
+shouldThrow('document.querySelectorAll(":lang(;)").length');
+shouldThrow('document.querySelectorAll(":lang(.)").length');
+shouldThrow('document.querySelectorAll(":lang(+)").length');
+shouldThrow('document.querySelectorAll(":lang(-)").length');
+shouldThrow('document.querySelectorAll(":lang(=)").length');
+shouldThrow('document.querySelectorAll(":lang(&&)").length');
+
+debug('')
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("target1")).color', 'rgb(0, 0, 0)');
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (175445 => 175446)


--- trunk/Source/WebCore/ChangeLog	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/ChangeLog	2014-11-01 03:06:27 UTC (rev 175446)
@@ -1,3 +1,40 @@
+2014-10-31  Dhi Aurrahman  <[email protected]>
+
+        Add initial parsing functionality of :lang pseudo class in Selectors Level 4.
+        https://bugs.webkit.org/show_bug.cgi?id=138170
+
+        Reviewed by Benjamin Poulain.
+
+        Add initial parsing functionality of :lang pseudo class in Selectors Level 4,
+        as specified in [1].
+
+        It parses comma-separated list of string arguments. Currently, it throws error
+        on arguments with "*" (e.g. :lang(zh, *-hant)).
+
+        Add additional test file fast/selectors/lang-invalid.html along side the 
+        fast/css/css-selector-text.html.
+
+        [1] http://dev.w3.org/csswg/selectors4/#the-lang-pseudo
+
+        Test: fast/selectors/lang-invalid.html
+
+        * css/CSSGrammar.y.in:
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::detectFunctionTypeToken):
+        * css/CSSParserValues.cpp:
+        (WebCore::CSSParserSelector::setArgumentList):
+        * css/CSSParserValues.h:
+        * css/CSSSelector.cpp:
+        (WebCore::appendArgumentList):
+        (WebCore::CSSSelector::selectorText):
+        (WebCore::CSSSelector::setArgumentList):
+        * css/CSSSelector.h:
+        (WebCore::CSSSelector::argumentList):
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::checkOne):
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::addPseudoClassType):
+
 2014-10-31  Chris Dumez  <[email protected]>
 
         StyleBuilder: Stop using custom code for -webkit-hyphenate-limit-lines

Modified: trunk/Source/WebCore/css/CSSGrammar.y.in (175445 => 175446)


--- trunk/Source/WebCore/css/CSSGrammar.y.in	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSGrammar.y.in	2014-11-01 03:06:27 UTC (rev 175446)
@@ -62,6 +62,7 @@
     case NTHCHILDFUNCTION:
     case NTHCHILDSELECTORSEPARATOR:
 #if ENABLE_CSS_SELECTORS_LEVEL4
+    case LANGFUNCTION:
     case MATCHESFUNCTION:
 #endif
     case UNICODERANGE:
@@ -229,6 +230,7 @@
 %token <string> NTHCHILDFUNCTION
 
 #if ENABLE_CSS_SELECTORS_LEVEL4
+%token <string> LANGFUNCTION
 %token <string> MATCHESFUNCTION
 #endif
 
@@ -328,6 +330,12 @@
 %type <valueList> calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr
 %destructor { delete $$; } calc_func_expr calc_func_expr_list calc_func_paren_expr expr key_list maybe_media_value valid_calc_func_expr valid_expr
 
+#if ENABLE_CSS_SELECTORS_LEVEL4
+%union { Vector<CSSParserString>* stringList; }
+%type <stringList> comma_separated_identifiers
+%destructor { delete $$; } comma_separated_identifiers
+#endif
+
 %type <string> min_or_max
 
 %type <string> element_name
@@ -1089,6 +1097,24 @@
     }
     ;
 
+#if ENABLE_CSS_SELECTORS_LEVEL4
+comma_separated_identifiers:
+    IDENT %prec UNIMPORTANT_TOK {
+        $$ = new Vector<CSSParserString>;
+        $$->append($1);
+    }
+    | comma_separated_identifiers maybe_space ',' maybe_space IDENT %prec UNIMPORTANT_TOK {
+        $$ = $1;
+        if ($$)
+            $1->append($5);
+    }
+    | comma_separated_identifiers error {
+        $$ = nullptr;
+        delete $1;
+    }
+    ;
+#endif
+
 complex_selector_with_trailing_whitespace:
     complex_selector WHITESPACE;
 
@@ -1337,6 +1363,18 @@
     }
 
 #if ENABLE_CSS_SELECTORS_LEVEL4
+    | ':' LANGFUNCTION maybe_space comma_separated_identifiers maybe_space ')' {
+        $$ = nullptr;
+        if ($4) {
+          auto selector = std::make_unique<CSSParserSelector>();
+          selector->setMatch(CSSSelector::PseudoClass);
+          selector->setArgumentList(*std::unique_ptr<Vector<CSSParserString>>($4));
+          selector->setPseudoClassValue($2);
+          if (selector->pseudoClassType() == CSSSelector::PseudoClassLang)
+              $$ = selector.release();
+        }
+    }
+
     | ':' MATCHESFUNCTION maybe_space nested_selector_list maybe_space ')' {
         $$ = nullptr;
         if ($4) {
@@ -1837,7 +1875,7 @@
 opening_parenthesis:
     '(' | FUNCTION | CALCFUNCTION | MINFUNCTION | MAXFUNCTION | ANYFUNCTION | NOTFUNCTION
 #if ENABLE_CSS_SELECTORS_LEVEL4
-    | MATCHESFUNCTION
+    | LANGFUNCTION | MATCHESFUNCTION
 #endif
 #if ENABLE_VIDEO_TRACK
     | CUEFUNCTION

Modified: trunk/Source/WebCore/css/CSSParser.cpp (175445 => 175446)


--- trunk/Source/WebCore/css/CSSParser.cpp	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSParser.cpp	2014-11-01 03:06:27 UTC (rev 175446)
@@ -10670,6 +10670,12 @@
             m_token = CALCFUNCTION;
             return true;
         }
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+        if (isEqualToCSSIdentifier(name, "lang")) {
+            m_token = LANGFUNCTION;
+            return true;
+        }
+#endif
         return false;
 
 #if ENABLE(CSS_SELECTORS_LEVEL4)

Modified: trunk/Source/WebCore/css/CSSParserValues.cpp (175445 => 175446)


--- trunk/Source/WebCore/css/CSSParserValues.cpp	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSParserValues.cpp	2014-11-01 03:06:27 UTC (rev 175446)
@@ -261,6 +261,16 @@
     m_selector->setSelectorList(WTF::move(selectorList));
 }
 
+void CSSParserSelector::setArgumentList(Vector<CSSParserString>& stringVector)
+{
+    ASSERT_WITH_MESSAGE(!stringVector.isEmpty(), "No CSS Selector takes an empty argument list.");
+    auto argumentList = std::make_unique<Vector<AtomicString>>();
+    argumentList->reserveInitialCapacity(stringVector.size());
+    for (const AtomicString& argument : stringVector)
+        argumentList->append(argument);
+    m_selector->setArgumentList(WTF::move(argumentList));
+}
+
 void CSSParserSelector::setPseudoClassValue(const CSSParserString& pseudoClassString)
 {
     ASSERT(m_selector->match() == CSSSelector::PseudoClass);

Modified: trunk/Source/WebCore/css/CSSParserValues.h (175445 => 175446)


--- trunk/Source/WebCore/css/CSSParserValues.h	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSParserValues.h	2014-11-01 03:06:27 UTC (rev 175446)
@@ -201,6 +201,9 @@
 
 
     void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector);
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+    void setArgumentList(Vector<CSSParserString>& stringVector);
+#endif
 
     void setPseudoClassValue(const CSSParserString& pseudoClassString);
     CSSSelector::PseudoClassType pseudoClassType() const { return m_selector->pseudoClassType(); }

Modified: trunk/Source/WebCore/css/CSSSelector.cpp (175445 => 175446)


--- trunk/Source/WebCore/css/CSSSelector.cpp	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSSelector.cpp	2014-11-01 03:06:27 UTC (rev 175446)
@@ -253,6 +253,18 @@
 
 }
 
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+static void appendArgumentList(StringBuilder& str, const Vector<AtomicString>& argumentList)
+{
+    const AtomicString& lastArgument = argumentList.last();
+    for (const AtomicString argument : argumentList) {
+        str.append(argument);
+        if (argument != lastArgument)
+            str.appendLiteral(", ");
+    }
+}
+#endif
+
 static void appendSelectorList(StringBuilder& str, const CSSSelectorList* selectorList)
 {
     const CSSSelector* firstSubSelector = selectorList->first();
@@ -395,7 +407,13 @@
                 break;
             case CSSSelector::PseudoClassLang:
                 str.appendLiteral(":lang(");
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+                ASSERT_WITH_MESSAGE(cs->argumentList() && !cs->argumentList().isEmpty(), "An empty :lang() is invalid and should never be generated by the parser.");
+                appendArgumentList(str, *cs->argumentList());
+                str.append(')');
+#else
                 appendPseudoClassFunctionTail(str, cs);
+#endif
                 break;
             case CSSSelector::PseudoClassLastChild:
                 str.appendLiteral(":last-child");
@@ -606,6 +624,14 @@
     m_data.m_rareData->m_argument = value;
 }
 
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+void CSSSelector::setArgumentList(std::unique_ptr<Vector<AtomicString>> argumentList)
+{
+    createRareData();
+    m_data.m_rareData->m_argumentList = WTF::move(argumentList);
+}
+#endif
+
 void CSSSelector::setSelectorList(std::unique_ptr<CSSSelectorList> selectorList)
 {
     createRareData();

Modified: trunk/Source/WebCore/css/CSSSelector.h (175445 => 175446)


--- trunk/Source/WebCore/css/CSSSelector.h	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/CSSSelector.h	2014-11-01 03:06:27 UTC (rev 175446)
@@ -207,11 +207,17 @@
         const QualifiedName& attribute() const;
         const AtomicString& attributeCanonicalLocalName() const;
         const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; }
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+        const Vector<AtomicString>* argumentList() const { return m_hasRareData ? m_data.m_rareData->m_argumentList.get() : nullptr; }
+#endif
         const CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : nullptr; }
 
         void setValue(const AtomicString&);
         void setAttribute(const QualifiedName&, bool isCaseInsensitive);
         void setArgument(const AtomicString&);
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+        void setArgumentList(std::unique_ptr<Vector<AtomicString>>);
+#endif
         void setSelectorList(std::unique_ptr<CSSSelectorList>);
 
         bool parseNth() const;
@@ -309,7 +315,10 @@
             int m_b; // Used for :nth-*
             QualifiedName m_attribute; // used for attribute selector
             AtomicString m_attributeCanonicalLocalName;
-            AtomicString m_argument; // Used for :contains, :lang and :nth-*
+            AtomicString m_argument; // Used for :contains and :nth-*
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+            std::unique_ptr<Vector<AtomicString>> m_argumentList;
+#endif
             std::unique_ptr<CSSSelectorList> m_selectorList; // Used for :-webkit-any and :not
         
         private:

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (175445 => 175446)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2014-11-01 03:06:27 UTC (rev 175446)
@@ -859,7 +859,12 @@
             break;
         case CSSSelector::PseudoClassLang:
             {
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+                ASSERT(selector->argumentList() && !selector->argumentList()->isEmpty());
+                const AtomicString& argument = selector->argumentList()->first();
+#else
                 const AtomicString& argument = selector->argument();
+#endif                
                 if (argument.isNull())
                     return false;
                 return matchesLangPseudoClass(element, argument.impl());

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (175445 => 175446)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-11-01 01:31:46 UTC (rev 175445)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-11-01 03:06:27 UTC (rev 175446)
@@ -727,7 +727,12 @@
 
     case CSSSelector::PseudoClassLang:
         {
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+            ASSERT(selector.argumentList() && !selector.argumentList()->isEmpty());
+            const AtomicString& argument = selector.argumentList()->first();
+#else
             const AtomicString& argument = selector.argument();
+#endif
             if (argument.isEmpty())
                 return FunctionType::CannotMatchAnything;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to