<!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>[183316] 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/183316">183316</a></dd>
<dt>Author</dt> <dd>rniwa@webkit.org</dd>
<dt>Date</dt> <dd>2015-04-25 15:03:30 -0700 (Sat, 25 Apr 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>class methods should be non-enumerable
https://bugs.webkit.org/show_bug.cgi?id=143181

Reviewed by Darin Adler.

Source/JavaScriptCore:

Fixed the bug by using Object.defineProperty to define methods.

This patch adds the concept of link time constants and uses it to resolve Object.defineProperty
inside CodeBlock's constructor since bytecode can be linked against multiple global objects.

* bytecode/CodeBlock.cpp: 
(JSC::CodeBlock::CodeBlock): Resolve link time constants that are used. Ignore ones with register
index of zero.
* bytecode/SpecialPointer.h: Added a new enum for link time constants. It currently contains
exactly one entry for Object.defineProperty.
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::addConstant): Added. Like addConstant that takes JSValue, allocate a new
constant register for the link time constant we're adding.
(JSC::UnlinkedCodeBlock::registerIndexForLinkTimeConstant): Added.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitMoveLinkTimeConstant): Added. Like addConstantValue, allocate a new
register for the specified link time constant and notify UnlinkedCodeBlock about it.
(JSC::BytecodeGenerator::emitCallDefineProperty): Added. Create a new property descriptor and call
Object.defineProperty with it.
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::PropertyListNode::emitBytecode): Make static and non-static getters and setters for classes
non-enumerable by using emitCallDefineProperty to define them.
(JSC::PropertyListNode::emitPutConstantProperty): Ditto for a non-accessor properties.
(JSC::ClassExprNode::emitBytecode): Make prototype.constructor non-enumerable and make prototype
property on the class non-writable, non-configurable, and non-enumerable by using defineProperty.
* runtime/CommonIdentifiers.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init): Set m_definePropertyFunction.
(JSC::JSGlobalObject::visitChildren): Visit m_definePropertyFunction.
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::definePropertyFunction): Added.
(JSC::JSGlobalObject::actualPointerFor): Added a variant that takes LinkTimeConstant.
(JSC::JSGlobalObject::jsCellForLinkTimeConstant): Like actualPointerFor, takes LinkTimeConstant and
returns a JSCell; e.g. Object.defineProperty.
* runtime/ObjectConstructor.cpp:
(JSC::ObjectConstructor::addDefineProperty): Added. Returns Object.defineProperty.
* runtime/ObjectConstructor.h:

LayoutTests:

Added a regression test.

Also fixed a test that previously relied on &quot;prototype&quot; property being writable
since this is no longer the case.

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

<h3>Modified Paths</h3>
<ul>
<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="#trunkLayoutTestsjsscripttestsclasssyntaxextendsjs">trunk/LayoutTests/js/script-tests/class-syntax-extends.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeSpecialPointerh">trunk/Source/JavaScriptCore/bytecode/SpecialPointer.h</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="#trunkSourceJavaScriptCoreruntimeCommonIdentifiersh">trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjecth">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeObjectConstructorcpp">trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeObjectConstructorh">trunk/Source/JavaScriptCore/runtime/ObjectConstructor.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsclasssyntaxprototypeexpectedtxt">trunk/LayoutTests/js/class-syntax-prototype-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsclasssyntaxprototypehtml">trunk/LayoutTests/js/class-syntax-prototype.html</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsclasssyntaxprototypejs">trunk/LayoutTests/js/script-tests/class-syntax-prototype.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/LayoutTests/ChangeLog        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2015-04-23  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        class methods should be non-enumerable
+        https://bugs.webkit.org/show_bug.cgi?id=143181
+
+        Reviewed by Darin Adler.
+
+        Added a regression test.
+
+        Also fixed a test that previously relied on &quot;prototype&quot; property being writable
+        since this is no longer the case.
+
+        * js/class-syntax-extends-expected.txt:
+        * js/class-syntax-prototype.html: Added.
+        * js/script-tests/class-syntax-extends.js:
+        * js/script-tests/class-syntax-prototype.js: Added.
+
</ins><span class="cx"> 2015-04-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Implement String.fromCodePoint
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxextendsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/class-syntax-extends-expected.txt (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-extends-expected.txt        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/LayoutTests/js/class-syntax-extends-expected.txt        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> PASS x.__proto__ is Function.prototype
</span><span class="cx"> PASS x = class extends 3 { constructor() { } }; x.__proto__ threw exception TypeError: The superclass is not an object..
</span><span class="cx"> PASS x = class extends &quot;abc&quot; { constructor() { } }; x.__proto__ threw exception TypeError: The superclass is not an object..
</span><del>-PASS baseWithBadPrototype = class { constructor() { } }; baseWithBadPrototype.prototype = 3 did not throw exception.
</del><ins>+PASS baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype did not throw exception.
</ins><span class="cx"> PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
</span><span class="cx"> PASS baseWithBadPrototype.prototype = &quot;abc&quot; did not throw exception.
</span><span class="cx"> PASS x = class extends baseWithBadPrototype { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
</span></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxprototypeexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-prototype-expected.txt (0 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-prototype-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-prototype-expected.txt        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+Tests for the descriptors of the properties implicitly defined by ES6 class syntax
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS class A {}; descriptor(A, &quot;prototype&quot;).writable is false
+PASS class A {}; var x = A.prototype; A.prototype = 3; A.prototype is x
+PASS class A {}; descriptor(A, &quot;prototype&quot;).enumerable is false
+PASS class A {}; A.foo = &quot;foo&quot;; enumeratedProperties(A).includes(&quot;foo&quot;) is true
+PASS class A {}; enumeratedProperties(A).includes(&quot;prototype&quot;) is false
+PASS class A {}; descriptor(A, &quot;prototype&quot;).configurable is false
+PASS class A {}; Object.defineProperty(A, &quot;prototype&quot;, {value: &quot;foo&quot;}) threw exception TypeError: Attempting to change value of a readonly property..
+PASS class A { static foo() {} }; descriptor(A, &quot;foo&quot;).writable is true
+PASS class A { static foo() {} }; A.foo = 3; A.foo is 3
+PASS class A { static foo() {} }; descriptor(A, &quot;foo&quot;).enumerable is false
+PASS class A { static foo() {} }; enumeratedProperties(A).includes(&quot;foo&quot;) is false
+PASS class A { static foo() {} }; descriptor(A, &quot;foo&quot;).configurable is true
+PASS class A { static foo() {} }; Object.defineProperty(A, &quot;foo&quot;, {value: &quot;bar&quot;}); A.foo is &quot;bar&quot;
+PASS class A { static get foo() {} }; descriptor(A, &quot;foo&quot;).writable is undefined
+PASS class A { static get foo() { return 5; } }; A.foo = 3; A.foo is 5
+PASS class A { static get foo() {} }; descriptor(A, &quot;foo&quot;).enumerable is false
+PASS class A { static get foo() {} }; enumeratedProperties(A).includes(&quot;foo&quot;) is false
+PASS class A { static get foo() {} }; enumeratedProperties(new A).includes(&quot;foo&quot;) is false
+PASS class A { static get foo() {} }; descriptor(A, &quot;foo&quot;).configurable is true
+PASS class A { static get foo() {} }; Object.defineProperty(A, &quot;foo&quot;, {value: &quot;bar&quot;}); A.foo is &quot;bar&quot;
+PASS class A { foo() {} }; descriptor(A.prototype, &quot;foo&quot;).writable is true
+PASS class A { foo() {} }; A.prototype.foo = 3; A.prototype.foo is 3
+PASS class A { foo() {} }; descriptor(A.prototype, &quot;foo&quot;).enumerable is false
+PASS class A { foo() {} }; enumeratedProperties(A.prototype).includes(&quot;foo&quot;) is false
+PASS class A { foo() {} }; enumeratedProperties(new A).includes(&quot;foo&quot;) is false
+PASS class A { foo() {} }; descriptor(A.prototype, &quot;foo&quot;).configurable is true
+PASS class A { foo() {} }; Object.defineProperty(A.prototype, &quot;foo&quot;, {value: &quot;bar&quot;}); A.prototype.foo is &quot;bar&quot;
+PASS class A { get foo() {} }; descriptor(A.prototype, &quot;foo&quot;).writable is undefined
+PASS class A { get foo() { return 5; } }; A.prototype.foo = 3; A.prototype.foo is 5
+PASS class A { get foo() {} }; descriptor(A.prototype, &quot;foo&quot;).enumerable is false
+PASS class A { get foo() {} }; enumeratedProperties(A.prototype).includes(&quot;foo&quot;) is false
+PASS class A { get foo() {} }; enumeratedProperties(new A).includes(&quot;foo&quot;) is false
+PASS class A { get foo() {} }; descriptor(A.prototype, &quot;foo&quot;).configurable is true
+PASS class A { get foo() {} }; Object.defineProperty(A.prototype, &quot;foo&quot;, {value: &quot;bar&quot;}); A.prototype.foo is &quot;bar&quot;
+PASS class A { }; descriptor(A.prototype, &quot;constructor&quot;).writable is true
+PASS class A { }; A.prototype.constructor = 3; A.prototype.constructor is 3
+PASS class A { }; x = {}; A.prototype.constructor = function () { return x; }; (new A) instanceof A is true
+PASS class A { }; descriptor(A.prototype, &quot;constructor&quot;).enumerable is false
+PASS class A { }; enumeratedProperties(A.prototype).includes(&quot;constructor&quot;) is false
+PASS class A { }; enumeratedProperties(new A).includes(&quot;constructor&quot;) is false
+PASS class A { }; descriptor(A.prototype, &quot;constructor&quot;).configurable is true
+PASS class A { }; Object.defineProperty(A.prototype, &quot;constructor&quot;, {value: &quot;bar&quot;}); A.prototype.constructor is &quot;bar&quot;
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsclasssyntaxprototypehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/class-syntax-prototype.html (0 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/class-syntax-prototype.html                                (rev 0)
+++ trunk/LayoutTests/js/class-syntax-prototype.html        2015-04-25 22:03:30 UTC (rev 183316)
</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-prototype.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="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/class-syntax-extends.js (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-extends.js        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/LayoutTests/js/script-tests/class-syntax-extends.js        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx"> shouldBe('x.__proto__', 'Function.prototype');
</span><span class="cx"> shouldThrow('x = class extends 3 { constructor() { } }; x.__proto__', '&quot;TypeError: The superclass is not an object.&quot;');
</span><span class="cx"> shouldThrow('x = class extends &quot;abc&quot; { constructor() { } }; x.__proto__', '&quot;TypeError: The superclass is not an object.&quot;');
</span><del>-shouldNotThrow('baseWithBadPrototype = class { constructor() { } }; baseWithBadPrototype.prototype = 3');
</del><ins>+shouldNotThrow('baseWithBadPrototype = function () {}; baseWithBadPrototype.prototype = 3; new baseWithBadPrototype');
</ins><span class="cx"> shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '&quot;TypeError: The superclass\'s prototype is not an object.&quot;');
</span><span class="cx"> shouldNotThrow('baseWithBadPrototype.prototype = &quot;abc&quot;');
</span><span class="cx"> shouldThrow('x = class extends baseWithBadPrototype { constructor() { } }', '&quot;TypeError: The superclass\'s prototype is not an object.&quot;');
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsclasssyntaxprototypejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/class-syntax-prototype.js (0 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/class-syntax-prototype.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/class-syntax-prototype.js        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -0,0 +1,62 @@
</span><ins>+description('Tests for the descriptors of the properties implicitly defined by ES6 class syntax');
+
+function descriptor(object, propertyName) {
+    return Object.getOwnPropertyDescriptor(object, propertyName);
+}
+
+function enumeratedProperties(object) {
+    var properties = [];
+    for (var propertyName in object)
+        properties.push(propertyName);
+    return properties;
+}
+
+shouldBeFalse('class A {}; descriptor(A, &quot;prototype&quot;).writable');
+shouldBe('class A {}; var x = A.prototype; A.prototype = 3; A.prototype', 'x');
+shouldBeFalse('class A {}; descriptor(A, &quot;prototype&quot;).enumerable');
+shouldBeTrue('class A {}; A.foo = &quot;foo&quot;; enumeratedProperties(A).includes(&quot;foo&quot;)');
+shouldBeFalse('class A {}; enumeratedProperties(A).includes(&quot;prototype&quot;)');
+shouldBeFalse('class A {}; descriptor(A, &quot;prototype&quot;).configurable');
+shouldThrow('class A {}; Object.defineProperty(A, &quot;prototype&quot;, {value: &quot;foo&quot;})', '&quot;TypeError: Attempting to change value of a readonly property.&quot;');
+
+shouldBeTrue('class A { static foo() {} }; descriptor(A, &quot;foo&quot;).writable');
+shouldBe('class A { static foo() {} }; A.foo = 3; A.foo', '3');
+shouldBeFalse('class A { static foo() {} }; descriptor(A, &quot;foo&quot;).enumerable');
+shouldBeFalse('class A { static foo() {} }; enumeratedProperties(A).includes(&quot;foo&quot;)');
+shouldBeTrue('class A { static foo() {} }; descriptor(A, &quot;foo&quot;).configurable');
+shouldBe('class A { static foo() {} }; Object.defineProperty(A, &quot;foo&quot;, {value: &quot;bar&quot;}); A.foo', '&quot;bar&quot;');
+
+shouldBe('class A { static get foo() {} }; descriptor(A, &quot;foo&quot;).writable', 'undefined');
+shouldBe('class A { static get foo() { return 5; } }; A.foo = 3; A.foo', '5');
+shouldBeFalse('class A { static get foo() {} }; descriptor(A, &quot;foo&quot;).enumerable');
+shouldBeFalse('class A { static get foo() {} }; enumeratedProperties(A).includes(&quot;foo&quot;)');
+shouldBeFalse('class A { static get foo() {} }; enumeratedProperties(new A).includes(&quot;foo&quot;)');
+shouldBeTrue('class A { static get foo() {} }; descriptor(A, &quot;foo&quot;).configurable');
+shouldBe('class A { static get foo() {} }; Object.defineProperty(A, &quot;foo&quot;, {value: &quot;bar&quot;}); A.foo', '&quot;bar&quot;');
+
+shouldBeTrue('class A { foo() {} }; descriptor(A.prototype, &quot;foo&quot;).writable');
+shouldBe('class A { foo() {} }; A.prototype.foo = 3; A.prototype.foo', '3');
+shouldBeFalse('class A { foo() {} }; descriptor(A.prototype, &quot;foo&quot;).enumerable');
+shouldBeFalse('class A { foo() {} }; enumeratedProperties(A.prototype).includes(&quot;foo&quot;)');
+shouldBeFalse('class A { foo() {} }; enumeratedProperties(new A).includes(&quot;foo&quot;)');
+shouldBeTrue('class A { foo() {} }; descriptor(A.prototype, &quot;foo&quot;).configurable');
+shouldBe('class A { foo() {} }; Object.defineProperty(A.prototype, &quot;foo&quot;, {value: &quot;bar&quot;}); A.prototype.foo', '&quot;bar&quot;');
+
+shouldBe('class A { get foo() {} }; descriptor(A.prototype, &quot;foo&quot;).writable', 'undefined');
+shouldBe('class A { get foo() { return 5; } }; A.prototype.foo = 3; A.prototype.foo', '5');
+shouldBeFalse('class A { get foo() {} }; descriptor(A.prototype, &quot;foo&quot;).enumerable');
+shouldBeFalse('class A { get foo() {} }; enumeratedProperties(A.prototype).includes(&quot;foo&quot;)');
+shouldBeFalse('class A { get foo() {} }; enumeratedProperties(new A).includes(&quot;foo&quot;)');
+shouldBeTrue('class A { get foo() {} }; descriptor(A.prototype, &quot;foo&quot;).configurable');
+shouldBe('class A { get foo() {} }; Object.defineProperty(A.prototype, &quot;foo&quot;, {value: &quot;bar&quot;}); A.prototype.foo', '&quot;bar&quot;');
+
+shouldBeTrue('class A { }; descriptor(A.prototype, &quot;constructor&quot;).writable');
+shouldBe('class A { }; A.prototype.constructor = 3; A.prototype.constructor', '3');
+shouldBeTrue('class A { }; x = {}; A.prototype.constructor = function () { return x; }; (new A) instanceof A');
+shouldBeFalse('class A { }; descriptor(A.prototype, &quot;constructor&quot;).enumerable');
+shouldBeFalse('class A { }; enumeratedProperties(A.prototype).includes(&quot;constructor&quot;)');
+shouldBeFalse('class A { }; enumeratedProperties(new A).includes(&quot;constructor&quot;)');
+shouldBeTrue('class A { }; descriptor(A.prototype, &quot;constructor&quot;).configurable');
+shouldBe('class A { }; Object.defineProperty(A.prototype, &quot;constructor&quot;, {value: &quot;bar&quot;}); A.prototype.constructor', '&quot;bar&quot;');
+
+var successfullyParsed = true;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2015-04-23  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
+
+        class methods should be non-enumerable
+        https://bugs.webkit.org/show_bug.cgi?id=143181
+
+        Reviewed by Darin Adler.
+
+        Fixed the bug by using Object.defineProperty to define methods.
+
+        This patch adds the concept of link time constants and uses it to resolve Object.defineProperty
+        inside CodeBlock's constructor since bytecode can be linked against multiple global objects.
+
+        * bytecode/CodeBlock.cpp: 
+        (JSC::CodeBlock::CodeBlock): Resolve link time constants that are used. Ignore ones with register
+        index of zero.
+        * bytecode/SpecialPointer.h: Added a new enum for link time constants. It currently contains
+        exactly one entry for Object.defineProperty.
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::addConstant): Added. Like addConstant that takes JSValue, allocate a new
+        constant register for the link time constant we're adding.
+        (JSC::UnlinkedCodeBlock::registerIndexForLinkTimeConstant): Added.
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitMoveLinkTimeConstant): Added. Like addConstantValue, allocate a new
+        register for the specified link time constant and notify UnlinkedCodeBlock about it.
+        (JSC::BytecodeGenerator::emitCallDefineProperty): Added. Create a new property descriptor and call
+        Object.defineProperty with it.
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::PropertyListNode::emitBytecode): Make static and non-static getters and setters for classes
+        non-enumerable by using emitCallDefineProperty to define them.
+        (JSC::PropertyListNode::emitPutConstantProperty): Ditto for a non-accessor properties.
+        (JSC::ClassExprNode::emitBytecode): Make prototype.constructor non-enumerable and make prototype
+        property on the class non-writable, non-configurable, and non-enumerable by using defineProperty.
+        * runtime/CommonIdentifiers.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init): Set m_definePropertyFunction.
+        (JSC::JSGlobalObject::visitChildren): Visit m_definePropertyFunction.
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::definePropertyFunction): Added.
+        (JSC::JSGlobalObject::actualPointerFor): Added a variant that takes LinkTimeConstant.
+        (JSC::JSGlobalObject::jsCellForLinkTimeConstant): Like actualPointerFor, takes LinkTimeConstant and
+        returns a JSCell; e.g. Object.defineProperty.
+        * runtime/ObjectConstructor.cpp:
+        (JSC::ObjectConstructor::addDefineProperty): Added. Returns Object.defineProperty.
+        * runtime/ObjectConstructor.h:
+
</ins><span class="cx"> 2015-04-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Implement String.fromCodePoint
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -1761,6 +1761,13 @@
</span><span class="cx">     setConstantRegisters(unlinkedCodeBlock-&gt;constantRegisters(), unlinkedCodeBlock-&gt;constantsSourceCodeRepresentation());
</span><span class="cx">     if (unlinkedCodeBlock-&gt;usesGlobalObject())
</span><span class="cx">         m_constantRegisters[unlinkedCodeBlock-&gt;globalObjectRegister().toConstantIndex()].set(*m_vm, ownerExecutable, m_globalObject.get());
</span><ins>+
+    for (unsigned i = 0; i &lt; LinkTimeConstantCount; i++) {
+        LinkTimeConstant type = static_cast&lt;LinkTimeConstant&gt;(i);
+        if (unsigned registerIndex = unlinkedCodeBlock-&gt;registerIndexForLinkTimeConstant(type))
+            m_constantRegisters[registerIndex].set(*m_vm, ownerExecutable, m_globalObject-&gt;jsCellForLinkTimeConstant(type));
+    }
+
</ins><span class="cx">     m_functionDecls.resizeToFit(unlinkedCodeBlock-&gt;numberOfFunctionDecls());
</span><span class="cx">     for (size_t count = unlinkedCodeBlock-&gt;numberOfFunctionDecls(), i = 0; i &lt; count; ++i) {
</span><span class="cx">         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock-&gt;functionDecl(i);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeSpecialPointerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/SpecialPointer.h (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/SpecialPointer.h        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/bytecode/SpecialPointer.h        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -41,6 +41,11 @@
</span><span class="cx"> };
</span><span class="cx"> } // namespace Special
</span><span class="cx"> 
</span><ins>+enum class LinkTimeConstant {
+    DefinePropertyFunction,
+};
+const unsigned LinkTimeConstantCount = 1;
+
</ins><span class="cx"> inline bool pointerIsFunction(Special::Pointer pointer)
</span><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(pointer, pointer &lt; Special::TableSize);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -261,6 +261,8 @@
</span><span class="cx">     , m_bytecodeCommentIterator(0)
</span><span class="cx"> #endif
</span><span class="cx"> {
</span><ins>+    for (auto&amp; constantRegisterIndex : m_linkTimeConstants)
+        constantRegisterIndex = 0;
</ins><span class="cx">     ASSERT(m_constructorKind == static_cast&lt;unsigned&gt;(info.constructorKind()));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -331,6 +331,23 @@
</span><span class="cx">         m_constantsSourceCodeRepresentation.append(sourceCodeRepresentation);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><ins>+    unsigned addConstant(LinkTimeConstant type)
+    {
+        unsigned result = m_constantRegisters.size();
+        ASSERT(result);
+        unsigned index = static_cast&lt;unsigned&gt;(type);
+        ASSERT(index &lt; LinkTimeConstantCount);
+        m_linkTimeConstants[index] = result;
+        m_constantRegisters.append(WriteBarrier&lt;Unknown&gt;());
+        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
+        return result;
+    }
+    unsigned registerIndexForLinkTimeConstant(LinkTimeConstant type)
+    {
+        unsigned index = static_cast&lt;unsigned&gt;(type);
+        ASSERT(index &lt; LinkTimeConstantCount);
+        return m_linkTimeConstants[index];
+    }
</ins><span class="cx">     unsigned addOrFindConstant(JSValue);
</span><span class="cx">     const Vector&lt;WriteBarrier&lt;Unknown&gt;&gt;&amp; constantRegisters() { return m_constantRegisters; }
</span><span class="cx">     const WriteBarrier&lt;Unknown&gt;&amp; constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
</span><span class="lines">@@ -556,6 +573,7 @@
</span><span class="cx">     Vector&lt;Identifier&gt; m_identifiers;
</span><span class="cx">     Vector&lt;WriteBarrier&lt;Unknown&gt;&gt; m_constantRegisters;
</span><span class="cx">     Vector&lt;SourceCodeRepresentation&gt; m_constantsSourceCodeRepresentation;
</span><ins>+    std::array&lt;unsigned, LinkTimeConstantCount&gt; m_linkTimeConstants;
</ins><span class="cx">     typedef Vector&lt;WriteBarrier&lt;UnlinkedFunctionExecutable&gt;&gt; FunctionExpressionVector;
</span><span class="cx">     FunctionExpressionVector m_functionDecls;
</span><span class="cx">     FunctionExpressionVector m_functionExprs;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -149,6 +149,9 @@
</span><span class="cx">     , m_codeType(GlobalCode)
</span><span class="cx">     , m_vm(&amp;vm)
</span><span class="cx"> {
</span><ins>+    for (auto&amp; constantRegister : m_linkTimeConstantRegisters)
+        constantRegister = nullptr;
+
</ins><span class="cx">     m_codeBlock-&gt;setNumParameters(1); // Allocate space for &quot;this&quot;
</span><span class="cx"> 
</span><span class="cx">     emitOpcode(op_enter);
</span><span class="lines">@@ -179,6 +182,9 @@
</span><span class="cx">     , m_vm(&amp;vm)
</span><span class="cx">     , m_isBuiltinFunction(codeBlock-&gt;isBuiltinFunction())
</span><span class="cx"> {
</span><ins>+    for (auto&amp; constantRegister : m_linkTimeConstantRegisters)
+        constantRegister = nullptr;
+
</ins><span class="cx">     if (m_isBuiltinFunction)
</span><span class="cx">         m_shouldEmitDebugHooks = false;
</span><span class="cx">     
</span><span class="lines">@@ -494,6 +500,9 @@
</span><span class="cx">     , m_codeType(EvalCode)
</span><span class="cx">     , m_vm(&amp;vm)
</span><span class="cx"> {
</span><ins>+    for (auto&amp; constantRegister : m_linkTimeConstantRegisters)
+        constantRegister = nullptr;
+
</ins><span class="cx">     m_symbolTable-&gt;setUsesNonStrictEval(codeBlock-&gt;usesEval() &amp;&amp; !codeBlock-&gt;isStrictMode());
</span><span class="cx">     m_codeBlock-&gt;setNumParameters(1);
</span><span class="cx"> 
</span><span class="lines">@@ -984,6 +993,24 @@
</span><span class="cx">     return &amp;m_constantPoolRegisters[index];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeGenerator::emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant type)
+{
+    unsigned constantIndex = static_cast&lt;unsigned&gt;(type);
+    if (!m_linkTimeConstantRegisters[constantIndex]) {
+        int index = m_nextConstantOffset;
+        m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
+        ++m_nextConstantOffset;
+        m_codeBlock-&gt;addConstant(type);
+        m_linkTimeConstantRegisters[constantIndex] = &amp;m_constantPoolRegisters[index];
+    }
+
+    emitOpcode(op_mov);
+    instructions().append(dst-&gt;index());
+    instructions().append(m_linkTimeConstantRegisters[constantIndex]-&gt;index());
+
+    return dst;
+}
+
</ins><span class="cx"> unsigned BytecodeGenerator::addRegExp(RegExp* r)
</span><span class="cx"> {
</span><span class="cx">     return m_codeBlock-&gt;addRegExp(r);
</span><span class="lines">@@ -1950,6 +1977,41 @@
</span><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
+    RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&amp; position)
+{
+    RefPtr&lt;RegisterID&gt; descriptorRegister = emitNewObject(newTemporary());
+
+    RefPtr&lt;RegisterID&gt; trueRegister = emitLoad(newTemporary(), true);
+    if (options &amp; PropertyConfigurable)
+        emitDirectPutById(descriptorRegister.get(), propertyNames().configurable, trueRegister.get(), PropertyNode::Unknown);
+    if (options &amp; PropertyWritable)
+        emitDirectPutById(descriptorRegister.get(), propertyNames().writable, trueRegister.get(), PropertyNode::Unknown);
+    else if (valueRegister) {
+        RefPtr&lt;RegisterID&gt; falseRegister = emitLoad(newTemporary(), false);
+        emitDirectPutById(descriptorRegister.get(), propertyNames().writable, falseRegister.get(), PropertyNode::Unknown);
+    }
+    if (options &amp; PropertyEnumerable)
+        emitDirectPutById(descriptorRegister.get(), propertyNames().enumerable, trueRegister.get(), PropertyNode::Unknown);
+
+    if (valueRegister)
+        emitDirectPutById(descriptorRegister.get(), propertyNames().value, valueRegister, PropertyNode::Unknown);
+    if (getterRegister)
+        emitDirectPutById(descriptorRegister.get(), propertyNames().get, getterRegister, PropertyNode::Unknown);
+    if (setterRegister)
+        emitDirectPutById(descriptorRegister.get(), propertyNames().set, setterRegister, PropertyNode::Unknown);
+
+    RefPtr&lt;RegisterID&gt; definePropertyRegister = emitMoveLinkTimeConstant(newTemporary(), LinkTimeConstant::DefinePropertyFunction);
+
+    CallArguments callArguments(*this, nullptr, 3);
+    emitLoad(callArguments.thisRegister(), jsUndefined());
+    emitMove(callArguments.argumentRegister(0), newObj);
+    emitMove(callArguments.argumentRegister(1), propertyNameRegister);
+    emitMove(callArguments.argumentRegister(2), descriptorRegister.get());
+
+    emitCall(newTemporary(), definePropertyRegister.get(), NoExpectedFunction, callArguments, position, position, position);
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
</span><span class="cx"> {
</span><span class="cx">     if (isConstructor()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -458,6 +458,7 @@
</span><span class="cx">         RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier&amp; name);
</span><span class="cx">         RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
</span><span class="cx"> 
</span><ins>+        RegisterID* emitMoveLinkTimeConstant(RegisterID* dst, LinkTimeConstant);
</ins><span class="cx">         RegisterID* emitMoveEmptyValue(RegisterID* dst);
</span><span class="cx">         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
</span><span class="cx"> 
</span><span class="lines">@@ -489,6 +490,14 @@
</span><span class="cx">         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&amp;, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><span class="cx">         RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><span class="cx"> 
</span><ins>+        enum PropertyDescriptorOption {
+            PropertyConfigurable = 1,
+            PropertyWritable     = 1 &lt;&lt; 1,
+            PropertyEnumerable   = 1 &lt;&lt; 2,
+        };
+        void emitCallDefineProperty(RegisterID* newObj, RegisterID* propertyNameRegister,
+            RegisterID* valueRegister, RegisterID* getterRegister, RegisterID* setterRegister, unsigned options, const JSTextPosition&amp;);
+
</ins><span class="cx">         void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function&lt;void(BytecodeGenerator&amp;, RegisterID*)&gt;&amp; callBack);
</span><span class="cx">         
</span><span class="cx">         RegisterID* emitReturn(RegisterID* src);
</span><span class="lines">@@ -720,6 +729,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_linkTimeConstantRegisters[LinkTimeConstantCount];
</ins><span class="cx"> 
</span><span class="cx">         SegmentedVector&lt;RegisterID, 32&gt; m_constantPoolRegisters;
</span><span class="cx">         SegmentedVector&lt;RegisterID, 32&gt; m_calleeRegisters;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -362,7 +362,8 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             RegisterID* value = generator.emitNode(node-&gt;m_assign);
</span><del>-            if (node-&gt;needsSuperBinding())
</del><ins>+            bool isClassProperty = node-&gt;needsSuperBinding();
+            if (isClassProperty)
</ins><span class="cx">                 emitPutHomeObject(generator, value, dst);
</span><span class="cx"> 
</span><span class="cx">             // This is a get/set property, find its entry in the map.
</span><span class="lines">@@ -403,10 +404,16 @@
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (pair.second &amp;&amp; pair.second-&gt;needsSuperBinding())
</del><ins>+            ASSERT(!pair.second || isClassProperty == pair.second-&gt;needsSuperBinding());
+            if (isClassProperty &amp;&amp; pair.second)
</ins><span class="cx">                 emitPutHomeObject(generator, secondReg, dst);
</span><span class="cx"> 
</span><del>-            generator.emitPutGetterSetter(dst, *node-&gt;name(), getterReg.get(), setterReg.get());
</del><ins>+            if (isClassProperty) {
+                RefPtr&lt;RegisterID&gt; propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node-&gt;name());
+                generator.emitCallDefineProperty(dst, propertyNameRegister.get(),
+                    nullptr, getterReg.get(), setterReg.get(), BytecodeGenerator::PropertyConfigurable, m_position);
+            } else
+                generator.emitPutGetterSetter(dst, *node-&gt;name(), getterReg.get(), setterReg.get());
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -416,8 +423,19 @@
</span><span class="cx"> void PropertyListNode::emitPutConstantProperty(BytecodeGenerator&amp; generator, RegisterID* newObj, PropertyNode&amp; node)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;RegisterID&gt; value = generator.emitNode(node.m_assign);
</span><del>-    if (node.needsSuperBinding())
</del><ins>+    if (node.needsSuperBinding()) {
</ins><span class="cx">         emitPutHomeObject(generator, value.get(), newObj);
</span><ins>+
+        RefPtr&lt;RegisterID&gt; propertyNameRegister;
+        if (node.name())
+            propertyNameRegister = generator.emitLoad(generator.newTemporary(), *node.name());
+        else
+            propertyNameRegister = generator.emitNode(node.m_expression);
+
+        generator.emitCallDefineProperty(newObj, propertyNameRegister.get(),
+            value.get(), nullptr, nullptr, BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
+        return;
+    }
</ins><span class="cx">     if (node.name()) {
</span><span class="cx">         generator.emitDirectPutById(newObj, *node.name(), value.get(), node.putType());
</span><span class="cx">         return;
</span><span class="lines">@@ -2871,7 +2889,6 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;RegisterID&gt; constructor;
</span><del>-    RefPtr&lt;RegisterID&gt; prototype;
</del><span class="cx"> 
</span><span class="cx">     // FIXME: Make the prototype non-configurable &amp; non-writable.
</span><span class="cx">     if (m_constructorExpression)
</span><span class="lines">@@ -2881,7 +2898,8 @@
</span><span class="cx">             m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base, m_name);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    prototype = generator.emitGetById(generator.newTemporary(), constructor.get(), generator.propertyNames().prototype);
</del><ins>+    const auto&amp; propertyNames = generator.propertyNames();
+    RefPtr&lt;RegisterID&gt; prototype = generator.emitNewObject(generator.newTemporary());
</ins><span class="cx"> 
</span><span class="cx">     if (superclass) {
</span><span class="cx">         RefPtr&lt;RegisterID&gt; protoParent = generator.newTemporary();
</span><span class="lines">@@ -2910,6 +2928,13 @@
</span><span class="cx">         emitPutHomeObject(generator, constructor.get(), prototype.get());
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    RefPtr&lt;RegisterID&gt; constructorNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.constructor);
+    generator.emitCallDefineProperty(prototype.get(), constructorNameRegister.get(), constructor.get(), nullptr, nullptr,
+        BytecodeGenerator::PropertyConfigurable | BytecodeGenerator::PropertyWritable, m_position);
+
+    RefPtr&lt;RegisterID&gt; prototypeNameRegister = generator.emitLoad(generator.newTemporary(), propertyNames.prototype);
+    generator.emitCallDefineProperty(constructor.get(), prototypeNameRegister.get(), prototype.get(), nullptr, nullptr, 0, m_position);
+
</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="trunkSourceJavaScriptCoreruntimeCommonIdentifiersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -91,6 +91,7 @@
</span><span class="cx">     macro(constructor) \
</span><span class="cx">     macro(count) \
</span><span class="cx">     macro(counters) \
</span><ins>+    macro(defineProperty) \
</ins><span class="cx">     macro(description) \
</span><span class="cx">     macro(descriptions) \
</span><span class="cx">     macro(displayName) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -332,6 +332,10 @@
</span><span class="cx">     
</span><span class="cx">     ObjectConstructor* objectConstructor = ObjectConstructor::create(vm, this, ObjectConstructor::createStructure(vm, this, m_functionPrototype.get()), m_objectPrototype.get());
</span><span class="cx">     m_objectConstructor.set(vm, this, objectConstructor);
</span><ins>+
+    JSFunction* definePropertyFunction = m_objectConstructor-&gt;addDefineProperty(exec, this);
+    m_definePropertyFunction.set(vm, this, definePropertyFunction);
+
</ins><span class="cx">     JSCell* functionConstructor = FunctionConstructor::create(vm, FunctionConstructor::createStructure(vm, this, m_functionPrototype.get()), m_functionPrototype.get());
</span><span class="cx">     JSCell* arrayConstructor = ArrayConstructor::create(vm, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get());
</span><span class="cx">     
</span><span class="lines">@@ -458,7 +462,9 @@
</span><span class="cx">     m_specialPointers[Special::ApplyFunction] = m_applyFunction.get();
</span><span class="cx">     m_specialPointers[Special::ObjectConstructor] = objectConstructor;
</span><span class="cx">     m_specialPointers[Special::ArrayConstructor] = arrayConstructor;
</span><del>-    
</del><ins>+
+    m_linkTimeConstants[static_cast&lt;unsigned&gt;(LinkTimeConstant::DefinePropertyFunction)] = m_definePropertyFunction.get();
+
</ins><span class="cx">     ConsolePrototype* consolePrototype = ConsolePrototype::create(vm, this, ConsolePrototype::createStructure(vm, this, m_objectPrototype.get()));
</span><span class="cx">     m_consoleStructure.set(vm, this, JSConsole::createStructure(vm, this, consolePrototype));
</span><span class="cx">     JSConsole* consoleObject = JSConsole::create(vm, m_consoleStructure.get());
</span><span class="lines">@@ -717,6 +723,7 @@
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_evalFunction);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_callFunction);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_applyFunction);
</span><ins>+    visitor.append(&amp;thisObject-&gt;m_definePropertyFunction);
</ins><span class="cx">     visitor.append(&amp;thisObject-&gt;m_arrayProtoValuesFunction);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_throwTypeErrorGetterSetter);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -191,6 +191,7 @@
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_evalFunction;
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_callFunction;
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_applyFunction;
</span><ins>+    WriteBarrier&lt;JSFunction&gt; m_definePropertyFunction;
</ins><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_arrayProtoValuesFunction;
</span><span class="cx">     WriteBarrier&lt;GetterSetter&gt; m_throwTypeErrorGetterSetter;
</span><span class="cx"> 
</span><span class="lines">@@ -257,9 +258,10 @@
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     std::array&lt;TypedArrayData, NUMBER_OF_TYPED_ARRAY_TYPES&gt; m_typedArrays;
</span><del>-        
-    void* m_specialPointers[Special::TableSize]; // Special pointers used by the LLInt and JIT.
</del><span class="cx"> 
</span><ins>+    JSCell* m_specialPointers[Special::TableSize]; // Special pointers used by the LLInt and JIT.
+    JSCell* m_linkTimeConstants[LinkTimeConstantCount];
+
</ins><span class="cx">     String m_name;
</span><span class="cx"> 
</span><span class="cx">     Debugger* m_debugger;
</span><span class="lines">@@ -400,6 +402,7 @@
</span><span class="cx">     JSFunction* evalFunction() const { return m_evalFunction.get(); }
</span><span class="cx">     JSFunction* callFunction() const { return m_callFunction.get(); }
</span><span class="cx">     JSFunction* applyFunction() const { return m_applyFunction.get(); }
</span><ins>+    JSFunction* definePropertyFunction() const { return m_definePropertyFunction.get(); }
</ins><span class="cx">     JSFunction* arrayProtoValuesFunction() const { return m_arrayProtoValuesFunction.get(); }
</span><span class="cx">     GetterSetter* throwTypeErrorGetterSetter(VM&amp; vm)
</span><span class="cx">     {
</span><span class="lines">@@ -523,11 +526,17 @@
</span><span class="cx">         return typedArrayStructure(type) == structure;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void* actualPointerFor(Special::Pointer pointer)
</del><ins>+    JSCell* actualPointerFor(Special::Pointer pointer)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(pointer &lt; Special::TableSize);
</span><span class="cx">         return m_specialPointers[pointer];
</span><span class="cx">     }
</span><ins>+    JSCell* jsCellForLinkTimeConstant(LinkTimeConstant type)
+    {
+        unsigned index = static_cast&lt;unsigned&gt;(type);
+        ASSERT(index &lt; LinkTimeConstantCount);
+        return m_linkTimeConstants[index];
+    }
</ins><span class="cx"> 
</span><span class="cx">     WatchpointSet* masqueradesAsUndefinedWatchpoint() { return m_masqueradesAsUndefinedWatchpoint.get(); }
</span><span class="cx">     WatchpointSet* havingABadTimeWatchpoint() { return m_havingABadTimeWatchpoint.get(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeObjectConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -98,6 +98,14 @@
</span><span class="cx">         JSC_NATIVE_FUNCTION(&quot;getOwnPropertySymbols&quot;, objectConstructorGetOwnPropertySymbols, DontEnum, 1);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSFunction* ObjectConstructor::addDefineProperty(ExecState* exec, JSGlobalObject* globalObject)
+{
+    VM&amp; vm = exec-&gt;vm();
+    JSFunction* definePropertyFunction = JSFunction::create(vm, globalObject, 3, vm.propertyNames-&gt;defineProperty.string(), objectConstructorDefineProperty);
+    putDirectWithoutTransition(vm, vm.propertyNames-&gt;defineProperty, definePropertyFunction, DontEnum);
+    return definePropertyFunction;
+}
+
</ins><span class="cx"> bool ObjectConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &amp;slot)
</span><span class="cx"> {
</span><span class="cx">     return getStaticFunctionSlot&lt;JSObject&gt;(exec, objectConstructorTable, jsCast&lt;ObjectConstructor*&gt;(object), propertyName, slot);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeObjectConstructorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ObjectConstructor.h (183315 => 183316)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ObjectConstructor.h        2015-04-25 22:00:51 UTC (rev 183315)
+++ trunk/Source/JavaScriptCore/runtime/ObjectConstructor.h        2015-04-25 22:03:30 UTC (rev 183316)
</span><span class="lines">@@ -54,6 +54,8 @@
</span><span class="cx">         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    JSFunction* addDefineProperty(ExecState*, JSGlobalObject*);
+
</ins><span class="cx"> protected:
</span><span class="cx">     void finishCreation(VM&amp;, JSGlobalObject*, ObjectPrototype*);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>