<!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>[181293] 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/181293">181293</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2015-03-09 16:47:06 -0700 (Mon, 09 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Support extends and super keywords
https://bugs.webkit.org/show_bug.cgi?id=142200

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Added the support for ES6 class syntax inheritance.

Added ConstructorKind as well as boolean flags indicating the constructor kind to
various classes in UnlinkedCodeBlock as well as AST nodes.

Each method stores the associated class as its homeObjectPrivateName. This value is used to
make super calls.

* bytecode/UnlinkedCodeBlock.cpp:
(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):

* bytecode/UnlinkedCodeBlock.h:
(JSC::ExecutableInfo::ExecutableInfo):
(JSC::UnlinkedFunctionExecutable::constructorKindIsDerived): Added.
(JSC::UnlinkedCodeBlock::constructorKindIsDerived): Added.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator): Don't emit op_create_this in a derived class
as the object is allocated by the highest base class's constructor. Also set &quot;this&quot; to null
and store the original value in m_newTargetRegister. &quot;this&quot; is supposed to be in TDZ but
that will be implemented in a separate patch.
(JSC::BytecodeGenerator::emitReturn): Allow &quot;undefined&quot; to be returned from a derived class.
In a derived class's constructor, not returning &quot;undefined&quot; or an object results in a type
error instead of &quot;this&quot; being returned.
(JSC::BytecodeGenerator::emitThrowTypeError): Added.

* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::constructorKindIsDerived): Added.
(JSC::BytecodeGenerator::newTarget): Added.

* bytecompiler/NodesCodegen.cpp:
(JSC::SuperNode::emitBytecode): Added. Emits the code to obtain the callee's parent class.
(JSC::emitSuperBaseForCallee): Added. Emits the code to obtain the parent class's prototype.
(JSC::emitPutHomeObject): Added.
(JSC::PropertyListNode::emitBytecode): Stores the home object when adding methods.
(JSC::PropertyListNode::emitPutConstantProperty): Ditto.
(JSC::BracketAccessorNode::emitBytecode): Added the support for super['foo'].
(JSC::DotAccessorNode::emitBytecode): Added the support for super.foo.
(JSC::FunctionCallValueNode::emitBytecode): Added the support for super().
(JSC::FunctionCallBracketNode::emitBytecode): Added the support for super['foo']().
(JSC::FunctionCallDotNode::emitBytecode): Added the support for super.foo().
(JSC::DeleteBracketNode::emitBytecode): Forbid &quot;delete super.foo&quot;.
(JSC::DeleteDotNode::emitBytecode): Forbid &quot;delete super['foo']&quot;.
(JSC::ClassExprNode::emitBytecode): Added the support for &quot;classHeritage&quot;. This is the main
logic for inheritance. When a class B inherits from a class A, set B.__proto__ to A and set
B.prototype.__proto__ to A.prototype. Throw exceptions when either A or A.__proto__ is not
an object.

* parser/ASTBuilder.h:
(JSC::ASTBuilder::superExpr): Added.

* parser/NodeConstructors.h:
(JSC::SuperNode::SuperNode): Added.

* parser/Nodes.cpp:
(JSC::FunctionBodyNode::FunctionBodyNode):

* parser/Nodes.h:
(JSC::ExpressionNode::isSuperNode):
(JSC::PropertyNode::type):
(JSC::PropertyNode::needsSuperBinding):

* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseFunctionBody):
(JSC::Parser&lt;LexerType&gt;::parseFunctionInfo): Throw a parser error if super() is used outside
of class constructors.
(JSC::Parser&lt;LexerType&gt;::parseFunctionDeclaration):
(JSC::Parser&lt;LexerType&gt;::parseClass): ConstructorKind is &quot;derived&quot; if and only if the parent
class is specified in the declaration / expression.
(JSC::Parser&lt;LexerType&gt;::parseGetterSetter):
(JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
(JSC::Parser&lt;LexerType&gt;::parseMemberExpression): Added the support for &quot;super()&quot;, &quot;super.foo&quot;,
and &quot;super['foo']&quot;. Throw a semantic error if &quot;super&quot; appears by itself.

* parser/Parser.h:
(JSC::Scope::Scope): Added m_hasDirectSuper. This variable keeps track of the use of &quot;super()&quot;
so that parseFunctionInfo can spit an error if it's used outside of class constructors.
(JSC::Scope::hasDirectSuper): Added.
(JSC::Scope::setHasDirectSuper): Added.

* parser/ParserModes.h:
(JSC::ConstructorKind): Added.

* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::superExpr): Added.

* runtime/CommonIdentifiers.h: Added homeObjectPrivateName.

* runtime/Executable.h:
(JSC::EvalExecutable::executableInfo): 
(JSC::ProgramExecutable::executableInfo):

LayoutTests:

Added tests for &quot;extends&quot; and &quot;super&quot; keywords.

* TestExpectations:
* js/class-syntax-extends-expected.txt: Added.
* js/class-syntax-extends.html: Added.
* js/class-syntax-super-expected.txt: Added.
* js/class-syntax-super.html: Added.
* js/script-tests/class-syntax-extends.js: Added.
* js/script-tests/class-syntax-super.js: Added.</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="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodeConstructorsh">trunk/Source/JavaScriptCore/parser/NodeConstructors.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodescpp">trunk/Source/JavaScriptCore/parser/Nodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodesh">trunk/Source/JavaScriptCore/parser/Nodes.h</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="#trunkSourceJavaScriptCoreparserParserModesh">trunk/Source/JavaScriptCore/parser/ParserModes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonIdentifiersh">trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeExecutableh">trunk/Source/JavaScriptCore/runtime/Executable.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsclasssyntaxextendsexpectedtxt">trunk/LayoutTests/js/class-syntax-extends-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxextendshtml">trunk/LayoutTests/js/class-syntax-extends.html</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxsuperexpectedtxt">trunk/LayoutTests/js/class-syntax-super-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxsuperhtml">trunk/LayoutTests/js/class-syntax-super.html</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsclasssyntaxextendsjs">trunk/LayoutTests/js/script-tests/class-syntax-extends.js</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsclasssyntaxsuperjs">trunk/LayoutTests/js/script-tests/class-syntax-super.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/LayoutTests/ChangeLog        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2015-03-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Support extends and super keywords
+        https://bugs.webkit.org/show_bug.cgi?id=142200
+
+        Reviewed by Filip Pizlo.
+
+        Added tests for &quot;extends&quot; and &quot;super&quot; keywords.
+
+        * TestExpectations:
+        * js/class-syntax-extends-expected.txt: Added.
+        * js/class-syntax-extends.html: Added.
+        * js/class-syntax-super-expected.txt: Added.
+        * js/class-syntax-super.html: Added.
+        * js/script-tests/class-syntax-extends.js: Added.
+        * js/script-tests/class-syntax-super.js: Added.
+
</ins><span class="cx"> 2015-03-09  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r176978): Inline-blocks with overflowing contents have ascents that are too large
</span></span></pre></div>
<a id="trunkLayoutTestsTestExpectations"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/TestExpectations (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/TestExpectations        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/LayoutTests/TestExpectations        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -69,6 +69,8 @@
</span><span class="cx"> # ES6 class syntax hasn't been enabled yet.
</span><span class="cx"> webkit.org/b/140491 js/class-syntax-declaration.html [ Failure ]
</span><span class="cx"> webkit.org/b/140491 js/class-syntax-expression.html [ Failure ]
</span><ins>+webkit.org/b/140491 js/class-syntax-extends.html [ Failure ]
+webkit.org/b/140491 js/class-syntax-super.html [ Failure ]
</ins><span class="cx"> 
</span><span class="cx"> # This test verifies dynamic manipulation of the mroot and msqrt elements.
</span><span class="cx"> mathml/roots-removeChild.html [ ImageOnlyFailure ]
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxextendsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-extends-expected.txt (0 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-extends-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-extends-expected.txt        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+Tests for ES6 class syntax &quot;extends&quot;
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS (new Base) instanceof Base is true
+PASS (new Derived) instanceof Derived is true
+PASS (new Derived).baseMethod() is &quot;base&quot;
+PASS (new Derived).overridenMethod() is &quot;derived&quot;
+PASS Derived.staticBaseMethod() is &quot;base&quot;
+PASS Derived.staticOverridenMethod() is &quot;derived&quot;
+PASS x = class extends threw exception SyntaxError: Unexpected end of script.
+PASS x = class extends threw exception SyntaxError: Unexpected end of script.
+PASS x = class extends Base { threw exception SyntaxError: Unexpected end of script.
+PASS x = class extends Base {} threw exception SyntaxError: Class declaration without a constructor is not supported yet..
+PASS x = class extends Base { constructor() { } } did not throw exception.
+PASS x.__proto__ is Base
+PASS x.prototype.__proto__ is Base.prototype
+PASS x = class extends null { constructor() { } }; x.__proto__ is Function.prototype
+PASS x.__proto__ is Function.prototype
+PASS x = class extends 3 { constructor() { } }; x.__proto__ threw exception TypeError: The superclass is not an object..
+PASS x = class extends &quot;abc&quot; { constructor() { } }; x.__proto__ threw exception TypeError: The superclass is not an object..
+baseWithBadPrototype = class { constructor() { } }; baseWithBadPrototype.prototype = 3
+PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
+baseWithBadPrototype.prototype = &quot;abc&quot;
+PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
+PASS baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } } did not throw exception.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxextendshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-extends.html (0 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-extends.html                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-extends.html        2015-03-09 23:47:06 UTC (rev 181293)
</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-extends.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="trunkLayoutTestsjsclasssyntaxsuperexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-super-expected.txt (0 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-super-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-super-expected.txt        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+Tests for ES6 class syntax &quot;super&quot;
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS (new Base) instanceof Base is true
+PASS (new Derived) instanceof Derived is true
+PASS (new Derived).callBaseMethod() is baseMethodValue
+PASS x = (new Derived).callBaseMethod; x() is baseMethodValue
+PASS (new Derived).callBaseMethodInGetter is baseMethodValue
+PASS (new Derived).callBaseMethodInSetter = 1; valueInSetter is baseMethodValue
+PASS (new Derived).baseMethodInGetterSetter is (new Base).baseMethod
+PASS (new Derived).baseMethodInGetterSetter = 1; valueInSetter is (new Base).baseMethod
+PASS Derived.staticMethod() is &quot;base3&quot;
+PASS (new SecondDerived).chainMethod() is [&quot;base&quot;, &quot;derived&quot;, &quot;secondDerived&quot;]
+PASS x = class extends Base { constructor() { super(); } super() {} } threw exception SyntaxError: Unexpected keyword 'super'. Expected an indentifier..
+PASS x = class extends Base { constructor() { super(); } method() { super() } } threw exception SyntaxError: Cannot call super() outside of a class constructor..
+PASS x = class extends Base { constructor() { super(); } method() { super } } threw exception SyntaxError: Cannot reference super..
+PASS x = class extends Base { constructor() { super(); } method() { return new super } } did not throw exception.
+PASS (new x).method() instanceof Base is true
+PASS (new x).method() instanceof x is false
+PASS x = class extends Base { constructor() { super(); } method1() { delete (super.foo) } method2() { delete super[&quot;foo&quot;] } } did not throw exception.
+PASS (new x).method1() threw exception ReferenceError: Cannot delete a super property.
+PASS (new x).method2() threw exception ReferenceError: Cannot delete a super property.
+PASS new (class { constructor() { return undefined; } }) instanceof Object is true
+PASS new (class { constructor() { return 1; } }) instanceof Object is true
+PASS new (class extends Base { constructor() { return undefined } }) is undefined
+PASS x = { }; new (class extends Base { constructor() { return x } }); is x
+PASS x instanceof Base is false
+PASS new (class extends Base { constructor() { } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
+PASS new (class extends Base { constructor() { return 1; } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
+PASS new (class extends null { constructor() { return undefined } }) is undefined
+PASS x = { }; new (class extends null { constructor() { return x } }); is x
+PASS x instanceof Object is true
+PASS new (class extends null { constructor() { } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
+PASS new (class extends null { constructor() { return 1; } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
+PASS new (class extends null { constructor() { super() } }) did not throw exception.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxsuperhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-super.html (0 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-super.html                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-super.html        2015-03-09 23:47:06 UTC (rev 181293)
</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-super.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="trunkLayoutTestsjsscripttestsclasssyntaxextendsjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/class-syntax-extends.js (0 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-extends.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/class-syntax-extends.js        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+//@ skip
+
+description('Tests for ES6 class syntax &quot;extends&quot;');
+
+class Base {
+    constructor() { }
+    baseMethod() { return 'base'; }
+    overridenMethod() { return 'base'; }
+    static staticBaseMethod() { return 'base'; }
+    static staticOverridenMethod() { return 'base'; }
+}
+
+class Derived extends Base {
+    constructor() { super(); }
+    overridenMethod() { return 'derived'; }
+    static staticOverridenMethod() { return 'derived'; }
+}
+
+shouldBeTrue('(new Base) instanceof Base');
+shouldBeTrue('(new Derived) instanceof Derived');
+shouldBe('(new Derived).baseMethod()', '&quot;base&quot;');
+shouldBe('(new Derived).overridenMethod()', '&quot;derived&quot;');
+shouldBe('Derived.staticBaseMethod()', '&quot;base&quot;');
+shouldBe('Derived.staticOverridenMethod()', '&quot;derived&quot;');
+
+shouldThrow('x = class extends', '&quot;SyntaxError: Unexpected end of script&quot;');
+shouldThrow('x = class extends', '&quot;SyntaxError: Unexpected end of script&quot;');
+shouldThrow('x = class extends Base {', '&quot;SyntaxError: Unexpected end of script&quot;');
+shouldThrow('x = class extends Base {}', '&quot;SyntaxError: Class declaration without a constructor is not supported yet.&quot;');
+shouldNotThrow('x = class extends Base { constructor() { } }');
+shouldBe('x.__proto__', 'Base');
+shouldBe('x.prototype.__proto__', 'Base.prototype');
+shouldBe('x = class extends null { constructor() { } }; x.__proto__', 'Function.prototype');
+shouldBe('x.__proto__', 'Function.prototype');
+shouldThrow('x = class extends 3 { constructor() { } }; x.__proto__', '&quot;TypeError: The superclass is not an object.&quot;');
+shouldThrow('x = class extends &quot;abc&quot; { constructor() { } }; x.__proto__', '&quot;TypeError: The superclass is not an object.&quot;');
+evalAndLog('baseWithBadPrototype = class { constructor() { } }; baseWithBadPrototype.prototype = 3');
+shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '&quot;TypeError: The superclass\'s prototype is not an object.&quot;');
+evalAndLog('baseWithBadPrototype.prototype = &quot;abc&quot;');
+shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '&quot;TypeError: The superclass\'s prototype is not an object.&quot;');
+shouldNotThrow('baseWithBadPrototype.prototype = null; x = class extends baseWithBadPrototype { constructor() { } }');
+
+var successfullyParsed = true;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxsuperjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/class-syntax-super.js (0 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-super.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/class-syntax-super.js        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -0,0 +1,65 @@
</span><ins>+//@ skip
+
+description('Tests for ES6 class syntax &quot;super&quot;');
+
+var baseMethodValue = {};
+var valueInSetter = null;
+
+class Base {
+    constructor() { }
+    baseMethod() { return baseMethodValue; }
+    chainMethod() { return 'base'; }
+    static staticMethod() { return 'base3'; }
+}
+
+class Derived extends Base {
+    constructor() { super(); }
+    chainMethod() { return [super.chainMethod(), 'derived']; }
+    callBaseMethod() { return super.baseMethod(); }
+    get callBaseMethodInGetter() { return super['baseMethod'](); }
+    set callBaseMethodInSetter() { window.valueInSetter = super.baseMethod(); }
+    get baseMethodInGetterSetter() { return super.baseMethod; }
+    set baseMethodInGetterSetter() { window.valueInSetter = super['baseMethod']; }
+    static staticMethod() { return super.staticMethod(); }
+}
+
+class SecondDerived extends Derived {
+    constructor() { super(); }
+    chainMethod() { return super.chainMethod().concat(['secondDerived']); }
+}
+
+shouldBeTrue('(new Base) instanceof Base');
+shouldBeTrue('(new Derived) instanceof Derived');
+shouldBe('(new Derived).callBaseMethod()', 'baseMethodValue');
+shouldBe('x = (new Derived).callBaseMethod; x()', 'baseMethodValue');
+shouldBe('(new Derived).callBaseMethodInGetter', 'baseMethodValue');
+shouldBe('(new Derived).callBaseMethodInSetter = 1; valueInSetter', 'baseMethodValue');
+shouldBe('(new Derived).baseMethodInGetterSetter', '(new Base).baseMethod');
+shouldBe('(new Derived).baseMethodInGetterSetter = 1; valueInSetter', '(new Base).baseMethod');
+shouldBe('Derived.staticMethod()', '&quot;base3&quot;');
+shouldBe('(new SecondDerived).chainMethod()', '[&quot;base&quot;, &quot;derived&quot;, &quot;secondDerived&quot;]');
+shouldThrow('x = class extends Base { constructor() { super(); } super() {} }', '&quot;SyntaxError: Unexpected keyword \'super\'. Expected an indentifier.&quot;');
+shouldThrow('x = class extends Base { constructor() { super(); } method() { super() } }',
+    '&quot;SyntaxError: Cannot call super() outside of a class constructor.&quot;');
+shouldThrow('x = class extends Base { constructor() { super(); } method() { super } }', '&quot;SyntaxError: Cannot reference super.&quot;');
+shouldNotThrow('x = class extends Base { constructor() { super(); } method() { return new super } }');
+shouldBeTrue('(new x).method() instanceof Base');
+shouldBeFalse('(new x).method() instanceof x');
+shouldNotThrow('x = class extends Base { constructor() { super(); } method1() { delete (super.foo) } method2() { delete super[&quot;foo&quot;] } }');
+shouldThrow('(new x).method1()', '&quot;ReferenceError: Cannot delete a super property&quot;');
+shouldThrow('(new x).method2()', '&quot;ReferenceError: Cannot delete a super property&quot;');
+shouldBeTrue('new (class { constructor() { return undefined; } }) instanceof Object');
+shouldBeTrue('new (class { constructor() { return 1; } }) instanceof Object');
+shouldBe('new (class extends Base { constructor() { return undefined } })', 'undefined');
+shouldBe('x = { }; new (class extends Base { constructor() { return x } });', 'x');
+shouldBeFalse('x instanceof Base');
+shouldThrow('new (class extends Base { constructor() { } })', '&quot;TypeError: Cannot return a non-object type in the constructor of a derived class.&quot;');
+shouldThrow('new (class extends Base { constructor() { return 1; } })', '&quot;TypeError: Cannot return a non-object type in the constructor of a derived class.&quot;');
+shouldBe('new (class extends null { constructor() { return undefined } })', 'undefined');
+shouldBe('x = { }; new (class extends null { constructor() { return x } });', 'x');
+shouldBeTrue('x instanceof Object');
+shouldThrow('new (class extends null { constructor() { } })', '&quot;TypeError: Cannot return a non-object type in the constructor of a derived class.&quot;');
+shouldThrow('new (class extends null { constructor() { return 1; } })', '&quot;TypeError: Cannot return a non-object type in the constructor of a derived class.&quot;');
+shouldNotThrow('new (class extends null { constructor() { super() } })');
+
+var successfullyParsed = true;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -1,3 +1,104 @@
</span><ins>+2015-03-09  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        Support extends and super keywords
+        https://bugs.webkit.org/show_bug.cgi?id=142200
+
+        Reviewed by Filip Pizlo.
+
+        Added the support for ES6 class syntax inheritance.
+
+        Added ConstructorKind as well as boolean flags indicating the constructor kind to
+        various classes in UnlinkedCodeBlock as well as AST nodes.
+
+        Each method stores the associated class as its homeObjectPrivateName. This value is used to
+        make super calls.
+
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::generateFunctionCodeBlock):
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        (JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
+
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::ExecutableInfo::ExecutableInfo):
+        (JSC::UnlinkedFunctionExecutable::constructorKindIsDerived): Added.
+        (JSC::UnlinkedCodeBlock::constructorKindIsDerived): Added.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator): Don't emit op_create_this in a derived class
+        as the object is allocated by the highest base class's constructor. Also set &quot;this&quot; to null
+        and store the original value in m_newTargetRegister. &quot;this&quot; is supposed to be in TDZ but
+        that will be implemented in a separate patch.
+        (JSC::BytecodeGenerator::emitReturn): Allow &quot;undefined&quot; to be returned from a derived class.
+        In a derived class's constructor, not returning &quot;undefined&quot; or an object results in a type
+        error instead of &quot;this&quot; being returned.
+        (JSC::BytecodeGenerator::emitThrowTypeError): Added.
+
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::constructorKindIsDerived): Added.
+        (JSC::BytecodeGenerator::newTarget): Added.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::SuperNode::emitBytecode): Added. Emits the code to obtain the callee's parent class.
+        (JSC::emitSuperBaseForCallee): Added. Emits the code to obtain the parent class's prototype.
+        (JSC::emitPutHomeObject): Added.
+        (JSC::PropertyListNode::emitBytecode): Stores the home object when adding methods.
+        (JSC::PropertyListNode::emitPutConstantProperty): Ditto.
+        (JSC::BracketAccessorNode::emitBytecode): Added the support for super['foo'].
+        (JSC::DotAccessorNode::emitBytecode): Added the support for super.foo.
+        (JSC::FunctionCallValueNode::emitBytecode): Added the support for super().
+        (JSC::FunctionCallBracketNode::emitBytecode): Added the support for super['foo']().
+        (JSC::FunctionCallDotNode::emitBytecode): Added the support for super.foo().
+        (JSC::DeleteBracketNode::emitBytecode): Forbid &quot;delete super.foo&quot;.
+        (JSC::DeleteDotNode::emitBytecode): Forbid &quot;delete super['foo']&quot;.
+        (JSC::ClassExprNode::emitBytecode): Added the support for &quot;classHeritage&quot;. This is the main
+        logic for inheritance. When a class B inherits from a class A, set B.__proto__ to A and set
+        B.prototype.__proto__ to A.prototype. Throw exceptions when either A or A.__proto__ is not
+        an object.
+
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::superExpr): Added.
+
+        * parser/NodeConstructors.h:
+        (JSC::SuperNode::SuperNode): Added.
+
+        * parser/Nodes.cpp:
+        (JSC::FunctionBodyNode::FunctionBodyNode):
+
+        * parser/Nodes.h:
+        (JSC::ExpressionNode::isSuperNode):
+        (JSC::PropertyNode::type):
+        (JSC::PropertyNode::needsSuperBinding):
+
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionBody):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionInfo): Throw a parser error if super() is used outside
+        of class constructors.
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionDeclaration):
+        (JSC::Parser&lt;LexerType&gt;::parseClass): ConstructorKind is &quot;derived&quot; if and only if the parent
+        class is specified in the declaration / expression.
+        (JSC::Parser&lt;LexerType&gt;::parseGetterSetter):
+        (JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
+        (JSC::Parser&lt;LexerType&gt;::parseMemberExpression): Added the support for &quot;super()&quot;, &quot;super.foo&quot;,
+        and &quot;super['foo']&quot;. Throw a semantic error if &quot;super&quot; appears by itself.
+
+        * parser/Parser.h:
+        (JSC::Scope::Scope): Added m_hasDirectSuper. This variable keeps track of the use of &quot;super()&quot;
+        so that parseFunctionInfo can spit an error if it's used outside of class constructors.
+        (JSC::Scope::hasDirectSuper): Added.
+        (JSC::Scope::setHasDirectSuper): Added.
+
+        * parser/ParserModes.h:
+        (JSC::ConstructorKind): Added.
+
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::superExpr): Added.
+
+        * runtime/CommonIdentifiers.h: Added homeObjectPrivateName.
+
+        * runtime/Executable.h:
+        (JSC::EvalExecutable::executableInfo): 
+        (JSC::ProgramExecutable::executableInfo):
+
</ins><span class="cx"> 2015-03-08  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         JITThunks keeps finalized Weaks around, pinning WeakBlocks.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -61,7 +61,8 @@
</span><span class="cx">     function-&gt;finishParsing(executable-&gt;parameters(), executable-&gt;name(), executable-&gt;functionMode());
</span><span class="cx">     executable-&gt;recordParse(function-&gt;features(), function-&gt;hasCapturedVariables());
</span><span class="cx">     
</span><del>-    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&amp;vm, FunctionCode, ExecutableInfo(function-&gt;needsActivation(), function-&gt;usesEval(), function-&gt;isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction));
</del><ins>+    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&amp;vm, FunctionCode,
+        ExecutableInfo(function-&gt;needsActivation(), function-&gt;usesEval(), function-&gt;isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable-&gt;constructorKindIsDerived()));
</ins><span class="cx">     auto generator(std::make_unique&lt;BytecodeGenerator&gt;(vm, function.get(), result, debuggerMode, profilerMode));
</span><span class="cx">     error = generator-&gt;generate();
</span><span class="cx">     if (error.isValid())
</span><span class="lines">@@ -84,6 +85,7 @@
</span><span class="cx">     , m_isInStrictContext(node-&gt;isInStrictContext())
</span><span class="cx">     , m_hasCapturedVariables(false)
</span><span class="cx">     , m_isBuiltinFunction(kind == UnlinkedBuiltinFunction)
</span><ins>+    , m_constructorKindIsDerived(node-&gt;constructorKindIsDerived())
</ins><span class="cx">     , m_name(node-&gt;ident())
</span><span class="cx">     , m_inferredName(node-&gt;inferredName())
</span><span class="cx">     , m_parameters(node-&gt;parameters())
</span><span class="lines">@@ -229,6 +231,7 @@
</span><span class="cx">     , m_isConstructor(info.m_isConstructor)
</span><span class="cx">     , m_hasCapturedVariables(false)
</span><span class="cx">     , m_isBuiltinFunction(info.m_isBuiltinFunction)
</span><ins>+    , m_constructorKindIsDerived(info.m_constructorKindIsDerived)
</ins><span class="cx">     , m_firstLine(0)
</span><span class="cx">     , m_lineCount(0)
</span><span class="cx">     , m_endColumn(UINT_MAX)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -65,12 +65,13 @@
</span><span class="cx"> typedef unsigned UnlinkedLLIntCallLinkInfo;
</span><span class="cx"> 
</span><span class="cx"> struct ExecutableInfo {
</span><del>-    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction)
</del><ins>+    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, bool constructorKindIsDerived)
</ins><span class="cx">         : m_needsActivation(needsActivation)
</span><span class="cx">         , m_usesEval(usesEval)
</span><span class="cx">         , m_isStrictMode(isStrictMode)
</span><span class="cx">         , m_isConstructor(isConstructor)
</span><span class="cx">         , m_isBuiltinFunction(isBuiltinFunction)
</span><ins>+        , m_constructorKindIsDerived(constructorKindIsDerived)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     bool m_needsActivation : 1;
</span><span class="lines">@@ -78,6 +79,7 @@
</span><span class="cx">     bool m_isStrictMode : 1;
</span><span class="cx">     bool m_isConstructor : 1;
</span><span class="cx">     bool m_isBuiltinFunction : 1;
</span><ins>+    bool m_constructorKindIsDerived : 1;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> enum UnlinkedFunctionKind {
</span><span class="lines">@@ -116,6 +118,7 @@
</span><span class="cx">             return JSParseStrict;
</span><span class="cx">         return JSParseNormal;
</span><span class="cx">     }
</span><ins>+    bool constructorKindIsDerived() const { return m_constructorKindIsDerived; }
</ins><span class="cx"> 
</span><span class="cx">     unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
</span><span class="cx">     unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
</span><span class="lines">@@ -167,6 +170,7 @@
</span><span class="cx">     bool m_isInStrictContext : 1;
</span><span class="cx">     bool m_hasCapturedVariables : 1;
</span><span class="cx">     bool m_isBuiltinFunction : 1;
</span><ins>+    bool m_constructorKindIsDerived : 1;
</ins><span class="cx"> 
</span><span class="cx">     Identifier m_name;
</span><span class="cx">     Identifier m_inferredName;
</span><span class="lines">@@ -341,7 +345,9 @@
</span><span class="cx">     bool isNumericCompareFunction() const { return m_isNumericCompareFunction; }
</span><span class="cx"> 
</span><span class="cx">     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
</span><del>-    
</del><ins>+
+    bool constructorKindIsDerived() const { return m_constructorKindIsDerived; }
+
</ins><span class="cx">     void shrinkToFit()
</span><span class="cx">     {
</span><span class="cx">         m_jumpTargets.shrinkToFit();
</span><span class="lines">@@ -533,6 +539,7 @@
</span><span class="cx">     bool m_isConstructor : 1;
</span><span class="cx">     bool m_hasCapturedVariables : 1;
</span><span class="cx">     bool m_isBuiltinFunction : 1;
</span><ins>+    bool m_constructorKindIsDerived : 1;
</ins><span class="cx">     unsigned m_firstLine;
</span><span class="cx">     unsigned m_lineCount;
</span><span class="cx">     unsigned m_endColumn;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -401,7 +401,12 @@
</span><span class="cx">     addCallee(functionNode, calleeRegister);
</span><span class="cx"> 
</span><span class="cx">     if (isConstructor()) {
</span><del>-        emitCreateThis(&amp;m_thisRegister);
</del><ins>+        if (constructorKindIsDerived()) {
+            m_newTargetRegister = addVar();
+            emitMove(m_newTargetRegister, &amp;m_thisRegister);
+            emitLoad(&amp;m_thisRegister, jsNull());
+        } else
+            emitCreateThis(&amp;m_thisRegister);
</ins><span class="cx">     } else if (functionNode-&gt;usesThis() || codeBlock-&gt;usesEval()) {
</span><span class="cx">         m_codeBlock-&gt;addPropertyAccessInstruction(instructions().size());
</span><span class="cx">         emitOpcode(op_to_this);
</span><span class="lines">@@ -1901,14 +1906,19 @@
</span><span class="cx">         instructions().append(m_lexicalEnvironmentRegister ? m_lexicalEnvironmentRegister-&gt;index() : emitLoad(0, JSValue())-&gt;index());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (isConstructor() &amp;&amp; src-&gt;index() != m_thisRegister.index()) {
-        RefPtr&lt;Label&gt; isObjectLabel = newLabel();
</del><ins>+    bool thisMightBeUninitialized = constructorKindIsDerived();
+    if (isConstructor() &amp;&amp; (src-&gt;index() != m_thisRegister.index() || thisMightBeUninitialized)) {
+        RefPtr&lt;Label&gt; isObjectOrUndefinedLabel = newLabel();
</ins><span class="cx"> 
</span><del>-        emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
</del><ins>+        emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectOrUndefinedLabel.get());
</ins><span class="cx"> 
</span><del>-        emitUnaryNoDstOp(op_ret, &amp;m_thisRegister);
</del><ins>+        if (constructorKindIsDerived()) {
+            emitJumpIfTrue(emitIsUndefined(newTemporary(), src), isObjectOrUndefinedLabel.get());
+            emitThrowTypeError(&quot;Cannot return a non-object type in the constructor of a derived class.&quot;);
+        } else
+            emitUnaryNoDstOp(op_ret, &amp;m_thisRegister);
</ins><span class="cx"> 
</span><del>-        emitLabel(isObjectLabel.get());
</del><ins>+        emitLabel(isObjectOrUndefinedLabel.get());
</ins><span class="cx">     }
</span><span class="cx">     return emitUnaryNoDstOp(op_ret, src);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -269,7 +269,12 @@
</span><span class="cx">         ParserArena&amp; parserArena() const { return m_scopeNode-&gt;parserArena(); }
</span><span class="cx">         const CommonIdentifiers&amp; propertyNames() const { return *m_vm-&gt;propertyNames; }
</span><span class="cx"> 
</span><del>-        bool isConstructor() { return m_codeBlock-&gt;isConstructor(); }
</del><ins>+        bool isConstructor() const { return m_codeBlock-&gt;isConstructor(); }
+#if ENABLE(ES6_CLASS_SYNTAX)
+        bool constructorKindIsDerived() const { return m_codeBlock-&gt;constructorKindIsDerived(); }
+#else
+        bool constructorKindIsDerived() const { return false; }
+#endif
</ins><span class="cx"> 
</span><span class="cx">         ParserError generate();
</span><span class="cx"> 
</span><span class="lines">@@ -290,7 +295,8 @@
</span><span class="cx"> 
</span><span class="cx">         // Returns the register storing &quot;this&quot;
</span><span class="cx">         RegisterID* thisRegister() { return &amp;m_thisRegister; }
</span><del>-        
</del><ins>+        RegisterID* newTarget() { return m_newTargetRegister; }
+
</ins><span class="cx">         RegisterID* scopeRegister() { return m_scopeRegister; }
</span><span class="cx"> 
</span><span class="cx">         // Returns the next available temporary register. Registers returned by
</span><span class="lines">@@ -763,6 +769,7 @@
</span><span class="cx">         RegisterID* m_emptyValueRegister { nullptr };
</span><span class="cx">         RegisterID* m_globalObjectRegister { nullptr };
</span><span class="cx">         RegisterID* m_localArgumentsRegister { nullptr };
</span><ins>+        RegisterID* m_newTargetRegister { nullptr };
</ins><span class="cx"> 
</span><span class="cx">         Vector&lt;Identifier, 16&gt; m_watchableVariables;
</span><span class="cx">         SegmentedVector&lt;RegisterID, 32&gt; m_constantPoolRegisters;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -156,6 +156,30 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// ------------------------------ SuperNode -------------------------------------
+
+RegisterID* SuperNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return 0;
+
+    RegisterID callee;
+    callee.setIndex(JSStack::Callee);
+
+    RefPtr&lt;RegisterID&gt; homeObject = generator.emitGetById(generator.newTemporary(), &amp;callee, generator.propertyNames().homeObjectPrivateName);
+    RefPtr&lt;RegisterID&gt; protoParent = generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
+    return generator.emitGetById(generator.finalDestination(dst), protoParent.get(), generator.propertyNames().constructor);
+}
+
+static RegisterID* emitSuperBaseForCallee(BytecodeGenerator&amp; generator)
+{
+    RegisterID callee;
+    callee.setIndex(JSStack::Callee);
+
+    RefPtr&lt;RegisterID&gt; homeObject = generator.emitGetById(generator.newTemporary(), &amp;callee, generator.propertyNames().homeObjectPrivateName);
+    return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
+}
+
</ins><span class="cx"> // ------------------------------ ResolveNode ----------------------------------
</span><span class="cx"> 
</span><span class="cx"> bool ResolveNode::isPure(BytecodeGenerator&amp; generator) const
</span><span class="lines">@@ -294,6 +318,11 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ PropertyListNode -----------------------------
</span><span class="cx"> 
</span><ins>+static inline void emitPutHomeObject(BytecodeGenerator&amp; generator, RegisterID* function, RegisterID* homeObject)
+{
+    generator.emitPutById(function, generator.propertyNames().homeObjectPrivateName, homeObject);
+}
+
</ins><span class="cx"> RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx">     // Fast case: this loop just handles regular value properties.
</span><span class="lines">@@ -330,6 +359,8 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             RegisterID* value = generator.emitNode(node-&gt;m_assign);
</span><ins>+            if (node-&gt;needsSuperBinding())
+                emitPutHomeObject(generator, value, dst);
</ins><span class="cx"> 
</span><span class="cx">             // This is a get/set property, find its entry in the map.
</span><span class="cx">             ASSERT(node-&gt;m_type == PropertyNode::Getter || node-&gt;m_type == PropertyNode::Setter);
</span><span class="lines">@@ -344,12 +375,14 @@
</span><span class="cx">             // Generate the paired node now.
</span><span class="cx">             RefPtr&lt;RegisterID&gt; getterReg;
</span><span class="cx">             RefPtr&lt;RegisterID&gt; setterReg;
</span><ins>+            RegisterID* secondReg = nullptr;
</ins><span class="cx"> 
</span><span class="cx">             if (node-&gt;m_type == PropertyNode::Getter) {
</span><span class="cx">                 getterReg = value;
</span><span class="cx">                 if (pair.second) {
</span><span class="cx">                     ASSERT(pair.second-&gt;m_type == PropertyNode::Setter);
</span><span class="cx">                     setterReg = generator.emitNode(pair.second-&gt;m_assign);
</span><ins>+                    secondReg = setterReg.get();
</ins><span class="cx">                 } else {
</span><span class="cx">                     setterReg = generator.newTemporary();
</span><span class="cx">                     generator.emitLoad(setterReg.get(), jsUndefined());
</span><span class="lines">@@ -360,12 +393,16 @@
</span><span class="cx">                 if (pair.second) {
</span><span class="cx">                     ASSERT(pair.second-&gt;m_type == PropertyNode::Getter);
</span><span class="cx">                     getterReg = generator.emitNode(pair.second-&gt;m_assign);
</span><ins>+                    secondReg = getterReg.get();
</ins><span class="cx">                 } else {
</span><span class="cx">                     getterReg = generator.newTemporary();
</span><span class="cx">                     generator.emitLoad(getterReg.get(), jsUndefined());
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span><ins>+            if (pair.second &amp;&amp; pair.second-&gt;needsSuperBinding())
+                emitPutHomeObject(generator, secondReg, dst);
+
</ins><span class="cx">             generator.emitPutGetterSetter(dst, *node-&gt;name(), getterReg.get(), setterReg.get());
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -375,18 +412,30 @@
</span><span class="cx"> 
</span><span class="cx"> void PropertyListNode::emitPutConstantProperty(BytecodeGenerator&amp; generator, RegisterID* newObj, PropertyNode&amp; node)
</span><span class="cx"> {
</span><ins>+    RefPtr&lt;RegisterID&gt; value = generator.emitNode(node.m_assign);
+    if (node.needsSuperBinding())
+        emitPutHomeObject(generator, value.get(), newObj);
</ins><span class="cx">     if (node.name()) {
</span><del>-        generator.emitDirectPutById(newObj, *node.name(), generator.emitNode(node.m_assign), node.putType());
</del><ins>+        generator.emitDirectPutById(newObj, *node.name(), value.get(), node.putType());
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     RefPtr&lt;RegisterID&gt; propertyName = generator.emitNode(node.m_expression);
</span><del>-    generator.emitDirectPutByVal(newObj, propertyName.get(), generator.emitNode(node.m_assign));
</del><ins>+    generator.emitDirectPutByVal(newObj, propertyName.get(), value.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ BracketAccessorNode --------------------------------
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><ins>+    if (m_base-&gt;isSuperNode()) {
+        // FIXME: Should we generate the profiler info?
+        if (m_subscript-&gt;isString()) {
+            const Identifier&amp; id = static_cast&lt;StringNode*&gt;(m_subscript)-&gt;value();
+            return generator.emitGetById(generator.finalDestination(dst), emitSuperBaseForCallee(generator), id);
+        }
+        return generator.emitGetByVal(generator.finalDestination(dst), emitSuperBaseForCallee(generator), generator.emitNode(m_subscript));
+    }
+
</ins><span class="cx">     if (m_base-&gt;isResolveNode() 
</span><span class="cx">         &amp;&amp; generator.willResolveToArgumentsRegister(static_cast&lt;ResolveNode*&gt;(m_base)-&gt;identifier())
</span><span class="cx">         &amp;&amp; !generator.symbolTable().slowArguments()) {
</span><span class="lines">@@ -431,7 +480,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> nonArgumentsPath:
</span><del>-    RefPtr&lt;RegisterID&gt; base = generator.emitNode(m_base);
</del><ins>+    RefPtr&lt;RegisterID&gt; base = m_base-&gt;isSuperNode() ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
</ins><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">     RegisterID* finalDest = generator.finalDestination(dst);
</span><span class="cx">     RegisterID* ret = generator.emitGetById(finalDest, base.get(), m_ident);
</span><span class="lines">@@ -521,6 +570,13 @@
</span><span class="cx">     RefPtr&lt;RegisterID&gt; func = generator.emitNode(m_expr);
</span><span class="cx">     RefPtr&lt;RegisterID&gt; returnValue = generator.finalDestination(dst, func.get());
</span><span class="cx">     CallArguments callArguments(generator, m_args);
</span><ins>+    if (m_expr-&gt;isSuperNode()) {
+        ASSERT(generator.constructorKindIsDerived());
+        generator.emitMove(callArguments.thisRegister(), generator.newTarget());
+        RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+        generator.emitMove(generator.thisRegister(), ret);
+        return ret;
+    }
</ins><span class="cx">     generator.emitLoad(callArguments.thisRegister(), jsUndefined());
</span><span class="cx">     RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><span class="cx">     if (generator.vm()-&gt;typeProfiler()) {
</span><span class="lines">@@ -574,13 +630,17 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>-    RefPtr&lt;RegisterID&gt; base = generator.emitNode(m_base);
</del><ins>+    bool baseIsSuper = m_base-&gt;isSuperNode();
+    RefPtr&lt;RegisterID&gt; base = baseIsSuper ? emitSuperBaseForCallee(generator) : generator.emitNode(m_base);
</ins><span class="cx">     RefPtr&lt;RegisterID&gt; property = generator.emitNode(m_subscript);
</span><span class="cx">     generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
</span><span class="cx">     RefPtr&lt;RegisterID&gt; function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get());
</span><span class="cx">     RefPtr&lt;RegisterID&gt; returnValue = generator.finalDestination(dst, function.get());
</span><span class="cx">     CallArguments callArguments(generator, m_args);
</span><del>-    generator.emitMove(callArguments.thisRegister(), base.get());
</del><ins>+    if (baseIsSuper)
+        generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
+    else
+        generator.emitMove(callArguments.thisRegister(), base.get());
</ins><span class="cx">     RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><span class="cx">     if (generator.vm()-&gt;typeProfiler()) {
</span><span class="cx">         generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
</span><span class="lines">@@ -596,9 +656,13 @@
</span><span class="cx">     RefPtr&lt;RegisterID&gt; function = generator.tempDestination(dst);
</span><span class="cx">     RefPtr&lt;RegisterID&gt; returnValue = generator.finalDestination(dst, function.get());
</span><span class="cx">     CallArguments callArguments(generator, m_args);
</span><del>-    generator.emitNode(callArguments.thisRegister(), m_base);
</del><ins>+    bool baseIsSuper = m_base-&gt;isSuperNode();
+    if (baseIsSuper)
+        generator.emitMove(callArguments.thisRegister(), generator.thisRegister());
+    else
+        generator.emitNode(callArguments.thisRegister(), m_base);
</ins><span class="cx">     generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
</span><del>-    generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
</del><ins>+    generator.emitGetById(function.get(), baseIsSuper ? emitSuperBaseForCallee(generator) : callArguments.thisRegister(), m_ident);
</ins><span class="cx">     RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><span class="cx">     if (generator.vm()-&gt;typeProfiler()) {
</span><span class="cx">         generator.emitProfileType(returnValue.get(), ProfileTypeBytecodeDoesNotHaveGlobalID, nullptr);
</span><span class="lines">@@ -940,6 +1004,8 @@
</span><span class="cx">     RefPtr&lt;RegisterID&gt; r1 = generator.emitNode(m_subscript);
</span><span class="cx"> 
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><ins>+    if (m_base-&gt;isSuperNode())
+        return emitThrowReferenceError(generator, &quot;Cannot delete a super property&quot;);
</ins><span class="cx">     return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -950,6 +1016,8 @@
</span><span class="cx">     RefPtr&lt;RegisterID&gt; r0 = generator.emitNode(m_base);
</span><span class="cx"> 
</span><span class="cx">     generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><ins>+    if (m_base-&gt;isSuperNode())
+        return emitThrowReferenceError(generator, &quot;Cannot delete a super property&quot;);
</ins><span class="cx">     return generator.emitDeleteById(generator.finalDestination(dst), r0.get(), m_ident);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2807,11 +2875,42 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span><del>-    ASSERT(!m_parentClassExpression);
</del><ins>+    RefPtr&lt;RegisterID&gt; superclass;
+    if (m_classHeritage) {
+        superclass = generator.newTemporary();
+        generator.emitNode(superclass.get(), m_classHeritage);
+    }
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;RegisterID&gt; constructor = generator.emitNode(dst, m_constructorExpression);
</span><ins>+    // FIXME: Make the prototype non-configurable &amp; non-writable.
</ins><span class="cx">     RefPtr&lt;RegisterID&gt; prototype = generator.emitGetById(generator.newTemporary(), constructor.get(), generator.propertyNames().prototype);
</span><span class="cx"> 
</span><ins>+    if (superclass) {
+        RefPtr&lt;RegisterID&gt; tempRegister = generator.newTemporary();
+        RefPtr&lt;Label&gt; superclassIsNullLabel = generator.newLabel();
+        generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
+
+        // FIXME: Throw TypeError if it's a generator function.
+        RefPtr&lt;Label&gt; superclassIsObjectLabel = generator.newLabel();
+        generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
+        generator.emitThrowTypeError(ASCIILiteral(&quot;The superclass is not an object.&quot;));
+        generator.emitLabel(superclassIsObjectLabel.get());
+
+        RefPtr&lt;RegisterID&gt; protoParent = generator.newTemporary();
+        generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
+
+        RefPtr&lt;Label&gt; protoParentIsObjectOrNullLabel = generator.newLabel();
+        generator.emitJumpIfTrue(generator.emitUnaryOp(op_is_object_or_null, tempRegister.get(), protoParent.get()), protoParentIsObjectOrNullLabel.get());
+        generator.emitThrowTypeError(ASCIILiteral(&quot;The superclass's prototype is not an object.&quot;));
+        generator.emitLabel(protoParentIsObjectOrNullLabel.get());
+
+        generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
+        generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
+
+        generator.emitLabel(superclassIsNullLabel.get());
+        emitPutHomeObject(generator, constructor.get(), prototype.get());
+    }
+
</ins><span class="cx">     if (m_staticMethods)
</span><span class="cx">         generator.emitNode(constructor.get(), m_staticMethods);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -169,6 +169,10 @@
</span><span class="cx">         usesThis();
</span><span class="cx">         return new (m_parserArena) ThisNode(location);
</span><span class="cx">     }
</span><ins>+    ExpressionNode* superExpr(const JSTokenLocation&amp; location)
+    {
+        return new (m_parserArena) SuperNode(location);
+    }
</ins><span class="cx">     ExpressionNode* createResolve(const JSTokenLocation&amp; location, const Identifier* ident, const JSTextPosition&amp; start)
</span><span class="cx">     {
</span><span class="cx">         if (m_vm-&gt;propertyNames-&gt;arguments == *ident)
</span><span class="lines">@@ -298,9 +302,9 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    FunctionBodyNode* createFunctionBody(const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext)
</del><ins>+    FunctionBodyNode* createFunctionBody(const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, bool inStrictContext, ConstructorKind constructorKind)
</ins><span class="cx">     {
</span><del>-        return new (m_parserArena) FunctionBodyNode(m_parserArena, startLocation, endLocation, startColumn, endColumn, inStrictContext);
</del><ins>+        return new (m_parserArena) FunctionBodyNode(m_parserArena, startLocation, endLocation, startColumn, endColumn, inStrictContext, constructorKind);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void setFunctionNameStart(FunctionBodyNode* body, int functionNameStart)
</span><span class="lines">@@ -309,23 +313,26 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     NEVER_INLINE PropertyNode* createGetterOrSetterProperty(const JSTokenLocation&amp; location, PropertyNode::Type type, bool,
</span><del>-        const Identifier* name, const ParserFunctionInfo&lt;ASTBuilder&gt;&amp; info, unsigned getOrSetStartOffset)
</del><ins>+        const Identifier* name, const ParserFunctionInfo&lt;ASTBuilder&gt;&amp; info, unsigned getOrSetStartOffset, SuperBinding superBinding)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(name);
</span><span class="cx">         info.body-&gt;setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
</span><span class="cx">         info.body-&gt;setInferredName(*name);
</span><span class="cx">         info.body-&gt;setFunctionKeywordStart(getOrSetStartOffset);
</span><del>-        return new (m_parserArena) PropertyNode(*name, new (m_parserArena) FuncExprNode(location, m_vm-&gt;propertyNames-&gt;nullIdentifier,
-            info.body, m_sourceCode-&gt;subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters), type, PropertyNode::Unknown);
</del><ins>+        SourceCode source = m_sourceCode-&gt;subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
+        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, m_vm-&gt;propertyNames-&gt;nullIdentifier, info.body, source, info.parameters);
+        return new (m_parserArena) PropertyNode(*name, funcExpr, type, PropertyNode::Unknown, superBinding);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM* vm, ParserArena&amp; parserArena, const JSTokenLocation&amp; location, PropertyNode::Type type, bool, double name, const ParserFunctionInfo&lt;ASTBuilder&gt;&amp; info, unsigned getOrSetStartOffset)
</del><ins>+    NEVER_INLINE PropertyNode* createGetterOrSetterProperty(VM* vm, ParserArena&amp; parserArena, const JSTokenLocation&amp; location, PropertyNode::Type type, bool,
+        double name, const ParserFunctionInfo&lt;ASTBuilder&gt;&amp; info, unsigned getOrSetStartOffset, SuperBinding superBinding)
</ins><span class="cx">     {
</span><span class="cx">         info.body-&gt;setLoc(info.bodyStartLine, info.bodyEndLine, location.startOffset, location.lineStartOffset);
</span><span class="cx">         info.body-&gt;setFunctionKeywordStart(getOrSetStartOffset);
</span><span class="cx">         const Identifier&amp; ident = parserArena.identifierArena().makeNumericIdentifier(vm, name);
</span><del>-        return new (m_parserArena) PropertyNode(ident, new (m_parserArena) FuncExprNode(location, vm-&gt;propertyNames-&gt;nullIdentifier,
-            info.body, m_sourceCode-&gt;subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn), info.parameters), type, PropertyNode::Unknown);
</del><ins>+        SourceCode source = m_sourceCode-&gt;subExpression(info.openBraceOffset, info.closeBraceOffset, info.bodyStartLine, info.bodyStartColumn);
+        FuncExprNode* funcExpr = new (m_parserArena) FuncExprNode(location, vm-&gt;propertyNames-&gt;nullIdentifier, info.body, source, info.parameters);
+        return new (m_parserArena) PropertyNode(ident, funcExpr, type, PropertyNode::Unknown, superBinding);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     ArgumentsNode* createArguments() { return new (m_parserArena) ArgumentsNode(); }
</span><span class="lines">@@ -333,11 +340,11 @@
</span><span class="cx">     ArgumentListNode* createArgumentsList(const JSTokenLocation&amp; location, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, arg); }
</span><span class="cx">     ArgumentListNode* createArgumentsList(const JSTokenLocation&amp; location, ArgumentListNode* args, ExpressionNode* arg) { return new (m_parserArena) ArgumentListNode(location, args, arg); }
</span><span class="cx"> 
</span><del>-    PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool)
</del><ins>+    PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding = SuperBinding::NotNeeded)
</ins><span class="cx">     {
</span><span class="cx">         if (node-&gt;isFuncExprNode())
</span><span class="cx">             static_cast&lt;FuncExprNode*&gt;(node)-&gt;body()-&gt;setInferredName(*propertyName);
</span><del>-        return new (m_parserArena) PropertyNode(*propertyName, node, type, putType);
</del><ins>+        return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding);
</ins><span class="cx">     }
</span><span class="cx">     PropertyNode* createProperty(VM* vm, ParserArena&amp; parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodeConstructorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/NodeConstructors.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -112,8 +112,13 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-inline ResolveNode::ResolveNode(const JSTokenLocation&amp; location, const Identifier&amp; ident, const JSTextPosition&amp; start)
</del><ins>+    inline SuperNode::SuperNode(const JSTokenLocation&amp; location)
</ins><span class="cx">         : ExpressionNode(location)
</span><ins>+    {
+    }
+
+    inline ResolveNode::ResolveNode(const JSTokenLocation&amp; location, const Identifier&amp; ident, const JSTextPosition&amp; start)
+        : ExpressionNode(location)
</ins><span class="cx">         , m_ident(ident)
</span><span class="cx">         , m_start(start)
</span><span class="cx">     {
</span><span class="lines">@@ -159,10 +164,11 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    inline PropertyNode::PropertyNode(const Identifier&amp; name, ExpressionNode* assign, Type type, PutType putType)
</del><ins>+    inline PropertyNode::PropertyNode(const Identifier&amp; name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding = SuperBinding::NotNeeded)
</ins><span class="cx">         : m_name(&amp;name)
</span><span class="cx">         , m_assign(assign)
</span><span class="cx">         , m_type(type)
</span><ins>+        , m_needsSuperBinding(superBinding == SuperBinding::Needed)
</ins><span class="cx">         , m_putType(putType)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="lines">@@ -172,6 +178,7 @@
</span><span class="cx">         , m_expression(name)
</span><span class="cx">         , m_assign(assign)
</span><span class="cx">         , m_type(type)
</span><ins>+        , m_needsSuperBinding(false)
</ins><span class="cx">         , m_putType(putType)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="lines">@@ -787,11 +794,11 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    inline ClassExprNode::ClassExprNode(const JSTokenLocation&amp; location, const Identifier&amp; name, ExpressionNode* constructorExpression, ExpressionNode* parentClassExpression, PropertyListNode* instanceMethods, PropertyListNode* staticMethods)
</del><ins>+    inline ClassExprNode::ClassExprNode(const JSTokenLocation&amp; location, const Identifier&amp; name, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* instanceMethods, PropertyListNode* staticMethods)
</ins><span class="cx">         : ExpressionNode(location)
</span><span class="cx">         , m_name(name)
</span><span class="cx">         , m_constructorExpression(constructorExpression)
</span><del>-        , m_parentClassExpression(parentClassExpression)
</del><ins>+        , m_classHeritage(classHeritage)
</ins><span class="cx">         , m_instanceMethods(instanceMethods)
</span><span class="cx">         , m_staticMethods(staticMethods)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.cpp (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.cpp        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/Nodes.cpp        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -167,12 +167,13 @@
</span><span class="cx">         patterns()[i]-&gt;deref();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FunctionBodyNode::FunctionBodyNode(ParserArena&amp;, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, bool isInStrictContext)
</del><ins>+FunctionBodyNode::FunctionBodyNode(ParserArena&amp;, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, bool isInStrictContext, ConstructorKind constructorKind)
</ins><span class="cx">     : StatementNode(endLocation)
</span><span class="cx">     , m_startColumn(startColumn)
</span><span class="cx">     , m_endColumn(endColumn)
</span><span class="cx">     , m_startStartOffset(startLocation.startOffset)
</span><span class="cx">     , m_isInStrictContext(isInStrictContext)
</span><ins>+    , m_constructorKindIsDerived(constructorKind == ConstructorKind::Derived)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -164,6 +164,7 @@
</span><span class="cx">         virtual bool isSubtract() const { return false; }
</span><span class="cx">         virtual bool isBoolean() const { return false; }
</span><span class="cx">         virtual bool isSpreadExpression() const { return false; }
</span><ins>+        virtual bool isSuperNode() const { return false; }
</ins><span class="cx"> 
</span><span class="cx">         virtual void emitBytecodeInConditionContext(BytecodeGenerator&amp;, Label*, Label*, FallThroughMode);
</span><span class="cx"> 
</span><span class="lines">@@ -445,6 +446,15 @@
</span><span class="cx">         virtual RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    class SuperNode final : public ExpressionNode {
+    public:
+        SuperNode(const JSTokenLocation&amp;);
+
+    private:
+        virtual bool isSuperNode() const override { return true; }
+        virtual RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
+    };
+
</ins><span class="cx">     class ResolveNode : public ExpressionNode {
</span><span class="cx">     public:
</span><span class="cx">         ResolveNode(const JSTokenLocation&amp;, const Identifier&amp;, const JSTextPosition&amp; start);
</span><span class="lines">@@ -501,22 +511,24 @@
</span><span class="cx">         enum Type { Constant = 1, Getter = 2, Setter = 4 };
</span><span class="cx">         enum PutType { Unknown, KnownDirect };
</span><span class="cx"> 
</span><del>-        PropertyNode(const Identifier&amp;, ExpressionNode*, Type, PutType);
</del><ins>+        PropertyNode(const Identifier&amp;, ExpressionNode*, Type, PutType, SuperBinding);
</ins><span class="cx">         PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType);
</span><del>-        
</del><ins>+
</ins><span class="cx">         ExpressionNode* expressionName() const { return m_expression; }
</span><span class="cx">         const Identifier* name() const { return m_name; }
</span><span class="cx"> 
</span><del>-        Type type() const { return m_type; }
-        PutType putType() const { return m_putType; }
</del><ins>+        Type type() const { return static_cast&lt;Type&gt;(m_type); }
+        bool needsSuperBinding() const { return m_needsSuperBinding; }
+        PutType putType() const { return static_cast&lt;PutType&gt;(m_putType); }
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         friend class PropertyListNode;
</span><span class="cx">         const Identifier* m_name;
</span><span class="cx">         ExpressionNode* m_expression;
</span><span class="cx">         ExpressionNode* m_assign;
</span><del>-        Type m_type;
-        PutType m_putType;
</del><ins>+        unsigned m_type : 3;
+        unsigned m_needsSuperBinding : 1;
+        unsigned m_putType : 1;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class PropertyListNode : public ExpressionNode {
</span><span class="lines">@@ -1547,7 +1559,7 @@
</span><span class="cx">     public:
</span><span class="cx">         using ParserArenaDeletable::operator new;
</span><span class="cx"> 
</span><del>-        FunctionBodyNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, bool isInStrictContext);
</del><ins>+        FunctionBodyNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, bool isInStrictContext, ConstructorKind);
</ins><span class="cx"> 
</span><span class="cx">         FunctionParameters* parameters() const { return m_parameters.get(); }
</span><span class="cx"> 
</span><span class="lines">@@ -1575,6 +1587,7 @@
</span><span class="cx"> 
</span><span class="cx">         int startStartOffset() const { return m_startStartOffset; }
</span><span class="cx">         bool isInStrictContext() const { return m_isInStrictContext; }
</span><ins>+        bool constructorKindIsDerived() { return m_constructorKindIsDerived; }
</ins><span class="cx"> 
</span><span class="cx">     protected:
</span><span class="cx">         Identifier m_ident;
</span><span class="lines">@@ -1587,7 +1600,8 @@
</span><span class="cx">         unsigned m_endColumn;
</span><span class="cx">         SourceCode m_source;
</span><span class="cx">         int m_startStartOffset;
</span><del>-        bool m_isInStrictContext;
</del><ins>+        bool m_isInStrictContext : 1;
+        bool m_constructorKindIsDerived : 1;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class FunctionNode final : public ScopeNode {
</span><span class="lines">@@ -1644,7 +1658,7 @@
</span><span class="cx"> 
</span><span class="cx">         const Identifier&amp; m_name;
</span><span class="cx">         ExpressionNode* m_constructorExpression;
</span><del>-        ExpressionNode* m_parentClassExpression;
</del><ins>+        ExpressionNode* m_classHeritage;
</ins><span class="cx">         PropertyListNode* m_instanceMethods;
</span><span class="cx">         PropertyListNode* m_staticMethods;
</span><span class="cx">     };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -1255,7 +1255,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; TreeFunctionBody Parser&lt;LexerType&gt;::parseFunctionBody(TreeBuilder&amp; context)
</del><ins>+template &lt;class TreeBuilder&gt; TreeFunctionBody Parser&lt;LexerType&gt;::parseFunctionBody(TreeBuilder&amp; context, ConstructorKind constructorKind)
</ins><span class="cx"> {
</span><span class="cx">     JSTokenLocation startLocation(tokenLocation());
</span><span class="cx">     unsigned startColumn = tokenColumn();
</span><span class="lines">@@ -1263,14 +1263,14 @@
</span><span class="cx"> 
</span><span class="cx">     if (match(CLOSEBRACE)) {
</span><span class="cx">         unsigned endColumn = tokenColumn();
</span><del>-        return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode());
</del><ins>+        return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode(), constructorKind);
</ins><span class="cx">     }
</span><span class="cx">     DepthManager statementDepth(&amp;m_statementDepth);
</span><span class="cx">     m_statementDepth = 0;
</span><span class="cx">     typename TreeBuilder::FunctionBodyBuilder bodyBuilder(const_cast&lt;VM*&gt;(m_vm), m_lexer.get());
</span><span class="cx">     failIfFalse(parseSourceElements(bodyBuilder, CheckForStrictMode), &quot;Cannot parse body of this function&quot;);
</span><span class="cx">     unsigned endColumn = tokenColumn();
</span><del>-    return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode());
</del><ins>+    return context.createFunctionBody(startLocation, tokenLocation(), startColumn, endColumn, strictMode(), constructorKind);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static const char* stringForFunctionMode(FunctionParseMode mode)
</span><span class="lines">@@ -1290,7 +1290,8 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-template &lt;class TreeBuilder&gt; bool Parser&lt;LexerType&gt;::parseFunctionInfo(TreeBuilder&amp; context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ParserFunctionInfo&lt;TreeBuilder&gt;&amp; info)
</del><ins>+template &lt;class TreeBuilder&gt; bool Parser&lt;LexerType&gt;::parseFunctionInfo(TreeBuilder&amp; context, FunctionRequirements requirements, FunctionParseMode mode,
+    bool nameIsInContainingScope, ConstructorKind constructorKind, ParserFunctionInfo&lt;TreeBuilder&gt;&amp; info)
</ins><span class="cx"> {
</span><span class="cx">     AutoPopScopeRef functionScope(this, pushScope());
</span><span class="cx">     functionScope-&gt;setIsFunction();
</span><span class="lines">@@ -1343,7 +1344,7 @@
</span><span class="cx">             endLocation.startOffset - endLocation.lineStartOffset;
</span><span class="cx">         unsigned currentLineStartOffset = m_token.m_location.lineStartOffset;
</span><span class="cx"> 
</span><del>-        info.body = context.createFunctionBody(startLocation, endLocation, info.bodyStartColumn, bodyEndColumn, cachedInfo-&gt;strictMode);
</del><ins>+        info.body = context.createFunctionBody(startLocation, endLocation, info.bodyStartColumn, bodyEndColumn, cachedInfo-&gt;strictMode, constructorKind);
</ins><span class="cx">         
</span><span class="cx">         functionScope-&gt;restoreFromSourceProviderCache(cachedInfo);
</span><span class="cx">         failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), &quot;Parser error&quot;);
</span><span class="lines">@@ -1366,15 +1367,19 @@
</span><span class="cx">     }
</span><span class="cx">     m_lastFunctionName = lastFunctionName;
</span><span class="cx">     ParserState oldState = saveState();
</span><del>-    info.body = parseFunctionBody(context);
</del><ins>+    info.body = parseFunctionBody(context, constructorKind);
</ins><span class="cx">     restoreState(oldState);
</span><span class="cx">     failIfFalse(info.body, &quot;Cannot parse the body of this &quot;, stringForFunctionMode(mode));
</span><span class="cx">     context.setEndOffset(info.body, m_lexer-&gt;currentOffset());
</span><span class="cx">     if (functionScope-&gt;strictMode() &amp;&amp; info.name) {
</span><del>-        RELEASE_ASSERT(mode == FunctionMode);
</del><ins>+        RELEASE_ASSERT(mode == FunctionMode || mode == MethodMode);
</ins><span class="cx">         semanticFailIfTrue(m_vm-&gt;propertyNames-&gt;arguments == *info.name, &quot;'&quot;, info.name-&gt;impl(), &quot;' is not a valid function name in strict mode&quot;);
</span><span class="cx">         semanticFailIfTrue(m_vm-&gt;propertyNames-&gt;eval == *info.name, &quot;'&quot;, info.name-&gt;impl(), &quot;' is not a valid function name in strict mode&quot;);
</span><span class="cx">     }
</span><ins>+    if (functionScope-&gt;hasDirectSuper()) {
+        bool nameIsConstructor = info.name &amp;&amp; *info.name == m_vm-&gt;propertyNames-&gt;constructor;
+        semanticFailIfTrue(mode != MethodMode || !nameIsConstructor, &quot;Cannot call super() outside of a class constructor&quot;);
+    }
</ins><span class="cx">     info.closeBraceOffset = m_token.m_data.offset;
</span><span class="cx">     unsigned closeBraceLine = m_token.m_data.line;
</span><span class="cx">     unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset;
</span><span class="lines">@@ -1415,7 +1420,7 @@
</span><span class="cx">     unsigned functionKeywordStart = tokenStart();
</span><span class="cx">     next();
</span><span class="cx">     ParserFunctionInfo&lt;TreeBuilder&gt; info;
</span><del>-    failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, info)), &quot;Cannot parse this function&quot;);
</del><ins>+    failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, ConstructorKind::Base, info)), &quot;Cannot parse this function&quot;);
</ins><span class="cx">     failIfFalse(info.name, &quot;Function statements must have a name&quot;);
</span><span class="cx">     failIfFalseIfStrict(declareVariable(info.name), &quot;Cannot declare a function named '&quot;, info.name-&gt;impl(), &quot;' in strict mode&quot;);
</span><span class="cx">     return context.createFuncDeclStatement(location, info, functionKeywordStart);
</span><span class="lines">@@ -1465,8 +1470,8 @@
</span><span class="cx">     if (consume(EXTENDS)) {
</span><span class="cx">         parentClass = parsePrimaryExpression(context);
</span><span class="cx">         failIfFalse(parentClass, &quot;Cannot parse the parent class name&quot;);
</span><del>-        failWithMessage(&quot;Inheritance is not supported yet&quot;);
</del><span class="cx">     }
</span><ins>+    const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
</ins><span class="cx"> 
</span><span class="cx">     consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings, &quot;Expected opening '{' at the start of a class body&quot;);
</span><span class="cx"> 
</span><span class="lines">@@ -1498,11 +1503,11 @@
</span><span class="cx">         if (isGetter || isSetter) {
</span><span class="cx">             semanticFailIfTrue(isStaticMethod, &quot;Cannot declare a static&quot;, stringForFunctionMode(isGetter ? GetterMode : SetterMode));
</span><span class="cx">             nextExpectIdentifier(LexerFlagsIgnoreReservedWords);
</span><del>-            property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart);
</del><ins>+            property = parseGetterSetter(context, alwaysStrictInsideClass, isGetter ? PropertyNode::Getter : PropertyNode::Setter, methodStart, SuperBinding::Needed);
</ins><span class="cx">             failIfFalse(property, &quot;Cannot parse this method&quot;);
</span><span class="cx">         } else {
</span><span class="cx">             ParserFunctionInfo&lt;TreeBuilder&gt; methodInfo;
</span><del>-            failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, false, methodInfo)), &quot;Cannot parse this method&quot;);
</del><ins>+            failIfFalse((parseFunctionInfo(context, FunctionNeedsName, MethodMode, false, constructorKind, methodInfo)), &quot;Cannot parse this method&quot;);
</ins><span class="cx">             failIfFalse(methodInfo.name, &quot;method must have a name&quot;);
</span><span class="cx">             failIfFalse(declareVariable(methodInfo.name), &quot;Cannot declare a method named '&quot;, methodInfo.name-&gt;impl(), &quot;'&quot;);
</span><span class="cx"> 
</span><span class="lines">@@ -1520,7 +1525,7 @@
</span><span class="cx">             // FIXME: Syntax error when super() is called
</span><span class="cx">             semanticFailIfTrue(isStaticMethod &amp;&amp; *methodInfo.name == propertyNames.prototype,
</span><span class="cx">                 &quot;Cannot declare a static method named 'prototype'&quot;);
</span><del>-            property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass);
</del><ins>+            property = context.createProperty(methodInfo.name, method, PropertyNode::Constant, PropertyNode::Unknown, alwaysStrictInsideClass, SuperBinding::Needed);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         TreePropertyList&amp; tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail;
</span><span class="lines">@@ -2007,13 +2012,13 @@
</span><span class="cx">     JSTokenLocation methodLocation(tokenLocation());
</span><span class="cx">     unsigned methodStart = tokenStart();
</span><span class="cx">     ParserFunctionInfo&lt;TreeBuilder&gt; methodInfo;
</span><del>-    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, methodInfo)), &quot;Cannot parse this method&quot;);
</del><ins>+    failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, MethodMode, false, ConstructorKind::Base, methodInfo)), &quot;Cannot parse this method&quot;);
</ins><span class="cx">     methodInfo.name = methodName;
</span><span class="cx">     return context.createFunctionExpr(methodLocation, methodInfo, methodStart);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-template &lt;class TreeBuilder&gt; TreeProperty Parser&lt;LexerType&gt;::parseGetterSetter(TreeBuilder&amp; context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset)
</del><ins>+template &lt;class TreeBuilder&gt; TreeProperty Parser&lt;LexerType&gt;::parseGetterSetter(TreeBuilder&amp; context, bool strict, PropertyNode::Type type, unsigned getterOrSetterStartOffset, SuperBinding superBinding)
</ins><span class="cx"> {
</span><span class="cx">     const Identifier* stringPropertyName = 0;
</span><span class="cx">     double numericPropertyName = 0;
</span><span class="lines">@@ -2028,14 +2033,14 @@
</span><span class="cx">     ParserFunctionInfo&lt;TreeBuilder&gt; info;
</span><span class="cx">     if (type == PropertyNode::Getter) {
</span><span class="cx">         failIfFalse(match(OPENPAREN), &quot;Expected a parameter list for getter definition&quot;);
</span><del>-        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, info)), &quot;Cannot parse getter definition&quot;);
</del><ins>+        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, ConstructorKind::Base, info)), &quot;Cannot parse getter definition&quot;);
</ins><span class="cx">     } else {
</span><span class="cx">         failIfFalse(match(OPENPAREN), &quot;Expected a parameter list for setter definition&quot;);
</span><del>-        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, info)), &quot;Cannot parse setter definition&quot;);
</del><ins>+        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, ConstructorKind::Base, info)), &quot;Cannot parse setter definition&quot;);
</ins><span class="cx">     }
</span><span class="cx">     if (stringPropertyName)
</span><del>-        return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, getterOrSetterStartOffset);
-    return context.createGetterOrSetterProperty(const_cast&lt;VM*&gt;(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, getterOrSetterStartOffset);
</del><ins>+        return context.createGetterOrSetterProperty(location, type, strict, stringPropertyName, info, getterOrSetterStartOffset, superBinding);
+    return context.createGetterOrSetterProperty(const_cast&lt;VM*&gt;(m_vm), m_parserArena, location, type, strict, numericPropertyName, info, getterOrSetterStartOffset, superBinding);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="lines">@@ -2220,7 +2225,7 @@
</span><span class="cx">         next();
</span><span class="cx">         ParserFunctionInfo&lt;TreeBuilder&gt; info;
</span><span class="cx">         info.name = &amp;m_vm-&gt;propertyNames-&gt;nullIdentifier;
</span><del>-        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, info)), &quot;Cannot parse function expression&quot;);
</del><ins>+        failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, ConstructorKind::Base, info)), &quot;Cannot parse function expression&quot;);
</ins><span class="cx">         return context.createFunctionExpr(location, info, functionKeywordStart);
</span><span class="cx">     }
</span><span class="cx"> #if ENABLE(ES6_CLASS_SYNTAX)
</span><span class="lines">@@ -2370,8 +2375,18 @@
</span><span class="cx">         newCount++;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    base = parsePrimaryExpression(context);
-    
</del><ins>+#if ENABLE(ES6_CLASS_SYNTAX)
+    bool baseIsSuper = match(SUPER);
+#else
+    bool baseIsSuper = false;
+#endif
+
+    if (baseIsSuper) {
+        base = context.superExpr(location);
+        next();
+    } else
+        base = parsePrimaryExpression(context);
+
</ins><span class="cx">     failIfFalse(base, &quot;Cannot parse base expression&quot;);
</span><span class="cx">     while (true) {
</span><span class="cx">         location = tokenLocation();
</span><span class="lines">@@ -2402,6 +2417,8 @@
</span><span class="cx">                 JSTextPosition expressionEnd = lastTokenEndPosition();
</span><span class="cx">                 TreeArguments arguments = parseArguments(context, AllowSpread);
</span><span class="cx">                 failIfFalse(arguments, &quot;Cannot parse call arguments&quot;);
</span><ins>+                if (baseIsSuper)
+                    currentScope()-&gt;setHasDirectSuper();
</ins><span class="cx">                 base = context.makeFunctionCallNode(startLocation, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition());
</span><span class="cx">             }
</span><span class="cx">             m_nonLHSCount = nonLHSCount;
</span><span class="lines">@@ -2419,8 +2436,10 @@
</span><span class="cx">         default:
</span><span class="cx">             goto endMemberExpression;
</span><span class="cx">         }
</span><ins>+        baseIsSuper = false;
</ins><span class="cx">     }
</span><span class="cx"> endMemberExpression:
</span><ins>+    semanticFailIfTrue(baseIsSuper &amp;&amp; !newCount, &quot;Cannot reference super&quot;);
</ins><span class="cx">     while (newCount--)
</span><span class="cx">         base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition());
</span><span class="cx">     return base;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -113,6 +113,7 @@
</span><span class="cx">         , m_shadowsArguments(false)
</span><span class="cx">         , m_usesEval(false)
</span><span class="cx">         , m_needsFullActivation(false)
</span><ins>+        , m_hasDirectSuper(false)
</ins><span class="cx">         , m_allowsNewDecls(true)
</span><span class="cx">         , m_strictMode(strictMode)
</span><span class="cx">         , m_isFunction(isFunction)
</span><span class="lines">@@ -128,6 +129,7 @@
</span><span class="cx">         , m_shadowsArguments(rhs.m_shadowsArguments)
</span><span class="cx">         , m_usesEval(rhs.m_usesEval)
</span><span class="cx">         , m_needsFullActivation(rhs.m_needsFullActivation)
</span><ins>+        , m_hasDirectSuper(rhs.m_hasDirectSuper)
</ins><span class="cx">         , m_allowsNewDecls(rhs.m_allowsNewDecls)
</span><span class="cx">         , m_strictMode(rhs.m_strictMode)
</span><span class="cx">         , m_isFunction(rhs.m_isFunction)
</span><span class="lines">@@ -263,6 +265,13 @@
</span><span class="cx"> 
</span><span class="cx">     void setNeedsFullActivation() { m_needsFullActivation = true; }
</span><span class="cx"> 
</span><ins>+#if ENABLE(ES6_CLASS_SYNTAX)
+    bool hasDirectSuper() { return m_hasDirectSuper; }
+#else
+    bool hasDirectSuper() { return false; }
+#endif
+    void setHasDirectSuper() { m_hasDirectSuper = true; }
+
</ins><span class="cx">     bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
</span><span class="cx">     {
</span><span class="cx">         if (nestedScope-&gt;m_usesEval)
</span><span class="lines">@@ -356,6 +365,7 @@
</span><span class="cx">     bool m_shadowsArguments : 1;
</span><span class="cx">     bool m_usesEval : 1;
</span><span class="cx">     bool m_needsFullActivation : 1;
</span><ins>+    bool m_hasDirectSuper : 1;
</ins><span class="cx">     bool m_allowsNewDecls : 1;
</span><span class="cx">     bool m_strictMode : 1;
</span><span class="cx">     bool m_isFunction : 1;
</span><span class="lines">@@ -738,8 +748,8 @@
</span><span class="cx">     template &lt;class TreeBuilder&gt; ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&amp;, SpreadMode);
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeProperty parseProperty(TreeBuilder&amp;, bool strict);
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeExpression parsePropertyMethod(TreeBuilder&amp; context, const Identifier* methodName);
</span><del>-    template &lt;class TreeBuilder&gt; TreeProperty parseGetterSetter(TreeBuilder&amp;, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset);
-    template &lt;class TreeBuilder&gt; ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&amp;);
</del><ins>+    template &lt;class TreeBuilder&gt; TreeProperty parseGetterSetter(TreeBuilder&amp;, bool strict, PropertyNode::Type, unsigned getterOrSetterStartOffset, SuperBinding = SuperBinding::NotNeeded);
+    template &lt;class TreeBuilder&gt; ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&amp;, ConstructorKind);
</ins><span class="cx">     template &lt;class TreeBuilder&gt; ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&amp;);
</span><span class="cx">     enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext };
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeExpression parseVarDeclarationList(TreeBuilder&amp;, int&amp; declarations, TreeDeconstructionPattern&amp; lastPattern, TreeExpression&amp; lastInitializer, JSTextPosition&amp; identStart, JSTextPosition&amp; initStart, JSTextPosition&amp; initEnd, VarDeclarationListContext);
</span><span class="lines">@@ -749,7 +759,7 @@
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&amp;, DeconstructionKind, int depth = 0);
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&amp;);
</span><span class="cx"> 
</span><del>-    template &lt;class TreeBuilder&gt; NEVER_INLINE bool parseFunctionInfo(TreeBuilder&amp;, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ParserFunctionInfo&lt;TreeBuilder&gt;&amp;);
</del><ins>+    template &lt;class TreeBuilder&gt; NEVER_INLINE bool parseFunctionInfo(TreeBuilder&amp;, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, ConstructorKind, ParserFunctionInfo&lt;TreeBuilder&gt;&amp;);
</ins><span class="cx"> #if ENABLE(ES6_CLASS_SYNTAX)
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&amp;, FunctionRequirements);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserModesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ParserModes.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ParserModes.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/ParserModes.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -34,6 +34,9 @@
</span><span class="cx"> enum JSParserStrictness { JSParseNormal, JSParseBuiltin, JSParseStrict };
</span><span class="cx"> enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
</span><span class="cx"> 
</span><ins>+enum class ConstructorKind { Base, Derived };
+enum class SuperBinding { Needed, NotNeeded };
+
</ins><span class="cx"> enum ProfilerMode { ProfilerOff, ProfilerOn };
</span><span class="cx"> enum DebuggerMode { DebuggerOff, DebuggerOn };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx">     enum { NoneExpr = 0,
</span><span class="cx">         ResolveEvalExpr, ResolveExpr, IntegerExpr, DoubleExpr, StringExpr,
</span><span class="cx">         ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
</span><del>-        FunctionExpr, ClassExpr, BracketExpr, DotExpr, CallExpr,
</del><ins>+        FunctionExpr, ClassExpr, SuperExpr, BracketExpr, DotExpr, CallExpr,
</ins><span class="cx">         NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
</span><span class="cx">         ConditionalExpr, AssignmentExpr, TypeofExpr,
</span><span class="cx">         DeleteExpr, ArrayLiteralExpr, BindingDeconstruction,
</span><span class="lines">@@ -146,6 +146,7 @@
</span><span class="cx">     ExpressionType createUnaryPlus(const JSTokenLocation&amp;, ExpressionType) { return UnaryExpr; }
</span><span class="cx">     ExpressionType createVoid(const JSTokenLocation&amp;, ExpressionType) { return UnaryExpr; }
</span><span class="cx">     ExpressionType thisExpr(const JSTokenLocation&amp;) { return ThisExpr; }
</span><ins>+    ExpressionType superExpr(const JSTokenLocation&amp;) { return SuperExpr; }
</ins><span class="cx">     ExpressionType createResolve(const JSTokenLocation&amp;, const Identifier*, int) { return ResolveExpr; }
</span><span class="cx">     ExpressionType createObjectLiteral(const JSTokenLocation&amp;) { return ObjectLiteralExpr; }
</span><span class="cx">     ExpressionType createObjectLiteral(const JSTokenLocation&amp;, int) { return ObjectLiteralExpr; }
</span><span class="lines">@@ -168,14 +169,14 @@
</span><span class="cx">     ClassExpression createClassExpr(const JSTokenLocation&amp;, const Identifier&amp;, ExpressionType, ExpressionType, PropertyList, PropertyList) { return ClassExpr; }
</span><span class="cx"> #endif
</span><span class="cx">     ExpressionType createFunctionExpr(const JSTokenLocation&amp;, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;, int) { return FunctionExpr; }
</span><del>-    int createFunctionBody(const JSTokenLocation&amp;, const JSTokenLocation&amp;, int, int, bool) { return FunctionBodyResult; }
</del><ins>+    int createFunctionBody(const JSTokenLocation&amp;, const JSTokenLocation&amp;, int, int, bool, ConstructorKind) { return FunctionBodyResult; }
</ins><span class="cx">     void setFunctionNameStart(int, int) { }
</span><span class="cx">     int createArguments() { return ArgumentsResult; }
</span><span class="cx">     int createArguments(int) { return ArgumentsResult; }
</span><span class="cx">     ExpressionType createSpreadExpression(const JSTokenLocation&amp;, ExpressionType, int, int, int) { return SpreadExpr; }
</span><span class="cx">     int createArgumentsList(const JSTokenLocation&amp;, int) { return ArgumentsListResult; }
</span><span class="cx">     int createArgumentsList(const JSTokenLocation&amp;, int, int) { return ArgumentsListResult; }
</span><del>-    Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete)
</del><ins>+    Property createProperty(const Identifier* name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding = SuperBinding::NotNeeded)
</ins><span class="cx">     {
</span><span class="cx">         if (!complete)
</span><span class="cx">             return Property(type);
</span><span class="lines">@@ -230,14 +231,14 @@
</span><span class="cx">     int createDebugger(const JSTokenLocation&amp;, int, int) { return StatementResult; }
</span><span class="cx">     int createConstStatement(const JSTokenLocation&amp;, int, int, int) { return StatementResult; }
</span><span class="cx">     int appendConstDecl(const JSTokenLocation&amp;, int, const Identifier*, int) { return StatementResult; }
</span><del>-    Property createGetterOrSetterProperty(const JSTokenLocation&amp;, PropertyNode::Type type, bool strict, const Identifier* name, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;, unsigned)
</del><ins>+    Property createGetterOrSetterProperty(const JSTokenLocation&amp;, PropertyNode::Type type, bool strict, const Identifier* name, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;, unsigned, SuperBinding)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(name);
</span><span class="cx">         if (!strict)
</span><span class="cx">             return Property(type);
</span><span class="cx">         return Property(name, type);
</span><span class="cx">     }
</span><del>-    Property createGetterOrSetterProperty(VM* vm, ParserArena&amp; parserArena, const JSTokenLocation&amp;, PropertyNode::Type type, bool strict, double name, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;, unsigned)
</del><ins>+    Property createGetterOrSetterProperty(VM* vm, ParserArena&amp; parserArena, const JSTokenLocation&amp;, PropertyNode::Type type, bool strict, double name, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;, unsigned, SuperBinding)
</ins><span class="cx">     {
</span><span class="cx">         if (!strict)
</span><span class="cx">             return Property(type);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonIdentifiersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -261,7 +261,8 @@
</span><span class="cx">     macro(isFinite) \
</span><span class="cx">     macro(TypeError) \
</span><span class="cx">     macro(undefined) \
</span><del>-    macro(BuiltinLog)
</del><ins>+    macro(BuiltinLog) \
+    macro(homeObject)
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeExecutableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Executable.h (181292 => 181293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Executable.h        2015-03-09 23:43:34 UTC (rev 181292)
+++ trunk/Source/JavaScriptCore/runtime/Executable.h        2015-03-09 23:47:06 UTC (rev 181293)
</span><span class="lines">@@ -467,7 +467,7 @@
</span><span class="cx"> 
</span><span class="cx">     void clearCode();
</span><span class="cx"> 
</span><del>-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
</del><ins>+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, false); }
</ins><span class="cx"> 
</span><span class="cx">     unsigned numVariables() { return m_unlinkedEvalCodeBlock-&gt;numVariables(); }
</span><span class="cx">     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock-&gt;numberOfFunctionDecls(); }
</span><span class="lines">@@ -522,7 +522,7 @@
</span><span class="cx"> 
</span><span class="cx">     void clearCode();
</span><span class="cx"> 
</span><del>-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
</del><ins>+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false, false); }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ScriptExecutable;
</span></span></pre>
</div>
</div>

</body>
</html>