Title: [176902] trunk
Revision
176902
Author
[email protected]
Date
2014-12-05 21:09:11 -0800 (Fri, 05 Dec 2014)

Log Message

Implement parser for :lang pseudo class selector arguments that contain wildcard '*' subtags
https://bugs.webkit.org/show_bug.cgi?id=139014

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

Source/WebCore:

Consider each language range in :lang() that consists of an asterisk
immediately followed by an identifier beginning with an ASCII hyphen
as a valid input for the selector as specified in [1].

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

Test: fast/css/parsing-css-lang.html

* css/CSSGrammar.y.in:
* css/CSSParser.cpp:
(WebCore::CSSParser::realLex):

LayoutTests:

* fast/css/css-selector-text-expected.txt: Updated for asterisk containing input.
* fast/css/css-selector-text.html: Updated for asterisk containing input.
* fast/css/parsing-css-lang-expected.txt: Added.
* fast/css/parsing-css-lang.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (176901 => 176902)


--- trunk/LayoutTests/ChangeLog	2014-12-06 02:04:13 UTC (rev 176901)
+++ trunk/LayoutTests/ChangeLog	2014-12-06 05:09:11 UTC (rev 176902)
@@ -1,3 +1,15 @@
+2014-12-05  Dhi Aurrahman  <[email protected]>
+
+        Implement parser for :lang pseudo class selector arguments that contain wildcard '*' subtags
+        https://bugs.webkit.org/show_bug.cgi?id=139014
+
+        Reviewed by Benjamin Poulain.
+
+        * fast/css/css-selector-text-expected.txt: Updated for asterisk containing input.
+        * fast/css/css-selector-text.html: Updated for asterisk containing input.
+        * fast/css/parsing-css-lang-expected.txt: Added.
+        * fast/css/parsing-css-lang.html: Added.
+
 2014-12-05  Benjamin Poulain  <[email protected]>
 
         Fix style sharing with the "type" and "readonly" attributes

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


--- trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2014-12-06 02:04:13 UTC (rev 176901)
+++ trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2014-12-06 05:09:11 UTC (rev 176902)
@@ -47,6 +47,16 @@
 PASS parseThenSerializeRule(':target { }') is ':target { }'
 PASS parseThenSerializeRule(':visited { }') is ':visited { }'
 
+PASS parseThenSerializeRule(':lang(*-) { }') is ':lang(*-) { }'
+PASS parseThenSerializeRule(':lang(*--) { }') is ':lang(*--) { }'
+PASS parseThenSerializeRule(':lang(*---) { }') is ':lang(*---) { }'
+PASS parseThenSerializeRule(':lang(*----) { }') is ':lang(*----) { }'
+
+PASS parseThenSerializeRule(':lang(*-ab) { }') is ':lang(*-ab) { }'
+PASS parseThenSerializeRule(':lang(*-ab-) { }') is ':lang(*-ab-) { }'
+PASS parseThenSerializeRule(':lang(*-1996) { }') is ':lang(*-1996) { }'
+PASS parseThenSerializeRule(':lang(*-DE-1996) { }') is ':lang(*-DE-1996) { }'
+
 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) { }'
@@ -294,6 +304,76 @@
 PASS parseThenSerializeRule(':lang(    en    ,    en    ,   en    ) { }') is ':lang(en, en, en) { }'
 PASS parseThenSerializeRule(':lang(    en,en,en    ) { }') is ':lang(en, en, en) { }'
 
+PASS parseThenSerializeRule(':lang(*-DE, *-CH, *-EN) { }') is ':lang(*-DE, *-CH, *-EN) { }'
+PASS parseThenSerializeRule(':lang(*-DE,*-CH,*-EN) { }') is ':lang(*-DE, *-CH, *-EN) { }'
+PASS parseThenSerializeRule(':lang(   *-DE  ,  *-CH  ,  *-EN  ) { }') is ':lang(*-DE, *-CH, *-EN) { }'
+
+PASS parseThenSerializeRule(':lang(\\*) { }') is ':lang(*) { }'
+PASS parseThenSerializeRule(':lang(*-\\*) { }') is ':lang(*-*) { }'
+PASS parseThenSerializeRule(':lang(*-\\*-\\*) { }') is ':lang(*-*-*) { }'
+PASS parseThenSerializeRule(':lang(*-\\*-\\*-\\*) { }') is ':lang(*-*-*-*) { }'
+
+PASS parseThenSerializeRule(':lang(ab-\\*) { }') is ':lang(ab-*) { }'
+PASS parseThenSerializeRule(':lang(*-ab-\\*) { }') is ':lang(*-ab-*) { }'
+PASS parseThenSerializeRule(':lang(*-ab-\\*-) { }') is ':lang(*-ab-*-) { }'
+PASS parseThenSerializeRule(':lang(*-foo-\\3A) { }') is ':lang(*-foo-:) { }'
+PASS parseThenSerializeRule(':lang(*-foo-\\3A\\`\\)) { }') is ':lang(*-foo-:`)) { }'
+PASS parseThenSerializeRule(':lang(*-foo-\\*) { }') is ':lang(*-foo-*) { }'
+PASS parseThenSerializeRule(':lang(*-foo-\\0072 aisin) { }') is ':lang(*-foo-raisin) { }'
+PASS parseThenSerializeRule(':lang(*-foo-\\0062 \\0061 r) { }') is ':lang(*-foo-bar) { }'
+PASS parseThenSerializeRule(':lang(*-foo-col\\6Fr) { }') is ':lang(*-foo-color) { }'
+
+PASS parseThenSerializeRule(':lang(\\*    ) { }') is ':lang(*) { }'
+PASS parseThenSerializeRule(':lang(*-    ) { }') is ':lang(*-) { }'
+PASS parseThenSerializeRule(':lang(*-en    ) { }') is ':lang(*-en) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*    ) { }') is ':lang(*-en-*) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr    ) { }') is ':lang(*-en-*-fr) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,br    ) { }') is ':lang(*-en-*-fr, br) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr, br    ) { }') is ':lang(*-en-*-fr, br) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,   br    ) { }') is ':lang(*-en-*-fr, br) { }'
+PASS parseThenSerializeRule(':lang(  *-en-\\*-fr,   br    ) { }') is ':lang(*-en-*-fr, br) { }'
+PASS parseThenSerializeRule(':lang(    *-en-\\*-fr,   br    ) { }') is ':lang(*-en-*-fr, br) { }'
+PASS parseThenSerializeRule(':lang(    *-en-\\*-fr  ,   br    ) { }') is ':lang(*-en-*-fr, br) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,*-br-zh    ) { }') is ':lang(*-en-*-fr, *-br-zh) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr, *-br-zh    ) { }') is ':lang(*-en-*-fr, *-br-zh) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,   *-br-zh    ) { }') is ':lang(*-en-*-fr, *-br-zh) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,     *-br-zh    ) { }') is ':lang(*-en-*-fr, *-br-zh) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,       *-br-zh    ) { }') is ':lang(*-en-*-fr, *-br-zh) { }'
+
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,br-\\*-zh    ) { }') is ':lang(*-en-*-fr, br-*-zh) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr, br-\\*-zh    ) { }') is ':lang(*-en-*-fr, br-*-zh) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,   br-\\*-zh    ) { }') is ':lang(*-en-*-fr, br-*-zh) { }'
+PASS parseThenSerializeRule(':lang(*-en-\\*-fr,      br-\\*-zh    ) { }') is ':lang(*-en-*-fr, br-*-zh) { }'
+PASS parseThenSerializeRule(':lang(  *-en-\\*-fr,      br-\\*-zh    ) { }') is ':lang(*-en-*-fr, br-*-zh) { }'
+PASS parseThenSerializeRule(':lang(  *-en-\\*-fr ,      br-\\*-zh    ) { }') is ':lang(*-en-*-fr, br-*-zh) { }'
+PASS parseThenSerializeRule(':lang(  *-en-\\*-fr  ,      br-\\*-zh    ) { }') is ':lang(*-en-*-fr, br-*-zh) { }'
+
+PASS parseThenSerializeRule(':lang(\\*) { }') is ':lang(*) { }'
+PASS parseThenSerializeRule(':lang(\\* ) { }') is ':lang(*) { }'
+PASS parseThenSerializeRule(':lang(\\*   ) { }') is ':lang(*) { }'
+PASS parseThenSerializeRule(':lang( \\*   ) { }') is ':lang(*) { }'
+PASS parseThenSerializeRule(':lang(  \\*) { }') is ':lang(*) { }'
+PASS parseThenSerializeRule(':lang(   \\*   ) { }') is ':lang(*) { }'
+
+PASS parseThenSerializeRule(':lang(   \\*,id-\\*-sumatra   ) { }') is ':lang(*, id-*-sumatra) { }'
+PASS parseThenSerializeRule(':lang(   \\* ,id-\\*-sumatra) { }') is ':lang(*, id-*-sumatra) { }'
+PASS parseThenSerializeRule(':lang(   \\*  ,  id-\\*-sumatra  ) { }') is ':lang(*, id-*-sumatra) { }'
+PASS parseThenSerializeRule(':lang(   \\*   ,    id-\\*-sumatra  ) { }') is ':lang(*, id-*-sumatra) { }'
+
+PASS parseThenSerializeRule(':lang(*-1996) { }') is ':lang(*-1996) { }'
+PASS parseThenSerializeRule(':lang(*-1996, *-1997) { }') is ':lang(*-1996, *-1997) { }'
+PASS parseThenSerializeRule(':lang(*-1996, *-1997 ) { }') is ':lang(*-1996, *-1997) { }'
+PASS parseThenSerializeRule(':lang(   *-1996   ,  *-1997   ) { }') is ':lang(*-1996, *-1997) { }'
+PASS parseThenSerializeRule(':lang(   *-1996   ,*-1997   ) { }') is ':lang(*-1996, *-1997) { }'
+PASS parseThenSerializeRule(':lang(   *-1996,*-1997   ) { }') is ':lang(*-1996, *-1997) { }'
+
+PASS parseThenSerializeRule(':lang(en-\\*) { }') is ':lang(en-*) { }'
+PASS parseThenSerializeRule(':lang(en-\\*, fr-\\*) { }') is ':lang(en-*, fr-*) { }'
+PASS parseThenSerializeRule(':lang(en-\\*, fr-\\* ) { }') is ':lang(en-*, fr-*) { }'
+PASS parseThenSerializeRule(':lang(   en-\\*   ,  fr-\\*   ) { }') is ':lang(en-*, fr-*) { }'
+PASS parseThenSerializeRule(':lang(   en-\\*   ,fr-\\*   ) { }') is ':lang(en-*, fr-*) { }'
+PASS parseThenSerializeRule(':lang(   en-\\*,fr-\\*   ) { }') is ':lang(en-*, fr-*) { }'
+
 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').
@@ -316,6 +396,27 @@
 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 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(de-*)') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-en-*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-en-fr-*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-en-*fr) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-*en-fr) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-1997)') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-1997-*)') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*a*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*a) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(a*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-a, a*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-a, a**) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-a, *a) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-a, **a) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*- a*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-a, br fr) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-a, br fr en *) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
 
 PASS parseThenSerializeRule(':role(a) { }') is ':role(a) { }'
 PASS parseThenSerializeRule(':role(button) { }') is ':role(button) { }'

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


--- trunk/LayoutTests/fast/css/css-selector-text.html	2014-12-06 02:04:13 UTC (rev 176901)
+++ trunk/LayoutTests/fast/css/css-selector-text.html	2014-12-06 05:09:11 UTC (rev 176902)
@@ -80,6 +80,20 @@
 
 debug('');
 
+testSelectorRoundTrip(":lang(*-)");
+testSelectorRoundTrip(":lang(*--)");
+testSelectorRoundTrip(":lang(*---)");
+testSelectorRoundTrip(":lang(*----)");
+
+debug('');
+
+testSelectorRoundTrip(":lang(*-ab)");
+testSelectorRoundTrip(":lang(*-ab-)");
+testSelectorRoundTrip(":lang(*-1996)");
+testSelectorRoundTrip(":lang(*-DE-1996)");
+
+debug('');
+
 testSelectorRoundTrip(":lang(a)");
 testSelectorRoundTrip(":lang(a, b, c)");
 testSelectorRoundTrip(":lang(fr, de, en, id)");
@@ -88,7 +102,7 @@
 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('')
+debug('');
 
 testSelectorRoundTrip(":lang(a, a, a)");
 testSelectorRoundTrip(":lang(en, en, en)");
@@ -375,6 +389,96 @@
 
 debug('');
 
+shouldBe("parseThenSerializeRule(':lang(*-DE, *-CH, *-EN) { }')", "':lang(*-DE, *-CH, *-EN) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-DE,*-CH,*-EN) { }')", "':lang(*-DE, *-CH, *-EN) { }'");
+shouldBe("parseThenSerializeRule(':lang(   *-DE  ,  *-CH  ,  *-EN  ) { }')", "':lang(*-DE, *-CH, *-EN) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(\\\\*) { }')", "':lang(*) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-\\\\*) { }')", "':lang(*-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-\\\\*-\\\\*) { }')", "':lang(*-*-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-\\\\*-\\\\*-\\\\*) { }')", "':lang(*-*-*-*) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(ab-\\\\*) { }')", "':lang(ab-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-ab-\\\\*) { }')", "':lang(*-ab-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-ab-\\\\*-) { }')", "':lang(*-ab-*-) { }'");
+
+shouldBe("parseThenSerializeRule(':lang(*-foo-\\\\3A) { }')", "':lang(*-foo-:) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-foo-\\\\3A\\\\`\\\\)) { }')", "':lang(*-foo-:`)) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-foo-\\\\*) { }')", "':lang(*-foo-*) { }'");
+
+shouldBe("parseThenSerializeRule(':lang(*-foo-\\\\0072 aisin) { }')", "':lang(*-foo-raisin) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-foo-\\\\0062 \\\\0061 r) { }')", "':lang(*-foo-bar) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-foo-col\\\\6Fr) { }')", "':lang(*-foo-color) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(\\\\*    ) { }')", "':lang(*) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-    ) { }')", "':lang(*-) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en    ) { }')", "':lang(*-en) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*    ) { }')", "':lang(*-en-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr    ) { }')", "':lang(*-en-*-fr) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,br    ) { }')", "':lang(*-en-*-fr, br) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr, br    ) { }')", "':lang(*-en-*-fr, br) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,   br    ) { }')", "':lang(*-en-*-fr, br) { }'");
+shouldBe("parseThenSerializeRule(':lang(  *-en-\\\\*-fr,   br    ) { }')", "':lang(*-en-*-fr, br) { }'");
+shouldBe("parseThenSerializeRule(':lang(    *-en-\\\\*-fr,   br    ) { }')", "':lang(*-en-*-fr, br) { }'");
+shouldBe("parseThenSerializeRule(':lang(    *-en-\\\\*-fr  ,   br    ) { }')", "':lang(*-en-*-fr, br) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,*-br-zh    ) { }')", "':lang(*-en-*-fr, *-br-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr, *-br-zh    ) { }')", "':lang(*-en-*-fr, *-br-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,   *-br-zh    ) { }')", "':lang(*-en-*-fr, *-br-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,     *-br-zh    ) { }')", "':lang(*-en-*-fr, *-br-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,       *-br-zh    ) { }')", "':lang(*-en-*-fr, *-br-zh) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,br-\\\\*-zh    ) { }')", "':lang(*-en-*-fr, br-*-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr, br-\\\\*-zh    ) { }')", "':lang(*-en-*-fr, br-*-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,   br-\\\\*-zh    ) { }')", "':lang(*-en-*-fr, br-*-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-en-\\\\*-fr,      br-\\\\*-zh    ) { }')", "':lang(*-en-*-fr, br-*-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(  *-en-\\\\*-fr,      br-\\\\*-zh    ) { }')", "':lang(*-en-*-fr, br-*-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(  *-en-\\\\*-fr ,      br-\\\\*-zh    ) { }')", "':lang(*-en-*-fr, br-*-zh) { }'");
+shouldBe("parseThenSerializeRule(':lang(  *-en-\\\\*-fr  ,      br-\\\\*-zh    ) { }')", "':lang(*-en-*-fr, br-*-zh) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(\\\\*) { }')", "':lang(*) { }'");
+shouldBe("parseThenSerializeRule(':lang(\\\\* ) { }')", "':lang(*) { }'");
+shouldBe("parseThenSerializeRule(':lang(\\\\*   ) { }')", "':lang(*) { }'");
+shouldBe("parseThenSerializeRule(':lang( \\\\*   ) { }')", "':lang(*) { }'");
+shouldBe("parseThenSerializeRule(':lang(  \\\\*) { }')", "':lang(*) { }'");
+shouldBe("parseThenSerializeRule(':lang(   \\\\*   ) { }')", "':lang(*) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(   \\\\*,id-\\\\*-sumatra   ) { }')", "':lang(*, id-*-sumatra) { }'");
+shouldBe("parseThenSerializeRule(':lang(   \\\\* ,id-\\\\*-sumatra) { }')", "':lang(*, id-*-sumatra) { }'");
+shouldBe("parseThenSerializeRule(':lang(   \\\\*  ,  id-\\\\*-sumatra  ) { }')", "':lang(*, id-*-sumatra) { }'");
+shouldBe("parseThenSerializeRule(':lang(   \\\\*   ,    id-\\\\*-sumatra  ) { }')", "':lang(*, id-*-sumatra) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(*-1996) { }')", "':lang(*-1996) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-1996, *-1997) { }')", "':lang(*-1996, *-1997) { }'");
+shouldBe("parseThenSerializeRule(':lang(*-1996, *-1997 ) { }')", "':lang(*-1996, *-1997) { }'");
+shouldBe("parseThenSerializeRule(':lang(   *-1996   ,  *-1997   ) { }')", "':lang(*-1996, *-1997) { }'");
+shouldBe("parseThenSerializeRule(':lang(   *-1996   ,*-1997   ) { }')", "':lang(*-1996, *-1997) { }'");
+shouldBe("parseThenSerializeRule(':lang(   *-1996,*-1997   ) { }')", "':lang(*-1996, *-1997) { }'");
+
+debug('');
+
+shouldBe("parseThenSerializeRule(':lang(en-\\\\*) { }')", "':lang(en-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(en-\\\\*, fr-\\\\*) { }')", "':lang(en-*, fr-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(en-\\\\*, fr-\\\\* ) { }')", "':lang(en-*, fr-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(   en-\\\\*   ,  fr-\\\\*   ) { }')", "':lang(en-*, fr-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(   en-\\\\*   ,fr-\\\\*   ) { }')", "':lang(en-*, fr-*) { }'");
+shouldBe("parseThenSerializeRule(':lang(   en-\\\\*,fr-\\\\*   ) { }')", "':lang(en-*, fr-*) { }'");
+
+debug('');
+
 shouldThrow("parseThenSerializeRule(':lang() { }')");
 shouldThrow("parseThenSerializeRule(':lang(12, b, c) { }')");
 shouldThrow("parseThenSerializeRule(':lang(a, 12, c) { }')");
@@ -398,6 +502,28 @@
 shouldThrow("parseThenSerializeRule(':lang([]) { }')");
 shouldThrow("parseThenSerializeRule(':lang(@media screen {}) { }')");
 
+shouldThrow("parseThenSerializeRule(':lang(*)')");
+shouldThrow("parseThenSerializeRule(':lang(**)')");
+shouldThrow("parseThenSerializeRule(':lang(-*-)')");
+shouldThrow("parseThenSerializeRule(':lang(*-*) { }')");
+shouldThrow("parseThenSerializeRule(':lang(de-*)')");
+shouldThrow("parseThenSerializeRule(':lang(*-en-*) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-en-fr-*) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-en-*fr) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-*en-fr) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-1997)')");
+shouldThrow("parseThenSerializeRule(':lang(*-1997-*)')");
+shouldThrow("parseThenSerializeRule(':lang(*a*) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*a) { }')");
+shouldThrow("parseThenSerializeRule(':lang(a*) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-a, a*) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-a, a**) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-a, *a) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-a, **a) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*- a*) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-a, br fr) { }')");
+shouldThrow("parseThenSerializeRule(':lang(*-a, br fr en *) { }')");
+
 debug('');
 
 testSelectorRoundTrip(":role(a)");

Added: trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt (0 => 176902)


--- trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt	2014-12-06 05:09:11 UTC (rev 176902)
@@ -0,0 +1,286 @@
+Test the parsing of :lang(stringList) for querySelector and style.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+valid language ranges
+PASS document.querySelector(":lang(e)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(e)"
+PASS document.querySelector(":lang(e    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(e)"
+PASS document.querySelector(":lang(en)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en)"
+PASS document.querySelector(":lang(en    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en)"
+PASS document.querySelector(":lang(en-)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-)"
+PASS document.querySelector(":lang(en-    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-)"
+PASS document.querySelector(":lang(en--)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en--)"
+PASS document.querySelector(":lang(en--    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en--)"
+PASS document.querySelector(":lang(en---)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en---)"
+PASS document.querySelector(":lang(en---    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en---)"
+PASS document.querySelector(":lang(en-fr)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-fr)"
+PASS document.querySelector(":lang(en-fr    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-fr)"
+PASS document.querySelector(":lang(en-fr-)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-fr-)"
+PASS document.querySelector(":lang(en-fr-    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-fr-)"
+PASS document.querySelector(":lang(en-fr--)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-fr--)"
+PASS document.querySelector(":lang(en-fr--    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-fr--)"
+PASS document.querySelector(":lang(en--fr)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en--fr)"
+PASS document.querySelector(":lang(en--fr    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en--fr)"
+PASS document.querySelector(":lang(en---fr)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en---fr)"
+PASS document.querySelector(":lang(en---fr    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en---fr)"
+PASS document.querySelector(":lang(en---fr---)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en---fr---)"
+PASS document.querySelector(":lang(en---fr---    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en---fr---)"
+PASS document.querySelector(":lang(de-DE)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-DE)"
+PASS document.querySelector(":lang(de-DE    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-DE)"
+PASS document.querySelector(":lang(de-DE-1996)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-DE-1996)"
+PASS document.querySelector(":lang(de-DE-1996    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-DE-1996)"
+PASS document.querySelector(":lang(de-Latn-DE)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-Latn-DE)"
+PASS document.querySelector(":lang(de-Latn-DE    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-Latn-DE)"
+PASS document.querySelector(":lang(de-Latf-DE)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-Latf-DE)"
+PASS document.querySelector(":lang(de-Latf-DE    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-Latf-DE)"
+PASS document.querySelector(":lang(de-Latn-DE-1996)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-Latn-DE-1996)"
+PASS document.querySelector(":lang(de-Latn-DE-1996    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-Latn-DE-1996)"
+PASS document.querySelector(":lang(de-CH)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-CH)"
+PASS document.querySelector(":lang(de-CH    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(de-CH)"
+PASS document.querySelector(":lang(it-CH)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(it-CH)"
+PASS document.querySelector(":lang(it-CH    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(it-CH)"
+PASS document.querySelector(":lang(fr-CH)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(fr-CH)"
+PASS document.querySelector(":lang(fr-CH    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(fr-CH)"
+PASS document.querySelector(":lang(rm-CH)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(rm-CH)"
+PASS document.querySelector(":lang(rm-CH    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(rm-CH)"
+PASS document.querySelector(":lang(*-)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-)"
+PASS document.querySelector(":lang(*-    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-)"
+PASS document.querySelector(":lang(*--)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*--)"
+PASS document.querySelector(":lang(*--    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*--)"
+PASS document.querySelector(":lang(*---)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*---)"
+PASS document.querySelector(":lang(*---    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*---)"
+PASS document.querySelector(":lang(*----)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*----)"
+PASS document.querySelector(":lang(*----    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*----)"
+PASS document.querySelector(":lang(*-CH)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-CH)"
+PASS document.querySelector(":lang(*-CH    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-CH)"
+PASS document.querySelector(":lang(*-DE-1996)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-DE-1996)"
+PASS document.querySelector(":lang(*-DE-1996    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-DE-1996)"
+PASS document.querySelector(":lang(*-1996)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-1996)"
+PASS document.querySelector(":lang(*-1996    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-1996)"
+PASS document.querySelector(":lang(*-br-zh)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-br-zh)"
+PASS document.querySelector(":lang(*-br-zh    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-br-zh)"
+PASS document.querySelector(":lang(id-\\*-sumatra)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(id-*-sumatra)"
+PASS document.querySelector(":lang(id-\\*-sumatra    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(id-*-sumatra)"
+PASS document.querySelector(":lang(*-en-\\*-fr)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-en-*-fr)"
+PASS document.querySelector(":lang(*-en-\\*-fr    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-en-*-fr)"
+PASS document.querySelector(":lang(*-en-\\*-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-en-*-*)"
+PASS document.querySelector(":lang(*-en-\\*-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-en-*-*)"
+PASS document.querySelector(":lang(\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*)"
+PASS document.querySelector(":lang(\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*)"
+PASS document.querySelector(":lang(*-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-*)"
+PASS document.querySelector(":lang(*-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-*)"
+PASS document.querySelector(":lang(*-\\*-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-*-*)"
+PASS document.querySelector(":lang(*-\\*-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-*-*)"
+PASS document.querySelector(":lang(*-\\*-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-*-*)"
+PASS document.querySelector(":lang(*-\\*-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-*-*)"
+PASS document.querySelector(":lang(ab-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(ab-*)"
+PASS document.querySelector(":lang(ab-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(ab-*)"
+PASS document.querySelector(":lang(*-ab-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*)"
+PASS document.querySelector(":lang(*-ab-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*)"
+PASS document.querySelector(":lang(*-ab-\\*-)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*-)"
+PASS document.querySelector(":lang(*-ab-\\*-    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*-)"
+PASS document.querySelector(":lang(*-ab-\\*--)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*--)"
+PASS document.querySelector(":lang(*-ab-\\*--    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*--)"
+PASS document.querySelector(":lang(*-ab-\\*---)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*---)"
+PASS document.querySelector(":lang(*-ab-\\*---    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-ab-*---)"
+PASS document.querySelector(":lang(*-foo-\\:)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:)"
+PASS document.querySelector(":lang(*-foo-\\:    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:)"
+PASS document.querySelector(":lang(*-foo-\\:)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:)"
+PASS document.querySelector(":lang(*-foo-\\:    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:)"
+PASS document.querySelector(":lang(*-foo-\\:\\`\\))") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:`))"
+PASS document.querySelector(":lang(*-foo-\\:\\`\\)    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:`))"
+PASS document.querySelector(":lang(*-foo-\\:\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:*)"
+PASS document.querySelector(":lang(*-foo-\\:\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(*-foo-:*)"
+PASS document.querySelector(":lang(en-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-*)"
+PASS document.querySelector(":lang(en-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(en-*)"
+PASS document.querySelector(":lang(fr-\\*)") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(fr-*)"
+PASS document.querySelector(":lang(fr-\\*    )") did not throw exception.
+PASS document.getElementById('style-container').sheet.cssRules.length is 1
+PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is ":lang(fr-*)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/css/parsing-css-lang.html (0 => 176902)


--- trunk/LayoutTests/fast/css/parsing-css-lang.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/parsing-css-lang.html	2014-12-06 05:09:11 UTC (rev 176902)
@@ -0,0 +1,91 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style id="style-container">
+</style>
+</head>
+<body>
+</body>
+<script>
+description('Test the parsing of :lang(stringList) for querySelector and style.');
+
+function testValidLanguageRange(languageRangeString, expectedSerializedLanguageRange) {
+    shouldNotThrow('document.querySelector(":lang(' + languageRangeString.replace(/\\/g, '\\\\') + ')")', '"Error: SyntaxError: DOM Exception 12"');
+
+    var styleContainer = document.getElementById('style-container');
+    styleContainer.innerHTML = ':lang(' + languageRangeString + ') { }';
+    shouldBe("document.getElementById('style-container').sheet.cssRules.length", "1");
+    if (!expectedSerializedLanguageRange)
+        expectedSerializedLanguageRange = languageRangeString;
+    shouldBeEqualToString("document.getElementById('style-container').sheet.cssRules[0].selectorText", ':lang(' + expectedSerializedLanguageRange.replace(/\\/g, '') + ')');
+    styleContainer.innerHTML = '';
+}
+
+var validLanguageRanges = [
+    
+    "e",
+    "en",
+    "en-",
+    "en--",
+    "en---",
+    "en-fr",
+    "en-fr-",
+    "en-fr--",
+    "en--fr",
+    "en---fr",
+    "en---fr---",
+
+    "de-DE",
+    "de-DE-1996", 
+    "de-Latn-DE", 
+    "de-Latf-DE", 
+    "de-Latn-DE-1996", 
+    "de-CH", 
+    "it-CH", 
+    "fr-CH", 
+    "rm-CH",
+
+    "*-",
+    "*--",
+    "*---",
+    "*----",
+
+    "*-CH",
+    "*-DE-1996",
+    "*-1996",
+    "*-br-zh",
+    "id-\\*-sumatra",
+    "*-en-\\*-fr",
+    "*-en-\\*-\\*",
+
+    "\\*",
+    "*-\\*",
+    "*-\\*-\\*",
+    "*-\\*-\\*",
+
+    "ab-\\*",
+    "*-ab-\\*",
+    "*-ab-\\*-",
+    "*-ab-\\*--",
+    "*-ab-\\*---",
+
+    "*-foo-\\:",
+    "*-foo-\\:",
+    "*-foo-\\:\\`\\)",
+    "*-foo-\\:\\*",
+
+    "en-\\*",
+    "fr-\\*"
+];
+
+debug("valid language ranges");
+for (var i = 0; i < validLanguageRanges.length; ++i) {
+    var languageRangeString = validLanguageRanges[i];
+    testValidLanguageRange(languageRangeString);
+    testValidLanguageRange(languageRangeString + "    ", languageRangeString);
+}
+
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (176901 => 176902)


--- trunk/Source/WebCore/ChangeLog	2014-12-06 02:04:13 UTC (rev 176901)
+++ trunk/Source/WebCore/ChangeLog	2014-12-06 05:09:11 UTC (rev 176902)
@@ -1,3 +1,22 @@
+2014-12-05  Dhi Aurrahman  <[email protected]>
+
+        Implement parser for :lang pseudo class selector arguments that contain wildcard '*' subtags
+        https://bugs.webkit.org/show_bug.cgi?id=139014
+
+        Reviewed by Benjamin Poulain.
+
+        Consider each language range in :lang() that consists of an asterisk 
+        immediately followed by an identifier beginning with an ASCII hyphen 
+        as a valid input for the selector as specified in [1].
+
+        [1] http://dev.w3.org/csswg/selectors4/#the-lang-pseudo 
+
+        Test: fast/css/parsing-css-lang.html
+
+        * css/CSSGrammar.y.in:
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::realLex):
+
 2014-12-05  Simon Fraser  <[email protected]>
 
         Programmatic scrolling and content changes are not always synchronized

Modified: trunk/Source/WebCore/css/CSSGrammar.y.in (176901 => 176902)


--- trunk/Source/WebCore/css/CSSGrammar.y.in	2014-12-06 02:04:13 UTC (rev 176901)
+++ trunk/Source/WebCore/css/CSSGrammar.y.in	2014-12-06 05:09:11 UTC (rev 176902)
@@ -234,6 +234,7 @@
 
 #if ENABLE_CSS_SELECTORS_LEVEL4
 %token <string> DIRFUNCTION
+%token <string> LANGRANGE
 %token <string> LANGFUNCTION
 %token <string> ROLEFUNCTION
 #endif
@@ -335,9 +336,10 @@
 %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
+%type <string> lang_range
 %union { Vector<CSSParserString>* stringList; }
-%type <stringList> comma_separated_identifiers
-%destructor { delete $$; } comma_separated_identifiers
+%type <stringList> comma_separated_lang_ranges
+%destructor { delete $$; } comma_separated_lang_ranges
 #endif
 
 %type <string> min_or_max
@@ -1102,17 +1104,19 @@
     ;
 
 #if ENABLE_CSS_SELECTORS_LEVEL4
-comma_separated_identifiers:
-    IDENT %prec UNIMPORTANT_TOK {
+lang_range: LANGRANGE | IDENT 
+
+comma_separated_lang_ranges:
+    lang_range %prec UNIMPORTANT_TOK {
         $$ = new Vector<CSSParserString>;
         $$->append($1);
     }
-    | comma_separated_identifiers maybe_space ',' maybe_space IDENT %prec UNIMPORTANT_TOK {
+    | comma_separated_lang_ranges maybe_space ',' maybe_space lang_range %prec UNIMPORTANT_TOK {
         $$ = $1;
         if ($$)
             $1->append($5);
     }
-    | comma_separated_identifiers error {
+    | comma_separated_lang_ranges error {
         $$ = nullptr;
         delete $1;
     }
@@ -1388,7 +1392,7 @@
             $$ = selector.release();
     }
 
-    | ':' LANGFUNCTION maybe_space comma_separated_identifiers maybe_space ')' {
+    | ':' LANGFUNCTION maybe_space comma_separated_lang_ranges maybe_space ')' {
         $$ = nullptr;
         if ($4) {
           auto selector = std::make_unique<CSSParserSelector>();

Modified: trunk/Source/WebCore/css/CSSParser.cpp (176901 => 176902)


--- trunk/Source/WebCore/css/CSSParser.cpp	2014-12-06 02:04:13 UTC (rev 176901)
+++ trunk/Source/WebCore/css/CSSParser.cpp	2014-12-06 05:09:11 UTC (rev 176902)
@@ -11486,6 +11486,18 @@
         if (*currentCharacter<SrcCharacterType>() == '=') {
             ++currentCharacter<SrcCharacterType>();
             m_token = CONTAINS;
+        } else if (*currentCharacter<SrcCharacterType>() == '-') {
+            result = currentCharacter<SrcCharacterType>();
+
+            CSSParserString parsedIdentifier;
+            parseIdentifier(result, parsedIdentifier, hasEscape);
+
+            StringBuilder parsedLangRange;
+            parsedLangRange.append('*');
+            parsedLangRange.append(parsedIdentifier);
+
+            m_token = LANGRANGE;
+            yylval->string.init(parsedLangRange.toString());
         }
         break;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to