<!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>[213697] 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/213697">213697</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2017-03-09 18:00:33 -0800 (Thu, 09 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[ESnext] Implement Object Rest - Implementing Object Rest Destructuring
https://bugs.webkit.org/show_bug.cgi?id=167962

Patch by Caio Lima &lt;ticaiolima@gmail.com&gt; on 2017-03-09
Reviewed by Keith Miller.

JSTests:

* stress/object-rest-deconstruct.js: Added.
(let.assert):
(let.assertPropDescriptor):
(catch):
(get 3):
(foo):
(let.src.get y):
(let.src.set y):
(let.gen):

Source/JavaScriptCore:

Object Rest/Spread Destructing proposal is in stage 3[1] and this
Patch is a prototype implementation of it. A simple change over the
parser was necessary to support the new '...' token on Object Pattern
destruction rule. In the bytecode generator side, We changed the
bytecode generated on ObjectPatternNode::bindValue to store in an
array identifiers of already destructed properties, following spec draft
section[2], and then pass it as excludedNames to CopyDataProperties.
The rest destruction the calls copyDataProperties to perform the
copy of rest properties in rhs.

We also implemented CopyDataProperties as private JS global operation
on builtins/GlobalOperations.js following it's specification on [3].
It is implemented using Set object to verify if a property is on
excludedNames to keep this algorithm with O(n + m) complexity, where n
= number of source's own properties and m = excludedNames.length.

As a requirement to use JSSets as constants, a change in
CodeBlock::create API was necessary, because JSSet creation can throws OOM
exception. Now, CodeBlock::finishCreation returns ```false``` if an
execption is throwed by
CodeBlock::setConstantIdentifierSetRegisters and then we return
nullptr to ScriptExecutable::newCodeBlockFor. It is responsible to
check if CodeBlock was constructed properly and then, throw OOM
exception to the correct scope.

[1] - https://github.com/sebmarkbage/ecmascript-rest-spread
[2] - http://sebmarkbage.github.io/ecmascript-rest-spread/#Rest-RuntimeSemantics-PropertyDestructuringAssignmentEvaluation
[3] - http://sebmarkbage.github.io/ecmascript-rest-spread/#AbstractOperations-CopyDataProperties

* builtins/BuiltinNames.h:
* builtins/GlobalOperations.js:
(globalPrivate.copyDataProperties):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::setConstantIdentifierSetRegisters):
* bytecode/CodeBlock.h:
* bytecode/EvalCodeBlock.h:
(JSC::EvalCodeBlock::create):
* bytecode/FunctionCodeBlock.h:
(JSC::FunctionCodeBlock::create):
* bytecode/ModuleProgramCodeBlock.h:
(JSC::ModuleProgramCodeBlock::create):
* bytecode/ProgramCodeBlock.h:
(JSC::ProgramCodeBlock::create):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedCodeBlock::addSetConstant):
(JSC::UnlinkedCodeBlock::constantIdentifierSets):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitLoad):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ObjectPatternNode::bindValue):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::appendObjectPatternEntry):
(JSC::ASTBuilder::appendObjectPatternRestEntry):
(JSC::ASTBuilder::setContainsObjectRestElement):
* parser/Nodes.h:
(JSC::ObjectPatternNode::appendEntry):
(JSC::ObjectPatternNode::setContainsRestElement):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseDestructuringPattern):
(JSC::Parser&lt;LexerType&gt;::parseProperty):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::operatorStackPop):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::privateToObject):
* runtime/JSGlobalObjectFunctions.h:
* runtime/ScriptExecutable.cpp:
(JSC::ScriptExecutable::newCodeBlockFor):

Source/WTF:

* wtf/HashSet.h:
(WTF::=):

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="#trunkSourceJavaScriptCorebuiltinsBuiltinNamesh">trunk/Source/JavaScriptCore/builtins/BuiltinNames.h</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="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeEvalCodeBlockh">trunk/Source/JavaScriptCore/bytecode/EvalCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeFunctionCodeBlockh">trunk/Source/JavaScriptCore/bytecode/FunctionCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeModuleProgramCodeBlockh">trunk/Source/JavaScriptCore/bytecode/ModuleProgramCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeProgramCodeBlockh">trunk/Source/JavaScriptCore/bytecode/ProgramCodeBlock.h</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="#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>
<li><a href="#trunkSourceJavaScriptCoreruntimeObjectConstructorcpp">trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeScriptExecutablecpp">trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSetPrototypecpp">trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfHashSeth">trunk/Source/WTF/wtf/HashSet.h</a></li>
</ul>

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

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/JSTests/ChangeLog        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2017-03-09  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+        https://bugs.webkit.org/show_bug.cgi?id=167962
+
+        Reviewed by Keith Miller.
+
+        * stress/object-rest-deconstruct.js: Added.
+        (let.assert):
+        (let.assertPropDescriptor):
+        (catch):
+        (get 3):
+        (foo):
+        (let.src.get y):
+        (let.src.set y):
+        (let.gen):
+
</ins><span class="cx"> 2017-03-09  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: Make the Unity AngryBots demo run
</span></span></pre></div>
<a id="trunkJSTestsstressobjectrestdeconstructjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/object-rest-deconstruct.js (0 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/object-rest-deconstruct.js                                (rev 0)
+++ trunk/JSTests/stress/object-rest-deconstruct.js        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -0,0 +1,246 @@
</span><ins>+let assert = (e) =&gt; {
+    if (!e)
+        throw Error(&quot;Bad assertion!&quot;);
+}
+
+let assertPropDescriptor = (restObj, prop) =&gt; {
+    let desc = Object.getOwnPropertyDescriptor(restObj, prop);
+    assert(desc.enumerable);
+    assert(desc.writable);
+    assert(desc.configurable);
+}
+
+// Base Case
+(() =&gt; {
+    let obj = {x: 1, y: 2, a: 5, b: 3}
+
+    let {a, b, ...rest} = obj;
+
+    assert(a === 5);
+    assert(b === 3);
+
+    assert(rest.x === 1);
+    assert(rest.y === 2);
+
+    assertPropDescriptor(rest, 'x');
+    assertPropDescriptor(rest, 'y');
+})();
+
+// Empty Object
+(() =&gt; {
+    let obj = {}
+
+    let {a, b, ...rest} = obj;
+
+    assert(a === undefined);
+    assert(b === undefined);
+
+    assert(typeof rest === &quot;object&quot;);
+})();
+
+// Number case
+(() =&gt; {
+    let obj = 3;
+
+    let {...rest} = obj;
+
+    assert(typeof rest === &quot;object&quot;);
+})();
+
+// String case
+(() =&gt; {
+    let obj = &quot;foo&quot;;
+
+    let {...rest} = obj;
+
+    assert(typeof rest === &quot;object&quot;);
+})();
+
+// Symbol case
+(() =&gt; {
+    let obj = Symbol(&quot;foo&quot;);
+
+    let {...rest} = obj;
+
+    assert(typeof rest === &quot;object&quot;);
+})();
+
+// null case
+(() =&gt; {
+    let obj = null;
+
+    try {
+        let {...rest} = obj;
+        assert(false);
+    } catch (e) {
+        assert(e.message == &quot;Right side of assignment cannot be destructured&quot;);
+    }
+
+})();
+
+// undefined case
+(() =&gt; {
+    let obj = undefined;
+
+    try {
+        let {...rest} = obj;
+        assert(false);
+    } catch (e) {
+        assert(e.message == &quot;Right side of assignment cannot be destructured&quot;);
+    }
+
+})();
+
+// getter case
+(() =&gt; {
+    let obj = {a: 3, b: 4};
+    Object.defineProperty(obj, &quot;x&quot;, { get: () =&gt; 3, enumerable: true });
+
+    let {a, b, ...rest} = obj;
+
+    assert(a === 3);
+    assert(b === 4);
+
+    assert(rest.x === 3);
+    assertPropDescriptor(rest, 'x');
+})();
+
+// Skip non-enumerable case
+(() =&gt; {
+    let obj = {a: 3, b: 4};
+    Object.defineProperty(obj, &quot;x&quot;, { value: 4, enumerable: false });
+
+    let {...rest} = obj;
+
+    assert(rest.a === 3);
+    assert(rest.b === 4);
+    assert(rest.x === undefined);
+})();
+
+// Don't copy descriptor case
+(() =&gt; {
+    let obj = {};
+    Object.defineProperty(obj, &quot;a&quot;, { value: 3, configurable: false, enumerable: true });
+    Object.defineProperty(obj, &quot;b&quot;, { value: 4, writable: false, enumerable: true });
+
+    let {...rest} = obj;
+
+    assert(rest.a === 3);
+    assert(rest.b === 4);
+
+    assertPropDescriptor(rest, 'a');
+    assertPropDescriptor(rest, 'b');
+})();
+
+// Nested base case
+(() =&gt; {
+    let obj = {a: 1, b: 2, c: 3, d: 4, e: 5};
+
+    let {a, b, ...{c, e}} = obj;
+
+    assert(a === 1);
+    assert(b === 2);
+    assert(c === 3);
+    assert(e === 5);
+})();
+
+// Nested rest case
+(() =&gt; {
+    let obj = {a: 1, b: 2, c: 3, d: 4, e: 5};
+
+    let {a, b, ...{c, ...rest}} = obj;
+
+    assert(a === 1);
+    assert(b === 2);
+    assert(c === 3);
+
+    assert(rest.d === 4);
+    assert(rest.e === 5);
+})();
+
+// Destructuring Only Own Properties
+(() =&gt; {
+    var o = Object.create({ x: 1, y: 2 });
+    o.z = 3;
+
+    var x, y, z;
+
+    // Destructuring assignment allows nested objects
+    ({ x, ...{y , z} } = o);
+
+    assert(x === 1);
+    assert(y === undefined);
+    assert(z === 3);
+})();
+
+// Destructuring function parameter
+
+(() =&gt; {
+
+    var o = { x: 1, y: 2, w: 3, z: 4 };
+    
+    function foo({ x, y, ...rest }) {
+        assert(x === 1);
+        assert(y === 2);
+        assert(rest.w === 3);
+        assert(rest.z === 4);
+    }
+    foo(o);
+})();
+
+// Destructuring arrow function parameter
+
+(() =&gt; {
+
+    var o = { x: 1, y: 2, w: 3, z: 4 };
+    
+    (({ x, y, ...rest }) =&gt; {
+        assert(x === 1);
+        assert(y === 2);
+        assert(rest.w === 3);
+        assert(rest.z === 4);
+    })(o);
+})();
+
+// Destructuring to a property
+(() =&gt; {
+
+    var o = { x: 1, y: 2};
+    
+    let settedValue;
+    let src = {};
+    ({...src.y} = o);
+    assert(src.y.x === 1);
+    assert(src.y.y === 2);
+})();
+
+// Destructuring with setter
+(() =&gt; {
+
+    var o = { x: 1, y: 2};
+    
+    let settedValue;
+    let src = {
+        get y() { throw Error(&quot;The property should not be accessed&quot;); }, 
+        set y(v) {
+            settedValue = v;
+        }
+    }
+    src.y = undefined;
+    ({...src.y} = o);
+    assert(settedValue.x === 1);
+    assert(settedValue.y === 2);
+})();
+
+// Destructuring yield
+(() =&gt; {
+
+    var o = { x: 1, y: 2, w: 3, z: 4 };
+    
+    let gen = (function * (o) {
+        ({...{ x = yield }} = o);
+    })(o);
+    
+    assert(gen.next().value === undefined);
+})();
+
</ins></span></pre></div>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/LayoutTests/ChangeLog        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2017-03-09  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+        https://bugs.webkit.org/show_bug.cgi?id=167962
+
+        Reviewed by Keith Miller.
+
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/parser-syntax-check.js:
+
</ins><span class="cx"> 2017-03-09  Matt Baker  &lt;mattbaker@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Add XHR breakpoints UI
</span></span></pre></div>
<a id="trunkLayoutTestsjsparsersyntaxcheckexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/parser-syntax-check-expected.txt        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1167,8 +1167,32 @@
</span><span class="cx"> PASS Valid:   &quot;function f() { var {x: [y, {z: {z: [...z]}}]} = 20 }&quot;
</span><span class="cx"> PASS Invalid: &quot;var [...y, ...z] = 20&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 [...y, ...z] = 20 }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.&quot;
</span><del>-PASS Invalid: &quot;var [...{...y}] = 20&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '...'. Expected a property name.&quot;
-PASS Invalid: &quot;function f() { var [...{...y}] = 20 }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '...'. Expected a property name.&quot;
</del><ins>+PASS Valid:   &quot;var [...{...y}] = 20&quot; with TypeError
+PASS Valid:   &quot;function f() { var [...{...y}] = 20 }&quot;
+PASS Valid:   &quot;var {a, b, ...r} = {a: 1, b: 2, c: 3};&quot;
+PASS Valid:   &quot;function f() { var {a, b, ...r} = {a: 1, b: 2, c: 3}; }&quot;
+PASS Valid:   &quot;var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4};&quot;
+PASS Valid:   &quot;function f() { var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4}; }&quot;
+PASS Valid:   &quot;var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4};&quot;
+PASS Valid:   &quot;function f() { var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4}; }&quot;
+PASS Valid:   &quot;var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4};&quot;
+PASS Valid:   &quot;function f() { var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4}; }&quot;
+PASS Valid:   &quot;(({a, b, ...r}) =&gt; {})({a: 1, b: 2, c: 3, d: 4});&quot;
+PASS Valid:   &quot;function f() { (({a, b, ...r}) =&gt; {})({a: 1, b: 2, c: 3, d: 4}); }&quot;
+PASS Valid:   &quot;(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});&quot;
+PASS Valid:   &quot;function f() { (function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4}); }&quot;
+PASS Valid:   &quot;var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});&quot;
+PASS Valid:   &quot;function f() { var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4}); }&quot;
+PASS Valid:   &quot;function * foo(o) { ({...{ x = yield }} = o); }&quot;
+PASS Valid:   &quot;function f() { function * foo(o) { ({...{ x = yield }} = o); } }&quot;
+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;
+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;
+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;
+PASS Invalid: &quot;function f() { 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;
+PASS Invalid: &quot;var {...r, ...e} = {a: 1, b: 2};&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token ','. Expected a closing '}' following a rest element destructuring pattern.&quot;
+PASS Invalid: &quot;function f() { var {...r, ...e} = {a: 1, b: 2}; }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token ','. Expected a closing '}' following a rest element destructuring pattern.&quot;
+PASS Invalid: &quot;function * (o) { ({ ...{ x: yield } } = o); }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '('&quot;
+PASS Invalid: &quot;function f() { function * (o) { ({ ...{ x: yield } } = o); } }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '('&quot;
</ins><span class="cx"> Rest parameter
</span><span class="cx"> PASS Valid:   &quot;function foo(...a) { }&quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { function foo(...a) { } }&quot;
</span><span class="lines">@@ -1236,8 +1260,8 @@
</span><span class="cx"> PASS Valid:   &quot;function f() { let x = (a = 20, ...[...[b = 40]]) =&gt; { } }&quot;
</span><span class="cx"> PASS Valid:   &quot;let x = (a = 20, ...{b}) =&gt; { }&quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { let x = (a = 20, ...{b}) =&gt; { } }&quot;
</span><del>-PASS Invalid: &quot;let x = (a = 20, ...{...b}) =&gt; { }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '...'&quot;
-PASS Invalid: &quot;function f() { let x = (a = 20, ...{...b}) =&gt; { } }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '...'&quot;
</del><ins>+PASS Valid:   &quot;let x = (a = 20, ...{...b}) =&gt; { }&quot;
+PASS Valid:   &quot;function f() { let x = (a = 20, ...{...b}) =&gt; { } }&quot;
</ins><span class="cx"> PASS Invalid: &quot;let x = (a = 20, ...{124}) =&gt; { }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '...'&quot;
</span><span class="cx"> PASS Invalid: &quot;function f() { let x = (a = 20, ...{124}) =&gt; { } }&quot;. Produced the following syntax error: &quot;SyntaxError: Unexpected token '...'&quot;
</span><span class="cx"> non-simple parameter list
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsparsersyntaxcheckjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -691,7 +691,19 @@
</span><span class="cx"> valid(&quot;var {x: [y, ...[...[...{z: [...z]}]]]} = 20&quot;);
</span><span class="cx"> valid(&quot;var {x: [y, {z: {z: [...z]}}]} = 20&quot;);
</span><span class="cx"> invalid(&quot;var [...y, ...z] = 20&quot;);
</span><del>-invalid(&quot;var [...{...y}] = 20&quot;);
</del><ins>+valid(&quot;var [...{...y}] = 20&quot;);
+valid(&quot;var {a, b, ...r} = {a: 1, b: 2, c: 3};&quot;);
+valid(&quot;var {a, b, ...{d}} = {a: 1, b: 2, c: 3, d: 4};&quot;);
+valid(&quot;var {a, b, ...{d = 15}} = {a: 1, b: 2, c: 3, d: 4};&quot;);
+valid(&quot;var {a, b, ...{d = 15, ...r}} = {a: 1, b: 2, c: 3, d: 4};&quot;);
+valid(&quot;(({a, b, ...r}) =&gt; {})({a: 1, b: 2, c: 3, d: 4});&quot;);
+valid(&quot;(function ({a, b, ...r}) {})({a: 1, b: 2, c: 3, d: 4});&quot;);
+valid(&quot;var a, b, c; ({a, b, ...r} = {a: 1, b: 2, c: 3, d: 4});&quot;);
+valid(&quot;function * foo(o) { ({...{ x = yield }} = o); }&quot;);
+invalid(&quot;var {...r = {a: 2}} = {a: 1, b: 2};&quot;);
+invalid(&quot;var {...r, b} = {a: 1, b: 2};&quot;);
+invalid(&quot;var {...r, ...e} = {a: 1, b: 2};&quot;);
+invalid(&quot;function * (o) { ({ ...{ x: yield } } = o); }&quot;);
</ins><span class="cx"> 
</span><span class="cx"> debug(&quot;Rest parameter&quot;);
</span><span class="cx"> valid(&quot;function foo(...a) { }&quot;);
</span><span class="lines">@@ -727,7 +739,7 @@
</span><span class="cx"> valid(&quot;let x = (a = 20, ...[...b]) =&gt; { }&quot;);
</span><span class="cx"> valid(&quot;let x = (a = 20, ...[...[b = 40]]) =&gt; { }&quot;);
</span><span class="cx"> valid(&quot;let x = (a = 20, ...{b}) =&gt; { }&quot;);
</span><del>-invalid(&quot;let x = (a = 20, ...{...b}) =&gt; { }&quot;);
</del><ins>+valid(&quot;let x = (a = 20, ...{...b}) =&gt; { }&quot;);
</ins><span class="cx"> invalid(&quot;let x = (a = 20, ...{124}) =&gt; { }&quot;);
</span><span class="cx"> 
</span><span class="cx"> debug(&quot;non-simple parameter list&quot;)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1,3 +1,82 @@
</span><ins>+2017-03-09  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+        https://bugs.webkit.org/show_bug.cgi?id=167962
+
+        Reviewed by Keith Miller.
+
+        Object Rest/Spread Destructing proposal is in stage 3[1] and this
+        Patch is a prototype implementation of it. A simple change over the
+        parser was necessary to support the new '...' token on Object Pattern
+        destruction rule. In the bytecode generator side, We changed the
+        bytecode generated on ObjectPatternNode::bindValue to store in an
+        array identifiers of already destructed properties, following spec draft
+        section[2], and then pass it as excludedNames to CopyDataProperties.
+        The rest destruction the calls copyDataProperties to perform the
+        copy of rest properties in rhs.
+
+        We also implemented CopyDataProperties as private JS global operation
+        on builtins/GlobalOperations.js following it's specification on [3].
+        It is implemented using Set object to verify if a property is on
+        excludedNames to keep this algorithm with O(n + m) complexity, where n
+        = number of source's own properties and m = excludedNames.length. 
+
+        As a requirement to use JSSets as constants, a change in
+        CodeBlock::create API was necessary, because JSSet creation can throws OOM
+        exception. Now, CodeBlock::finishCreation returns ```false``` if an
+        execption is throwed by
+        CodeBlock::setConstantIdentifierSetRegisters and then we return
+        nullptr to ScriptExecutable::newCodeBlockFor. It is responsible to
+        check if CodeBlock was constructed properly and then, throw OOM
+        exception to the correct scope.
+
+        [1] - https://github.com/sebmarkbage/ecmascript-rest-spread
+        [2] - http://sebmarkbage.github.io/ecmascript-rest-spread/#Rest-RuntimeSemantics-PropertyDestructuringAssignmentEvaluation
+        [3] - http://sebmarkbage.github.io/ecmascript-rest-spread/#AbstractOperations-CopyDataProperties
+
+        * builtins/BuiltinNames.h:
+        * builtins/GlobalOperations.js:
+        (globalPrivate.copyDataProperties):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        (JSC::CodeBlock::setConstantIdentifierSetRegisters):
+        * bytecode/CodeBlock.h:
+        * bytecode/EvalCodeBlock.h:
+        (JSC::EvalCodeBlock::create):
+        * bytecode/FunctionCodeBlock.h:
+        (JSC::FunctionCodeBlock::create):
+        * bytecode/ModuleProgramCodeBlock.h:
+        (JSC::ModuleProgramCodeBlock::create):
+        * bytecode/ProgramCodeBlock.h:
+        (JSC::ProgramCodeBlock::create):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedCodeBlock::addSetConstant):
+        (JSC::UnlinkedCodeBlock::constantIdentifierSets):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitLoad):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ObjectPatternNode::bindValue):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::appendObjectPatternEntry):
+        (JSC::ASTBuilder::appendObjectPatternRestEntry):
+        (JSC::ASTBuilder::setContainsObjectRestElement):
+        * parser/Nodes.h:
+        (JSC::ObjectPatternNode::appendEntry):
+        (JSC::ObjectPatternNode::setContainsRestElement):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseDestructuringPattern):
+        (JSC::Parser&lt;LexerType&gt;::parseProperty):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::operatorStackPop):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::privateToObject):
+        * runtime/JSGlobalObjectFunctions.h:
+        * runtime/ScriptExecutable.cpp:
+        (JSC::ScriptExecutable::newCodeBlockFor):
+
</ins><span class="cx"> 2017-03-09  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement a StackTrace utility object that can capture stack traces for debugging.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebuiltinsBuiltinNamesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/builtins/BuiltinNames.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/builtins/BuiltinNames.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/builtins/BuiltinNames.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -158,6 +158,7 @@
</span><span class="cx">     macro(stringIncludesInternal) \
</span><span class="cx">     macro(stringSplitFast) \
</span><span class="cx">     macro(stringSubstrInternal) \
</span><ins>+    macro(toObject) \
</ins><span class="cx">     macro(makeBoundFunction) \
</span><span class="cx">     macro(hasOwnLengthProperty) \
</span><span class="cx">     macro(importModule) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebuiltinsGlobalOperationsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/builtins/GlobalOperations.js (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/builtins/GlobalOperations.js        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/builtins/GlobalOperations.js        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -79,3 +79,29 @@
</span><span class="cx">         return constructor;
</span><span class="cx">     @throwTypeError(&quot;|this|.constructor[Symbol.species] is not a constructor&quot;);
</span><span class="cx"> }
</span><ins>+
+@globalPrivate
+function copyDataProperties(target, source, excludedSet)
+{
+    if (!@isObject(target))
+        @throwTypeError(&quot;target needs to be an object&quot;);
+    
+    if (source === @undefined || source === null)
+        return target;
+    
+    let from = @toObject(source);
+    let keys = @Object.@getOwnPropertyNames(from);
+    let keysLength = keys.length;
+    for (let i = 0; i &lt; keysLength; i++) {
+        let nextKey = keys[i];
+        if (!excludedSet.@has(nextKey)) {
+            let desc = @Object.@getOwnPropertyDescriptor(from, nextKey);
+            if (desc.enumerable &amp;&amp; desc !== @undefined) {
+                let propValue = from[nextKey];
+                @Object.@defineProperty(target, nextKey, {value: propValue, enumerable: true, writable: true, configurable: true});
+            }
+        }
+    }
+
+    return target;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -58,6 +58,8 @@
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;JSLexicalEnvironment.h&quot;
</span><span class="cx"> #include &quot;JSModuleEnvironment.h&quot;
</span><ins>+#include &quot;JSSet.h&quot;
+#include &quot;JSString.h&quot;
</ins><span class="cx"> #include &quot;LLIntData.h&quot;
</span><span class="cx"> #include &quot;LLIntEntrypoint.h&quot;
</span><span class="cx"> #include &quot;LLIntPrototypeLoadAdaptiveStructureWatchpoint.h&quot;
</span><span class="lines">@@ -393,7 +395,7 @@
</span><span class="cx">     setNumParameters(unlinkedCodeBlock-&gt;numParameters());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CodeBlock::finishCreation(VM&amp; vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
</del><ins>+bool CodeBlock::finishCreation(VM&amp; vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
</ins><span class="cx">     JSScope* scope)
</span><span class="cx"> {
</span><span class="cx">     Base::finishCreation(vm);
</span><span class="lines">@@ -402,6 +404,8 @@
</span><span class="cx">         vm.functionHasExecutedCache()-&gt;removeUnexecutedRange(ownerExecutable-&gt;sourceID(), ownerExecutable-&gt;typeProfilingStartOffset(), ownerExecutable-&gt;typeProfilingEndOffset());
</span><span class="cx"> 
</span><span class="cx">     setConstantRegisters(unlinkedCodeBlock-&gt;constantRegisters(), unlinkedCodeBlock-&gt;constantsSourceCodeRepresentation());
</span><ins>+    if (!setConstantIdentifierSetRegisters(vm, unlinkedCodeBlock-&gt;constantIdentifierSets()))
+        return false;
</ins><span class="cx">     if (unlinkedCodeBlock-&gt;usesGlobalObject())
</span><span class="cx">         m_constantRegisters[unlinkedCodeBlock-&gt;globalObjectRegister().toConstantIndex()].set(*m_vm, this, m_globalObject.get());
</span><span class="cx"> 
</span><span class="lines">@@ -822,6 +826,8 @@
</span><span class="cx">     
</span><span class="cx">     heap()-&gt;m_codeBlocks-&gt;add(this);
</span><span class="cx">     heap()-&gt;reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction));
</span><ins>+    
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CodeBlock::~CodeBlock()
</span><span class="lines">@@ -857,6 +863,31 @@
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool CodeBlock::setConstantIdentifierSetRegisters(VM&amp; vm, const Vector&lt;ConstantIndentifierSetEntry&gt;&amp; constants)
+{
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    JSGlobalObject* globalObject = m_globalObject.get();
+    ExecState* exec = globalObject-&gt;globalExec();
+
+    for (const auto&amp; entry : constants) {
+        Structure* setStructure = globalObject-&gt;setStructure();
+        RETURN_IF_EXCEPTION(scope, false);
+        JSSet* jsSet = JSSet::create(exec, vm, setStructure);
+        RETURN_IF_EXCEPTION(scope, false);
+
+        const HashSet&lt;UniquedStringImpl*&gt;&amp; set = entry.first;
+        for (auto setEntry : set) {
+            JSString* jsString = jsOwnedString(&amp;vm, setEntry);
+            jsSet-&gt;add(exec, JSValue(jsString));
+            RETURN_IF_EXCEPTION(scope, false);
+        }
+        m_constantRegisters[entry.second].set(vm, this, JSValue(jsSet));
+    }
+    
+    scope.release();
+    return true;
+}
+
</ins><span class="cx"> void CodeBlock::setConstantRegisters(const Vector&lt;WriteBarrier&lt;Unknown&gt;&gt;&amp; constants, const Vector&lt;SourceCodeRepresentation&gt;&amp; constantsSourceCodeRepresentation)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(constants.size() == constantsSourceCodeRepresentation.size());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -121,7 +121,7 @@
</span><span class="cx">     CodeBlock(VM*, Structure*, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, RefPtr&lt;SourceProvider&gt;&amp;&amp;, unsigned sourceOffset, unsigned firstLineColumnOffset);
</span><span class="cx"> 
</span><span class="cx">     void finishCreation(VM&amp;, CopyParsedBlockTag, CodeBlock&amp; other);
</span><del>-    void finishCreation(VM&amp;, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
</del><ins>+    bool finishCreation(VM&amp;, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*);
</ins><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;JSGlobalObject&gt; m_globalObject;
</span><span class="cx"> 
</span><span class="lines">@@ -917,6 +917,8 @@
</span><span class="cx"> 
</span><span class="cx">     void updateAllPredictionsAndCountLiveness(unsigned&amp; numberOfLiveNonArgumentValueProfiles, unsigned&amp; numberOfSamplesInProfiles);
</span><span class="cx"> 
</span><ins>+    bool setConstantIdentifierSetRegisters(VM&amp;, const Vector&lt;ConstantIndentifierSetEntry&gt;&amp; constants);
+
</ins><span class="cx">     void setConstantRegisters(const Vector&lt;WriteBarrier&lt;Unknown&gt;&gt;&amp; constants, const Vector&lt;SourceCodeRepresentation&gt;&amp; constantsSourceCodeRepresentation);
</span><span class="cx"> 
</span><span class="cx">     void replaceConstant(int index, JSValue value)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeEvalCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/EvalCodeBlock.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/EvalCodeBlock.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecode/EvalCodeBlock.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -51,7 +51,8 @@
</span><span class="cx">     {
</span><span class="cx">         EvalCodeBlock* instance = new (NotNull, allocateCell&lt;EvalCodeBlock&gt;(vm-&gt;heap))
</span><span class="cx">             EvalCodeBlock(vm, vm-&gt;evalCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider));
</span><del>-        instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
</del><ins>+        if (!instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+            return nullptr;
</ins><span class="cx">         return instance;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeFunctionCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/FunctionCodeBlock.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/FunctionCodeBlock.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecode/FunctionCodeBlock.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -52,7 +52,8 @@
</span><span class="cx">     {
</span><span class="cx">         FunctionCodeBlock* instance = new (NotNull, allocateCell&lt;FunctionCodeBlock&gt;(vm-&gt;heap))
</span><span class="cx">             FunctionCodeBlock(vm, vm-&gt;functionCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider), sourceOffset, firstLineColumnOffset);
</span><del>-        instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
</del><ins>+        if (!instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+            return nullptr;
</ins><span class="cx">         return instance;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeModuleProgramCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ModuleProgramCodeBlock.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ModuleProgramCodeBlock.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecode/ModuleProgramCodeBlock.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -52,7 +52,8 @@
</span><span class="cx">     {
</span><span class="cx">         ModuleProgramCodeBlock* instance = new (NotNull, allocateCell&lt;ModuleProgramCodeBlock&gt;(vm-&gt;heap))
</span><span class="cx">             ModuleProgramCodeBlock(vm, vm-&gt;moduleProgramCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider), firstLineColumnOffset);
</span><del>-        instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
</del><ins>+        if (!instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+            return nullptr;
</ins><span class="cx">         return instance;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeProgramCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ProgramCodeBlock.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ProgramCodeBlock.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecode/ProgramCodeBlock.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -52,7 +52,8 @@
</span><span class="cx">     {
</span><span class="cx">         ProgramCodeBlock* instance = new (NotNull, allocateCell&lt;ProgramCodeBlock&gt;(vm-&gt;heap))
</span><span class="cx">             ProgramCodeBlock(vm, vm-&gt;programCodeBlockStructure.get(), ownerExecutable, unlinkedCodeBlock, scope, WTFMove(sourceProvider), firstLineColumnOffset);
</span><del>-        instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope);
</del><ins>+        if (!instance-&gt;finishCreation(*vm, ownerExecutable, unlinkedCodeBlock, scope))
+            return nullptr;
</ins><span class="cx">         return instance;
</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 (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -41,9 +41,12 @@
</span><span class="cx"> #include &quot;UnlinkedFunctionExecutable.h&quot;
</span><span class="cx"> #include &quot;VariableEnvironment.h&quot;
</span><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><ins>+#include &lt;algorithm&gt;
</ins><span class="cx"> #include &lt;wtf/BitVector.h&gt;
</span><ins>+#include &lt;wtf/HashSet.h&gt;
</ins><span class="cx"> #include &lt;wtf/TriState.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><ins>+#include &lt;wtf/text/UniquedStringImpl.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -65,6 +68,7 @@
</span><span class="cx"> typedef unsigned UnlinkedArrayAllocationProfile;
</span><span class="cx"> typedef unsigned UnlinkedObjectAllocationProfile;
</span><span class="cx"> typedef unsigned UnlinkedLLIntCallLinkInfo;
</span><ins>+typedef std::pair&lt;HashSet&lt;UniquedStringImpl*&gt;, unsigned&gt; ConstantIndentifierSetEntry;
</ins><span class="cx"> 
</span><span class="cx"> struct UnlinkedStringJumpTable {
</span><span class="cx">     struct OffsetLocation {
</span><span class="lines">@@ -182,6 +186,16 @@
</span><span class="cx">         m_bitVectors.append(WTFMove(bitVector));
</span><span class="cx">         return m_bitVectors.size() - 1;
</span><span class="cx">     }
</span><ins>+    
+    void addSetConstant(HashSet&lt;UniquedStringImpl*&gt;&amp; set)
+    {
+        VM&amp; vm = *this-&gt;vm();
+        auto locker = lockDuringMarking(vm.heap, *this);
+        unsigned result = m_constantRegisters.size();
+        m_constantRegisters.append(WriteBarrier&lt;Unknown&gt;());
+        m_constantsSourceCodeRepresentation.append(SourceCodeRepresentation::Other);
+        m_constantIdentifierSets.append(ConstantIndentifierSetEntry(set, result));
+    }
</ins><span class="cx"> 
</span><span class="cx">     unsigned addConstant(JSValue v, SourceCodeRepresentation sourceCodeRepresentation = SourceCodeRepresentation::Other)
</span><span class="cx">     {
</span><span class="lines">@@ -213,6 +227,7 @@
</span><span class="cx">         return m_linkTimeConstants[index];
</span><span class="cx">     }
</span><span class="cx">     const Vector&lt;WriteBarrier&lt;Unknown&gt;&gt;&amp; constantRegisters() { return m_constantRegisters; }
</span><ins>+    const Vector&lt;ConstantIndentifierSetEntry&gt;&amp; constantIdentifierSets() { return m_constantIdentifierSets; }
</ins><span class="cx">     const WriteBarrier&lt;Unknown&gt;&amp; constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
</span><span class="cx">     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index &gt;= FirstConstantRegisterIndex; }
</span><span class="cx">     ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
</span><span class="lines">@@ -446,6 +461,7 @@
</span><span class="cx">     Vector&lt;Identifier&gt; m_identifiers;
</span><span class="cx">     Vector&lt;BitVector&gt; m_bitVectors;
</span><span class="cx">     Vector&lt;WriteBarrier&lt;Unknown&gt;&gt; m_constantRegisters;
</span><ins>+    Vector&lt;ConstantIndentifierSetEntry&gt; m_constantIdentifierSets;
</ins><span class="cx">     Vector&lt;SourceCodeRepresentation&gt; m_constantsSourceCodeRepresentation;
</span><span class="cx">     typedef Vector&lt;WriteBarrier&lt;UnlinkedFunctionExecutable&gt;&gt; FunctionExpressionVector;
</span><span class="cx">     FunctionExpressionVector m_functionDecls;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1920,6 +1920,27 @@
</span><span class="cx">     return constantID;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, HashSet&lt;UniquedStringImpl*&gt;&amp; set)
+{
+    for (ConstantIndentifierSetEntry entry : m_codeBlock-&gt;constantIdentifierSets()) {
+        if (entry.first != set)
+            continue;
+        
+        return &amp;m_constantPoolRegisters[entry.second];
+    }
+    
+    unsigned index = m_nextConstantOffset;
+    m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
+    ++m_nextConstantOffset;
+    m_codeBlock-&gt;addSetConstant(set);
+    RegisterID* m_setRegister = &amp;m_constantPoolRegisters[index];
+    
+    if (dst)
+        return emitMove(dst, m_setRegister);
+    
+    return m_setRegister;
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitLoadGlobalObject(RegisterID* dst)
</span><span class="cx"> {
</span><span class="cx">     if (!m_globalObjectRegister) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -587,6 +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><ins>+        RegisterID* emitLoad(RegisterID* dst, HashSet&lt;UniquedStringImpl*&gt;&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 (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -41,8 +41,10 @@
</span><span class="cx"> #include &quot;Parser.h&quot;
</span><span class="cx"> #include &quot;StackAlignment.h&quot;
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><ins>+#include &lt;wtf/HashSet.h&gt;
</ins><span class="cx"> #include &lt;wtf/Threading.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><ins>+#include &lt;wtf/text/UniquedStringImpl.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace WTF;
</span><span class="cx"> 
</span><span class="lines">@@ -4027,25 +4029,56 @@
</span><span class="cx"> void ObjectPatternNode::bindValue(BytecodeGenerator&amp; generator, RegisterID* rhs) const
</span><span class="cx"> {
</span><span class="cx">     generator.emitRequireObjectCoercible(rhs, ASCIILiteral(&quot;Right side of assignment cannot be destructured&quot;));
</span><ins>+    
+    HashSet&lt;UniquedStringImpl*&gt; excludedSet;
+
</ins><span class="cx">     for (const auto&amp; target : m_targetPatterns) {
</span><del>-        RefPtr&lt;RegisterID&gt; temp = generator.newTemporary();
-        if (!target.propertyExpression) {
-            // Should not emit get_by_id for indexed ones.
-            std::optional&lt;uint32_t&gt; optionalIndex = parseIndex(target.propertyName);
-            if (!optionalIndex)
-                generator.emitGetById(temp.get(), rhs, target.propertyName);
-            else {
-                RefPtr&lt;RegisterID&gt; index = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
-                generator.emitGetByVal(temp.get(), rhs, index.get());
</del><ins>+        if (target.bindingType == BindingType::Element) {
+            RefPtr&lt;RegisterID&gt; temp = generator.newTemporary();
+            if (!target.propertyExpression) {
+                
+                // Should not emit get_by_id for indexed ones.
+                std::optional&lt;uint32_t&gt; optionalIndex = parseIndex(target.propertyName);
+                if (!optionalIndex)
+                    generator.emitGetById(temp.get(), rhs, target.propertyName);
+                else {
+                    RefPtr&lt;RegisterID&gt; pIndex = generator.emitLoad(nullptr, jsNumber(optionalIndex.value()));
+                    generator.emitGetByVal(temp.get(), rhs, pIndex.get());
+                }
+            } else {
+                RefPtr&lt;RegisterID&gt; propertyName = generator.emitNode(target.propertyExpression);
+                generator.emitGetByVal(temp.get(), rhs, propertyName.get());
</ins><span class="cx">             }
</span><ins>+            
+            if (UNLIKELY(m_containsRestElement))
+                excludedSet.add(target.propertyName.impl());
+            
+            if (target.defaultValue)
+                assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
+            target.pattern-&gt;bindValue(generator, temp.get());
</ins><span class="cx">         } else {
</span><del>-            RefPtr&lt;RegisterID&gt; propertyName = generator.emitNode(target.propertyExpression);
-            generator.emitGetByVal(temp.get(), rhs, propertyName.get());
</del><ins>+            RefPtr&lt;RegisterID&gt; excludedSetReg = generator.emitLoad(generator.newTemporary(), excludedSet);
+        
+            RefPtr&lt;RegisterID&gt; newObject = generator.emitNewObject(generator.newTemporary());
+            
+            // 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++), newObject.get());
+            generator.emitMove(args.argumentRegister(argumentCount++), rhs);
+            generator.emitMove(args.argumentRegister(argumentCount++), excludedSetReg.get());
+
+            RefPtr&lt;RegisterID&gt; result = generator.newTemporary();
+            generator.emitCall(result.get(), copyDataProperties.get(), NoExpectedFunction, args, divot(), divotStart(), divotEnd(), DebuggableCall::No);
+            target.pattern-&gt;bindValue(generator, result.get());
</ins><span class="cx">         }
</span><del>-
-        if (target.defaultValue)
-            assignDefaultValueIfUndefined(generator, temp.get(), target.defaultValue);
-        target.pattern-&gt;bindValue(generator, temp.get());
</del><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -942,16 +942,26 @@
</span><span class="cx">     
</span><span class="cx">     void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation&amp; location, bool wasString, const Identifier&amp; identifier, DestructuringPattern pattern, ExpressionNode* defaultValue)
</span><span class="cx">     {
</span><del>-        node-&gt;appendEntry(location, identifier, wasString, pattern, defaultValue);
</del><ins>+        node-&gt;appendEntry(location, identifier, wasString, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
</ins><span class="cx">         tryInferNameInPattern(pattern, defaultValue);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void appendObjectPatternEntry(ObjectPattern node, const JSTokenLocation&amp; location, ExpressionNode* propertyExpression, DestructuringPattern pattern, ExpressionNode* defaultValue)
</span><span class="cx">     {
</span><del>-        node-&gt;appendEntry(location, propertyExpression, pattern, defaultValue);
</del><ins>+        node-&gt;appendEntry(location, propertyExpression, pattern, defaultValue, ObjectPatternNode::BindingType::Element);
</ins><span class="cx">         tryInferNameInPattern(pattern, defaultValue);
</span><span class="cx">     }
</span><ins>+    
+    void appendObjectPatternRestEntry(ObjectPattern node, const JSTokenLocation&amp; location, DestructuringPattern pattern)
+    {
+        node-&gt;appendEntry(location, nullptr, pattern, nullptr, ObjectPatternNode::BindingType::RestElement);
+    }
</ins><span class="cx"> 
</span><ins>+    void setContainsObjectRestElement(ObjectPattern node, bool containsRestElement)
+    {
+        node-&gt;setContainsRestElement(containsRestElement);
+    }
+
</ins><span class="cx">     BindingPattern createBindingLocation(const JSTokenLocation&amp;, const Identifier&amp; boundProperty, const JSTextPosition&amp; start, const JSTextPosition&amp; end, AssignmentContext context)
</span><span class="cx">     {
</span><span class="cx">         return new (m_parserArena) BindingNode(boundProperty, start, end, context);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -2129,20 +2129,29 @@
</span><span class="cx">         Vector&lt;Entry&gt; m_targetPatterns;
</span><span class="cx">     };
</span><span class="cx">     
</span><del>-    class ObjectPatternNode : public DestructuringPatternNode, public ParserArenaDeletable {
</del><ins>+    class ObjectPatternNode : public DestructuringPatternNode, public ThrowableExpressionData, public ParserArenaDeletable {
</ins><span class="cx">     public:
</span><span class="cx">         using ParserArenaDeletable::operator new;
</span><span class="cx">         
</span><span class="cx">         ObjectPatternNode();
</span><del>-        void appendEntry(const JSTokenLocation&amp;, const Identifier&amp; identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
</del><ins>+        enum class BindingType {
+            Element,
+            RestElement
+        };
+        void appendEntry(const JSTokenLocation&amp;, const Identifier&amp; identifier, bool wasString, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
</ins><span class="cx">         {
</span><del>-            m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue });
</del><ins>+            m_targetPatterns.append(Entry{ identifier, nullptr, wasString, pattern, defaultValue, bindingType });
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        void appendEntry(const JSTokenLocation&amp;, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue)
</del><ins>+        void appendEntry(const JSTokenLocation&amp;, ExpressionNode* propertyExpression, DestructuringPatternNode* pattern, ExpressionNode* defaultValue, BindingType bindingType)
</ins><span class="cx">         {
</span><del>-            m_targetPatterns.append(Entry{ Identifier(), propertyExpression, false, pattern, defaultValue });
</del><ins>+            m_targetPatterns.append(Entry{ Identifier(), propertyExpression, false, pattern, defaultValue, bindingType });
</ins><span class="cx">         }
</span><ins>+        
+        void setContainsRestElement(bool containsRestElement)
+        {
+            m_containsRestElement = containsRestElement;
+        }
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         void collectBoundIdentifiers(Vector&lt;Identifier&gt;&amp;) const override;
</span><span class="lines">@@ -2154,7 +2163,9 @@
</span><span class="cx">             bool wasString;
</span><span class="cx">             DestructuringPatternNode* pattern;
</span><span class="cx">             ExpressionNode* defaultValue;
</span><ins>+            BindingType bindingType;
</ins><span class="cx">         };
</span><ins>+        bool m_containsRestElement { false };
</ins><span class="cx">         Vector&lt;Entry&gt; m_targetPatterns;
</span><span class="cx">     };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1002,6 +1002,8 @@
</span><span class="cx">         if (hasDestructuringPattern)
</span><span class="cx">             *hasDestructuringPattern = true;
</span><span class="cx"> 
</span><ins>+        bool restElementWasFound = false;
+
</ins><span class="cx">         do {
</span><span class="cx">             bool wasString = false;
</span><span class="cx"> 
</span><span class="lines">@@ -1008,6 +1010,19 @@
</span><span class="cx">             if (match(CLOSEBRACE))
</span><span class="cx">                 break;
</span><span class="cx"> 
</span><ins>+            if (UNLIKELY(match(DOTDOTDOT))) {
+                JSTokenLocation location = m_token.m_location;
+                next();
+                auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
+                if (kind == DestructuringKind::DestructureToExpressions &amp;&amp; !innerPattern)
+                    return 0;
+                propagateError();
+                context.appendObjectPatternRestEntry(objectPattern, location, innerPattern);
+                restElementWasFound = true;
+                context.setContainsObjectRestElement(objectPattern, restElementWasFound);
+                break;
+            }
+
</ins><span class="cx">             const Identifier* propertyName = nullptr;
</span><span class="cx">             TreeExpression propertyExpression = 0;
</span><span class="cx">             TreeDestructuringPattern innerPattern = 0;
</span><span class="lines">@@ -1082,7 +1097,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (kind == DestructuringKind::DestructureToExpressions &amp;&amp; !match(CLOSEBRACE))
</span><span class="cx">             return 0;
</span><del>-        consumeOrFail(CLOSEBRACE, &quot;Expected either a closing '}' or an ',' after a property destructuring pattern&quot;);
</del><ins>+        consumeOrFail(CLOSEBRACE, restElementWasFound ? &quot;Expected a closing '}' following a rest element destructuring pattern&quot; : &quot;Expected either a closing '}' or an ',' after a property destructuring pattern&quot;);
</ins><span class="cx">         pattern = objectPattern;
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -3763,6 +3778,10 @@
</span><span class="cx">         context.setEndOffset(node, m_lexer-&gt;currentOffset());
</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><ins>+    case DOTDOTDOT: {
+        classifyExpressionError(ErrorIndicatesPattern);
+        FALLTHROUGH;
+    }
</ins><span class="cx">     default:
</span><span class="cx">         failIfFalse(m_token.m_type &amp; KeywordTokenFlag, &quot;Expected a property name&quot;);
</span><span class="cx">         wasIdent = true; // Treat keyword token as an identifier
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -352,6 +352,12 @@
</span><span class="cx">     void appendObjectPatternEntry(ArrayPattern, const JSTokenLocation&amp;, Expression, DestructuringPattern, Expression)
</span><span class="cx">     {
</span><span class="cx">     }
</span><ins>+    void appendObjectPatternRestEntry(ObjectPattern, const JSTokenLocation&amp;, DestructuringPattern)
+    {
+    }
+    void setContainsObjectRestElement(ObjectPattern, bool)
+    {
+    }
</ins><span class="cx"> 
</span><span class="cx">     DestructuringPattern createBindingLocation(const JSTokenLocation&amp;, const Identifier&amp;, const JSTextPosition&amp;, const JSTextPosition&amp;, AssignmentContext)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -735,6 +735,7 @@
</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><ins>+    JSFunction* privateFuncToObject = JSFunction::create(vm, this, 0, String(), privateToObject);
</ins><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">@@ -789,6 +790,7 @@
</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><ins>+        GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().toObjectPrivateName(), privateFuncToObject, DontEnum | DontDelete | ReadOnly),
</ins><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 (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -735,6 +735,11 @@
</span><span class="cx">     thisObject-&gt;setPrototype(vm, exec, value, shouldThrowIfCantSet);
</span><span class="cx">     return JSValue::encode(jsUndefined());
</span><span class="cx"> }
</span><ins>+
+EncodedJSValue JSC_HOST_CALL privateToObject(ExecState* exec)
+{
+    return JSValue::encode(JSValue(exec-&gt;argument(0).toObject(exec)));
+}
</ins><span class="cx">     
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -50,6 +50,7 @@
</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><ins>+EncodedJSValue JSC_HOST_CALL privateToObject(ExecState*);
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState*);
</span><span class="cx"> 
</span><span class="cx"> double jsToNumber(StringView);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeObjectConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -105,6 +105,7 @@
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().definePropertyPrivateName(), objectConstructorDefineProperty, DontEnum, 3);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().getPrototypeOfPrivateName(), objectConstructorGetPrototypeOf, DontEnum, 1);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().getOwnPropertyNamesPrivateName(), objectConstructorGetOwnPropertyNames, DontEnum, 1);
</span><ins>+    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().getOwnPropertyDescriptorPrivateName(), objectConstructorGetOwnPropertyDescriptor, DontEnum, 1);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // ES 19.1.1.1 Object([value])
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeScriptExecutablecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -176,14 +176,24 @@
</span><span class="cx">     ASSERT(vm-&gt;heap.isDeferred());
</span><span class="cx">     ASSERT(endColumn() != UINT_MAX);
</span><span class="cx"> 
</span><ins>+    JSGlobalObject* globalObject = scope-&gt;globalObject();
+    ExecState* exec = globalObject-&gt;globalExec();
+
</ins><span class="cx">     if (classInfo(*vm) == EvalExecutable::info()) {
</span><span class="cx">         EvalExecutable* executable = jsCast&lt;EvalExecutable*&gt;(this);
</span><span class="cx">         RELEASE_ASSERT(kind == CodeForCall);
</span><span class="cx">         RELEASE_ASSERT(!executable-&gt;m_evalCodeBlock);
</span><span class="cx">         RELEASE_ASSERT(!function);
</span><del>-        return EvalCodeBlock::create(vm,
</del><ins>+        auto codeBlock = EvalCodeBlock::create(vm,
</ins><span class="cx">             executable, executable-&gt;m_unlinkedEvalCodeBlock.get(), scope,
</span><span class="cx">             executable-&gt;source().provider());
</span><ins>+        if (!codeBlock) {
+            exception = throwException(
+                exec, throwScope,
+                createOutOfMemoryError(exec));
+            return nullptr;
+        }
+        return codeBlock;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (classInfo(*vm) == ProgramExecutable::info()) {
</span><span class="lines">@@ -191,9 +201,16 @@
</span><span class="cx">         RELEASE_ASSERT(kind == CodeForCall);
</span><span class="cx">         RELEASE_ASSERT(!executable-&gt;m_programCodeBlock);
</span><span class="cx">         RELEASE_ASSERT(!function);
</span><del>-        return ProgramCodeBlock::create(vm,
</del><ins>+        auto codeBlock = ProgramCodeBlock::create(vm,
</ins><span class="cx">             executable, executable-&gt;m_unlinkedProgramCodeBlock.get(), scope,
</span><span class="cx">             executable-&gt;source().provider(), startColumn());
</span><ins>+        if (!codeBlock) {
+            exception = throwException(
+                exec, throwScope,
+                createOutOfMemoryError(exec));
+            return nullptr;
+        }
+        return codeBlock;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (classInfo(*vm) == ModuleProgramExecutable::info()) {
</span><span class="lines">@@ -201,9 +218,16 @@
</span><span class="cx">         RELEASE_ASSERT(kind == CodeForCall);
</span><span class="cx">         RELEASE_ASSERT(!executable-&gt;m_moduleProgramCodeBlock);
</span><span class="cx">         RELEASE_ASSERT(!function);
</span><del>-        return ModuleProgramCodeBlock::create(vm,
</del><ins>+        auto codeBlock = ModuleProgramCodeBlock::create(vm,
</ins><span class="cx">             executable, executable-&gt;m_unlinkedModuleProgramCodeBlock.get(), scope,
</span><span class="cx">             executable-&gt;source().provider(), startColumn());
</span><ins>+        if (!codeBlock) {
+            exception = throwException(
+                exec, throwScope,
+                createOutOfMemoryError(exec));
+            return nullptr;
+        }
+        return codeBlock;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(classInfo(*vm) == FunctionExecutable::info());
</span><span class="lines">@@ -210,7 +234,6 @@
</span><span class="cx">     RELEASE_ASSERT(function);
</span><span class="cx">     FunctionExecutable* executable = jsCast&lt;FunctionExecutable*&gt;(this);
</span><span class="cx">     RELEASE_ASSERT(!executable-&gt;codeBlockFor(kind));
</span><del>-    JSGlobalObject* globalObject = scope-&gt;globalObject();
</del><span class="cx">     ParserError error;
</span><span class="cx">     DebuggerMode debuggerMode = globalObject-&gt;hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;
</span><span class="cx">     UnlinkedFunctionCodeBlock* unlinkedCodeBlock = 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSetPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -67,6 +67,7 @@
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;clear, setProtoFuncClear, DontEnum, 0);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;deleteKeyword, setProtoFuncDelete, DontEnum, 1);
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;has, setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
</span><ins>+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().hasPrivateName(), setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
</ins><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0);
</span><span class="cx"> 
</span><span class="cx">     JSFunction* values = JSFunction::create(vm, globalObject, 0, vm.propertyNames-&gt;builtinNames().valuesPublicName().string(), setProtoFuncValues);
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/WTF/ChangeLog        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2017-03-09  Caio Lima  &lt;ticaiolima@gmail.com&gt;
+
+        [ESnext] Implement Object Rest - Implementing Object Rest Destructuring
+        https://bugs.webkit.org/show_bug.cgi?id=167962
+
+        Reviewed by Keith Miller.
+
+        * wtf/HashSet.h:
+        (WTF::=):
+
</ins><span class="cx"> 2017-03-09  Youenn Fablet  &lt;youenn@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Activate VideoToolbox when WebRTC is enabled on iOS
</span></span></pre></div>
<a id="trunkSourceWTFwtfHashSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/HashSet.h (213696 => 213697)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/HashSet.h        2017-03-10 01:48:30 UTC (rev 213696)
+++ trunk/Source/WTF/wtf/HashSet.h        2017-03-10 02:00:33 UTC (rev 213697)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2005, 2006, 2007, 2008, 2011, 2013, 2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * This library is free software; you can redistribute it and/or
</span><span class="cx">  * modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -120,6 +120,9 @@
</span><span class="cx"> 
</span><span class="cx">         template&lt;typename OtherCollection&gt;
</span><span class="cx">         bool operator==(const OtherCollection&amp;) const;
</span><ins>+        
+        template&lt;typename OtherCollection&gt;
+        bool operator!=(const OtherCollection&amp;) const;
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         HashTableType m_impl;
</span><span class="lines">@@ -362,6 +365,13 @@
</span><span class="cx">         }
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><ins>+    
+    template&lt;typename T, typename U, typename V&gt;
+    template&lt;typename OtherCollection&gt;
+    inline bool HashSet&lt;T, U, V&gt;::operator!=(const OtherCollection&amp; otherCollection) const
+    {
+        return !(*this == otherCollection);
+    }
</ins><span class="cx"> 
</span><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>