<!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>[176983] 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/176983">176983</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2014-12-08 15:55:04 -0800 (Mon, 08 Dec 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Fix the parsing of advanced :lang() after <a href="http://trac.webkit.org/projects/webkit/changeset/176902">r176902</a>
https://bugs.webkit.org/show_bug.cgi?id=139379

Reviewed by Andreas Kling.

Source/WebCore:

There were two mistakes that were only caught in debug:

The lexer was not calling isIdentifierStart() before parseIdentifier().
Some identifier we were parsing should have been invalid.
This was caught with an assertion in parseIdentifier().

The other issue is that we were accumulating pointer to freed memory.
The tokenizer for LANGRANGE was creating a new string with a StringBuilder.
The problem is that CSSParserString does not keep the source string alive.
Consequently, the list of language range was accumulating pointers to dead
StringImpls.

The fix there is to simply extend the token to take the original asterisk character
from the input. That is not elegant but that's efficient and we know
the buffer lifetime.

* css/CSSParser.cpp:
(WebCore::CSSParser::realLex):
* css/CSSGrammar.y.in: Fix the indentation of a language range rule.

LayoutTests:

Unskip and update the tests.

All the interesting cases were covered, I just had to update
the expectations.

* TestExpectations:
* fast/css/css-selector-text-expected.txt:
* fast/css/css-selector-text.html:
* fast/css/parsing-css-lang-expected.txt:
* fast/css/parsing-css-lang.html:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsTestExpectations">trunk/LayoutTests/TestExpectations</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="#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>
<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>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/LayoutTests/ChangeLog        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2014-12-08  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Fix the parsing of advanced :lang() after r176902
+        https://bugs.webkit.org/show_bug.cgi?id=139379
+
+        Reviewed by Andreas Kling.
+
+        Unskip and update the tests.
+
+        All the interesting cases were covered, I just had to update
+        the expectations.
+
+        * TestExpectations:
+        * fast/css/css-selector-text-expected.txt:
+        * fast/css/css-selector-text.html:
+        * fast/css/parsing-css-lang-expected.txt:
+        * fast/css/parsing-css-lang.html:
+
</ins><span class="cx"> 2014-12-08  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Inline elements whose parents have small line-height are laid out too low
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/LayoutTests/TestExpectations        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -130,10 +130,6 @@
</span><span class="cx"> webkit.org/b/135390 fast/css/fontloader-page-cache.html [ Skip ]
</span><span class="cx"> webkit.org/b/135390 http/tests/webfont/fontloader-loading-attribute.html [ Skip ]
</span><span class="cx"> 
</span><del>-# regression due to r176902:
-webkit.org/b/139014 [ Debug ] fast/css/parsing-css-lang.html [ Skip ]
-webkit.org/b/139014 [ Debug ] fast/css/css-selector-text.html [ Skip ]
-
</del><span class="cx"> # Various failures from the W3C CSS Shapes test suite import
</span><span class="cx"> 
</span><span class="cx"> webkit.org/b/137788 css3/shapes/shape-outside/shape-image/shape-image-010.html [ ImageOnlyFailure ]
</span></span></pre></div>
<a id="trunkLayoutTestsfastcsscssselectortextexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css/css-selector-text-expected.txt (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/css-selector-text-expected.txt        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/LayoutTests/fast/css/css-selector-text-expected.txt        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -47,14 +47,8 @@
</span><span class="cx"> PASS parseThenSerializeRule(':target { }') is ':target { }'
</span><span class="cx"> PASS parseThenSerializeRule(':visited { }') is ':visited { }'
</span><span class="cx"> 
</span><del>-PASS parseThenSerializeRule(':lang(*-) { }') is ':lang(*-) { }'
-PASS parseThenSerializeRule(':lang(*--) { }') is ':lang(*--) { }'
-PASS parseThenSerializeRule(':lang(*---) { }') is ':lang(*---) { }'
-PASS parseThenSerializeRule(':lang(*----) { }') is ':lang(*----) { }'
-
</del><span class="cx"> PASS parseThenSerializeRule(':lang(*-ab) { }') is ':lang(*-ab) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-ab-) { }') is ':lang(*-ab-) { }'
</span><del>-PASS parseThenSerializeRule(':lang(*-1996) { }') is ':lang(*-1996) { }'
</del><span class="cx"> PASS parseThenSerializeRule(':lang(*-DE-1996) { }') is ':lang(*-DE-1996) { }'
</span><span class="cx"> 
</span><span class="cx"> PASS parseThenSerializeRule(':lang(a) { }') is ':lang(a) { }'
</span><span class="lines">@@ -324,7 +318,6 @@
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-foo-col\\6Fr) { }') is ':lang(*-foo-color) { }'
</span><span class="cx"> 
</span><span class="cx"> PASS parseThenSerializeRule(':lang(\\*    ) { }') is ':lang(*) { }'
</span><del>-PASS parseThenSerializeRule(':lang(*-    ) { }') is ':lang(*-) { }'
</del><span class="cx"> PASS parseThenSerializeRule(':lang(*-en    ) { }') is ':lang(*-en) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-en-\\*    ) { }') is ':lang(*-en-*) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-en-\\*-fr    ) { }') is ':lang(*-en-*-fr) { }'
</span><span class="lines">@@ -360,13 +353,6 @@
</span><span class="cx"> PASS parseThenSerializeRule(':lang(   \\*  ,  id-\\*-sumatra  ) { }') is ':lang(*, id-*-sumatra) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(   \\*   ,    id-\\*-sumatra  ) { }') is ':lang(*, id-*-sumatra) { }'
</span><span class="cx"> 
</span><del>-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) { }'
-
</del><span class="cx"> PASS parseThenSerializeRule(':lang(en-\\*) { }') is ':lang(en-*) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(en-\\*, fr-\\*) { }') is ':lang(en-*, fr-*) { }'
</span><span class="cx"> PASS parseThenSerializeRule(':lang(en-\\*, fr-\\* ) { }') is ':lang(en-*, fr-*) { }'
</span><span class="lines">@@ -396,17 +382,22 @@
</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><del>-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').
</del><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(*----) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*)' { }) threw exception SyntaxError: Unexpected token '{'. Expected ')' to end a argument list..
+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').
</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(de-*)') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-en-*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-en-fr-*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-en-*fr) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-*en-fr) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><del>-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').
</del><ins>+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').
</ins><span class="cx"> PASS parseThenSerializeRule(':lang(*a*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*a) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(a*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="lines">@@ -417,6 +408,11 @@
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*- a*) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-a, br fr) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><span class="cx"> PASS parseThenSerializeRule(':lang(*-a, br fr en *) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
</span><ins>+PASS parseThenSerializeRule(':lang(*-1996, *-1997) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(*-1996, *-1997 ) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(   *-1996   ,  *-1997   ) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(   *-1996   ,*-1997   ) { }') threw exception TypeError: undefined is not an object (evaluating 'styleElement.sheet.cssRules[0].cssText').
+PASS parseThenSerializeRule(':lang(   *-1996,*-1997   ) { }') 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 (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/css-selector-text.html        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/LayoutTests/fast/css/css-selector-text.html        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -80,16 +80,8 @@
</span><span class="cx"> 
</span><span class="cx"> debug('');
</span><span class="cx"> 
</span><del>-testSelectorRoundTrip(&quot;:lang(*-)&quot;);
-testSelectorRoundTrip(&quot;:lang(*--)&quot;);
-testSelectorRoundTrip(&quot;:lang(*---)&quot;);
-testSelectorRoundTrip(&quot;:lang(*----)&quot;);
-
-debug('');
-
</del><span class="cx"> testSelectorRoundTrip(&quot;:lang(*-ab)&quot;);
</span><span class="cx"> testSelectorRoundTrip(&quot;:lang(*-ab-)&quot;);
</span><del>-testSelectorRoundTrip(&quot;:lang(*-1996)&quot;);
</del><span class="cx"> testSelectorRoundTrip(&quot;:lang(*-DE-1996)&quot;);
</span><span class="cx"> 
</span><span class="cx"> debug('');
</span><span class="lines">@@ -417,7 +409,6 @@
</span><span class="cx"> debug('');
</span><span class="cx"> 
</span><span class="cx"> shouldBe(&quot;parseThenSerializeRule(':lang(\\\\*    ) { }')&quot;, &quot;':lang(*) { }'&quot;);
</span><del>-shouldBe(&quot;parseThenSerializeRule(':lang(*-    ) { }')&quot;, &quot;':lang(*-) { }'&quot;);
</del><span class="cx"> shouldBe(&quot;parseThenSerializeRule(':lang(*-en    ) { }')&quot;, &quot;':lang(*-en) { }'&quot;);
</span><span class="cx"> shouldBe(&quot;parseThenSerializeRule(':lang(*-en-\\\\*    ) { }')&quot;, &quot;':lang(*-en-*) { }'&quot;);
</span><span class="cx"> shouldBe(&quot;parseThenSerializeRule(':lang(*-en-\\\\*-fr    ) { }')&quot;, &quot;':lang(*-en-*-fr) { }'&quot;);
</span><span class="lines">@@ -461,15 +452,6 @@
</span><span class="cx"> 
</span><span class="cx"> debug('');
</span><span class="cx"> 
</span><del>-shouldBe(&quot;parseThenSerializeRule(':lang(*-1996) { }')&quot;, &quot;':lang(*-1996) { }'&quot;);
-shouldBe(&quot;parseThenSerializeRule(':lang(*-1996, *-1997) { }')&quot;, &quot;':lang(*-1996, *-1997) { }'&quot;);
-shouldBe(&quot;parseThenSerializeRule(':lang(*-1996, *-1997 ) { }')&quot;, &quot;':lang(*-1996, *-1997) { }'&quot;);
-shouldBe(&quot;parseThenSerializeRule(':lang(   *-1996   ,  *-1997   ) { }')&quot;, &quot;':lang(*-1996, *-1997) { }'&quot;);
-shouldBe(&quot;parseThenSerializeRule(':lang(   *-1996   ,*-1997   ) { }')&quot;, &quot;':lang(*-1996, *-1997) { }'&quot;);
-shouldBe(&quot;parseThenSerializeRule(':lang(   *-1996,*-1997   ) { }')&quot;, &quot;':lang(*-1996, *-1997) { }'&quot;);
-
-debug('');
-
</del><span class="cx"> shouldBe(&quot;parseThenSerializeRule(':lang(en-\\\\*) { }')&quot;, &quot;':lang(en-*) { }'&quot;);
</span><span class="cx"> shouldBe(&quot;parseThenSerializeRule(':lang(en-\\\\*, fr-\\\\*) { }')&quot;, &quot;':lang(en-*, fr-*) { }'&quot;);
</span><span class="cx"> shouldBe(&quot;parseThenSerializeRule(':lang(en-\\\\*, fr-\\\\* ) { }')&quot;, &quot;':lang(en-*, fr-*) { }'&quot;);
</span><span class="lines">@@ -502,17 +484,23 @@
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang([]) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(@media screen {}) { }')&quot;);
</span><span class="cx"> 
</span><del>-shouldThrow(&quot;parseThenSerializeRule(':lang(*)')&quot;);
-shouldThrow(&quot;parseThenSerializeRule(':lang(**)')&quot;);
-shouldThrow(&quot;parseThenSerializeRule(':lang(-*-)')&quot;);
</del><ins>+shouldThrow(&quot;parseThenSerializeRule(':lang(*-) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(*-    ) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(*--) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(*---) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(*----) { }')&quot;);
+
+shouldThrow(&quot;parseThenSerializeRule(':lang(*)' { })&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(**) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(-*-) { }')&quot;);
</ins><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*-*) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(de-*)')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*-en-*) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*-en-fr-*) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*-en-*fr) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*-*en-fr) { }')&quot;);
</span><del>-shouldThrow(&quot;parseThenSerializeRule(':lang(*-1997)')&quot;);
-shouldThrow(&quot;parseThenSerializeRule(':lang(*-1997-*)')&quot;);
</del><ins>+shouldThrow(&quot;parseThenSerializeRule(':lang(*-1997) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(*-1997-*) { }')&quot;);
</ins><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*a*) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*a) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(a*) { }')&quot;);
</span><span class="lines">@@ -524,6 +512,12 @@
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*-a, br fr) { }')&quot;);
</span><span class="cx"> shouldThrow(&quot;parseThenSerializeRule(':lang(*-a, br fr en *) { }')&quot;);
</span><span class="cx"> 
</span><ins>+shouldThrow(&quot;parseThenSerializeRule(':lang(*-1996, *-1997) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(*-1996, *-1997 ) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(   *-1996   ,  *-1997   ) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(   *-1996   ,*-1997   ) { }')&quot;);
+shouldThrow(&quot;parseThenSerializeRule(':lang(   *-1996,*-1997   ) { }')&quot;);
+
</ins><span class="cx"> debug('');
</span><span class="cx"> 
</span><span class="cx"> testSelectorRoundTrip(&quot;:role(a)&quot;);
</span></span></pre></div>
<a id="trunkLayoutTestsfastcssparsingcsslangexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/LayoutTests/fast/css/parsing-css-lang-expected.txt        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -124,30 +124,6 @@
</span><span class="cx"> PASS document.querySelector(&quot;:lang(rm-CH    )&quot;) did not throw exception.
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules.length is 1
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(rm-CH)&quot;
</span><del>-PASS document.querySelector(&quot;:lang(*-)&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*-)&quot;
-PASS document.querySelector(&quot;:lang(*-    )&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*-)&quot;
-PASS document.querySelector(&quot;:lang(*--)&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*--)&quot;
-PASS document.querySelector(&quot;:lang(*--    )&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*--)&quot;
-PASS document.querySelector(&quot;:lang(*---)&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*---)&quot;
-PASS document.querySelector(&quot;:lang(*---    )&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*---)&quot;
-PASS document.querySelector(&quot;:lang(*----)&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*----)&quot;
-PASS document.querySelector(&quot;:lang(*----    )&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*----)&quot;
</del><span class="cx"> PASS document.querySelector(&quot;:lang(*-CH)&quot;) did not throw exception.
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules.length is 1
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*-CH)&quot;
</span><span class="lines">@@ -160,12 +136,6 @@
</span><span class="cx"> PASS document.querySelector(&quot;:lang(*-DE-1996    )&quot;) did not throw exception.
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules.length is 1
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*-DE-1996)&quot;
</span><del>-PASS document.querySelector(&quot;:lang(*-1996)&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*-1996)&quot;
-PASS document.querySelector(&quot;:lang(*-1996    )&quot;) did not throw exception.
-PASS document.getElementById('style-container').sheet.cssRules.length is 1
-PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*-1996)&quot;
</del><span class="cx"> PASS document.querySelector(&quot;:lang(*-br-zh)&quot;) did not throw exception.
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules.length is 1
</span><span class="cx"> PASS document.getElementById('style-container').sheet.cssRules[0].selectorText is &quot;:lang(*-br-zh)&quot;
</span></span></pre></div>
<a id="trunkLayoutTestsfastcssparsingcsslanghtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/css/parsing-css-lang.html (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/css/parsing-css-lang.html        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/LayoutTests/fast/css/parsing-css-lang.html        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -46,14 +46,8 @@
</span><span class="cx">     &quot;fr-CH&quot;, 
</span><span class="cx">     &quot;rm-CH&quot;,
</span><span class="cx"> 
</span><del>-    &quot;*-&quot;,
-    &quot;*--&quot;,
-    &quot;*---&quot;,
-    &quot;*----&quot;,
-
</del><span class="cx">     &quot;*-CH&quot;,
</span><span class="cx">     &quot;*-DE-1996&quot;,
</span><del>-    &quot;*-1996&quot;,
</del><span class="cx">     &quot;*-br-zh&quot;,
</span><span class="cx">     &quot;id-\\*-sumatra&quot;,
</span><span class="cx">     &quot;*-en-\\*-fr&quot;,
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/Source/WebCore/ChangeLog        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2014-12-08  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Fix the parsing of advanced :lang() after r176902
+        https://bugs.webkit.org/show_bug.cgi?id=139379
+
+        Reviewed by Andreas Kling.
+
+        There were two mistakes that were only caught in debug:
+
+        The lexer was not calling isIdentifierStart() before parseIdentifier().
+        Some identifier we were parsing should have been invalid.
+        This was caught with an assertion in parseIdentifier().
+
+        The other issue is that we were accumulating pointer to freed memory.
+        The tokenizer for LANGRANGE was creating a new string with a StringBuilder.
+        The problem is that CSSParserString does not keep the source string alive.
+        Consequently, the list of language range was accumulating pointers to dead
+        StringImpls.
+
+        The fix there is to simply extend the token to take the original asterisk character
+        from the input. That is not elegant but that's efficient and we know
+        the buffer lifetime.
+
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::realLex):
+        * css/CSSGrammar.y.in: Fix the indentation of a language range rule.
+
</ins><span class="cx"> 2014-12-08  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Try to fix the 32-bit build.
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSGrammaryin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSGrammar.y.in (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSGrammar.y.in        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/Source/WebCore/css/CSSGrammar.y.in        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -1395,12 +1395,12 @@
</span><span class="cx">     | ':' LANGFUNCTION maybe_space comma_separated_lang_ranges maybe_space ')' {
</span><span class="cx">         $$ = nullptr;
</span><span class="cx">         if ($4) {
</span><del>-          auto selector = std::make_unique&lt;CSSParserSelector&gt;();
-          selector-&gt;setMatch(CSSSelector::PseudoClass);
-          selector-&gt;setArgumentList(*std::unique_ptr&lt;Vector&lt;CSSParserString&gt;&gt;($4));
-          selector-&gt;setPseudoClassValue($2);
-          if (selector-&gt;pseudoClassType() == CSSSelector::PseudoClassLang)
-              $$ = selector.release();
</del><ins>+            auto selector = std::make_unique&lt;CSSParserSelector&gt;();
+            selector-&gt;setMatch(CSSSelector::PseudoClass);
+            selector-&gt;setArgumentList(*std::unique_ptr&lt;Vector&lt;CSSParserString&gt;&gt;($4));
+            selector-&gt;setPseudoClassValue($2);
+            if (selector-&gt;pseudoClassType() == CSSSelector::PseudoClassLang)
+                $$ = selector.release();
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorecssCSSParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/CSSParser.cpp (176982 => 176983)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/CSSParser.cpp        2014-12-08 23:34:03 UTC (rev 176982)
+++ trunk/Source/WebCore/css/CSSParser.cpp        2014-12-08 23:55:04 UTC (rev 176983)
</span><span class="lines">@@ -11487,18 +11487,16 @@
</span><span class="cx">             ++currentCharacter&lt;SrcCharacterType&gt;();
</span><span class="cx">             m_token = CONTAINS;
</span><span class="cx"> #if ENABLE(CSS_SELECTORS_LEVEL4)
</span><del>-        } else if (*currentCharacter&lt;SrcCharacterType&gt;() == '-') {
</del><ins>+        } else if (*currentCharacter&lt;SrcCharacterType&gt;() == '-' &amp;&amp; isIdentifierStart&lt;SrcCharacterType&gt;()) {
</ins><span class="cx">             result = currentCharacter&lt;SrcCharacterType&gt;();
</span><span class="cx"> 
</span><span class="cx">             CSSParserString parsedIdentifier;
</span><span class="cx">             parseIdentifier(result, parsedIdentifier, hasEscape);
</span><span class="cx"> 
</span><del>-            StringBuilder parsedLangRange;
-            parsedLangRange.append('*');
-            parsedLangRange.append(parsedIdentifier);
-
-            m_token = LANGRANGE;
-            yylval-&gt;string.init(parsedLangRange.toString());
</del><ins>+            if (parsedIdentifier.length()) {
+                m_token = LANGRANGE;
+                yylval-&gt;string.init(tokenStart&lt;SrcCharacterType&gt;(), parsedIdentifier.length() + 1);
+            }
</ins><span class="cx"> #endif
</span><span class="cx">         }
</span><span class="cx">         break;
</span></span></pre>
</div>
</div>

</body>
</html>