<!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>[204058] 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/204058">204058</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-08-02 18:28:16 -0700 (Tue, 02 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>update a class extending null w.r.t the ES7 spec
https://bugs.webkit.org/show_bug.cgi?id=160417

Reviewed by Keith Miller.

Source/JavaScriptCore:

When a class extends null, it should not be marked as a derived class.
This was changed in the ES2016 spec, and this patch makes the needed
changes in JSC to follow the spec. This allows classes to extend
null and have their default constructor invoked without throwing an exception.
This also prevents |this| from being under TDZ at the start of the constructor.
Because ES6 allows arbitrary expressions in the `class &lt;ident&gt; extends &lt;expr&gt;`
syntax, we don't know statically if a constructor is extending null or not.
Therefore, we don't always know statically if it's a base or derived constructor.
I solved this by putting a boolean on the constructor function under a private
symbol named isDerivedConstructor when doing class construction. We only need
to put this boolean on constructors that may extend null. Constructors that are
declared in a class with no extends syntax can tell statically that they are a base constructor.

I've also renamed the ConstructorKind::Derived enum value to be
ConstructorKind::Extends to better indicate that we can't answer
the &quot;am I a derived constructor?&quot; question statically.

* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createDefaultConstructor):
* builtins/BuiltinNames.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
(JSC::BytecodeGenerator::emitReturn):
(JSC::BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment):
(JSC::BytecodeGenerator::ensureThis):
(JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::makeFunction):
* bytecompiler/NodesCodegen.cpp:
(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallValueNode::emitBytecode):
(JSC::FunctionNode::emitBytecode):
(JSC::ClassExprNode::emitBytecode):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::Parser):
(JSC::Parser&lt;LexerType&gt;::parseFunctionInfo):
(JSC::Parser&lt;LexerType&gt;::parseClass):
(JSC::Parser&lt;LexerType&gt;::parseMemberExpression):
* parser/ParserModes.h:

LayoutTests:

* js/class-syntax-extends-expected.txt:
* js/class-syntax-super-expected.txt:
* js/script-tests/class-syntax-extends.js:
* js/script-tests/class-syntax-super.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangelog">trunk/JSTests/Changelog</a></li>
<li><a href="#trunkJSTeststest262yaml">trunk/JSTests/test262.yaml</a></li>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxextendsexpectedtxt">trunk/LayoutTests/js/class-syntax-extends-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxsuperexpectedtxt">trunk/LayoutTests/js/class-syntax-super-expected.txt</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>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebuiltinsBuiltinExecutablescpp">trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebuiltinsBuiltinNamesh">trunk/Source/JavaScriptCore/builtins/BuiltinNames.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="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserModesh">trunk/Source/JavaScriptCore/parser/ParserModes.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressclassderivedfromnulljs">trunk/JSTests/stress/class-derived-from-null.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangelog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/Changelog (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/Changelog        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/JSTests/Changelog        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2016-08-02  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        update a class extending null w.r.t the ES7 spec
+        https://bugs.webkit.org/show_bug.cgi?id=160417
+
+        Reviewed by Keith Miller.
+
+        * Changelog:
+        * stress/class-derived-from-null.js: Added.
+        (assert):
+        (test):
+        (test1.C):
+        (test1):
+        (jsNull):
+        (test2.C):
+        (test2):
+        (test3.C):
+        (test3.D):
+        (test3.E):
+        (test3):
+        (test4.E):
+        (test4):
+        (test5.E):
+        (test5):
+        (test6.Base):
+        (test6.D):
+        (test6.E):
+        (test6.F):
+        (test6.G):
+        (test6):
+        * test262.yaml:
+
</ins><span class="cx"> 2016-08-01  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Rationalize varargs stack overflow checks
</span></span></pre></div>
<a id="trunkJSTestsstressclassderivedfromnulljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/class-derived-from-null.js (0 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/class-derived-from-null.js                                (rev 0)
+++ trunk/JSTests/stress/class-derived-from-null.js        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -0,0 +1,128 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad!&quot;)
+}
+
+function test(f, count = 1000) {
+    for (let i = 0; i &lt; count; i++)
+        f();
+}
+
+function test1() {
+    class C extends null { }
+    assert((new C) instanceof C);
+    assert(!((new C) instanceof Object));
+    assert(Reflect.getPrototypeOf(C.prototype) === null);
+
+    let o = {}
+    class D extends null {
+        constructor() {
+            return o;
+        }
+    }
+    assert(new D === o);
+    assert(Reflect.getPrototypeOf(D.prototype) === null);
+
+    class E extends null {
+        constructor() {
+            return this;
+        }
+    }
+    assert((new E) instanceof E);
+    assert(!((new E) instanceof Object));
+    assert(Reflect.getPrototypeOf(E.prototype) === null);
+}
+test(test1);
+
+function jsNull() { return null; }
+function test2() {
+    class C extends jsNull() { }
+    assert((new C) instanceof C);
+    assert(!((new C) instanceof Object));
+    assert(Reflect.getPrototypeOf(C.prototype) === null);
+
+    let o = {}
+    class D extends jsNull() {
+        constructor() {
+            return o;
+        }
+    }
+    assert(new D === o);
+    assert(Reflect.getPrototypeOf(D.prototype) === null);
+
+    class E extends jsNull() {
+        constructor() {
+            return this;
+        }
+    }
+    assert((new E) instanceof E);
+    assert(!((new E) instanceof Object));
+    assert(Reflect.getPrototypeOf(E.prototype) === null);
+}
+test(test2);
+
+function test3() {
+    class C extends jsNull() { constructor() { super(); } }
+    let threw = false;
+    try {
+        new C;
+    } catch(e) {
+        threw = e.toString() === &quot;TypeError: function is not a constructor (evaluating 'super()')&quot;;
+    }
+    assert(threw);
+
+    class D extends jsNull() { constructor() { let arr = ()=&gt;super(); arr(); } }
+    threw = false;
+    try {
+        new D;
+    } catch(e) {
+        threw = e.toString() === &quot;TypeError: function is not a constructor (evaluating 'super()')&quot;;
+    }
+    assert(threw);
+
+    class E extends jsNull() { constructor() { let arr = ()=&gt;super(); return this; } }
+    assert((new E) instanceof E);
+    assert(!((new E) instanceof Object));
+    assert(Reflect.getPrototypeOf(E.prototype) === null);
+}
+test(test3);
+
+function test4() {
+    class E extends jsNull() { constructor() { return 25; } }
+    assert((new E) instanceof E);
+    assert(!((new E) instanceof Object));
+    assert(Reflect.getPrototypeOf(E.prototype) === null);
+}
+test(test4);
+
+function test5() {
+    class E extends jsNull() { constructor() { let arr = ()=&gt;this; return arr(); } }
+    assert((new E) instanceof E);
+    assert(!((new E) instanceof Object));
+    assert(Reflect.getPrototypeOf(E.prototype) === null);
+}
+test(test5);
+
+function test6() {
+    class Base { }
+    class D extends Base { }
+    class E extends jsNull() { constructor() { let ret = this; return ret; } }
+    class F extends jsNull() { constructor() { return 25; } }
+    class G extends jsNull() { constructor() { super(); } }
+    let result = Reflect.construct(E, [], D);
+    assert(result instanceof D);
+    assert(result instanceof Object);
+
+    result = Reflect.construct(F, [], D);
+    assert(result instanceof D);
+    assert(result instanceof Object);
+
+    let threw = false;
+    try {
+        Reflect.construct(G, [], D);
+    } catch(e) {
+        threw = e.toString() === &quot;TypeError: function is not a constructor (evaluating 'super()')&quot;;
+    }
+    assert(threw);
+}
+test(test6);
</ins></span></pre></div>
<a id="trunkJSTeststest262yaml"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/test262.yaml (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/test262.yaml        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/JSTests/test262.yaml        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -75898,9 +75898,9 @@
</span><span class="cx"> - path: test262/test/language/statements/class/subclass/class-definition-null-proto-super.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../../harness/assert.js&quot;, &quot;../../../../../harness/sta.js&quot;], [:strict]
</span><span class="cx"> - path: test262/test/language/statements/class/subclass/class-definition-null-proto-this.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../../harness/assert.js&quot;, &quot;../../../../../harness/sta.js&quot;], []
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../../harness/assert.js&quot;, &quot;../../../../../harness/sta.js&quot;], []
</ins><span class="cx"> - path: test262/test/language/statements/class/subclass/class-definition-null-proto-this.js
</span><del>-  cmd: runTest262 :fail, &quot;NoException&quot;, [&quot;../../../../../harness/assert.js&quot;, &quot;../../../../../harness/sta.js&quot;], [:strict]
</del><ins>+  cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../../harness/assert.js&quot;, &quot;../../../../../harness/sta.js&quot;], [:strict]
</ins><span class="cx"> - path: test262/test/language/statements/class/subclass/class-definition-null-proto.js
</span><span class="cx">   cmd: runTest262 :normal, &quot;NoException&quot;, [&quot;../../../../../harness/assert.js&quot;, &quot;../../../../../harness/sta.js&quot;], []
</span><span class="cx"> - path: test262/test/language/statements/class/subclass/class-definition-null-proto.js
</span></span></pre></div>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/LayoutTests/ChangeLog        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-08-02  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        update a class extending null w.r.t the ES7 spec
+        https://bugs.webkit.org/show_bug.cgi?id=160417
+
+        Reviewed by Keith Miller.
+
+        * js/class-syntax-extends-expected.txt:
+        * js/class-syntax-super-expected.txt:
+        * js/script-tests/class-syntax-extends.js:
+        * js/script-tests/class-syntax-super.js:
+
</ins><span class="cx"> 2016-08-02  Ryan Haddad  &lt;ryanhaddad@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Skip media/track/track-remove-crash.html on ios-simulator-wk2
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxextendsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/class-syntax-extends-expected.txt (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-extends-expected.txt        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/LayoutTests/js/class-syntax-extends-expected.txt        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -57,10 +57,10 @@
</span><span class="cx"> PASS new (class extends undefined { constructor () { this } }):::TypeError: The superclass is not an object.
</span><span class="cx"> PASS x = undefined; new (class extends x { constructor () { super(); } }):::TypeError: The superclass is not an object.
</span><span class="cx"> PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x
</span><del>-PASS new (class extends null { constructor () { this; } }):::ReferenceError: Cannot access uninitialized variable.
</del><ins>+PASS new (class extends null { constructor () { this; } })
</ins><span class="cx"> PASS new (class extends null { constructor () { super(); } }):::TypeError: function is not a constructor (evaluating 'super()')
</span><span class="cx"> PASS x = {}; new (class extends null { constructor () { return x } }):::x
</span><del>-PASS y = 12; new (class extends null { constructor () { return y; } }):::TypeError: Cannot return a non-object type in the constructor of a derived class.
</del><ins>+PASS y = 12; class C extends null { constructor () { return y; } }; new C instanceof C;
</ins><span class="cx"> PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x
</span><span class="cx"> PASS x = null; Object.getPrototypeOf((class extends x { }).prototype):::null
</span><span class="cx"> PASS Object.prototype.isPrototypeOf(class { })
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxsuperexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/class-syntax-super-expected.txt (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-super-expected.txt        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/LayoutTests/js/class-syntax-super-expected.txt        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -30,12 +30,12 @@
</span><span class="cx"> PASS x instanceof Base
</span><span class="cx"> PASS new (class extends Base { constructor() { } }):::ReferenceError: Cannot access uninitialized variable.
</span><span class="cx"> PASS new (class extends Base { constructor() { return 1; } }):::TypeError: Cannot return a non-object type in the constructor of a derived class.
</span><del>-PASS new (class extends null { constructor() { return undefined } }):::ReferenceError: Cannot access uninitialized variable.
</del><ins>+PASS new (class extends null { constructor() { return undefined } })
</ins><span class="cx"> PASS new (class extends null { constructor() { super(); return undefined } }):::TypeError: function is not a constructor (evaluating 'super()')
</span><span class="cx"> PASS x = { }; new (class extends null { constructor() { return x } });:::x
</span><span class="cx"> PASS x instanceof Object
</span><del>-PASS new (class extends null { constructor() { } }):::ReferenceError: Cannot access uninitialized variable.
-PASS new (class extends null { constructor() { return 1; } }):::TypeError: Cannot return a non-object type in the constructor of a derived class.
</del><ins>+PASS new (class extends null { constructor() { } })
+PASS new (class extends null { constructor() { return 1; } })
</ins><span class="cx"> PASS new (class extends null { constructor() { super() } }):::TypeError: function is not a constructor (evaluating 'super()')
</span><span class="cx"> PASS new (class { constructor() { super() } }):::SyntaxError: super is not valid in this context.
</span><span class="cx"> PASS function x() { super(); }:::SyntaxError: super is not valid in this context.
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxextendsjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/class-syntax-extends.js (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-extends.js        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/LayoutTests/js/script-tests/class-syntax-extends.js        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -115,10 +115,10 @@
</span><span class="cx"> shouldThrow('new (class extends undefined { constructor () { this } })', '&quot;TypeError: The superclass is not an object.&quot;');
</span><span class="cx"> shouldThrow('x = undefined; new (class extends x { constructor () { super(); } })', '&quot;TypeError: The superclass is not an object.&quot;');
</span><span class="cx"> shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
</span><del>-shouldThrow('new (class extends null { constructor () { this; } })', '&quot;ReferenceError: Cannot access uninitialized variable.&quot;');
</del><ins>+shouldNotThrow('new (class extends null { constructor () { this; } })');
</ins><span class="cx"> shouldThrow('new (class extends null { constructor () { super(); } })', '&quot;TypeError: function is not a constructor (evaluating \'super()\')&quot;');
</span><span class="cx"> shouldBe('x = {}; new (class extends null { constructor () { return x } })', 'x');
</span><del>-shouldThrow('y = 12; new (class extends null { constructor () { return y; } })', '&quot;TypeError: Cannot return a non-object type in the constructor of a derived class.&quot;');
</del><ins>+shouldBeTrue('y = 12; class C extends null { constructor () { return y; } }; new C instanceof C;', '&quot;TypeError: Cannot return a non-object type in the constructor of a derived class.&quot;');
</ins><span class="cx"> shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
</span><span class="cx"> shouldBe('x = null; Object.getPrototypeOf((class extends x { }).prototype)', 'null');
</span><span class="cx"> shouldBeTrue('Object.prototype.isPrototypeOf(class { })');
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxsuperjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/class-syntax-super.js (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-super.js        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/LayoutTests/js/script-tests/class-syntax-super.js        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -113,12 +113,12 @@
</span><span class="cx"> shouldBeFalse('x instanceof Base');
</span><span class="cx"> shouldThrow('new (class extends Base { constructor() { } })', '&quot;ReferenceError: Cannot access uninitialized variable.&quot;');
</span><span class="cx"> shouldThrow('new (class extends Base { constructor() { return 1; } })', '&quot;TypeError: Cannot return a non-object type in the constructor of a derived class.&quot;');
</span><del>-shouldThrow('new (class extends null { constructor() { return undefined } })');
</del><ins>+shouldNotThrow('new (class extends null { constructor() { return undefined } })');
</ins><span class="cx"> shouldThrow('new (class extends null { constructor() { super(); return undefined } })', '&quot;TypeError: function is not a constructor (evaluating \'super()\')&quot;');
</span><span class="cx"> shouldBe('x = { }; new (class extends null { constructor() { return x } });', 'x');
</span><span class="cx"> shouldBeTrue('x instanceof Object');
</span><del>-shouldThrow('new (class extends null { constructor() { } })', '&quot;ReferenceError: Cannot access uninitialized variable.&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;');
</del><ins>+shouldNotThrow('new (class extends null { constructor() { } })');
+shouldNotThrow('new (class extends null { constructor() { return 1; } })');
</ins><span class="cx"> shouldThrow('new (class extends null { constructor() { super() } })', '&quot;TypeError: function is not a constructor (evaluating \'super()\')&quot;');
</span><span class="cx"> shouldThrow('new (class { constructor() { super() } })', '&quot;SyntaxError: super is not valid in this context.&quot;');
</span><span class="cx"> shouldThrow('function x() { super(); }', '&quot;SyntaxError: super is not valid in this context.&quot;');
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2016-08-02  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        update a class extending null w.r.t the ES7 spec
+        https://bugs.webkit.org/show_bug.cgi?id=160417
+
+        Reviewed by Keith Miller.
+
+        When a class extends null, it should not be marked as a derived class.
+        This was changed in the ES2016 spec, and this patch makes the needed
+        changes in JSC to follow the spec. This allows classes to extend
+        null and have their default constructor invoked without throwing an exception.
+        This also prevents |this| from being under TDZ at the start of the constructor.
+        Because ES6 allows arbitrary expressions in the `class &lt;ident&gt; extends &lt;expr&gt;`
+        syntax, we don't know statically if a constructor is extending null or not.
+        Therefore, we don't always know statically if it's a base or derived constructor.
+        I solved this by putting a boolean on the constructor function under a private
+        symbol named isDerivedConstructor when doing class construction. We only need
+        to put this boolean on constructors that may extend null. Constructors that are
+        declared in a class with no extends syntax can tell statically that they are a base constructor.
+
+        I've also renamed the ConstructorKind::Derived enum value to be
+        ConstructorKind::Extends to better indicate that we can't answer
+        the &quot;am I a derived constructor?&quot; question statically.
+
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createDefaultConstructor):
+        * builtins/BuiltinNames.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
+        (JSC::BytecodeGenerator::emitReturn):
+        (JSC::BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment):
+        (JSC::BytecodeGenerator::ensureThis):
+        (JSC::BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::makeFunction):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::EvalFunctionCallNode::emitBytecode):
+        (JSC::FunctionCallValueNode::emitBytecode):
+        (JSC::FunctionNode::emitBytecode):
+        (JSC::ClassExprNode::emitBytecode):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::Parser):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionInfo):
+        (JSC::Parser&lt;LexerType&gt;::parseClass):
+        (JSC::Parser&lt;LexerType&gt;::parseMemberExpression):
+        * parser/ParserModes.h:
+
</ins><span class="cx"> 2016-08-02  Enrica Casucci  &lt;enrica@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Allow building with content filtering disabled.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebuiltinsBuiltinExecutablescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx">         break;
</span><span class="cx">     case ConstructorKind::Base:
</span><span class="cx">         return createExecutable(m_vm, makeSource(baseConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
</span><del>-    case ConstructorKind::Derived:
</del><ins>+    case ConstructorKind::Extends:
</ins><span class="cx">         return createExecutable(m_vm, makeSource(derivedConstructorCode), name, constructorKind, ConstructAbility::CanConstruct);
</span><span class="cx">     }
</span><span class="cx">     ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebuiltinsBuiltinNamesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/builtins/BuiltinNames.h (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/builtins/BuiltinNames.h        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/builtins/BuiltinNames.h        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -127,6 +127,7 @@
</span><span class="cx">     macro(isArray) \
</span><span class="cx">     macro(isArrayConstructor) \
</span><span class="cx">     macro(isConstructor) \
</span><ins>+    macro(isDerivedConstructor) \
</ins><span class="cx">     macro(isRegExpObject) \
</span><span class="cx">     macro(concatMemcpy) \
</span><span class="cx">     macro(appendMemcpy) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -560,9 +560,18 @@
</span><span class="cx">         if (SourceParseMode::ArrowFunctionMode != parseMode) {
</span><span class="cx">             if (isConstructor()) {
</span><span class="cx">                 emitMove(m_newTargetRegister, &amp;m_thisRegister);
</span><del>-                if (constructorKind() == ConstructorKind::Derived)
</del><ins>+                if (constructorKind() == ConstructorKind::Extends) {
+                    RefPtr&lt;Label&gt; isDerived = newLabel();
+                    RefPtr&lt;Label&gt; done = newLabel();
+                    m_isDerivedConstuctor = addVar();
+                    emitGetById(m_isDerivedConstuctor, &amp;m_calleeRegister, propertyNames().builtinNames().isDerivedConstructorPrivateName());
+                    emitJumpIfTrue(m_isDerivedConstuctor, isDerived.get());
+                    emitCreateThis(&amp;m_thisRegister);
+                    emitJump(done.get());
+                    emitLabel(isDerived.get());
</ins><span class="cx">                     emitMoveEmptyValue(&amp;m_thisRegister);
</span><del>-                else
</del><ins>+                    emitLabel(done.get());
+                } else
</ins><span class="cx">                     emitCreateThis(&amp;m_thisRegister);
</span><span class="cx">             } else if (constructorKind() != ConstructorKind::None)
</span><span class="cx">                 emitThrowTypeError(&quot;Cannot call a class constructor without |new|&quot;);
</span><span class="lines">@@ -948,7 +957,7 @@
</span><span class="cx">             functionSymbolTable-&gt;set(NoLockingNecessary, propertyNames().builtinNames().newTargetLocalPrivateName().impl(), SymbolTableEntry(VarOffset(offset)));
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        if (isConstructor() &amp;&amp; constructorKind() == ConstructorKind::Derived &amp;&amp; isSuperUsedInInnerArrowFunction()) {
</del><ins>+        if (isConstructor() &amp;&amp; constructorKind() == ConstructorKind::Extends &amp;&amp; isSuperUsedInInnerArrowFunction()) {
</ins><span class="cx">             offset = functionSymbolTable-&gt;takeNextScopeOffset(NoLockingNecessary);
</span><span class="cx">             functionSymbolTable-&gt;set(NoLockingNecessary, propertyNames().builtinNames().derivedConstructorPrivateName().impl(), SymbolTableEntry(VarOffset(offset)));
</span><span class="cx">         }
</span><span class="lines">@@ -970,7 +979,7 @@
</span><span class="cx">         addTarget.iterator-&gt;value.setIsLet();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (isConstructor() &amp;&amp; constructorKind() == ConstructorKind::Derived &amp;&amp; isSuperUsedInInnerArrowFunction()) {
</del><ins>+    if (isConstructor() &amp;&amp; constructorKind() == ConstructorKind::Extends &amp;&amp; isSuperUsedInInnerArrowFunction()) {
</ins><span class="cx">         auto derivedConstructor = environment.add(propertyNames().builtinNames().derivedConstructorPrivateName());
</span><span class="cx">         derivedConstructor.iterator-&gt;value.setIsCaptured();
</span><span class="cx">         derivedConstructor.iterator-&gt;value.setIsLet();
</span><span class="lines">@@ -3265,10 +3274,10 @@
</span><span class="cx"> RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
</span><span class="cx"> {
</span><span class="cx">     if (isConstructor()) {
</span><del>-        bool derived = constructorKind() == ConstructorKind::Derived;
</del><ins>+        bool mightBeDerived = constructorKind() == ConstructorKind::Extends;
</ins><span class="cx">         bool srcIsThis = src-&gt;index() == m_thisRegister.index();
</span><span class="cx"> 
</span><del>-        if (derived &amp;&amp; srcIsThis)
</del><ins>+        if (mightBeDerived &amp;&amp; srcIsThis)
</ins><span class="cx">             emitTDZCheck(src);
</span><span class="cx"> 
</span><span class="cx">         if (!srcIsThis) {
</span><span class="lines">@@ -3275,14 +3284,18 @@
</span><span class="cx">             RefPtr&lt;Label&gt; isObjectLabel = newLabel();
</span><span class="cx">             emitJumpIfTrue(emitIsObject(newTemporary(), src), isObjectLabel.get());
</span><span class="cx"> 
</span><del>-            if (derived) {
</del><ins>+            if (mightBeDerived) {
+                ASSERT(m_isDerivedConstuctor);
+                RefPtr&lt;Label&gt; returnThis = newLabel();
+                emitJumpIfFalse(m_isDerivedConstuctor, returnThis.get());
+                // Else, we're a derived constructor here.
</ins><span class="cx">                 RefPtr&lt;Label&gt; isUndefinedLabel = newLabel();
</span><span class="cx">                 emitJumpIfTrue(emitIsUndefined(newTemporary(), src), isUndefinedLabel.get());
</span><span class="cx">                 emitThrowTypeError(&quot;Cannot return a non-object type in the constructor of a derived class.&quot;);
</span><span class="cx">                 emitLabel(isUndefinedLabel.get());
</span><span class="cx">                 emitTDZCheck(&amp;m_thisRegister);
</span><ins>+                emitLabel(returnThis.get());
</ins><span class="cx">             }
</span><del>-
</del><span class="cx">             emitUnaryNoDstOp(op_ret, &amp;m_thisRegister);
</span><span class="cx">             emitLabel(isObjectLabel.get());
</span><span class="cx">         }
</span><span class="lines">@@ -4285,7 +4298,7 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitLoadArrowFunctionLexicalEnvironment(const Identifier&amp; identifier)
</span><span class="cx"> {
</span><del>-    ASSERT(m_codeBlock-&gt;isArrowFunction() || m_codeBlock-&gt;isArrowFunctionContext() || constructorKind() == ConstructorKind::Derived || m_codeType == EvalCode);
</del><ins>+    ASSERT(m_codeBlock-&gt;isArrowFunction() || m_codeBlock-&gt;isArrowFunctionContext() || constructorKind() == ConstructorKind::Extends || m_codeType == EvalCode);
</ins><span class="cx"> 
</span><span class="cx">     return emitResolveScope(nullptr, variable(identifier, ThisResolutionType::Scoped));
</span><span class="cx"> }
</span><span class="lines">@@ -4311,10 +4324,10 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::ensureThis()
</span><span class="cx"> {
</span><del>-    if (constructorKind() == ConstructorKind::Derived &amp;&amp; needsToUpdateArrowFunctionContext() &amp;&amp; isSuperCallUsedInInnerArrowFunction())
</del><ins>+    if (constructorKind() == ConstructorKind::Extends &amp;&amp; needsToUpdateArrowFunctionContext() &amp;&amp; isSuperCallUsedInInnerArrowFunction())
</ins><span class="cx">         emitLoadThisFromArrowFunctionLexicalEnvironment();
</span><span class="cx"> 
</span><del>-    if (constructorKind() == ConstructorKind::Derived || isDerivedConstructorContext())
</del><ins>+    if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext())
</ins><span class="cx">         emitTDZCheck(thisRegister());
</span><span class="cx"> 
</span><span class="cx">     return thisRegister();
</span><span class="lines">@@ -4357,7 +4370,7 @@
</span><span class="cx">     
</span><span class="cx"> void BytecodeGenerator::emitPutDerivedConstructorToArrowFunctionContextScope()
</span><span class="cx"> {
</span><del>-    if ((isConstructor() &amp;&amp; constructorKind() == ConstructorKind::Derived) || m_codeBlock-&gt;isClassContext()) {
</del><ins>+    if ((isConstructor() &amp;&amp; constructorKind() == ConstructorKind::Extends) || m_codeBlock-&gt;isClassContext()) {
</ins><span class="cx">         if (isSuperUsedInInnerArrowFunction()) {
</span><span class="cx">             ASSERT(m_arrowFunctionContextLexicalEnvironmentRegister);
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -829,7 +829,7 @@
</span><span class="cx">             DerivedContextType newDerivedContextType = DerivedContextType::None;
</span><span class="cx"> 
</span><span class="cx">             if (metadata-&gt;parseMode() == SourceParseMode::ArrowFunctionMode) {
</span><del>-                if (constructorKind() == ConstructorKind::Derived || isDerivedConstructorContext())
</del><ins>+                if (constructorKind() == ConstructorKind::Extends || isDerivedConstructorContext())
</ins><span class="cx">                     newDerivedContextType = DerivedContextType::DerivedConstructorContext;
</span><span class="cx">                 else if (m_codeBlock-&gt;isClassContext() || isDerivedClassContext())
</span><span class="cx">                     newDerivedContextType = DerivedContextType::DerivedMethodContext;
</span><span class="lines">@@ -910,6 +910,7 @@
</span><span class="cx">         RegisterID* m_emptyValueRegister { nullptr };
</span><span class="cx">         RegisterID* m_globalObjectRegister { nullptr };
</span><span class="cx">         RegisterID* m_newTargetRegister { nullptr };
</span><ins>+        RegisterID* m_isDerivedConstuctor { nullptr };
</ins><span class="cx">         RegisterID* m_linkTimeConstantRegisters[LinkTimeConstantCount];
</span><span class="cx">         RegisterID* m_arrowFunctionContextLexicalEnvironmentRegister { nullptr };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -751,7 +751,7 @@
</span><span class="cx">     //       eval(&quot;this.id = 'B'&quot;);
</span><span class="cx">     //    }
</span><span class="cx">     // }
</span><del>-    if (generator.constructorKind() == ConstructorKind::Derived &amp;&amp; generator.needsToUpdateArrowFunctionContext() &amp;&amp; generator.isThisUsedInInnerArrowFunction())
</del><ins>+    if (generator.constructorKind() == ConstructorKind::Extends &amp;&amp; generator.needsToUpdateArrowFunctionContext() &amp;&amp; generator.isThisUsedInInnerArrowFunction())
</ins><span class="cx">         generator.emitLoadThisFromArrowFunctionLexicalEnvironment();
</span><span class="cx"> 
</span><span class="cx">     Variable var = generator.variable(generator.propertyNames().eval);
</span><span class="lines">@@ -785,11 +785,11 @@
</span><span class="cx">         CallArguments callArguments(generator, m_args);
</span><span class="cx"> 
</span><span class="cx">         ASSERT(generator.isConstructor() || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
</span><del>-        ASSERT(generator.constructorKind() == ConstructorKind::Derived || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
</del><ins>+        ASSERT(generator.constructorKind() == ConstructorKind::Extends || generator.derivedContextType() == DerivedContextType::DerivedConstructorContext);
</ins><span class="cx">         generator.emitMove(callArguments.thisRegister(), generator.newTarget());
</span><span class="cx">         RegisterID* ret = generator.emitConstruct(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
</span><span class="cx"> 
</span><del>-        bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Derived;
</del><ins>+        bool isConstructorKindDerived = generator.constructorKind() == ConstructorKind::Extends;
</ins><span class="cx">         bool doWeUseArrowFunctionInConstructor = isConstructorKindDerived &amp;&amp; generator.needsToUpdateArrowFunctionContext();
</span><span class="cx"> 
</span><span class="cx">         if (generator.isDerivedConstructorContext() || (doWeUseArrowFunctionInConstructor &amp;&amp; generator.isSuperCallUsedInInnerArrowFunction()))
</span><span class="lines">@@ -3364,7 +3364,7 @@
</span><span class="cx"> 
</span><span class="cx">         // If there is no return we must automatically insert one.
</span><span class="cx">         if (!returnNode) {
</span><del>-            if (generator.constructorKind() == ConstructorKind::Derived &amp;&amp; generator.needsToUpdateArrowFunctionContext() &amp;&amp; generator.isSuperCallUsedInInnerArrowFunction())
</del><ins>+            if (generator.constructorKind() == ConstructorKind::Extends &amp;&amp; generator.needsToUpdateArrowFunctionContext() &amp;&amp; generator.isSuperCallUsedInInnerArrowFunction())
</ins><span class="cx">                 generator.emitLoadThisFromArrowFunctionLexicalEnvironment(); // Arrow function can invoke 'super' in constructor and before leave constructor we need load 'this' from lexical arrow function environment
</span><span class="cx">             
</span><span class="cx">             RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
</span><span class="lines">@@ -3460,10 +3460,32 @@
</span><span class="cx">         metadata-&gt;setEcmaName(ecmaName());
</span><span class="cx">         metadata-&gt;setClassSource(m_classSource);
</span><span class="cx">         constructor = generator.emitNode(dst, m_constructorExpression);
</span><ins>+        if (m_classHeritage) {
+            RefPtr&lt;RegisterID&gt; isDerivedConstructor = generator.newTemporary();
+            generator.emitUnaryOp(op_not, isDerivedConstructor.get(),
+                generator.emitUnaryOp(op_eq_null, isDerivedConstructor.get(), superclass.get()));
+            generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), isDerivedConstructor.get(), PropertyNode::Unknown);
+        }
</ins><span class="cx">     } else {
</span><del>-        constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
-            m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base,
-            m_name, ecmaName(), m_classSource);
</del><ins>+        if (m_classHeritage) {
+            constructor = generator.finalDestination(dst);
+            RefPtr&lt;RegisterID&gt; tempRegister = generator.newTemporary();
+            RefPtr&lt;Label&gt; superclassIsNullLabel = generator.newLabel();
+            RefPtr&lt;Label&gt; done = generator.newLabel();
+
+            generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
+            generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Extends, m_name, ecmaName(), m_classSource);
+            generator.emitLoad(tempRegister.get(), jsBoolean(true));
+            generator.emitJump(done.get());
+            generator.emitLabel(superclassIsNullLabel.get());
+            generator.emitNewDefaultConstructor(constructor.get(), ConstructorKind::Base, m_name, ecmaName(), m_classSource);
+            generator.emitLoad(tempRegister.get(), jsBoolean(false));
+            generator.emitLabel(done.get());
+            generator.emitDirectPutById(constructor.get(), generator.propertyNames().builtinNames().isDerivedConstructorPrivateName(), tempRegister.get(), PropertyNode::Unknown);
+        } else {
+            constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst),
+                ConstructorKind::Base, m_name, ecmaName(), m_classSource);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     const auto&amp; propertyNames = generator.propertyNames();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -224,7 +224,7 @@
</span><span class="cx">         scope-&gt;setEvalContextType(evalContextType);
</span><span class="cx">     
</span><span class="cx">     if (derivedContextType == DerivedContextType::DerivedConstructorContext) {
</span><del>-        scope-&gt;setConstructorKind(ConstructorKind::Derived);
</del><ins>+        scope-&gt;setConstructorKind(ConstructorKind::Extends);
</ins><span class="cx">         scope-&gt;setExpectedSuperBinding(SuperBinding::Needed);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -2101,7 +2101,7 @@
</span><span class="cx">     
</span><span class="cx">         if (m_defaultConstructorKind != ConstructorKind::None) {
</span><span class="cx">             constructorKind = m_defaultConstructorKind;
</span><del>-            expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Derived ? SuperBinding::Needed : SuperBinding::NotNeeded;
</del><ins>+            expectedSuperBinding = m_defaultConstructorKind == ConstructorKind::Extends ? SuperBinding::Needed : SuperBinding::NotNeeded;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         functionBodyType = StandardFunctionBodyBlock;
</span><span class="lines">@@ -2303,7 +2303,7 @@
</span><span class="cx">         parentClass = parseMemberExpression(context);
</span><span class="cx">         failIfFalse(parentClass, &quot;Cannot parse the parent class name&quot;);
</span><span class="cx">     }
</span><del>-    const ConstructorKind constructorKind = parentClass ? ConstructorKind::Derived : ConstructorKind::Base;
</del><ins>+    const ConstructorKind constructorKind = parentClass ? ConstructorKind::Extends : ConstructorKind::Base;
</ins><span class="cx"> 
</span><span class="cx">     consumeOrFail(OPENBRACE, &quot;Expected opening '{' at the start of a class body&quot;);
</span><span class="cx"> 
</span><span class="lines">@@ -4017,7 +4017,7 @@
</span><span class="cx">                                 ? functionScope-&gt;constructorKind()
</span><span class="cx">                                 : closestOrdinaryFunctionScope-&gt;constructorKind();
</span><span class="cx">                             semanticFailIfTrue(functionConstructorKind == ConstructorKind::None, &quot;super is not valid in this context&quot;);
</span><del>-                            semanticFailIfTrue(functionConstructorKind != ConstructorKind::Derived, &quot;super is not valid in this context&quot;);
</del><ins>+                            semanticFailIfTrue(functionConstructorKind != ConstructorKind::Extends, &quot;super is not valid in this context&quot;);
</ins><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                     if (currentScope()-&gt;isArrowFunction())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserModesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ParserModes.h (204057 => 204058)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ParserModes.h        2016-08-03 01:22:25 UTC (rev 204057)
+++ trunk/Source/JavaScriptCore/parser/ParserModes.h        2016-08-03 01:28:16 UTC (rev 204058)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> enum class JSParserBuiltinMode { NotBuiltin, Builtin };
</span><span class="cx"> enum class JSParserCodeType { Program, Function, Module };
</span><span class="cx"> 
</span><del>-enum class ConstructorKind { None, Base, Derived };
</del><ins>+enum class ConstructorKind { None, Base, Extends };
</ins><span class="cx"> enum class SuperBinding { Needed, NotNeeded };
</span><span class="cx"> 
</span><span class="cx"> enum DebuggerMode { DebuggerOff, DebuggerOn };
</span></span></pre>
</div>
</div>

</body>
</html>