<!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>[192436] trunk/Source/JavaScriptCore</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/192436">192436</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-11-13 11:13:39 -0800 (Fri, 13 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Allow any LeftHandSideExpression as a valid AssignmentElement
https://bugs.webkit.org/show_bug.cgi?id=151026

Patch by Caitlin Potter &lt;caitpotter88@gmail.com&gt; on 2015-11-13
Reviewed by Geoffrey Garen.

* bytecompiler/NodesCodegen.cpp:
(JSC::AssignmentElementNode::collectBoundIdentifiers):
(JSC::AssignmentElementNode::bindValue):
(JSC::AssignmentElementNode::toString):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::isAssignmentLocation):
(JSC::ASTBuilder::createAssignmentElement):
* parser/NodeConstructors.h:
(JSC::AssignmentElementNode::AssignmentElementNode):
* parser/Nodes.h:
(JSC::AssignmentElementNode::assignmentTarget):
(JSC::AssignmentElementNode::divotStart):
(JSC::AssignmentElementNode::divotEnd):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::createAssignmentElement):
(JSC::Parser&lt;LexerType&gt;::parseDestructuringPattern):
* parser/Parser.h:
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::operatorStackPop):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</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="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestses6yaml">trunk/Source/JavaScriptCore/tests/es6.yaml</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressrestelementsjs">trunk/Source/JavaScriptCore/tests/stress/rest-elements.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestses6destructuring_assignment_non_simple_targetjs">trunk/Source/JavaScriptCore/tests/es6/destructuring_assignment_non_simple_target.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestses6destructuring_initializer_scopingjs">trunk/Source/JavaScriptCore/tests/es6/destructuring_initializer_scoping.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressdestructuringassignmentsyntaxjs">trunk/Source/JavaScriptCore/tests/stress/destructuring-assignment-syntax.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-11-13  Caitlin Potter  &lt;caitpotter88@gmail.com&gt;
+
+        Allow any LeftHandSideExpression as a valid AssignmentElement
+        https://bugs.webkit.org/show_bug.cgi?id=151026
+
+        Reviewed by Geoffrey Garen.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::AssignmentElementNode::collectBoundIdentifiers):
+        (JSC::AssignmentElementNode::bindValue):
+        (JSC::AssignmentElementNode::toString):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::isAssignmentLocation):
+        (JSC::ASTBuilder::createAssignmentElement):
+        * parser/NodeConstructors.h:
+        (JSC::AssignmentElementNode::AssignmentElementNode):
+        * parser/Nodes.h:
+        (JSC::AssignmentElementNode::assignmentTarget):
+        (JSC::AssignmentElementNode::divotStart):
+        (JSC::AssignmentElementNode::divotEnd):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::createAssignmentElement):
+        (JSC::Parser&lt;LexerType&gt;::parseDestructuringPattern):
+        * parser/Parser.h:
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::operatorStackPop):
+
</ins><span class="cx"> 2015-11-13  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         op_assert should declare that it uses the first register argument
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -3397,7 +3397,65 @@
</span><span class="cx"> {
</span><span class="cx">     identifiers.append(m_boundProperty);
</span><span class="cx"> }
</span><del>-    
</del><ins>+
+void AssignmentElementNode::collectBoundIdentifiers(Vector&lt;Identifier&gt;&amp;) const
+{
+}
+
+void AssignmentElementNode::bindValue(BytecodeGenerator&amp; generator, RegisterID* value) const
+{
+    if (m_assignmentTarget-&gt;isResolveNode()) {
+        ResolveNode* lhs = static_cast&lt;ResolveNode*&gt;(m_assignmentTarget);
+        Variable var = generator.variable(lhs-&gt;identifier());
+        bool isReadOnly = var.isReadOnly();
+        if (RegisterID* local = var.local()) {
+            generator.emitTDZCheckIfNecessary(var, local, nullptr);
+
+            if (isReadOnly)
+                generator.emitReadOnlyExceptionIfNeeded(var);
+            else {
+                generator.invalidateForInContextForLocal(local);
+                generator.moveToDestinationIfNeeded(local, value);
+                generator.emitProfileType(local, divotStart(), divotEnd());
+            }
+            return;
+        }
+        if (generator.isStrictMode())
+            generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
+        RefPtr&lt;RegisterID&gt; scope = generator.emitResolveScope(nullptr, var);
+        generator.emitTDZCheckIfNecessary(var, nullptr, scope.get());
+        if (isReadOnly) {
+            bool threwException = generator.emitReadOnlyExceptionIfNeeded(var);
+            if (threwException)
+                return;
+        }
+        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
+        if (!isReadOnly) {
+            generator.emitPutToScope(scope.get(), var, value, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound, NotInitialization);
+            generator.emitProfileType(value, var, divotStart(), divotEnd());
+        }
+    } else if (m_assignmentTarget-&gt;isDotAccessorNode()) {
+        DotAccessorNode* lhs = static_cast&lt;DotAccessorNode*&gt;(m_assignmentTarget);
+        RefPtr&lt;RegisterID&gt; base = generator.emitNodeForLeftHandSide(lhs-&gt;base(), true, false);
+        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
+        generator.emitPutById(base.get(), lhs-&gt;identifier(), value);
+        generator.emitProfileType(value, divotStart(), divotEnd());
+    } else if (m_assignmentTarget-&gt;isBracketAccessorNode()) {
+        BracketAccessorNode* lhs = static_cast&lt;BracketAccessorNode*&gt;(m_assignmentTarget);
+        RefPtr&lt;RegisterID&gt; base = generator.emitNodeForLeftHandSide(lhs-&gt;base(), true, false);
+        RefPtr&lt;RegisterID&gt; property = generator.emitNodeForLeftHandSide(lhs-&gt;subscript(), true, false);
+        generator.emitExpressionInfo(divotEnd(), divotStart(), divotEnd());
+        generator.emitPutByVal(base.get(), property.get(), value);
+        generator.emitProfileType(value, divotStart(), divotEnd());
+    }
+}
+
+void AssignmentElementNode::toString(StringBuilder&amp; builder) const
+{
+    if (m_assignmentTarget-&gt;isResolveNode())
+        builder.append(static_cast&lt;ResolveNode*&gt;(m_assignmentTarget)-&gt;identifier().string());
+}
+
</ins><span class="cx"> RegisterID* SpreadExpressionNode::emitBytecode(BytecodeGenerator&amp;, RegisterID*)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -121,6 +121,7 @@
</span><span class="cx">     typedef ArrayPatternNode* ArrayPattern;
</span><span class="cx">     typedef ObjectPatternNode* ObjectPattern;
</span><span class="cx">     typedef BindingNode* BindingPattern;
</span><ins>+    typedef AssignmentElementNode* AssignmentElement;
</ins><span class="cx">     static const bool CreatesAST = true;
</span><span class="cx">     static const bool NeedsFreeVariableInfo = true;
</span><span class="cx">     static const bool CanUseFunctionCache = true;
</span><span class="lines">@@ -524,6 +525,26 @@
</span><span class="cx">         return pattern-&gt;isBindingNode();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool isAssignmentLocation(const Expression&amp; pattern)
+    {
+        return pattern-&gt;isAssignmentLocation();
+    }
+
+    bool isObjectLiteral(const Expression&amp; node)
+    {
+        return node-&gt;isObjectLiteral();
+    }
+
+    bool isArrayLiteral(const Expression&amp; node)
+    {
+        return node-&gt;isArrayLiteral();
+    }
+
+    bool isObjectOrArrayLiteral(const Expression&amp; node)
+    {
+        return isObjectLiteral(node) || isArrayLiteral(node);
+    }
+
</ins><span class="cx">     StatementNode* createEmptyStatement(const JSTokenLocation&amp; location) { return new (m_parserArena) EmptyStatementNode(location); }
</span><span class="cx"> 
</span><span class="cx">     StatementNode* createDeclarationStatement(const JSTokenLocation&amp; location, ExpressionNode* expr, int start, int end)
</span><span class="lines">@@ -836,6 +857,11 @@
</span><span class="cx">         return new (m_parserArena) BindingNode(boundProperty, start, end, context);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    AssignmentElement createAssignmentElement(const Expression&amp; assignmentTarget, const JSTextPosition&amp; start, const JSTextPosition&amp; end)
+    {
+        return new (m_parserArena) AssignmentElementNode(assignmentTarget, start, end);
+    }
+
</ins><span class="cx">     void setEndOffset(Node* node, int offset)
</span><span class="cx">     {
</span><span class="cx">         node-&gt;setEndOffset(offset);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodeConstructorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/NodeConstructors.h (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -1020,7 +1020,15 @@
</span><span class="cx">         , m_bindingContext(context)
</span><span class="cx">     {
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    inline AssignmentElementNode::AssignmentElementNode(ExpressionNode* assignmentTarget, const JSTextPosition&amp; start, const JSTextPosition&amp; end)
+        : DestructuringPatternNode()
+        , m_divotStart(start)
+        , m_divotEnd(end)
+        , m_assignmentTarget(assignmentTarget)
+    {
+    }
+
</ins><span class="cx">     inline DestructuringAssignmentNode::DestructuringAssignmentNode(const JSTokenLocation&amp; location, DestructuringPatternNode* bindings, ExpressionNode* initializer)
</span><span class="cx">         : ExpressionNode(location)
</span><span class="cx">         , m_bindings(bindings)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -153,6 +153,8 @@
</span><span class="cx"> 
</span><span class="cx">         virtual bool isNumber() const { return false; }
</span><span class="cx">         virtual bool isString() const { return false; }
</span><ins>+        virtual bool isObjectLiteral() const { return false; }
+        virtual bool isArrayLiteral() const { return false; }
</ins><span class="cx">         virtual bool isNull() const { return false; }
</span><span class="cx">         virtual bool isPure(BytecodeGenerator&amp;) const { return false; }        
</span><span class="cx">         virtual bool isConstant() const { return false; }
</span><span class="lines">@@ -592,6 +594,8 @@
</span><span class="cx">         ArrayNode(const JSTokenLocation&amp;, ElementNode*);
</span><span class="cx">         ArrayNode(const JSTokenLocation&amp;, int elision, ElementNode*);
</span><span class="cx"> 
</span><ins>+        virtual bool isArrayLiteral() const override { return true; }
+
</ins><span class="cx">         ArgumentListNode* toArgumentList(ParserArena&amp;, int, int) const;
</span><span class="cx"> 
</span><span class="cx">         ElementNode* elements() const { ASSERT(isSimpleArray()); return m_element; }
</span><span class="lines">@@ -647,6 +651,7 @@
</span><span class="cx">     public:
</span><span class="cx">         ObjectLiteralNode(const JSTokenLocation&amp;);
</span><span class="cx">         ObjectLiteralNode(const JSTokenLocation&amp;, PropertyListNode*);
</span><ins>+        virtual bool isObjectLiteral() const override { return true; }
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         virtual RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
</span><span class="lines">@@ -2048,6 +2053,24 @@
</span><span class="cx">         AssignmentContext m_bindingContext;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    class AssignmentElementNode : public DestructuringPatternNode {
+    public:
+        AssignmentElementNode(ExpressionNode* assignmentTarget, const JSTextPosition&amp; start, const JSTextPosition&amp; end);
+        const ExpressionNode* assignmentTarget() { return m_assignmentTarget; }
+
+        const JSTextPosition&amp; divotStart() const { return m_divotStart; }
+        const JSTextPosition&amp; divotEnd() const { return m_divotEnd; }
+
+    private:
+        virtual void collectBoundIdentifiers(Vector&lt;Identifier&gt;&amp;) const override;
+        virtual void bindValue(BytecodeGenerator&amp;, RegisterID*) const override;
+        virtual void toString(StringBuilder&amp;) const override;
+
+        JSTextPosition m_divotStart;
+        JSTextPosition m_divotEnd;
+        ExpressionNode* m_assignmentTarget;
+    };
+
</ins><span class="cx">     class DestructuringAssignmentNode : public ExpressionNode {
</span><span class="cx">     public:
</span><span class="cx">         DestructuringAssignmentNode(const JSTokenLocation&amp;, DestructuringPatternNode*, ExpressionNode*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -731,6 +731,12 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><ins>+template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern Parser&lt;LexerType&gt;::createAssignmentElement(TreeBuilder&amp; context, TreeExpression&amp; assignmentTarget, const JSTextPosition&amp; startPosition, const JSTextPosition&amp; endPosition)
+{
+    return context.createAssignmentElement(assignmentTarget, startPosition, endPosition);
+}
+
+template &lt;typename LexerType&gt;
</ins><span class="cx"> template &lt;class TreeBuilder&gt; TreeSourceElements Parser&lt;LexerType&gt;::parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&amp; context)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!match(OPENBRACE));
</span><span class="lines">@@ -766,6 +772,34 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><ins>+template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::parseBindingOrAssignmentElement(TreeBuilder&amp; context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
+{
+    if (kind == DestructureToExpressions)
+        return parseAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
+    return parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
+}
+
+template &lt;typename LexerType&gt;
+template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::parseAssignmentElement(TreeBuilder&amp; context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
+{
+    SavePoint savePoint = createSavePoint();
+    TreeDestructuringPattern assignmentTarget = 0;
+
+    if (match(OPENBRACE) || match(OPENBRACKET))
+        assignmentTarget = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth);
+    if (!assignmentTarget || match(DOT) || match(OPENBRACKET) || match(OPENPAREN) || match(TEMPLATE)) {
+        restoreSavePoint(savePoint);
+        JSTextPosition startPosition = tokenStartPosition();
+        auto element = parseMemberExpression(context);
+
+        semanticFailIfFalse(element &amp;&amp; context.isAssignmentLocation(element), &quot;Invalid destructuring assignment target&quot;);
+
+        return createAssignmentElement(context, element, startPosition, lastTokenEndPosition());
+    }
+    return assignmentTarget;
+}
+
+template &lt;typename LexerType&gt;
</ins><span class="cx"> template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::parseDestructuringPattern(TreeBuilder&amp; context, DestructuringKind kind, ExportType exportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
</span><span class="cx"> {
</span><span class="cx">     failIfStackOverflow();
</span><span class="lines">@@ -795,7 +829,7 @@
</span><span class="cx">             if (UNLIKELY(match(DOTDOTDOT))) {
</span><span class="cx">                 JSTokenLocation location = m_token.m_location;
</span><span class="cx">                 next();
</span><del>-                auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</del><ins>+                auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</ins><span class="cx">                 if (kind == DestructureToExpressions &amp;&amp; !innerPattern)
</span><span class="cx">                     return 0;
</span><span class="cx">                 failIfFalse(innerPattern, &quot;Cannot parse this destructuring pattern&quot;);
</span><span class="lines">@@ -808,7 +842,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             JSTokenLocation location = m_token.m_location;
</span><del>-            auto innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</del><ins>+            auto innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</ins><span class="cx">             if (kind == DestructureToExpressions &amp;&amp; !innerPattern)
</span><span class="cx">                 return 0;
</span><span class="cx">             failIfFalse(innerPattern, &quot;Cannot parse this destructuring pattern&quot;);
</span><span class="lines">@@ -816,8 +850,6 @@
</span><span class="cx">             context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
</span><span class="cx">         } while (consume(COMMA));
</span><span class="cx"> 
</span><del>-        if (kind == DestructureToExpressions &amp;&amp; !match(CLOSEBRACKET))
-            return 0;
</del><span class="cx">         consumeOrFail(CLOSEBRACKET, restElementWasFound ? &quot;Expected a closing ']' following a rest element destructuring pattern&quot; : &quot;Expected either a closing ']' or a ',' following an element destructuring pattern&quot;);
</span><span class="cx">         context.finishArrayPattern(arrayPattern, divotStart, divotStart, lastTokenEndPosition());
</span><span class="cx">         pattern = arrayPattern;
</span><span class="lines">@@ -845,7 +877,7 @@
</span><span class="cx">                 JSToken identifierToken = m_token;
</span><span class="cx">                 next();
</span><span class="cx">                 if (consume(COLON))
</span><del>-                    innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</del><ins>+                    innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</ins><span class="cx">                 else
</span><span class="cx">                     innerPattern = createBindingPattern(context, kind, exportType, *propertyName, depth + 1, identifierToken, bindingContext, duplicateIdentifier);
</span><span class="cx">             } else {
</span><span class="lines">@@ -878,7 +910,7 @@
</span><span class="cx">                     
</span><span class="cx">                     failWithMessage(&quot;Expected a ':' prior to a named destructuring property&quot;);
</span><span class="cx">                 }
</span><del>-                innerPattern = parseDestructuringPattern(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</del><ins>+                innerPattern = parseBindingOrAssignmentElement(context, kind, exportType, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</ins><span class="cx">             }
</span><span class="cx">             if (kind == DestructureToExpressions &amp;&amp; !innerPattern)
</span><span class="cx">                 return 0;
</span><span class="lines">@@ -2689,6 +2721,7 @@
</span><span class="cx">     JSTokenLocation location(tokenLocation());
</span><span class="cx">     int initialAssignmentCount = m_assignmentCount;
</span><span class="cx">     int initialNonLHSCount = m_nonLHSCount;
</span><ins>+    String assignmentPatternError = String();
</ins><span class="cx">     if (match(OPENBRACE) || match(OPENBRACKET)) {
</span><span class="cx">         SavePoint savePoint = createSavePoint();
</span><span class="cx">         auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression);
</span><span class="lines">@@ -2697,6 +2730,7 @@
</span><span class="cx">             if (rhs)
</span><span class="cx">                 return context.createDestructuringAssignment(location, pattern, rhs);
</span><span class="cx">         }
</span><ins>+        assignmentPatternError = m_errorMessage;
</ins><span class="cx">         restoreSavePoint(savePoint);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2711,6 +2745,10 @@
</span><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     TreeExpression lhs = parseConditionalExpression(context);
</span><ins>+    if (!assignmentPatternError.isNull() &amp;&amp; (lhs &amp;&amp; (context.isObjectOrArrayLiteral(lhs) &amp;&amp; match(EQUAL)))) {
+        setErrorMessage(assignmentPatternError);
+        return 0;
+    }
</ins><span class="cx">     failIfFalse(lhs, &quot;Cannot parse expression&quot;);
</span><span class="cx">     if (initialNonLHSCount != m_nonLHSCount) {
</span><span class="cx">         if (m_token.m_type &gt;= EQUAL &amp;&amp; m_token.m_type &lt;= OREQUAL)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -1160,6 +1160,9 @@
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeSourceElements parseArrowFunctionSingleExpressionBodySourceElements(TreeBuilder&amp;);
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeExpression parseArrowFunctionExpression(TreeBuilder&amp;);
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&amp;, DestructuringKind, ExportType, const Identifier&amp;, int depth, JSToken, AssignmentContext, const Identifier** duplicateIdentifier);
</span><ins>+    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern createAssignmentElement(TreeBuilder&amp;, TreeExpression&amp;, const JSTextPosition&amp;, const JSTextPosition&amp;);
+    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern parseBindingOrAssignmentElement(TreeBuilder&amp; context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth);
+    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern parseAssignmentElement(TreeBuilder&amp; context, DestructuringKind, ExportType, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth);
</ins><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&amp;, DestructuringKind, ExportType, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&amp;, AssignmentContext);
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeExpression parseDefaultValueForDestructuringPattern(TreeBuilder&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -346,12 +346,36 @@
</span><span class="cx">     {
</span><span class="cx">         return BindingDestructuring;
</span><span class="cx">     }
</span><ins>+    DestructuringPattern createAssignmentElement(const Expression&amp;, const JSTextPosition&amp;, const JSTextPosition&amp;)
+    {
+        return BindingDestructuring;
+    }
</ins><span class="cx"> 
</span><span class="cx">     bool isBindingNode(DestructuringPattern pattern)
</span><span class="cx">     {
</span><span class="cx">         return pattern == BindingDestructuring;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool isAssignmentLocation(ExpressionType type)
+    {
+        return type == ResolveExpr || type == DotExpr || type == BracketExpr;
+    }
+
+    bool isObjectLiteral(ExpressionType type)
+    {
+        return type == ObjectLiteralExpr;
+    }
+
+    bool isArrayLiteral(ExpressionType type)
+    {
+        return type == ArrayLiteralExpr;
+    }
+
+    bool isObjectOrArrayLiteral(ExpressionType type)
+    {
+        return isObjectLiteral(type) || isArrayLiteral(type);
+    }
+
</ins><span class="cx">     void setEndOffset(int, int) { }
</span><span class="cx">     int endOffset(int) { return 0; }
</span><span class="cx">     void setStartOffset(int, int) { }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestses6destructuring_assignment_non_simple_targetjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/es6/destructuring_assignment_non_simple_target.js (0 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/es6/destructuring_assignment_non_simple_target.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/es6/destructuring_assignment_non_simple_target.js        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function test() {
+    var msg = {};
+    ({
+        name: msg.name,
+        &quot;parameters&quot;: [msg.callback, ...msg[&quot;parameters&quot;]],
+        0: msg[0]
+    } = {
+        name: &quot;test&quot;,
+        parameters: [function cb() { return &quot;test&quot;; }, &quot;a&quot;, &quot;b&quot;, &quot;c&quot;],
+        &quot;0&quot;: NaN
+    });
+    return msg.name === &quot;test&quot; &amp;&amp; msg[0] !== msg[0] &amp;&amp; msg.callback() === &quot;test&quot; &amp;&amp; (msg.parameters + &quot;&quot;) === &quot;a,b,c&quot;;
+}
+
+if (!test())
+    throw new Error(&quot;Test failed&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestses6destructuring_initializer_scopingjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/es6/destructuring_initializer_scoping.js (0 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/es6/destructuring_initializer_scoping.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/es6/destructuring_initializer_scoping.js        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+var outer = [];
+function test() {
+    var a = {};
+    var defaultObj = {
+        name: &quot;default&quot;,
+        length: 3,
+        0: &quot;a&quot;,
+        1: &quot;b&quot;,
+        2: &quot;c&quot;,
+        [Symbol.iterator]: Array.prototype[Symbol.iterator]
+    };
+    function tester({ name } = { name: a.name } = [outer[0], ...outer[1]] = defaultObj) { return name; }
+    return tester() === &quot;default&quot; &amp;&amp; a.name === &quot;default&quot; &amp;&amp; (outer + &quot;&quot;) === &quot;a,b,c&quot;;
+}
+
+if (!test())
+    throw new Error(&quot;Test failed&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestses6yaml"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/es6.yaml (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/es6.yaml        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/tests/es6.yaml        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -214,6 +214,10 @@
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/destructuring_with_strings.js
</span><span class="cx">   cmd: runES6 :normal
</span><ins>+- path: es6/destructuring_assignment_non_simple_target.js
+  cmd: runES6 :normal
+- path: es6/destructuring_initializer_scoping.js
+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/for..of_loops_with_arrays.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/for..of_loops_with_astral_plane_strings.js
</span><span class="lines">@@ -747,7 +751,7 @@
</span><span class="cx"> - path: es6/destructuring_iterator_closing.js
</span><span class="cx">   cmd: runES6 :fail
</span><span class="cx"> - path: es6/destructuring_nested_rest.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/destructuring_with_generator_instances.js
</span><span class="cx">   cmd: runES6 :fail
</span><span class="cx"> - path: es6/destructuring_with_generic_iterables.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdestructuringassignmentsyntaxjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/destructuring-assignment-syntax.js (0 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/destructuring-assignment-syntax.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/destructuring-assignment-syntax.js        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -0,0 +1,59 @@
</span><ins>+
+function testSyntax(script) {
+    try {
+        eval(script);
+    } catch (error) {
+        if (error instanceof SyntaxError)
+            throw new Error(&quot;Bad error: &quot; + String(error));
+    }
+}
+
+function testSyntaxError(script, message) {
+    var error = null;
+    try {
+        eval(script);
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error(&quot;Expected syntax error not thrown&quot;);
+
+    if (String(error) !== message)
+        throw new Error(&quot;Bad error: &quot; + String(error));
+}
+
+testSyntax(&quot;({ a: this.a } = {})&quot;);
+testSyntax(&quot;({ a: this['a'] } = {})&quot;);
+testSyntax(&quot;({ a: this[\&quot;a\&quot;] } = {})&quot;);
+testSyntax(&quot;[this.a ] = []&quot;);
+testSyntax(&quot;[this['a']] = []&quot;);
+testSyntax(&quot;[this[0]] = []&quot;);
+testSyntax(&quot;[...this[0]] = []&quot;);
+testSyntax(&quot;[...[function f() {}.prop]] = []&quot;);
+testSyntax(&quot;[...[{prop: 1}.prop]] = []&quot;);
+testSyntax(&quot;[...[this[0], ...this[1]]] = []&quot;);
+testSyntax(&quot;({ a: obj.a } = {})&quot;);
+testSyntax(&quot;({ a: obj['a'] } = {})&quot;);
+testSyntax(&quot;({ a: obj[\&quot;a\&quot;] } = {})&quot;);
+testSyntax(&quot;({ a: function() {}['prop'] } = {})&quot;);
+testSyntax(&quot;({ a: {prop: 1}.prop } = {})&quot;);
+testSyntax(&quot;[obj.a ] = []&quot;);
+testSyntax(&quot;[obj['a']] = []&quot;);
+testSyntax(&quot;[obj[0]] = []&quot;);
+testSyntax(&quot;[function(){}.prop] = []&quot;);
+testSyntax(&quot;[{prop: 1}.prop] = []&quot;);
+
+
+testSyntaxError(&quot;[...c = 1] = []&quot;, &quot;SyntaxError: Unexpected token '='. Expected a closing ']' following a rest element destructuring pattern.&quot;);
+testSyntaxError(&quot;[...c, d] = []&quot;, &quot;SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.&quot;);
+testSyntaxError(&quot;[this] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[th\\u{69}s] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[function() {}] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;['string'] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[123] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[true] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[tru\\u0065] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[false] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[f\\u0061lse] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[null] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
+testSyntaxError(&quot;[n\\u{75}ll] = []&quot;, &quot;SyntaxError: Invalid destructuring assignment target.&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressrestelementsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/rest-elements.js (192435 => 192436)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/rest-elements.js        2015-11-13 19:10:23 UTC (rev 192435)
+++ trunk/Source/JavaScriptCore/tests/stress/rest-elements.js        2015-11-13 19:13:39 UTC (rev 192436)
</span><span class="lines">@@ -109,22 +109,12 @@
</span><span class="cx"> testSyntaxError(String.raw`(function ([a, ...[b, c]]) { })`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`);
</span><span class="cx"> testSyntaxError(String.raw`(function ([a, ...{ b, c }]) { })`, String.raw`SyntaxError: Unexpected token ']'. Expected identifier for a rest element destructuring pattern.`);
</span><span class="cx"> 
</span><del>-shouldThrow(function () {
-    [a, ...b, c] = 20;
-}, &quot;ReferenceError: Left side of assignment is not a reference.&quot;);
</del><span class="cx"> 
</span><del>-shouldThrow(function () {
-    [a, ...b,] = 20
-}, &quot;ReferenceError: Left side of assignment is not a reference.&quot;);
</del><ins>+testSyntaxError(String.raw`[a, ...b, c] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`);
+testSyntaxError(String.raw`[a, ...b,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`);
+testSyntaxError(String.raw`[a, ...b,,] = 20`, String.raw`SyntaxError: Unexpected token ','. Expected a closing ']' following a rest element destructuring pattern.`);
+testSyntaxError(String.raw`[a, ...b = 20] = 20`, String.raw`SyntaxError: Unexpected token '='. Expected a closing ']' following a rest element destructuring pattern.`);
</ins><span class="cx"> 
</span><del>-shouldThrow(function () {
-    [a, ...b,,] = 20
-}, &quot;ReferenceError: Left side of assignment is not a reference.&quot;);
-
-shouldThrow(function () {
-    [a, ...b = 20] = 20
-}, &quot;ReferenceError: Left side of assignment is not a reference.&quot;);
-
</del><span class="cx"> (function () {
</span><span class="cx">     var a, b, c;
</span><span class="cx">     [a, b, ...[...c]] = &quot;Cocoa&quot;;
</span></span></pre>
</div>
</div>

</body>
</html>