<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[176902] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/176902">176902</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2014-12-05 21:09:11 -0800 (Fri, 05 Dec 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>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 <diorahman@rockybars.com> 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.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastcsscssselectortextexpectedtxt">trunk/LayoutTests/fast/css/css-selector-text-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcsscssselectortexthtml">trunk/LayoutTests/fast/css/css-selector-text.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecssCSSGrammaryin">trunk/Source/WebCore/css/CSSGrammar.y.in</a></li>
<li><a href="#trunkSourceWebCorecssCSSParsercpp">trunk/Source/WebCore/css/CSSParser.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastcssparsingcsslangexpectedtxt">trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastcssparsingcsslanghtml">trunk/LayoutTests/fast/css/parsing-css-lang.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (176901 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-12-06 02:04:13 UTC (rev 176901)
+++ trunk/LayoutTests/ChangeLog        2014-12-06 05:09:11 UTC (rev 176902)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2014-12-05 Dhi Aurrahman <diorahman@rockybars.com>
+
+ 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.
+
</ins><span class="cx"> 2014-12-05 Benjamin Poulain <bpoulain@apple.com>
</span><span class="cx">
</span><span class="cx"> Fix style sharing with the "type" and "readonly" attributes
</span></span></pre></div>
<a id="trunkLayoutTestsfastcsscssselectortextexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css/css-selector-text-expected.txt (176901 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -47,6 +47,16 @@
</span><span class="cx"> PASS parseThenSerializeRule(':target { }') is ':target { }'
</span><span class="cx"> PASS parseThenSerializeRule(':visited { }') is ':visited { }'
</span><span class="cx">
</span><ins>+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) { }'
+
</ins><span class="cx"> PASS parseThenSerializeRule(':lang(a) { }') is ':lang(a) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(a, b, c) { }') is ':lang(a, b, c) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(fr, de, en, id) { }') is ':lang(fr, de, en, id) { }'
</span><span class="lines">@@ -294,6 +304,76 @@
</span><span class="cx"> PASS parseThenSerializeRule(':lang( en , en , en ) { }') is ':lang(en, en, en) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang( en,en,en ) { }') is ':lang(en, en, en) { }'
</span><span class="cx">
</span><ins>+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-*) { }'
+
</ins><span class="cx"> PASS parseThenSerializeRule(':lang() { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(12, b, c) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(a, 12, c) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="lines">@@ -316,6 +396,27 @@
</span><span class="cx"> PASS parseThenSerializeRule(':lang([) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang([]) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(@media screen {}) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><ins>+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').
</ins><span class="cx">
</span><span class="cx"> PASS parseThenSerializeRule(':role(a) { }') is ':role(a) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':role(button) { }') is ':role(button) { }'
</span></span></pre></div>
<a id="trunkLayoutTestsfastcsscssselectortexthtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css/css-selector-text.html (176901 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -80,6 +80,20 @@
</span><span class="cx">
</span><span class="cx"> debug('');
</span><span class="cx">
</span><ins>+testSelectorRoundTrip(":lang(*-)");
+testSelectorRoundTrip(":lang(*--)");
+testSelectorRoundTrip(":lang(*---)");
+testSelectorRoundTrip(":lang(*----)");
+
+debug('');
+
+testSelectorRoundTrip(":lang(*-ab)");
+testSelectorRoundTrip(":lang(*-ab-)");
+testSelectorRoundTrip(":lang(*-1996)");
+testSelectorRoundTrip(":lang(*-DE-1996)");
+
+debug('');
+
</ins><span class="cx"> testSelectorRoundTrip(":lang(a)");
</span><span class="cx"> testSelectorRoundTrip(":lang(a, b, c)");
</span><span class="cx"> testSelectorRoundTrip(":lang(fr, de, en, id)");
</span><span class="lines">@@ -88,7 +102,7 @@
</span><span class="cx"> testSelectorRoundTrip(":lang(de-CH, it-CH, fr-CH, rm-CH)");
</span><span class="cx"> 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)");
</span><span class="cx">
</span><del>-debug('')
</del><ins>+debug('');
</ins><span class="cx">
</span><span class="cx"> testSelectorRoundTrip(":lang(a, a, a)");
</span><span class="cx"> testSelectorRoundTrip(":lang(en, en, en)");
</span><span class="lines">@@ -375,6 +389,96 @@
</span><span class="cx">
</span><span class="cx"> debug('');
</span><span class="cx">
</span><ins>+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('');
+
</ins><span class="cx"> shouldThrow("parseThenSerializeRule(':lang() { }')");
</span><span class="cx"> shouldThrow("parseThenSerializeRule(':lang(12, b, c) { }')");
</span><span class="cx"> shouldThrow("parseThenSerializeRule(':lang(a, 12, c) { }')");
</span><span class="lines">@@ -398,6 +502,28 @@
</span><span class="cx"> shouldThrow("parseThenSerializeRule(':lang([]) { }')");
</span><span class="cx"> shouldThrow("parseThenSerializeRule(':lang(@media screen {}) { }')");
</span><span class="cx">
</span><ins>+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 *) { }')");
+
</ins><span class="cx"> debug('');
</span><span class="cx">
</span><span class="cx"> testSelectorRoundTrip(":role(a)");
</span></span></pre></div>
<a id="trunkLayoutTestsfastcssparsingcsslangexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt (0 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,286 @@
</span><ins>+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
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastcssparsingcsslanghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/css/parsing-css-lang.html (0 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -0,0 +1,91 @@
</span><ins>+<!doctype html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<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="../../resources/js-test-post.js"></script>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (176901 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2014-12-05 Dhi Aurrahman <diorahman@rockybars.com>
+
+ 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):
+
</ins><span class="cx"> 2014-12-05 Simon Fraser <simon.fraser@apple.com>
</span><span class="cx">
</span><span class="cx"> Programmatic scrolling and content changes are not always synchronized
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSGrammaryin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSGrammar.y.in (176901 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -234,6 +234,7 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE_CSS_SELECTORS_LEVEL4
</span><span class="cx"> %token <string> DIRFUNCTION
</span><ins>+%token <string> LANGRANGE
</ins><span class="cx"> %token <string> LANGFUNCTION
</span><span class="cx"> %token <string> ROLEFUNCTION
</span><span class="cx"> #endif
</span><span class="lines">@@ -335,9 +336,10 @@
</span><span class="cx"> %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
</span><span class="cx">
</span><span class="cx"> #if ENABLE_CSS_SELECTORS_LEVEL4
</span><ins>+%type <string> lang_range
</ins><span class="cx"> %union { Vector<CSSParserString>* stringList; }
</span><del>-%type <stringList> comma_separated_identifiers
-%destructor { delete $$; } comma_separated_identifiers
</del><ins>+%type <stringList> comma_separated_lang_ranges
+%destructor { delete $$; } comma_separated_lang_ranges
</ins><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> %type <string> min_or_max
</span><span class="lines">@@ -1102,17 +1104,19 @@
</span><span class="cx"> ;
</span><span class="cx">
</span><span class="cx"> #if ENABLE_CSS_SELECTORS_LEVEL4
</span><del>-comma_separated_identifiers:
- IDENT %prec UNIMPORTANT_TOK {
</del><ins>+lang_range: LANGRANGE | IDENT
+
+comma_separated_lang_ranges:
+ lang_range %prec UNIMPORTANT_TOK {
</ins><span class="cx"> $$ = new Vector<CSSParserString>;
</span><span class="cx"> $$->append($1);
</span><span class="cx"> }
</span><del>- | comma_separated_identifiers maybe_space ',' maybe_space IDENT %prec UNIMPORTANT_TOK {
</del><ins>+ | comma_separated_lang_ranges maybe_space ',' maybe_space lang_range %prec UNIMPORTANT_TOK {
</ins><span class="cx"> $$ = $1;
</span><span class="cx"> if ($$)
</span><span class="cx"> $1->append($5);
</span><span class="cx"> }
</span><del>- | comma_separated_identifiers error {
</del><ins>+ | comma_separated_lang_ranges error {
</ins><span class="cx"> $$ = nullptr;
</span><span class="cx"> delete $1;
</span><span class="cx"> }
</span><span class="lines">@@ -1388,7 +1392,7 @@
</span><span class="cx"> $$ = selector.release();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- | ':' LANGFUNCTION maybe_space comma_separated_identifiers maybe_space ')' {
</del><ins>+ | ':' LANGFUNCTION maybe_space comma_separated_lang_ranges maybe_space ')' {
</ins><span class="cx"> $$ = nullptr;
</span><span class="cx"> if ($4) {
</span><span class="cx"> auto selector = std::make_unique<CSSParserSelector>();
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSParser.cpp (176901 => 176902)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -11486,6 +11486,18 @@
</span><span class="cx"> if (*currentCharacter<SrcCharacterType>() == '=') {
</span><span class="cx"> ++currentCharacter<SrcCharacterType>();
</span><span class="cx"> m_token = CONTAINS;
</span><ins>+ } 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());
</ins><span class="cx"> }
</span><span class="cx"> break;
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>