<!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>[181973] 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/181973">181973</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2015-03-25 14:33:59 -0700 (Wed, 25 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>ES6: Classes: Program level class statement throws exception in strict mode
https://bugs.webkit.org/show_bug.cgi?id=143038

Reviewed by Ryosuke Niwa.

Source/JavaScriptCore:

Classes expose a name to the current lexical environment. This treats
&quot;class X {}&quot; like &quot;var X = class X {}&quot;. Ideally it would be &quot;let X = class X {}&quot;.
Also, improve error messages for class statements where the class is missing a name.

* parser/Parser.h:
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseClass):
Fill name in info parameter if needed. Better error message if name is needed and missing.

(JSC::Parser&lt;LexerType&gt;::parseClassDeclaration):
Pass info parameter to get name, and expose the name as a variable name.

(JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
Pass info parameter that is ignored.

* parser/ParserFunctionInfo.h:
Add a parser info for class, to extract the name.

LayoutTests:

This updates a number of existing tests that were relying on
poor behavior. `shouldBe` and friends use eval within a function
not at the global scope. This means `shouldBe('class X { ... }')`
behaves like `shouldBe('var x = ...')` not `shouldBe('x = ...')`.
This means `x` will not be available in the next `shouldBe` call.

Add a test specifically to cover the scoping of the class name
in regular and strict mode code. Currently we treat it like var
with one failing test that would pass when we treat it like let.

* js/class-syntax-name.html: Added.
* js/script-tests/class-syntax-name.js: Added.
(runTestShouldBe):
(runTestShouldBeTrue):
(runTestShouldThrow):
(runTestShouldNotThrow):
Test class name scoping.

* js/class-syntax-call-expected.txt:
* js/class-syntax-declaration-expected.txt:
* js/class-syntax-default-constructor-expected.txt:
* js/class-syntax-name-expected.txt: Added.
* js/script-tests/class-syntax-call.js:
* js/script-tests/class-syntax-declaration.js:
* js/script-tests/class-syntax-default-constructor.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxcallexpectedtxt">trunk/LayoutTests/js/class-syntax-call-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxdeclarationexpectedtxt">trunk/LayoutTests/js/class-syntax-declaration-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxdefaultconstructorexpectedtxt">trunk/LayoutTests/js/class-syntax-default-constructor-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsclasssyntaxcalljs">trunk/LayoutTests/js/script-tests/class-syntax-call.js</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsclasssyntaxdeclarationjs">trunk/LayoutTests/js/script-tests/class-syntax-declaration.js</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsclasssyntaxdefaultconstructorjs">trunk/LayoutTests/js/script-tests/class-syntax-default-constructor.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserFunctionInfoh">trunk/Source/JavaScriptCore/parser/ParserFunctionInfo.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsclasssyntaxnameexpectedtxt">trunk/LayoutTests/js/class-syntax-name-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxnamehtml">trunk/LayoutTests/js/class-syntax-name.html</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsclasssyntaxnamejs">trunk/LayoutTests/js/script-tests/class-syntax-name.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/LayoutTests/ChangeLog        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2015-03-25  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        ES6: Classes: Program level class statement throws exception in strict mode
+        https://bugs.webkit.org/show_bug.cgi?id=143038
+
+        Reviewed by Ryosuke Niwa.
+
+        This updates a number of existing tests that were relying on
+        poor behavior. `shouldBe` and friends use eval within a function
+        not at the global scope. This means `shouldBe('class X { ... }')`
+        behaves like `shouldBe('var x = ...')` not `shouldBe('x = ...')`.
+        This means `x` will not be available in the next `shouldBe` call.
+
+        Add a test specifically to cover the scoping of the class name
+        in regular and strict mode code. Currently we treat it like var
+        with one failing test that would pass when we treat it like let.
+
+        * js/class-syntax-name.html: Added.
+        * js/script-tests/class-syntax-name.js: Added.
+        (runTestShouldBe):
+        (runTestShouldBeTrue):
+        (runTestShouldThrow):
+        (runTestShouldNotThrow):
+        Test class name scoping.
+
+        * js/class-syntax-call-expected.txt:
+        * js/class-syntax-declaration-expected.txt:
+        * js/class-syntax-default-constructor-expected.txt:
+        * js/class-syntax-name-expected.txt: Added.
+        * js/script-tests/class-syntax-call.js:
+        * js/script-tests/class-syntax-declaration.js:
+        * js/script-tests/class-syntax-default-constructor.js:
+
</ins><span class="cx"> 2015-03-25  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Gardening: rebaseline after r181907.
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxcallexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/class-syntax-call-expected.txt (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-call-expected.txt        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/LayoutTests/js/class-syntax-call-expected.txt        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -3,9 +3,9 @@
</span><span class="cx"> On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-PASS class A { constructor() {} }; new A did not throw exception.
</del><ins>+PASS new A did not throw exception.
</ins><span class="cx"> PASS A() threw exception TypeError: Cannot call a class constructor.
</span><del>-PASS class B extends A { constructor() { super() } }; new B did not throw exception.
</del><ins>+PASS new B did not throw exception.
</ins><span class="cx"> PASS B() threw exception TypeError: Cannot call a class constructor.
</span><span class="cx"> PASS new (class { constructor() {} })() did not throw exception.
</span><span class="cx"> PASS (class { constructor() {} })() threw exception TypeError: Cannot call a class constructor.
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxdeclarationexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/class-syntax-declaration-expected.txt (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-declaration-expected.txt        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/LayoutTests/js/class-syntax-declaration-expected.txt        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -16,15 +16,17 @@
</span><span class="cx"> PASS (new A).__proto__ is A.prototype
</span><span class="cx"> PASS A.prototype.constructor is A
</span><span class="cx"> PASS class threw exception SyntaxError: Unexpected end of script.
</span><ins>+PASS class [ threw exception SyntaxError: Unexpected token '['.
+PASS class { threw exception SyntaxError: Class statements must have a name..
</ins><span class="cx"> PASS class X { threw exception SyntaxError: Unexpected end of script.
</span><span class="cx"> PASS class X { ( } threw exception SyntaxError: Unexpected token '('. Expected an identifier..
</span><span class="cx"> PASS class X {} did not throw exception.
</span><span class="cx"> PASS class X { constructor() {} constructor() {} } threw exception SyntaxError: Cannot declare multiple constructors in a single class..
</span><span class="cx"> PASS class X { constructor() {} static constructor() { return staticMethodValue; } } did not throw exception.
</span><del>-PASS X.constructor() is staticMethodValue
</del><ins>+PASS class X { constructor() {} static constructor() { return staticMethodValue; } }; X.constructor() is staticMethodValue
</ins><span class="cx"> PASS class X { constructor() {} static prototype() {} } threw exception SyntaxError: Cannot declare a static method named 'prototype'..
</span><span class="cx"> PASS class X { constructor() {} prototype() { return instanceMethodValue; } } did not throw exception.
</span><del>-PASS (new X).prototype() is instanceMethodValue
</del><ins>+PASS class X { constructor() {} prototype() { return instanceMethodValue; } }; (new X).prototype() is instanceMethodValue
</ins><span class="cx"> PASS class X { constructor() {} set foo(a) {} } did not throw exception.
</span><span class="cx"> PASS class X { constructor() {} set foo({x, y}) {} } did not throw exception.
</span><span class="cx"> PASS class X { constructor() {} set foo() {} } threw exception SyntaxError: Unexpected token ')'. setter functions must have one parameter..
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxdefaultconstructorexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/class-syntax-default-constructor-expected.txt (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-default-constructor-expected.txt        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/LayoutTests/js/class-syntax-default-constructor-expected.txt        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -3,11 +3,11 @@
</span><span class="cx"> On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-PASS class A { }; new A instanceof A is true
</del><ins>+PASS new A instanceof A is true
</ins><span class="cx"> PASS A() threw exception TypeError: Cannot call a class constructor.
</span><span class="cx"> PASS A.prototype.constructor instanceof Function is true
</span><span class="cx"> PASS A.prototype.constructor.name is &quot;A&quot;
</span><del>-PASS class B extends A { }; new B instanceof A; new B instanceof A is true
</del><ins>+PASS new B instanceof A; new B instanceof A is true
</ins><span class="cx"> PASS B() threw exception TypeError: Cannot call a class constructor.
</span><span class="cx"> PASS B.prototype.constructor.name is &quot;B&quot;
</span><span class="cx"> PASS A !== B is true
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxnameexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-name-expected.txt (0 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-name-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-name-expected.txt        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -0,0 +1,122 @@
</span><ins>+Tests for ES6 class name semantics in class statements and expressions
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+Class statement
+PASS A threw exception ReferenceError: Can't find variable: A.
+PASS 'use strict'; A threw exception ReferenceError: Can't find variable: A.
+PASS class {} threw exception SyntaxError: Class statements must have a name..
+PASS 'use strict'; class {} threw exception SyntaxError: Class statements must have a name..
+PASS class { constructor() {} } threw exception SyntaxError: Class statements must have a name..
+PASS 'use strict'; class { constructor() {} } threw exception SyntaxError: Class statements must have a name..
+PASS class A { constructor() {} } did not throw exception.
+PASS 'use strict'; class A { constructor() {} } did not throw exception.
+PASS class A { constructor() {} }; A.toString() is 'function A() {}'
+PASS 'use strict'; class A { constructor() {} }; A.toString() is 'function A() {}'
+PASS class A { constructor() {} }; (new A) instanceof A is true
+PASS 'use strict'; class A { constructor() {} }; (new A) instanceof A is true
+PASS class A { constructor() { this.base = A; } }; (new A).base.toString() is 'function A() { this.base = A; }'
+PASS 'use strict'; class A { constructor() { this.base = A; } }; (new A).base.toString() is 'function A() { this.base = A; }'
+PASS class A { constructor() {} }; class B extends A {}; did not throw exception.
+PASS 'use strict'; class A { constructor() {} }; class B extends A {}; did not throw exception.
+PASS class A { constructor() {} }; class B extends A { constructor() {} }; B.toString() is 'function B() {}'
+PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() {} }; B.toString() is 'function B() {}'
+PASS class A { constructor() {} }; class B extends A {}; (new B) instanceof A is true
+PASS 'use strict'; class A { constructor() {} }; class B extends A {}; (new B) instanceof A is true
+PASS class A { constructor() {} }; class B extends A {}; (new B) instanceof B is true
+PASS 'use strict'; class A { constructor() {} }; class B extends A {}; (new B) instanceof B is true
+PASS class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString() is 'function A() {}'
+PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString() is 'function A() {}'
+PASS class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString() is 'function B() { super(); this.base = A; this.derived = B; }'
+PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString() is 'function B() { super(); this.base = A; this.derived = B; }'
+
+Class expression
+PASS A threw exception ReferenceError: Can't find variable: A.
+PASS 'use strict'; A threw exception ReferenceError: Can't find variable: A.
+PASS (class {}) did not throw exception.
+PASS 'use strict'; (class {}) did not throw exception.
+PASS (class { constructor(){} }) did not throw exception.
+PASS 'use strict'; (class { constructor(){} }) did not throw exception.
+PASS typeof (class {}) is &quot;function&quot;
+PASS 'use strict'; typeof (class {}) is &quot;function&quot;
+PASS (class A {}) did not throw exception.
+PASS 'use strict'; (class A {}) did not throw exception.
+PASS typeof (class A {}) is &quot;function&quot;
+PASS 'use strict'; typeof (class A {}) is &quot;function&quot;
+PASS (class A {}); A threw exception ReferenceError: Can't find variable: A.
+PASS 'use strict'; (class A {}); A threw exception ReferenceError: Can't find variable: A.
+PASS new (class A {}) did not throw exception.
+PASS 'use strict'; new (class A {}) did not throw exception.
+PASS typeof (new (class A {})) is &quot;object&quot;
+PASS 'use strict'; typeof (new (class A {})) is &quot;object&quot;
+PASS (new (class A { constructor() { this.base = A; } })).base did not throw exception.
+PASS 'use strict'; (new (class A { constructor() { this.base = A; } })).base did not throw exception.
+PASS (new (class A { constructor() { this.base = A; } })).base.toString() is &quot;function A() { this.base = A; }&quot;
+PASS 'use strict'; (new (class A { constructor() { this.base = A; } })).base.toString() is &quot;function A() { this.base = A; }&quot;
+PASS class A {}; (class B extends A {}) did not throw exception.
+PASS 'use strict'; class A {}; (class B extends A {}) did not throw exception.
+PASS class A {}; (class B extends A {}); B threw exception ReferenceError: Can't find variable: B.
+PASS 'use strict'; class A {}; (class B extends A {}); B threw exception ReferenceError: Can't find variable: B.
+PASS class A {}; new (class B extends A {}) did not throw exception.
+PASS 'use strict'; class A {}; new (class B extends A {}) did not throw exception.
+PASS class A {}; new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } }) did not throw exception.
+PASS 'use strict'; class A {}; new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } }) did not throw exception.
+PASS class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A is true
+PASS 'use strict'; class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A is true
+PASS class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString() is 'function A() {}'
+PASS 'use strict'; class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString() is 'function A() {}'
+PASS class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString() is 'function B() { super(); this.base = A; this.derived = B; }'
+PASS 'use strict'; class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString() is 'function B() { super(); this.base = A; this.derived = B; }'
+
+Class expression assignment to variable
+PASS A threw exception ReferenceError: Can't find variable: A.
+PASS 'use strict'; A threw exception ReferenceError: Can't find variable: A.
+PASS var VarA = class {} did not throw exception.
+PASS 'use strict'; var VarA = class {} did not throw exception.
+PASS var VarA = class { constructor() {} }; VarA.toString() is 'function () {}'
+PASS 'use strict'; var VarA = class { constructor() {} }; VarA.toString() is 'function () {}'
+PASS VarA threw exception ReferenceError: Can't find variable: VarA.
+PASS 'use strict'; VarA threw exception ReferenceError: Can't find variable: VarA.
+PASS var VarA = class A { constructor() {} } did not throw exception.
+PASS 'use strict'; var VarA = class A { constructor() {} } did not throw exception.
+PASS var VarA = class A { constructor() {} }; VarA.toString() is 'function A() {}'
+PASS 'use strict'; var VarA = class A { constructor() {} }; VarA.toString() is 'function A() {}'
+PASS var VarA = class A { constructor() {} }; A.toString() threw exception ReferenceError: Can't find variable: A.
+PASS 'use strict'; var VarA = class A { constructor() {} }; A.toString() threw exception ReferenceError: Can't find variable: A.
+PASS var VarA = class A { constructor() {} }; (new VarA) instanceof VarA is true
+PASS 'use strict'; var VarA = class A { constructor() {} }; (new VarA) instanceof VarA is true
+PASS var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString() is 'function A() { this.base = A; }'
+PASS 'use strict'; var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString() is 'function A() { this.base = A; }'
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; did not throw exception.
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; did not throw exception.
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B threw exception ReferenceError: Can't find variable: B.
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B threw exception ReferenceError: Can't find variable: B.
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString() is 'function B() {}'
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString() is 'function B() {}'
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA is true
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA is true
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarB is true
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarB is true
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).base === VarA is true
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).base === VarA is true
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derived === VarB is true
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derived === VarB is true
+PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derivedVar === VarB is true
+PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derivedVar === VarB is true
+
+Class statement binding in other circumstances
+PASS var result = A; result threw exception ReferenceError: Can't find variable: A.
+PASS 'use strict'; var result = A; result threw exception ReferenceError: Can't find variable: A.
+FAIL var result = A; class A {}; result should throw an exception. Was undefined.
+FAIL 'use strict'; var result = A; class A {}; result should throw an exception. Was undefined.
+PASS class A {}; var result = A; result did not throw exception.
+PASS 'use strict'; class A {}; var result = A; result did not throw exception.
+PASS eval('var Foo = 10'); Foo is 10
+PASS 'use strict'; eval('var Foo = 10'); Foo threw exception ReferenceError: Can't find variable: Foo.
+PASS eval('class Bar { constructor() {} }'); Bar.toString() is 'function Bar() {}'
+PASS 'use strict'; eval('class Bar { constructor() {} }'); Bar.toString() threw exception ReferenceError: Can't find variable: Bar.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxnamehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-name.html (0 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-name.html                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-name.html        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;body&gt;
+&lt;script src=&quot;../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/class-syntax-name.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxcalljs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/class-syntax-call.js (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-call.js        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/LayoutTests/js/script-tests/class-syntax-call.js        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -1,8 +1,11 @@
</span><span class="cx"> description('Tests for calling the constructors of ES6 classes');
</span><span class="cx"> 
</span><del>-shouldNotThrow('class A { constructor() {} }; new A');
</del><ins>+class A { constructor() {} };
+class B extends A { constructor() { super() } };
+
+shouldNotThrow('new A');
</ins><span class="cx"> shouldThrow('A()', '&quot;TypeError: Cannot call a class constructor&quot;');
</span><del>-shouldNotThrow('class B extends A { constructor() { super() } }; new B');
</del><ins>+shouldNotThrow('new B');
</ins><span class="cx"> shouldThrow('B()', '&quot;TypeError: Cannot call a class constructor&quot;');
</span><span class="cx"> shouldNotThrow('new (class { constructor() {} })()');
</span><span class="cx"> shouldThrow('(class { constructor() {} })()', '&quot;TypeError: Cannot call a class constructor&quot;');
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxdeclarationjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/class-syntax-declaration.js (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-declaration.js        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/LayoutTests/js/script-tests/class-syntax-declaration.js        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -28,15 +28,17 @@
</span><span class="cx"> shouldBe(&quot;A.prototype.constructor&quot;, &quot;A&quot;);
</span><span class="cx"> 
</span><span class="cx"> shouldThrow(&quot;class&quot;, &quot;'SyntaxError: Unexpected end of script'&quot;);
</span><ins>+shouldThrow(&quot;class [&quot;, &quot;'SyntaxError: Unexpected token \\'[\\''&quot;);
+shouldThrow(&quot;class {&quot;, &quot;'SyntaxError: Class statements must have a name.'&quot;);
</ins><span class="cx"> shouldThrow(&quot;class X {&quot;, &quot;'SyntaxError: Unexpected end of script'&quot;);
</span><span class="cx"> shouldThrow(&quot;class X { ( }&quot;, &quot;'SyntaxError: Unexpected token \\'(\\'. Expected an identifier.'&quot;);
</span><span class="cx"> shouldNotThrow(&quot;class X {}&quot;);
</span><span class="cx"> shouldThrow(&quot;class X { constructor() {} constructor() {} }&quot;, &quot;'SyntaxError: Cannot declare multiple constructors in a single class.'&quot;);
</span><span class="cx"> shouldNotThrow(&quot;class X { constructor() {} static constructor() { return staticMethodValue; } }&quot;);
</span><del>-shouldBe(&quot;X.constructor()&quot;, &quot;staticMethodValue&quot;);
</del><ins>+shouldBe(&quot;class X { constructor() {} static constructor() { return staticMethodValue; } }; X.constructor()&quot;, &quot;staticMethodValue&quot;);
</ins><span class="cx"> shouldThrow(&quot;class X { constructor() {} static prototype() {} }&quot;, &quot;'SyntaxError: Cannot declare a static method named \\'prototype\\'.'&quot;);
</span><span class="cx"> shouldNotThrow(&quot;class X { constructor() {} prototype() { return instanceMethodValue; } }&quot;);
</span><del>-shouldBe(&quot;(new X).prototype()&quot;, &quot;instanceMethodValue&quot;);
</del><ins>+shouldBe(&quot;class X { constructor() {} prototype() { return instanceMethodValue; } }; (new X).prototype()&quot;, &quot;instanceMethodValue&quot;);
</ins><span class="cx"> 
</span><span class="cx"> shouldNotThrow(&quot;class X { constructor() {} set foo(a) {} }&quot;);
</span><span class="cx"> shouldNotThrow(&quot;class X { constructor() {} set foo({x, y}) {} }&quot;);
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxdefaultconstructorjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/class-syntax-default-constructor.js (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-default-constructor.js        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/LayoutTests/js/script-tests/class-syntax-default-constructor.js        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -1,11 +1,14 @@
</span><span class="cx"> 
</span><span class="cx"> description('Tests for ES6 class syntax default constructor');
</span><span class="cx"> 
</span><del>-shouldBeTrue('class A { }; new A instanceof A');
</del><ins>+class A { };
+class B extends A { };
+
+shouldBeTrue('new A instanceof A');
</ins><span class="cx"> shouldThrow('A()', '&quot;TypeError: Cannot call a class constructor&quot;');
</span><span class="cx"> shouldBeTrue('A.prototype.constructor instanceof Function');
</span><span class="cx"> shouldBe('A.prototype.constructor.name', '&quot;A&quot;');
</span><del>-shouldBeTrue('class B extends A { }; new B instanceof A; new B instanceof A');
</del><ins>+shouldBeTrue('new B instanceof A; new B instanceof A');
</ins><span class="cx"> shouldThrow('B()', '&quot;TypeError: Cannot call a class constructor&quot;');
</span><span class="cx"> shouldBe('B.prototype.constructor.name', '&quot;B&quot;');
</span><span class="cx"> shouldBeTrue('A !== B');
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxnamejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/class-syntax-name.js (0 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-name.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/class-syntax-name.js        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -0,0 +1,88 @@
</span><ins>+description('Tests for ES6 class name semantics in class statements and expressions');
+
+function runTestShouldBe(statement, result) {
+    shouldBe(statement, result);
+    shouldBe(&quot;'use strict'; &quot; + statement, result);
+}
+
+function runTestShouldBeTrue(statement) {
+    shouldBeTrue(statement);
+    shouldBeTrue(&quot;'use strict'; &quot; + statement);
+}
+
+function runTestShouldThrow(statement) {
+    shouldThrow(statement);
+    shouldThrow(&quot;'use strict'; &quot; + statement);
+}
+
+function runTestShouldNotThrow(statement) {
+    shouldNotThrow(statement);
+    shouldNotThrow(&quot;'use strict'; &quot; + statement);
+}
+
+// Class statement. Class name added to global scope. Class name is available inside class scope and in global scope.
+debug('Class statement');
+runTestShouldThrow(&quot;A&quot;);
+runTestShouldThrow(&quot;class {}&quot;);
+runTestShouldThrow(&quot;class { constructor() {} }&quot;);
+runTestShouldNotThrow(&quot;class A { constructor() {} }&quot;);
+runTestShouldBe(&quot;class A { constructor() {} }; A.toString()&quot;, &quot;'function A() {}'&quot;);
+runTestShouldBeTrue(&quot;class A { constructor() {} }; (new A) instanceof A&quot;);
+runTestShouldBe(&quot;class A { constructor() { this.base = A; } }; (new A).base.toString()&quot;, &quot;'function A() { this.base = A; }'&quot;);
+runTestShouldNotThrow(&quot;class A { constructor() {} }; class B extends A {};&quot;);
+runTestShouldBe(&quot;class A { constructor() {} }; class B extends A { constructor() {} }; B.toString()&quot;, &quot;'function B() {}'&quot;);
+runTestShouldBeTrue(&quot;class A { constructor() {} }; class B extends A {}; (new B) instanceof A&quot;);
+runTestShouldBeTrue(&quot;class A { constructor() {} }; class B extends A {}; (new B) instanceof B&quot;);
+runTestShouldBe(&quot;class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString()&quot;, &quot;'function A() {}'&quot;);
+runTestShouldBe(&quot;class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString()&quot;, &quot;'function B() { super(); this.base = A; this.derived = B; }'&quot;);
+
+// Class expression. Class name not added to scope. Class name is available inside class scope.
+debug(''); debug('Class expression');
+runTestShouldThrow(&quot;A&quot;);
+runTestShouldNotThrow(&quot;(class {})&quot;);
+runTestShouldNotThrow(&quot;(class { constructor(){} })&quot;);
+runTestShouldBe(&quot;typeof (class {})&quot;, '&quot;function&quot;');
+runTestShouldNotThrow(&quot;(class A {})&quot;);
+runTestShouldBe(&quot;typeof (class A {})&quot;, '&quot;function&quot;');
+runTestShouldThrow(&quot;(class A {}); A&quot;);
+runTestShouldNotThrow(&quot;new (class A {})&quot;);
+runTestShouldBe(&quot;typeof (new (class A {}))&quot;, '&quot;object&quot;');
+runTestShouldNotThrow(&quot;(new (class A { constructor() { this.base = A; } })).base&quot;);
+runTestShouldBe(&quot;(new (class A { constructor() { this.base = A; } })).base.toString()&quot;, '&quot;function A() { this.base = A; }&quot;');
+runTestShouldNotThrow(&quot;class A {}; (class B extends A {})&quot;);
+runTestShouldThrow(&quot;class A {}; (class B extends A {}); B&quot;);
+runTestShouldNotThrow(&quot;class A {}; new (class B extends A {})&quot;);
+runTestShouldNotThrow(&quot;class A {}; new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })&quot;);
+runTestShouldBeTrue(&quot;class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A&quot;);
+runTestShouldBe(&quot;class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString()&quot;, &quot;'function A() {}'&quot;);
+runTestShouldBe(&quot;class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString()&quot;, &quot;'function B() { super(); this.base = A; this.derived = B; }'&quot;);
+
+// Assignment of a class expression to a variable. Variable name available in scope, class name is not. Class name is available inside class scope.
+debug(''); debug('Class expression assignment to variable');
+runTestShouldThrow(&quot;A&quot;);
+runTestShouldNotThrow(&quot;var VarA = class {}&quot;);
+runTestShouldBe(&quot;var VarA = class { constructor() {} }; VarA.toString()&quot;, &quot;'function () {}'&quot;);
+runTestShouldThrow(&quot;VarA&quot;);
+runTestShouldNotThrow(&quot;var VarA = class A { constructor() {} }&quot;);
+runTestShouldBe(&quot;var VarA = class A { constructor() {} }; VarA.toString()&quot;, &quot;'function A() {}'&quot;);
+runTestShouldThrow(&quot;var VarA = class A { constructor() {} }; A.toString()&quot;);
+runTestShouldBeTrue(&quot;var VarA = class A { constructor() {} }; (new VarA) instanceof VarA&quot;);
+runTestShouldBe(&quot;var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString()&quot;, &quot;'function A() { this.base = A; }'&quot;);
+runTestShouldNotThrow(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} };&quot;);
+runTestShouldThrow(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B&quot;);
+runTestShouldBe(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString()&quot;, &quot;'function B() {}'&quot;);
+runTestShouldBeTrue(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA&quot;);
+runTestShouldBeTrue(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarB&quot;);
+runTestShouldBeTrue(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).base === VarA&quot;);
+runTestShouldBeTrue(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derived === VarB&quot;);
+runTestShouldBeTrue(&quot;var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() { super(); this.base = VarA; this.derived = B; this.derivedVar = VarB; } }; (new VarB).derivedVar === VarB&quot;);
+
+// FIXME: Class statement binding should be like `let`, not `var`.
+debug(''); debug('Class statement binding in other circumstances');
+runTestShouldThrow(&quot;var result = A; result&quot;);
+runTestShouldThrow(&quot;var result = A; class A {}; result&quot;);
+runTestShouldNotThrow(&quot;class A {}; var result = A; result&quot;);
+shouldBe(&quot;eval('var Foo = 10'); Foo&quot;, &quot;10&quot;);
+shouldThrow(&quot;'use strict'; eval('var Foo = 10'); Foo&quot;);
+shouldBe(&quot;eval('class Bar { constructor() {} }'); Bar.toString()&quot;, &quot;'function Bar() {}'&quot;);
+shouldThrow(&quot;'use strict'; eval('class Bar { constructor() {} }'); Bar.toString()&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2015-03-25  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        ES6: Classes: Program level class statement throws exception in strict mode
+        https://bugs.webkit.org/show_bug.cgi?id=143038
+
+        Reviewed by Ryosuke Niwa.
+
+        Classes expose a name to the current lexical environment. This treats
+        &quot;class X {}&quot; like &quot;var X = class X {}&quot;. Ideally it would be &quot;let X = class X {}&quot;.
+        Also, improve error messages for class statements where the class is missing a name.
+
+        * parser/Parser.h:
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseClass):
+        Fill name in info parameter if needed. Better error message if name is needed and missing.
+
+        (JSC::Parser&lt;LexerType&gt;::parseClassDeclaration):
+        Pass info parameter to get name, and expose the name as a variable name.
+
+        (JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
+        Pass info parameter that is ignored.
+
+        * parser/ParserFunctionInfo.h:
+        Add a parser info for class, to extract the name.
+
</ins><span class="cx"> 2015-03-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         New map and set modification tests in r181922 fails
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -1469,9 +1469,14 @@
</span><span class="cx">     JSTextPosition classStart = tokenStartPosition();
</span><span class="cx">     unsigned classStartLine = tokenLine();
</span><span class="cx"> 
</span><del>-    TreeClassExpression classExpr = parseClass(context, FunctionNeedsName);
</del><ins>+    ParserClassInfo&lt;TreeBuilder&gt; info;
+    TreeClassExpression classExpr = parseClass(context, FunctionNeedsName, info);
</ins><span class="cx">     failIfFalse(classExpr, &quot;Failed to parse class&quot;);
</span><ins>+    declareVariable(info.className);
</ins><span class="cx"> 
</span><ins>+    // FIXME: This should be like `let`, not `var`.
+    context.addVar(info.className, DeclarationStacks::HasInitializer);
+
</ins><span class="cx">     JSTextPosition classEnd = lastTokenEndPosition();
</span><span class="cx">     unsigned classEndLine = tokenLine();
</span><span class="cx"> 
</span><span class="lines">@@ -1479,7 +1484,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-template &lt;class TreeBuilder&gt; TreeClassExpression Parser&lt;LexerType&gt;::parseClass(TreeBuilder&amp; context, FunctionRequirements requirements)
</del><ins>+template &lt;class TreeBuilder&gt; TreeClassExpression Parser&lt;LexerType&gt;::parseClass(TreeBuilder&amp; context, FunctionRequirements requirements, ParserClassInfo&lt;TreeBuilder&gt;&amp; info)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(match(CLASSTOKEN));
</span><span class="cx">     JSTokenLocation location(tokenLocation());
</span><span class="lines">@@ -1491,9 +1496,12 @@
</span><span class="cx">     const Identifier* className = nullptr;
</span><span class="cx">     if (match(IDENT)) {
</span><span class="cx">         className = m_token.m_data.ident;
</span><ins>+        info.className = className;
</ins><span class="cx">         next();
</span><span class="cx">         failIfFalse(classScope-&gt;declareVariable(className), &quot;'&quot;, className-&gt;impl(), &quot;' is not a valid class name&quot;);
</span><span class="cx">     } else if (requirements == FunctionNeedsName) {
</span><ins>+        if (match(OPENBRACE))
+            semanticFail(&quot;Class statements must have a name&quot;);
</ins><span class="cx">         semanticFailureDueToKeyword(&quot;class name&quot;);
</span><span class="cx">         failDueToUnexpectedToken();
</span><span class="cx">     } else
</span><span class="lines">@@ -2263,8 +2271,10 @@
</span><span class="cx">         return context.createFunctionExpr(location, info);
</span><span class="cx">     }
</span><span class="cx"> #if ENABLE(ES6_CLASS_SYNTAX)
</span><del>-    case CLASSTOKEN:
-        return parseClass(context, FunctionNoRequirements);
</del><ins>+    case CLASSTOKEN: {
+        ParserClassInfo&lt;TreeBuilder&gt; info;
+        return parseClass(context, FunctionNoRequirements, info);
+    }
</ins><span class="cx"> #endif
</span><span class="cx">     case OPENBRACE:
</span><span class="cx">         if (strictMode())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -774,7 +774,7 @@
</span><span class="cx"> 
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE bool parseFunctionInfo(TreeBuilder&amp;, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, int functionKeywordStart, ParserFunctionInfo&lt;TreeBuilder&gt;&amp;);
</span><span class="cx"> #if ENABLE(ES6_CLASS_SYNTAX)
</span><del>-    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&amp;, FunctionRequirements);
</del><ins>+    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&amp;, FunctionRequirements, ParserClassInfo&lt;TreeBuilder&gt;&amp;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE int isBinaryOperator(JSTokenType);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserFunctionInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ParserFunctionInfo.h (181972 => 181973)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ParserFunctionInfo.h        2015-03-25 21:19:05 UTC (rev 181972)
+++ trunk/Source/JavaScriptCore/parser/ParserFunctionInfo.h        2015-03-25 21:33:59 UTC (rev 181973)
</span><span class="lines">@@ -40,6 +40,13 @@
</span><span class="cx">     unsigned bodyStartColumn = 0;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+#if ENABLE(ES6_CLASS_SYNTAX)
+template &lt;class TreeBuilder&gt;
+struct ParserClassInfo {
+    const Identifier* className = 0;
+};
+#endif
+
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre>
</div>
</div>

</body>
</html>