<!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>[214038] 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/214038">214038</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-16 05:58:14 -0700 (Thu, 16 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[ESnext] Implement Object Spread
https://bugs.webkit.org/show_bug.cgi?id=167963

Patch by Caio Lima &lt;ticaiolima@gmail.com&gt; on 2017-03-16
Reviewed by Yusuke Suzuki.

JSTests:

* stress/object-spread.js: Added.
(let.assert):
(assert.sameValue):
(let.o.get a):
(let.obj.get c):
(cthulhu.get x):
(let.obj.set c):
(calls.o.get z):
(calls.o.get a):
(try.let.obj.get foo):
(get calls):

Source/JavaScriptCore:

This patch implements ECMA262 stage 3 Object Spread proposal [1].
It's implemented using CopyDataProperties to copy all enumerable keys
from object being spreaded.

It's also fixing CopyDataProperties that was using
Object.getOwnPropertyNames to list all keys to be copied, and now is
using Relect.ownKeys.

[1] - https://github.com/sebmarkbage/ecmascript-rest-spread

* builtins/GlobalOperations.js:
(globalPrivate.copyDataProperties):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::setConstantIdentifierSetRegisters):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::addSetConstant):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitLoad):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::PropertyListNode::emitBytecode):
(JSC::ObjectPatternNode::bindValue):
(JSC::ObjectSpreadExpressionNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createObjectSpreadExpression):
(JSC::ASTBuilder::createProperty):
* parser/NodeConstructors.h:
(JSC::PropertyNode::PropertyNode):
(JSC::ObjectSpreadExpressionNode::ObjectSpreadExpressionNode):
* parser/Nodes.h:
(JSC::ObjectSpreadExpressionNode::expression):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseProperty):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createObjectSpreadExpression):
(JSC::SyntaxChecker::createProperty):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::privateToObject): Deleted.
* runtime/JSGlobalObjectFunctions.h:

LayoutTests:

* js/parser-syntax-check-expected.txt:
* js/script-tests/parser-syntax-check.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsparsersyntaxcheckexpectedtxt">trunk/LayoutTests/js/parser-syntax-check-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsparsersyntaxcheckjs">trunk/LayoutTests/js/script-tests/parser-syntax-check.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebuiltinsGlobalOperationsjs">trunk/Source/JavaScriptCore/builtins/GlobalOperations.js</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodeConstructorsh">trunk/Source/JavaScriptCore/parser/NodeConstructors.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodesh">trunk/Source/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionscpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionsh">trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressobjectspreadjs">trunk/JSTests/stress/object-spread.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/JSTests/ChangeLog        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2017-03-16  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [ESnext] Implement Object Spread
+        https://bugs.webkit.org/show_bug.cgi?id=167963
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/object-spread.js: Added.
+        (let.assert):
+        (assert.sameValue):
+        (let.o.get a):
+        (let.obj.get c):
+        (cthulhu.get x):
+        (let.obj.set c):
+        (calls.o.get z):
+        (calls.o.get a):
+        (try.let.obj.get foo):
+        (get calls):
+
</ins><span class="cx"> 2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Default parameter part should be retrieved by op_get_argument opcode instead of changing arity
</span></span></pre></div>
<a id="trunkJSTestsstressobjectspreadjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/object-spread.js (0 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/object-spread.js                                (rev 0)
+++ trunk/JSTests/stress/object-spread.js        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -0,0 +1,297 @@
</span><ins>+let assert = (a) =&gt; {
+    if (!a)
+        throw new Error(&quot;Bad Assertion&quot;);
+}
+
+assert.sameValue = (a, b) =&gt;  {
+    assert(a === b);
+}
+
+function validatePropertyDescriptor(o, p) {
+    let desc = Object.getOwnPropertyDescriptor(o, p);
+
+    assert(desc.enumerable);
+    assert(desc.configurable);
+    assert(desc.writable);
+}
+
+// Base cases
+
+(() =&gt; {
+    let obj = {a: 1, b: 2, ...{c: 3, d: 4}};
+
+    assert.sameValue(obj.a, 1);
+    assert(obj.b, 2);
+    assert(obj.c, 3);
+    assert(obj.d, 4);
+    validatePropertyDescriptor(obj, &quot;c&quot;);
+    validatePropertyDescriptor(obj, &quot;d&quot;);
+    assert(Object.keys(obj), 2);
+})();
+
+(() =&gt; {
+    let o = {c: 3, d: 4};
+    let obj = {a: 1, b: 2, ...o};
+
+    assert.sameValue(obj.a, 1);
+    assert.sameValue(obj.b, 2);
+    assert.sameValue(obj.c, 3);
+    assert.sameValue(obj.d, 4);
+    assert.sameValue(Object.keys(obj).length, 4);
+
+    validatePropertyDescriptor(obj, &quot;a&quot;);
+    validatePropertyDescriptor(obj, &quot;b&quot;);
+    validatePropertyDescriptor(obj, &quot;c&quot;);
+    validatePropertyDescriptor(obj, &quot;d&quot;);
+})();
+
+(() =&gt; {
+    let o = {a: 2, b: 3};
+    let o2 = {c: 4, d: 5};
+
+    let obj = {...o, ...o2};
+
+    assert.sameValue(obj.a, 2);
+    assert.sameValue(obj.b, 3);
+    assert.sameValue(obj.c, 4);
+    assert.sameValue(obj.d, 5);
+    assert.sameValue(Object.keys(obj).length, 4);
+})();
+
+// Empty case
+
+(() =&gt; {
+    let obj = {a: 1, b: 2, ...{}};
+
+    assert.sameValue(obj.a, 1);
+    assert.sameValue(obj.b, 2);
+    assert.sameValue(Object.keys(obj).length, 2);
+})();
+
+// Ignoring cases
+
+(() =&gt; {
+    let obj = {a: 1, ...null, b: 2, ...undefined, c: 3, ...{}, ...{...{}}, d: 4};
+
+    assert.sameValue(obj.a, 1);
+    assert.sameValue(obj.b, 2);
+    assert.sameValue(obj.c, 3);
+    assert.sameValue(obj.d, 4);
+
+    let keys = Object.keys(obj);
+    assert.sameValue(keys[0], &quot;a&quot;);
+    assert.sameValue(keys[1], &quot;b&quot;);
+    assert.sameValue(keys[2], &quot;c&quot;);
+    assert.sameValue(keys[3], &quot;d&quot;);
+})();
+
+// Null case
+
+(() =&gt; {
+    let obj = {a: 1, b: 2, ...null};
+
+    assert.sameValue(obj.a, 1);
+    assert.sameValue(obj.b, 2);
+    assert.sameValue(Object.keys(obj).length, 2);
+})();
+
+(() =&gt; {
+    let obj = {...null};
+
+    assert.sameValue(Object.keys(obj).length, 0);
+})();
+
+// Undefined case
+
+(() =&gt; {
+    let obj = {a: 1, b: 2, ...undefined};
+
+    assert.sameValue(obj.a, 1);
+    assert.sameValue(obj.b, 2);
+    assert.sameValue(Object.keys(obj).length, 2);
+})();
+
+(() =&gt; {
+    let obj = {...undefined};
+
+    assert.sameValue(Object.keys(obj).length, 0);
+})();
+
+// Getter case
+
+(() =&gt; {
+    let o = {
+        get a() {
+            return 42;
+        }
+    };
+
+    let obj = {...o, c: 4, d: 5};
+
+    assert.sameValue(Object.getOwnPropertyDescriptor(obj, &quot;a&quot;).value, 42);
+    assert.sameValue(obj.c, 4);
+    assert.sameValue(obj.d, 5);
+    assert.sameValue(Object.keys(obj).length, 3);
+
+    validatePropertyDescriptor(obj, &quot;a&quot;);
+})();
+
+(() =&gt; {
+    let o = {a: 2, b: 3}
+    let executedGetter = false;
+
+    let obj = {...o, get c() { executedGetter = true; }};
+
+    assert.sameValue(obj.a, 2);
+    assert.sameValue(obj.b, 3);
+    assert.sameValue(executedGetter, false)
+    assert.sameValue(Object.keys(obj).length, 3);
+})();
+
+(() =&gt; {
+    let getterCallCount = 0;
+    let o = {
+        get a() {
+            return ++getterCallCount;
+        }
+    };
+
+    let obj = {...o, c: 4, d: 5, a: 42, ...o};
+
+    assert.sameValue(obj.a, 2);
+    assert.sameValue(obj.c, 4);
+    assert.sameValue(obj.d, 5);
+    assert.sameValue(Object.keys(obj).length, 3);
+})();
+
+// Manipulate Object case
+
+(() =&gt; {
+    var o = { a: 0, b: 1 };
+    var cthulhu = { get x() {
+      delete o.a;
+      o.b = 42;
+      o.c = &quot;ni&quot;;
+    }};
+
+    let obj = {...cthulhu, ...o};
+
+    assert.sameValue(obj.hasOwnProperty(&quot;a&quot;), false);
+    assert.sameValue(obj.b, 42);
+    assert.sameValue(obj.c, &quot;ni&quot;);
+    assert(obj.hasOwnProperty(&quot;x&quot;));
+    assert.sameValue(Object.keys(obj).length, 3);
+})();
+
+// Override
+
+(() =&gt; {
+    let o = {a: 2, b: 3};
+
+    let obj = {a: 1, b: 7, ...o};
+
+    assert.sameValue(obj.a, 2);
+    assert.sameValue(obj.b, 3);
+    assert.sameValue(Object.keys(obj).length, 2);
+    assert.sameValue(o.a, 2);
+    assert.sameValue(o.b, 3);
+})();
+
+(() =&gt; {
+    let o = {a: 2, b: 3, c: 4, e: undefined, f: null, g: false};
+
+    let obj = {...o, a: 1, b: 7, d: 5, h: -0, i: Symbol(&quot;foo&quot;), j: o};
+
+    assert.sameValue(obj.a, 1);
+    assert.sameValue(obj.b, 7);
+    assert.sameValue(obj.c, 4);
+    assert.sameValue(obj.d, 5);
+    assert(obj.hasOwnProperty(&quot;e&quot;));
+    assert.sameValue(obj.f, null);
+    assert.sameValue(obj.g, false);
+    assert.sameValue(obj.h, -0);
+    assert.sameValue(obj.i.toString(), &quot;Symbol(foo)&quot;);
+    assert(Object.is(obj.j, o));
+    assert.sameValue(Object.keys(obj).length, 10);
+})();
+
+// Override Immutable
+
+(() =&gt; {
+    let o = {b: 2};
+    Object.defineProperty(o, &quot;a&quot;, {value: 1, enumerable: true, writable: false, configurable: true});
+
+    let obj = {...o, a: 3};
+
+    assert.sameValue(obj.a, 3)
+    assert.sameValue(obj.b, 2);
+    validatePropertyDescriptor(obj, &quot;a&quot;);
+    validatePropertyDescriptor(obj, &quot;b&quot;);
+})();
+
+// Setter
+
+(() =&gt; {
+    let executedSetter = false;
+
+    let obj = {set c(v) { executedSetter = true; }, ...{c: 1}};
+
+    assert.sameValue(obj.c, 1);
+    assert.sameValue(executedSetter, false);
+    assert.sameValue(Object.keys(obj).length, 1);
+})();
+
+// Skip non-enumerble
+
+(() =&gt; {
+    let o = {};
+    Object.defineProperty(o, &quot;b&quot;, {value: 3, enumerable: false});
+
+    let obj = {...o};
+
+    assert.sameValue(obj.hasOwnProperty(&quot;b&quot;), false)
+    assert.sameValue(Object.keys(obj).length, 0);
+})();
+
+// Spread order
+
+(() =&gt; {
+    var calls = []
+    var o = { get z() { calls.push('z') }, get a() { calls.push('a') } };
+    Object.defineProperty(o, 1, { get: () =&gt; { calls.push(1) }, enumerable: true });
+    Object.defineProperty(o, Symbol('foo'), { get: () =&gt; { calls.push(&quot;Symbol(foo)&quot;) }, enumerable: true });
+
+    let obj = {...o};
+
+    assert.sameValue(calls[0], 1);
+    assert.sameValue(calls[1], &quot;z&quot;);
+    assert.sameValue(calls[2], &quot;a&quot;);
+    assert.sameValue(calls[3], &quot;Symbol(foo)&quot;);
+    assert.sameValue(Object.keys(obj).length, 3);
+})();
+
+// Symbol property
+(() =&gt; {
+    let symbol = Symbol('foo');
+    let o = {};
+    o[symbol] = 1;
+
+    let obj = {...o, c: 4, d: 5};
+
+    assert.sameValue(obj[symbol], 1);
+    assert.sameValue(obj.c, 4);
+    assert.sameValue(obj.d, 5);
+    assert.sameValue(Object.keys(obj).length, 2);
+})();
+
+// Getter throw
+
+(() =&gt; {
+    try {
+        let obj = {...{ get foo() { throw new Error(&quot;Getter Exception&quot;); } }};
+        assert(false);
+    } catch(e) {
+        assert.sameValue(e.message, &quot;Getter Exception&quot;);
+    }
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/LayoutTests/ChangeLog        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2017-03-16  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [ESnext] Implement Object Spread
+        https://bugs.webkit.org/show_bug.cgi?id=167963
+
+        Reviewed by Yusuke Suzuki.
+
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/parser-syntax-check.js:
+
</ins><span class="cx"> 2017-03-16  Carlos Alberto Lopez Perez  &lt;clopez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WebRTC] SDP sess-id in the &quot;o=&quot; line should be a value between 0 and LLONG_MAX.
</span></span></pre></div>
<a id="trunkLayoutTestsjsparsersyntaxcheckexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/parser-syntax-check-expected.txt        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -1185,6 +1185,20 @@
</span><span class="cx"> PASS Valid:   &quot;function f() { var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4}); }&quot;
</span><span class="cx"> PASS Valid:   &quot;function * foo(o) { ({...{ x = yield }} = o); }&quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { function * foo(o) { ({...{ x = yield }} = o); } }&quot;
</span><ins>+PASS Valid:   &quot;let c = {}; let o = {a: 1, b: 2, ...c};&quot;
+PASS Valid:   &quot;function f() { let c = {}; let o = {a: 1, b: 2, ...c}; }&quot;
+PASS Valid:   &quot;let o = {a: 1, b: 3, ...{}};&quot;
+PASS Valid:   &quot;function f() { let o = {a: 1, b: 3, ...{}}; }&quot;
+PASS Valid:   &quot;let o = {a: 1, b: 2, ...null, c: 3};&quot;
+PASS Valid:   &quot;function f() { let o = {a: 1, b: 2, ...null, c: 3}; }&quot;
+PASS Valid:   &quot;let o = {a: 1, b: 2, ...undefined, c: 3};&quot;
+PASS Valid:   &quot;function f() { let o = {a: 1, b: 2, ...undefined, c: 3}; }&quot;
+PASS Valid:   &quot;let o = {a: 1, b: 2, ...{...{}}, c: 3};&quot;
+PASS Valid:   &quot;function f() { let o = {a: 1, b: 2, ...{...{}}, c: 3}; }&quot;
+PASS Valid:   &quot;let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5};&quot;
+PASS Valid:   &quot;function f() { let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5}; }&quot;
+PASS Valid:   &quot;function* gen() { yield {a: 1, b: 2, ...yield yield, d: 3, ...yield, e: 5}; }&quot;
+PASS Valid:   &quot;function f() { function* gen() { yield {a: 1, b: 2, ...yield yield, d: 3, ...yield, e: 5}; } }&quot;
</ins><span class="cx"> PASS Invalid: &quot;var {...r = {a: 2}} = {a: 1, b: 2};&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '='. Expected a closing '}' following a rest element destructuring pattern.&quot;
</span><span class="cx"> PASS Invalid: &quot;function f() { var {...r = {a: 2}} = {a: 1, b: 2}; }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '='. Expected a closing '}' following a rest element destructuring pattern.&quot;
</span><span class="cx"> PASS Invalid: &quot;var {...r, b} = {a: 1, b: 2};&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token ','. Expected a closing '}' following a rest element destructuring pattern.&quot;
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsparsersyntaxcheckjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -700,6 +700,13 @@
</span><span class="cx"> valid(&quot;(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});&quot;);
</span><span class="cx"> valid(&quot;var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});&quot;);
</span><span class="cx"> valid(&quot;function * foo(o) { ({...{ x = yield }} = o); }&quot;);
</span><ins>+valid(&quot;let c = {}; let o = {a: 1, b: 2, ...c};&quot;);
+valid(&quot;let o = {a: 1, b: 3, ...{}};&quot;);
+valid(&quot;let o = {a: 1, b: 2, ...null, c: 3};&quot;);
+valid(&quot;let o = {a: 1, b: 2, ...undefined, c: 3};&quot;);
+valid(&quot;let o = {a: 1, b: 2, ...{...{}}, c: 3};&quot;);
+valid(&quot;let c = {}; let o = {a: 1, b: 2, ...c, d: 3, ...c, e: 5};&quot;);
+valid(&quot;function* gen() { yield {a: 1, b: 2, ...yield yield, d: 3, ...yield, e: 5}; }&quot;);
</ins><span class="cx"> invalid(&quot;var {...r = {a: 2}} = {a: 1, b: 2};&quot;);
</span><span class="cx"> invalid(&quot;var {...r, b} = {a: 1, b: 2};&quot;);
</span><span class="cx"> invalid(&quot;var {...r, ...e} = {a: 1, b: 2};&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -1,3 +1,52 @@
</span><ins>+2017-03-16  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [ESnext] Implement Object Spread
+        https://bugs.webkit.org/show_bug.cgi?id=167963
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch implements ECMA262 stage 3 Object Spread proposal [1].
+        It's implemented using CopyDataProperties to copy all enumerable keys
+        from object being spreaded.
+
+        It's also fixing CopyDataProperties that was using
+        Object.getOwnPropertyNames to list all keys to be copied, and now is
+        using Relect.ownKeys.
+
+        [1] - https://github.com/sebmarkbage/ecmascript-rest-spread
+
+        * builtins/GlobalOperations.js:
+        (globalPrivate.copyDataProperties):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::setConstantIdentifierSetRegisters):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::addSetConstant):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitLoad):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::PropertyListNode::emitBytecode):
+        (JSC::ObjectPatternNode::bindValue):
+        (JSC::ObjectSpreadExpressionNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createObjectSpreadExpression):
+        (JSC::ASTBuilder::createProperty):
+        * parser/NodeConstructors.h:
+        (JSC::PropertyNode::PropertyNode):
+        (JSC::ObjectSpreadExpressionNode::ObjectSpreadExpressionNode):
+        * parser/Nodes.h:
+        (JSC::ObjectSpreadExpressionNode::expression):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseProperty):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createObjectSpreadExpression):
+        (JSC::SyntaxChecker::createProperty):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::privateToObject): Deleted.
+        * runtime/JSGlobalObjectFunctions.h:
+
</ins><span class="cx"> 2017-03-15  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Default parameter part should be retrieved by op_get_argument opcode instead of changing arity
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebuiltinsGlobalOperationsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/builtins/GlobalOperations.js (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/builtins/GlobalOperations.js        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/builtins/GlobalOperations.js        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -86,11 +86,11 @@
</span><span class="cx">     if (!@isObject(target))
</span><span class="cx">         @throwTypeError(&quot;target needs to be an object&quot;);
</span><span class="cx">     
</span><del>-    if (source === @undefined || source === null)
</del><ins>+    if (source == null)
</ins><span class="cx">         return target;
</span><span class="cx">     
</span><del>-    let from = @toObject(source);
-    let keys = @Object.@getOwnPropertyNames(from);
</del><ins>+    let from = @Object(source);
+    let keys = @Reflect.@ownKeys(from);
</ins><span class="cx">     let keysLength = keys.length;
</span><span class="cx">     for (let i = 0; i &lt; keysLength; i++) {
</span><span class="cx">         let nextKey = keys[i];
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -875,9 +875,9 @@
</span><span class="cx">         JSSet* jsSet = JSSet::create(exec, vm, setStructure);
</span><span class="cx">         RETURN_IF_EXCEPTION(scope, false);
</span><span class="cx"> 
</span><del>-        const HashSet&lt;UniquedStringImpl*&gt;&amp; set = entry.first;
-        for (auto setEntry : set) {
-            JSString* jsString = jsOwnedString(&amp;vm, setEntry);
</del><ins>+        const IdentifierSet&amp; set = entry.first;
+        for (auto&amp; setEntry : set) {
+            JSString* jsString = jsOwnedString(&amp;vm, setEntry.get());
</ins><span class="cx">             jsSet-&gt;add(exec, JSValue(jsString));
</span><span class="cx">             RETURN_IF_EXCEPTION(scope, false);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx"> typedef unsigned UnlinkedArrayAllocationProfile;
</span><span class="cx"> typedef unsigned UnlinkedObjectAllocationProfile;
</span><span class="cx"> typedef unsigned UnlinkedLLIntCallLinkInfo;
</span><del>-typedef std::pair&lt;HashSet&lt;UniquedStringImpl*&gt;, unsigned&gt; ConstantIndentifierSetEntry;
</del><ins>+typedef std::pair&lt;IdentifierSet, unsigned&gt; ConstantIndentifierSetEntry;
</ins><span class="cx"> 
</span><span class="cx"> struct UnlinkedStringJumpTable {
</span><span class="cx">     struct OffsetLocation {
</span><span class="lines">@@ -187,7 +187,7 @@
</span><span class="cx">         return m_bitVectors.size() - 1;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void addSetConstant(HashSet&lt;UniquedStringImpl*&gt;&amp; set)
</del><ins>+    void addSetConstant(IdentifierSet&amp; set)
</ins><span class="cx">     {
</span><span class="cx">         VM&amp; vm = *this-&gt;vm();
</span><span class="cx">         auto locker = lockDuringMarking(vm.heap, *this);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -1934,9 +1934,9 @@
</span><span class="cx">     return constantID;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, HashSet&lt;UniquedStringImpl*&gt;&amp; set)
</del><ins>+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, IdentifierSet&amp; set)
</ins><span class="cx"> {
</span><del>-    for (ConstantIndentifierSetEntry entry : m_codeBlock-&gt;constantIdentifierSets()) {
</del><ins>+    for (const auto&amp; entry : m_codeBlock-&gt;constantIdentifierSets()) {
</ins><span class="cx">         if (entry.first != set)
</span><span class="cx">             continue;
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -587,7 +587,7 @@
</span><span class="cx">         RegisterID* emitLoad(RegisterID* dst, bool);
</span><span class="cx">         RegisterID* emitLoad(RegisterID* dst, const Identifier&amp;);
</span><span class="cx">         RegisterID* emitLoad(RegisterID* dst, JSValue, SourceCodeRepresentation = SourceCodeRepresentation::Other);
</span><del>-        RegisterID* emitLoad(RegisterID* dst, HashSet&lt;UniquedStringImpl*&gt;&amp; excludedList);
</del><ins>+        RegisterID* emitLoad(RegisterID* dst, IdentifierSet&amp; excludedList);
</ins><span class="cx">         RegisterID* emitLoadGlobalObject(RegisterID* dst);
</span><span class="cx"> 
</span><span class="cx">         RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -516,7 +516,7 @@
</span><span class="cx">                 hasComputedProperty = true;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            if (node-&gt;m_type &amp; PropertyNode::Constant)
</del><ins>+            if (node-&gt;m_type &amp; PropertyNode::Constant || node-&gt;m_type &amp; PropertyNode::Spread)
</ins><span class="cx">                 continue;
</span><span class="cx"> 
</span><span class="cx">             // Duplicates are possible.
</span><span class="lines">@@ -538,6 +538,9 @@
</span><span class="cx">             if (node-&gt;m_type &amp; PropertyNode::Constant) {
</span><span class="cx">                 emitPutConstantProperty(generator, dst, *node);
</span><span class="cx">                 continue;
</span><ins>+            } else if (node-&gt;m_type &amp; PropertyNode::Spread) {
+                generator.emitNode(dst, node-&gt;m_assign);
+                continue;
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             RefPtr&lt;RegisterID&gt; value = generator.emitNode(node-&gt;m_assign);
</span><span class="lines">@@ -4030,7 +4033,7 @@
</span><span class="cx"> {
</span><span class="cx">     generator.emitRequireObjectCoercible(rhs, ASCIILiteral(&quot;Right side of assignment cannot be destructured&quot;));
</span><span class="cx">     
</span><del>-    HashSet&lt;UniquedStringImpl*&gt; excludedSet;
</del><ins>+    IdentifierSet excludedSet;
</ins><span class="cx"> 
</span><span class="cx">     for (const auto&amp; target : m_targetPatterns) {
</span><span class="cx">         if (target.bindingType == BindingType::Element) {
</span><span class="lines">@@ -4228,4 +4231,31 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* ObjectSpreadExpressionNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
+{
+    RefPtr&lt;RegisterID&gt; src = generator.newTemporary();
+    generator.emitNode(src.get(), m_expression);
+    IdentifierSet excludedSet;
+    
+    RefPtr&lt;RegisterID&gt; excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
+        
+    // load and call @copyDataProperties
+    auto var = generator.variable(generator.propertyNames().builtinNames().copyDataPropertiesPrivateName());
+    
+    RefPtr&lt;RegisterID&gt; scope = generator.newTemporary();
+    generator.moveToDestinationIfNeeded(scope.get(), generator.emitResolveScope(scope.get(), var));
+    RefPtr&lt;RegisterID&gt; copyDataProperties = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
+    
+    CallArguments args(generator, nullptr, 3);
+    unsigned argumentCount = 0;
+    generator.emitLoad(args.thisRegister(), jsUndefined());
+    generator.emitMove(args.argumentRegister(argumentCount++), dst);
+    generator.emitMove(args.argumentRegister(argumentCount++), src.get());
+    generator.emitMove(args.argumentRegister(argumentCount++), excludedSetReg.get());
+    
+    generator.emitCall(generator.newTemporary(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
+    
+    return 0;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -275,6 +275,13 @@
</span><span class="cx">         return node;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ExpressionNode* createObjectSpreadExpression(const JSTokenLocation&amp; location, ExpressionNode* expression, const JSTextPosition&amp; start, const JSTextPosition&amp; divot, const JSTextPosition&amp; end)
+    {
+        auto node = new (m_parserArena) ObjectSpreadExpressionNode(location, expression);
+        setExceptionLocation(node, start, divot, end);
+        return node;
+    }
+
</ins><span class="cx">     TemplateStringNode* createTemplateString(const JSTokenLocation&amp; location, const Identifier* cooked, const Identifier* raw)
</span><span class="cx">     {
</span><span class="cx">         return new (m_parserArena) TemplateStringNode(location, cooked, raw);
</span><span class="lines">@@ -493,6 +500,10 @@
</span><span class="cx">             static_cast&lt;ClassExprNode*&gt;(node)-&gt;setEcmaName(*propertyName);
</span><span class="cx">         return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding, isClassProperty);
</span><span class="cx">     }
</span><ins>+    PropertyNode* createProperty(ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty)
+    {
+        return new (m_parserArena) PropertyNode(node, type, putType, superBinding, isClassProperty);
+    }
</ins><span class="cx">     PropertyNode* createProperty(VM* vm, ParserArena&amp; parserArena, double propertyName, ExpressionNode* node, PropertyNode::Type type, PropertyNode::PutType putType, bool, SuperBinding superBinding, bool isClassProperty)
</span><span class="cx">     {
</span><span class="cx">         return new (m_parserArena) PropertyNode(parserArena.identifierArena().makeNumericIdentifier(vm, propertyName), node, type, putType, superBinding, isClassProperty);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodeConstructorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/NodeConstructors.h (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -234,9 +234,19 @@
</span><span class="cx">         , m_isClassProperty(isClassProperty)
</span><span class="cx">     {
</span><span class="cx">     }
</span><ins>+    
+    inline PropertyNode::PropertyNode(ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty)
+        : m_name(nullptr)
+        , m_assign(assign)
+        , m_type(type)
+        , m_needsSuperBinding(superBinding == SuperBinding::Needed)
+        , m_putType(putType)
+        , m_isClassProperty(isClassProperty)
+    {
+    }
</ins><span class="cx"> 
</span><span class="cx">     inline PropertyNode::PropertyNode(ExpressionNode* name, ExpressionNode* assign, Type type, PutType putType, SuperBinding superBinding, bool isClassProperty)
</span><del>-        : m_name(0)
</del><ins>+        : m_name(nullptr)
</ins><span class="cx">         , m_expression(name)
</span><span class="cx">         , m_assign(assign)
</span><span class="cx">         , m_type(type)
</span><span class="lines">@@ -294,6 +304,12 @@
</span><span class="cx">         , m_expression(expression)
</span><span class="cx">     {
</span><span class="cx">     }
</span><ins>+    
+    inline ObjectSpreadExpressionNode::ObjectSpreadExpressionNode(const JSTokenLocation&amp; location, ExpressionNode* expression)
+        : ExpressionNode(location)
+        , m_expression(expression)
+    {
+    }
</ins><span class="cx"> 
</span><span class="cx">     inline ArgumentListNode::ArgumentListNode(const JSTokenLocation&amp; location, ExpressionNode* expr)
</span><span class="cx">         : ExpressionNode(location)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -646,10 +646,11 @@
</span><span class="cx"> 
</span><span class="cx">     class PropertyNode : public ParserArenaFreeable {
</span><span class="cx">     public:
</span><del>-        enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16 };
</del><ins>+        enum Type { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16, Spread = 32 };
</ins><span class="cx">         enum PutType { Unknown, KnownDirect };
</span><span class="cx"> 
</span><span class="cx">         PropertyNode(const Identifier&amp;, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
</span><ins>+        PropertyNode(ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
</ins><span class="cx">         PropertyNode(ExpressionNode* propertyName, ExpressionNode*, Type, PutType, SuperBinding, bool isClassProperty);
</span><span class="cx"> 
</span><span class="cx">         ExpressionNode* expressionName() const { return m_expression; }
</span><span class="lines">@@ -665,7 +666,7 @@
</span><span class="cx">         const Identifier* m_name;
</span><span class="cx">         ExpressionNode* m_expression;
</span><span class="cx">         ExpressionNode* m_assign;
</span><del>-        unsigned m_type : 5;
</del><ins>+        unsigned m_type : 6;
</ins><span class="cx">         unsigned m_needsSuperBinding : 1;
</span><span class="cx">         unsigned m_putType : 1;
</span><span class="cx">         unsigned m_isClassProperty: 1;
</span><span class="lines">@@ -747,6 +748,18 @@
</span><span class="cx">         bool isSpreadExpression() const override { return true; }
</span><span class="cx">         ExpressionNode* m_expression;
</span><span class="cx">     };
</span><ins>+    
+    class ObjectSpreadExpressionNode : public ExpressionNode, public ThrowableExpressionData {
+    public:
+        ObjectSpreadExpressionNode(const JSTokenLocation&amp;, ExpressionNode*);
+        
+        ExpressionNode* expression() const { return m_expression; }
+        
+    private:
+        RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
+        
+        ExpressionNode* m_expression;
+    };
</ins><span class="cx"> 
</span><span class="cx">     class ArgumentListNode : public ExpressionNode {
</span><span class="cx">     public:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -3779,8 +3779,14 @@
</span><span class="cx">         return context.createProperty(propertyName, node, static_cast&lt;PropertyNode::Type&gt;(PropertyNode::Constant | PropertyNode::Computed), PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
</span><span class="cx">     }
</span><span class="cx">     case DOTDOTDOT: {
</span><del>-        classifyExpressionError(ErrorIndicatesPattern);
-        FALLTHROUGH;
</del><ins>+        auto spreadLocation = m_token.m_location;
+        auto start = m_token.m_startPosition;
+        auto divot = m_token.m_endPosition;
+        next();
+        TreeExpression elem = parseAssignmentExpressionOrPropagateErrorClass(context);
+        failIfFalse(elem, &quot;Cannot parse subject of a spread operation&quot;);
+        auto node = context.createObjectSpreadExpression(spreadLocation, elem, start, divot, m_lastTokenEndPosition);
+        return context.createProperty(node, PropertyNode::Spread, PropertyNode::Unknown, complete, SuperBinding::NotNeeded, isClassProperty);
</ins><span class="cx">     }
</span><span class="cx">     default:
</span><span class="cx">         failIfFalse(m_token.m_type &amp; KeywordTokenFlag, &quot;Expected a property name&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx">         ConditionalExpr, AssignmentExpr, TypeofExpr, NewTargetExpr,
</span><span class="cx">         DeleteExpr, ArrayLiteralExpr, BindingDestructuring, RestParameter,
</span><span class="cx">         ArrayDestructuring, ObjectDestructuring, SourceElementsResult,
</span><del>-        FunctionBodyResult, SpreadExpr, ArgumentsResult,
</del><ins>+        FunctionBodyResult, SpreadExpr, ObjectSpreadExpr, ArgumentsResult,
</ins><span class="cx">         PropertyListResult, ArgumentsListResult, ElementsListResult,
</span><span class="cx">         StatementResult, FormalParameterListResult, ClauseResult,
</span><span class="cx">         ClauseListResult, CommaExpr, DestructuringAssignment,
</span><span class="lines">@@ -194,6 +194,7 @@
</span><span class="cx">     int createArguments() { return ArgumentsResult; }
</span><span class="cx">     int createArguments(int) { return ArgumentsResult; }
</span><span class="cx">     ExpressionType createSpreadExpression(const JSTokenLocation&amp;, ExpressionType, int, int, int) { return SpreadExpr; }
</span><ins>+    ExpressionType createObjectSpreadExpression(const JSTokenLocation&amp;, ExpressionType, int, int, int) { return ObjectSpreadExpr; }
</ins><span class="cx">     TemplateString createTemplateString(const JSTokenLocation&amp;, const Identifier*, const Identifier*) { return TemplateStringResult; }
</span><span class="cx">     TemplateStringList createTemplateStringList(TemplateString) { return TemplateStringListResult; }
</span><span class="cx">     TemplateStringList createTemplateStringList(TemplateStringList, TemplateString) { return TemplateStringListResult; }
</span><span class="lines">@@ -212,6 +213,10 @@
</span><span class="cx">         ASSERT(name);
</span><span class="cx">         return Property(name, type);
</span><span class="cx">     }
</span><ins>+    Property createProperty(int, PropertyNode::Type type, PropertyNode::PutType, bool, SuperBinding, bool)
+    {
+        return Property(type);
+    }
</ins><span class="cx">     Property createProperty(VM* vm, ParserArena&amp; parserArena, double name, int, PropertyNode::Type type, PropertyNode::PutType, bool complete, SuperBinding, bool)
</span><span class="cx">     {
</span><span class="cx">         if (!complete)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -735,7 +735,6 @@
</span><span class="cx"> 
</span><span class="cx">     JSFunction* privateFuncGetTemplateObject = JSFunction::create(vm, this, 0, String(), getTemplateObject);
</span><span class="cx">     JSFunction* privateFuncImportModule = JSFunction::create(vm, this, 0, String(), globalFuncImportModule);
</span><del>-    JSFunction* privateFuncToObject = JSFunction::create(vm, this, 0, String(), privateToObject);
</del><span class="cx">     JSFunction* privateFuncTypedArrayLength = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncLength);
</span><span class="cx">     JSFunction* privateFuncTypedArrayGetOriginalConstructor = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncGetOriginalConstructor);
</span><span class="cx">     JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort);
</span><span class="lines">@@ -790,7 +789,6 @@
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().ownEnumerablePropertyKeysPrivateName(), JSFunction::create(vm, this, 0, String(), ownEnumerablePropertyKeys), DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().getTemplateObjectPrivateName(), privateFuncGetTemplateObject, DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().importModulePrivateName(), privateFuncImportModule, DontEnum | DontDelete | ReadOnly),
</span><del>-        GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().toObjectPrivateName(), privateFuncToObject, DontEnum | DontDelete | ReadOnly),
</del><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().enqueueJobPrivateName(), JSFunction::create(vm, this, 0, String(), enqueueJob), DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().ErrorPrivateName(), m_errorConstructor.get(), DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().RangeErrorPrivateName(), m_rangeErrorConstructor.get(), DontEnum | DontDelete | ReadOnly),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -736,11 +736,6 @@
</span><span class="cx">     return JSValue::encode(jsUndefined());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JSC_HOST_CALL privateToObject(ExecState* exec)
-{
-    return JSValue::encode(JSValue(exec-&gt;argument(0).toObject(exec)));
-}
-    
</del><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     dataLog(exec-&gt;argument(0).toWTFString(exec), &quot;\n&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h (214037 => 214038)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h        2017-03-16 11:59:24 UTC (rev 214037)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h        2017-03-16 12:58:14 UTC (rev 214038)
</span><span class="lines">@@ -50,7 +50,6 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*);
</span><del>-EncodedJSValue JSC_HOST_CALL privateToObject(ExecState*);
</del><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState*);
</span><span class="cx"> 
</span><span class="cx"> double jsToNumber(StringView);
</span></span></pre>
</div>
</div>

</body>
</html>