<!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>[187351] 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/187351">187351</a></dd>
<dt>Author</dt> <dd>saambarati1@gmail.com</dd>
<dt>Date</dt> <dd>2015-07-24 11:40:58 -0700 (Fri, 24 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[ES6] Add support for default parameters
https://bugs.webkit.org/show_bug.cgi?id=38409

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch implements ES6 default parameters according to the ES6
specification. This patch builds off the components introduced with 
&quot;let&quot; scoping and parsing function parameters in the same parser
arena as the function itself. &quot;let&quot; scoping allows functions with default 
parameter values to place their parameters under the TDZ. Parsing function
parameters in the same parser arena allows the FunctionParameters AST node
refer to ExpressionNodes.

The most subtle part of this patch is how we allocate lexical environments
when functions have default parameter values. If a function has default
parameter values then there must be a separate lexical environment for
its parameters. Then, the function's &quot;var&quot; lexical environment must have
the parameter lexical environment as its parent. The BytecodeGenerator
takes great care to not allocate the &quot;var&quot; lexical environment before its
really needed.

The &quot;arguments&quot; object for a function with default parameters will never be 
a mapped arugments object. It will always be a cloned arugments object.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::~BytecodeGenerator):
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::initializeNextParameter):
(JSC::BytecodeGenerator::initializeVarLexicalEnvironment):
(JSC::BytecodeGenerator::visibleNameForParameter):
(JSC::BytecodeGenerator::emitLoadGlobalObject):
(JSC::BytecodeGenerator::pushLexicalScopeInternal):
(JSC::BytecodeGenerator::pushLexicalScope):
(JSC::BytecodeGenerator::popLexicalScope):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::lastOpcodeID):
* bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
* jit/JITOperations.cpp:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createElementList):
(JSC::ASTBuilder::createFormalParameterList):
(JSC::ASTBuilder::appendParameter):
(JSC::ASTBuilder::createClause):
(JSC::ASTBuilder::createClauseList):
* parser/Nodes.h:
(JSC::FunctionParameters::size):
(JSC::FunctionParameters::at):
(JSC::FunctionParameters::hasDefaultParameterValues):
(JSC::FunctionParameters::append):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseVariableDeclarationList):
(JSC::Parser&lt;LexerType&gt;::createBindingPattern):
(JSC::Parser&lt;LexerType&gt;::tryParseDestructuringPatternExpression):
(JSC::Parser&lt;LexerType&gt;::parseDestructuringPattern):
(JSC::Parser&lt;LexerType&gt;::parseFormalParameters):
(JSC::Parser&lt;LexerType&gt;::parseFunctionParameters):
* parser/Parser.h:
(JSC::Scope::declareParameter):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createElementList):
(JSC::SyntaxChecker::createFormalParameterList):
(JSC::SyntaxChecker::appendParameter):
(JSC::SyntaxChecker::createClause):
(JSC::SyntaxChecker::createClauseList):
* tests/stress/es6-default-parameters.js: Added.
(assert):
(shouldThrow):
(shouldThrowSyntaxError):
(shouldThrowTDZ):
(basic):
(basicFunctionCaptureInDefault.basicFunctionCaptureInDefault.basicCaptured):
(basicCaptured.basicCaptured.tricky):
(strict):
(playground):
(scoping):
(augmentsArguments1):
(augmentsArguments2):
(augmentsArguments3):
(augmentsArguments4):
(augmentsArguments5):

LayoutTests:

* js/destructuring-assignment-default-values-expected.txt:
* js/parser-syntax-check-expected.txt:
* js/script-tests/destructuring-assignment-default-values.js:
(shouldThrow): Deleted.
* js/script-tests/parser-syntax-check.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsdestructuringassignmentdefaultvaluesexpectedtxt">trunk/LayoutTests/js/destructuring-assignment-default-values-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsparsersyntaxcheckexpectedtxt">trunk/LayoutTests/js/parser-syntax-check-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsdestructuringassignmentdefaultvaluesjs">trunk/LayoutTests/js/script-tests/destructuring-assignment-default-values.js</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="#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="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.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="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresses6defaultparametersjs">trunk/Source/JavaScriptCore/tests/stress/es6-default-parameters.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/LayoutTests/ChangeLog        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2015-07-24  Saam barati  &lt;saambarati1@gmail.com&gt;
+
+        [ES6] Add support for default parameters
+        https://bugs.webkit.org/show_bug.cgi?id=38409
+
+        Reviewed by Filip Pizlo.
+
+        * js/destructuring-assignment-default-values-expected.txt:
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/destructuring-assignment-default-values.js:
+        (shouldThrow): Deleted.
+        * js/script-tests/parser-syntax-check.js:
+
</ins><span class="cx"> 2015-07-24  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CSS &quot;content&quot; property is missing in getComputedStyles
</span></span></pre></div>
<a id="trunkLayoutTestsjsdestructuringassignmentdefaultvaluesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/destructuring-assignment-default-values-expected.txt (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/destructuring-assignment-default-values-expected.txt        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/LayoutTests/js/destructuring-assignment-default-values-expected.txt        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -33,11 +33,6 @@
</span><span class="cx"> PASS 120,120
</span><span class="cx"> PASS 3628800,3628800
</span><span class="cx"> PASS 1,1
</span><del>-PASS true,true
-PASS true,true
-PASS true,true
-PASS true,true
-PASS true,true
</del><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsjsparsersyntaxcheckexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/parser-syntax-check-expected.txt        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -867,6 +867,34 @@
</span><span class="cx"> PASS Invalid: &quot;function f() { ({set [x](x){}}) }&quot;
</span><span class="cx"> PASS Invalid: &quot;({[...x]: 1})&quot;
</span><span class="cx"> PASS Invalid: &quot;function f() { ({[...x]: 1}) }&quot;
</span><ins>+PASS Invalid: &quot;function f({a, a}) {}&quot;
+PASS Invalid: &quot;function f() { function f({a, a}) {} }&quot;
+PASS Invalid: &quot;function f({a}, a) {}&quot;
+PASS Invalid: &quot;function f() { function f({a}, a) {} }&quot;
+PASS Invalid: &quot;function f([b, b]) {}&quot;
+PASS Invalid: &quot;function f() { function f([b, b]) {} }&quot;
+PASS Invalid: &quot;function f([b], b) {}&quot;
+PASS Invalid: &quot;function f() { function f([b], b) {} }&quot;
+PASS Invalid: &quot;function f({a: {b}}, b) {}&quot;
+PASS Invalid: &quot;function f() { function f({a: {b}}, b) {} }&quot;
+PASS Valid:   &quot;function f(a, b = 20) {}&quot;
+PASS Valid:   &quot;function f() { function f(a, b = 20) {} }&quot;
+PASS Valid:   &quot;function f(a = 20, b = a) {}&quot;
+PASS Valid:   &quot;function f() { function f(a = 20, b = a) {} }&quot;
+PASS Valid:   &quot;function f({a = 20} = {a: 40}, b = a) {}&quot;
+PASS Valid:   &quot;function f() { function f({a = 20} = {a: 40}, b = a) {} }&quot;
+PASS Valid:   &quot;function f([a,b,c] = [1,2,3]) {}&quot;
+PASS Valid:   &quot;function f() { function f([a,b,c] = [1,2,3]) {} }&quot;
+PASS Invalid: &quot;function f(a, a=20) {}&quot;
+PASS Invalid: &quot;function f() { function f(a, a=20) {} }&quot;
+PASS Invalid: &quot;function f({a} = 20, a=20) {}&quot;
+PASS Invalid: &quot;function f() { function f({a} = 20, a=20) {} }&quot;
+PASS Invalid: &quot;function f([a,b,a] = [1,2,3]) {}&quot;
+PASS Invalid: &quot;function f() { function f([a,b,a] = [1,2,3]) {} }&quot;
+PASS Invalid: &quot;function f([a,b,c] = [1,2,3], a) {}&quot;
+PASS Invalid: &quot;function f() { function f([a,b,c] = [1,2,3], a) {} }&quot;
+PASS Invalid: &quot;function f([a,b,c] = [1,2,3], {a}) {}&quot;
+PASS Invalid: &quot;function f() { function f([a,b,c] = [1,2,3], {a}) {} }&quot;
</ins><span class="cx"> PASS Valid:   &quot;( function(){ return this || eval('this'); }().x = 'y' )&quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { ( function(){ return this || eval('this'); }().x = 'y' ) }&quot;
</span><span class="cx"> PASS Invalid: &quot;function(){ return this || eval('this'); }().x = 'y'&quot;
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsdestructuringassignmentdefaultvaluesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/destructuring-assignment-default-values.js (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/destructuring-assignment-default-values.js        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/LayoutTests/js/script-tests/destructuring-assignment-default-values.js        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -105,21 +105,3 @@
</span><span class="cx"> assert(test8(5).p, 120);
</span><span class="cx"> assert(test8(10).p, 3628800);
</span><span class="cx"> assert(test8(0).p, 1);
</span><del>-
-// FIXME: When we support default values in function parameters, we should remove this test.
-function shouldThrow(str) {
-    var thrown = false;
-    try {
-        eval(str);
-    } catch(e) {
-        thrown = true;
-    }
-
-    assert(true, thrown);
-}
-
-shouldThrow(&quot;(function({x = 40}) {})&quot;);
-shouldThrow(&quot;(function({y}, {x = 40}) {}&quot;);
-shouldThrow(&quot;(function([y], [x = 40]) {})&quot;);
-shouldThrow(&quot;(function({y}, {x: {z = 50}}) {})&quot;);
-shouldThrow(&quot;(function({y}, {x: [z = 50]}) {})&quot;);
</del></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsparsersyntaxcheckjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -526,6 +526,20 @@
</span><span class="cx"> invalid(&quot;({set [x](){}})&quot;)
</span><span class="cx"> invalid(&quot;({set [x](x){}})&quot;)
</span><span class="cx"> invalid(&quot;({[...x]: 1})&quot;)
</span><ins>+invalid(&quot;function f({a, a}) {}&quot;);
+invalid(&quot;function f({a}, a) {}&quot;);
+invalid(&quot;function f([b, b]) {}&quot;);
+invalid(&quot;function f([b], b) {}&quot;);
+invalid(&quot;function f({a: {b}}, b) {}&quot;);
+valid(&quot;function f(a, b = 20) {}&quot;);
+valid(&quot;function f(a = 20, b = a) {}&quot;);
+valid(&quot;function f({a = 20} = {a: 40}, b = a) {}&quot;);
+valid(&quot;function f([a,b,c] = [1,2,3]) {}&quot;);
+invalid(&quot;function f(a, a=20) {}&quot;);
+invalid(&quot;function f({a} = 20, a=20) {}&quot;);
+invalid(&quot;function f([a,b,a] = [1,2,3]) {}&quot;);
+invalid(&quot;function f([a,b,c] = [1,2,3], a) {}&quot;);
+invalid(&quot;function f([a,b,c] = [1,2,3], {a}) {}&quot;);
</ins><span class="cx"> valid(&quot;( function(){ return this || eval('this'); }().x = 'y' )&quot;);
</span><span class="cx"> invalid(&quot;function(){ return this || eval('this'); }().x = 'y'&quot;);
</span><span class="cx"> invalid(&quot;1 % +&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -1,3 +1,89 @@
</span><ins>+2015-07-24  Saam barati  &lt;saambarati1@gmail.com&gt;
+
+        [ES6] Add support for default parameters
+        https://bugs.webkit.org/show_bug.cgi?id=38409
+
+        Reviewed by Filip Pizlo.
+
+        This patch implements ES6 default parameters according to the ES6
+        specification. This patch builds off the components introduced with 
+        &quot;let&quot; scoping and parsing function parameters in the same parser
+        arena as the function itself. &quot;let&quot; scoping allows functions with default 
+        parameter values to place their parameters under the TDZ. Parsing function
+        parameters in the same parser arena allows the FunctionParameters AST node
+        refer to ExpressionNodes.
+
+        The most subtle part of this patch is how we allocate lexical environments
+        when functions have default parameter values. If a function has default
+        parameter values then there must be a separate lexical environment for
+        its parameters. Then, the function's &quot;var&quot; lexical environment must have
+        the parameter lexical environment as its parent. The BytecodeGenerator
+        takes great care to not allocate the &quot;var&quot; lexical environment before its
+        really needed.
+
+        The &quot;arguments&quot; object for a function with default parameters will never be 
+        a mapped arugments object. It will always be a cloned arugments object.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::generate):
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::~BytecodeGenerator):
+        (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+        (JSC::BytecodeGenerator::initializeNextParameter):
+        (JSC::BytecodeGenerator::initializeVarLexicalEnvironment):
+        (JSC::BytecodeGenerator::visibleNameForParameter):
+        (JSC::BytecodeGenerator::emitLoadGlobalObject):
+        (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+        (JSC::BytecodeGenerator::pushLexicalScope):
+        (JSC::BytecodeGenerator::popLexicalScope):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::lastOpcodeID):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::FunctionNode::emitBytecode):
+        * jit/JITOperations.cpp:
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createElementList):
+        (JSC::ASTBuilder::createFormalParameterList):
+        (JSC::ASTBuilder::appendParameter):
+        (JSC::ASTBuilder::createClause):
+        (JSC::ASTBuilder::createClauseList):
+        * parser/Nodes.h:
+        (JSC::FunctionParameters::size):
+        (JSC::FunctionParameters::at):
+        (JSC::FunctionParameters::hasDefaultParameterValues):
+        (JSC::FunctionParameters::append):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseVariableDeclarationList):
+        (JSC::Parser&lt;LexerType&gt;::createBindingPattern):
+        (JSC::Parser&lt;LexerType&gt;::tryParseDestructuringPatternExpression):
+        (JSC::Parser&lt;LexerType&gt;::parseDestructuringPattern):
+        (JSC::Parser&lt;LexerType&gt;::parseFormalParameters):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionParameters):
+        * parser/Parser.h:
+        (JSC::Scope::declareParameter):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createElementList):
+        (JSC::SyntaxChecker::createFormalParameterList):
+        (JSC::SyntaxChecker::appendParameter):
+        (JSC::SyntaxChecker::createClause):
+        (JSC::SyntaxChecker::createClauseList):
+        * tests/stress/es6-default-parameters.js: Added.
+        (assert):
+        (shouldThrow):
+        (shouldThrowSyntaxError):
+        (shouldThrowTDZ):
+        (basic):
+        (basicFunctionCaptureInDefault.basicFunctionCaptureInDefault.basicCaptured):
+        (basicCaptured.basicCaptured.tricky):
+        (strict):
+        (playground):
+        (scoping):
+        (augmentsArguments1):
+        (augmentsArguments2):
+        (augmentsArguments3):
+        (augmentsArguments4):
+        (augmentsArguments5):
+
</ins><span class="cx"> 2015-07-24  Xabier Rodriguez Calvar  &lt;calvaris@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove JS Promise constructor unused piece of code
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx"> ParserError BytecodeGenerator::generate()
</span><span class="cx"> {
</span><span class="cx">     SamplingRegion samplingRegion(&quot;Bytecode Generation&quot;);
</span><del>-    
</del><ins>+
</ins><span class="cx">     m_codeBlock-&gt;setThisRegister(m_thisRegister.virtualRegister());
</span><span class="cx">     
</span><span class="cx">     // If we have declared a variable named &quot;arguments&quot; and we are using arguments then we should
</span><span class="lines">@@ -71,11 +71,6 @@
</span><span class="cx">     if (m_needToInitializeArguments)
</span><span class="cx">         initializeVariable(variable(propertyNames().arguments), m_argumentsRegister);
</span><span class="cx"> 
</span><del>-    for (size_t i = 0; i &lt; m_destructuringParameters.size(); i++) {
-        auto&amp; entry = m_destructuringParameters[i];
-        entry.second-&gt;bindValue(*this, entry.first.get());
-    }
-
</del><span class="cx">     pushLexicalScope(m_scopeNode, true);
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -215,13 +210,15 @@
</span><span class="cx">     m_codeBlock-&gt;setSymbolTableConstantIndex(symbolTableConstantIndex);
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;Identifier&gt; boundParameterProperties;
</span><del>-    FunctionParameters&amp; parameters = *functionNode-&gt;parameters();
-    for (size_t i = 0; i &lt; parameters.size(); i++) {
-        auto pattern = parameters.at(i);
-        if (pattern-&gt;isBindingNode())
-            continue;
-        pattern-&gt;collectBoundIdentifiers(boundParameterProperties);
-        continue;
</del><ins>+    FunctionParameters&amp; parameters = *functionNode-&gt;parameters(); 
+    if (!parameters.hasDefaultParameterValues()) { 
+        // If we do have default parameters, they will be allocated in a separate scope.
+        for (size_t i = 0; i &lt; parameters.size(); i++) {
+            auto pattern = parameters.at(i).first;
+            if (pattern-&gt;isBindingNode())
+                continue;
+            pattern-&gt;collectBoundIdentifiers(boundParameterProperties);
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool shouldCaptureSomeOfTheThings = m_shouldEmitDebugHooks || m_codeBlock-&gt;needsFullScopeChain();
</span><span class="lines">@@ -265,45 +262,36 @@
</span><span class="cx">     
</span><span class="cx">     if (shouldCaptureSomeOfTheThings) {
</span><span class="cx">         m_lexicalEnvironmentRegister = addVar();
</span><del>-        m_codeBlock-&gt;setActivationRegister(m_lexicalEnvironmentRegister-&gt;virtualRegister());
-        emitOpcode(op_create_lexical_environment);
-        instructions().append(m_lexicalEnvironmentRegister-&gt;index());
-        instructions().append(scopeRegister()-&gt;index());
-        instructions().append(symbolTableConstantIndex);
-        instructions().append(addConstantValue(jsUndefined())-&gt;index());
-
-        emitOpcode(op_mov);
-        instructions().append(scopeRegister()-&gt;index());
-        instructions().append(m_lexicalEnvironmentRegister-&gt;index());
</del><ins>+        // We can allocate the &quot;var&quot; environment if we don't have default parameter expressions. If we have
+        // default parameter expressions, we have to hold off on allocating the &quot;var&quot; environment because
+        // the parent scope of the &quot;var&quot; environment is the parameter environment.
+        if (!parameters.hasDefaultParameterValues())
+            initializeVarLexicalEnvironment(symbolTableConstantIndex);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Make sure the code block knows about all of our parameters, and make sure that parameters
</span><span class="cx">     // needing destructuring are noted.
</span><span class="cx">     m_parameters.grow(parameters.size() + 1); // reserve space for &quot;this&quot;
</span><span class="cx">     m_thisRegister.setIndex(initializeNextParameter()-&gt;index()); // this
</span><del>-    for (unsigned i = 0; i &lt; parameters.size(); ++i) {
-        auto pattern = parameters.at(i);
-        RegisterID* reg = initializeNextParameter();
-        if (!pattern-&gt;isBindingNode())
-            m_destructuringParameters.append(std::make_pair(reg, pattern));
-    }
</del><ins>+    for (unsigned i = 0; i &lt; parameters.size(); ++i)
+        initializeNextParameter();
</ins><span class="cx">     
</span><span class="cx">     // Figure out some interesting facts about our arguments.
</span><span class="cx">     bool capturesAnyArgumentByName = false;
</span><span class="cx">     if (functionNode-&gt;hasCapturedVariables()) {
</span><span class="cx">         FunctionParameters&amp; parameters = *functionNode-&gt;parameters();
</span><span class="cx">         for (size_t i = 0; i &lt; parameters.size(); ++i) {
</span><del>-            auto pattern = parameters.at(i);
</del><ins>+            auto pattern = parameters.at(i).first;
</ins><span class="cx">             if (!pattern-&gt;isBindingNode())
</span><span class="cx">                 continue;
</span><span class="cx">             const Identifier&amp; ident = static_cast&lt;const BindingNode*&gt;(pattern)-&gt;boundProperty();
</span><span class="cx">             capturesAnyArgumentByName |= captures(ident.impl());
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-
</del><ins>+    
</ins><span class="cx">     if (capturesAnyArgumentByName)
</span><span class="cx">         ASSERT(m_lexicalEnvironmentRegister);
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Need to know what our functions are called. Parameters have some goofy behaviors when it
</span><span class="cx">     // comes to functions of the same name.
</span><span class="cx">     for (FunctionBodyNode* function : functionNode-&gt;functionStack())
</span><span class="lines">@@ -320,7 +308,7 @@
</span><span class="cx">         m_argumentsRegister-&gt;ref();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (needsArguments &amp;&amp; !codeBlock-&gt;isStrictMode()) {
</del><ins>+    if (needsArguments &amp;&amp; !codeBlock-&gt;isStrictMode() &amp;&amp; !parameters.hasDefaultParameterValues()) {
</ins><span class="cx">         // If we captured any formal parameter by name, then we use ScopedArguments. Otherwise we
</span><span class="cx">         // use DirectArguments. With ScopedArguments, we lift all of our arguments into the
</span><span class="cx">         // activation.
</span><span class="lines">@@ -335,7 +323,7 @@
</span><span class="cx">             for (unsigned i = 0; i &lt; parameters.size(); ++i) {
</span><span class="cx">                 ScopeOffset offset = functionSymbolTable-&gt;takeNextScopeOffset();
</span><span class="cx">                 functionSymbolTable-&gt;setArgumentOffset(vm, i, offset);
</span><del>-                if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i))) {
</del><ins>+                if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first)) {
</ins><span class="cx">                     VarOffset varOffset(offset);
</span><span class="cx">                     SymbolTableEntry entry(varOffset);
</span><span class="cx">                     // Stores to these variables via the ScopedArguments object will not do
</span><span class="lines">@@ -363,18 +351,20 @@
</span><span class="cx">             // We're going to put all parameters into the DirectArguments object. First ensure
</span><span class="cx">             // that the symbol table knows that this is happening.
</span><span class="cx">             for (unsigned i = 0; i &lt; parameters.size(); ++i) {
</span><del>-                if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i)))
</del><ins>+                if (UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first))
</ins><span class="cx">                     functionSymbolTable-&gt;set(name, SymbolTableEntry(VarOffset(DirectArgumentsOffset(i))));
</span><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             emitOpcode(op_create_direct_arguments);
</span><span class="cx">             instructions().append(m_argumentsRegister-&gt;index());
</span><span class="cx">         }
</span><del>-    } else {
</del><ins>+    } else if (!parameters.hasDefaultParameterValues()) {
</ins><span class="cx">         // Create the formal parameters the normal way. Any of them could be captured, or not. If
</span><del>-        // captured, lift them into the scope.
</del><ins>+        // captured, lift them into the scope. We can not do this if we have default parameter expressions
+        // because when default parameter expressions exist, they belong in their own lexical environment
+        // separate from the &quot;var&quot; lexical environment.
</ins><span class="cx">         for (unsigned i = 0; i &lt; parameters.size(); ++i) {
</span><del>-            UniquedStringImpl* name = visibleNameForParameter(parameters.at(i));
</del><ins>+            UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first);
</ins><span class="cx">             if (!name)
</span><span class="cx">                 continue;
</span><span class="cx">             
</span><span class="lines">@@ -387,7 +377,7 @@
</span><span class="cx">             
</span><span class="cx">             ScopeOffset offset = functionSymbolTable-&gt;takeNextScopeOffset();
</span><span class="cx">             const Identifier&amp; ident =
</span><del>-                static_cast&lt;const BindingNode*&gt;(parameters.at(i))-&gt;boundProperty();
</del><ins>+                static_cast&lt;const BindingNode*&gt;(parameters.at(i).first)-&gt;boundProperty();
</ins><span class="cx">             functionSymbolTable-&gt;set(name, SymbolTableEntry(VarOffset(offset)));
</span><span class="cx">             
</span><span class="cx">             emitOpcode(op_put_to_scope);
</span><span class="lines">@@ -400,15 +390,17 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (needsArguments &amp;&amp; codeBlock-&gt;isStrictMode()) {
</del><ins>+    if (needsArguments &amp;&amp; (codeBlock-&gt;isStrictMode() || parameters.hasDefaultParameterValues())) {
</ins><span class="cx">         // Allocate an out-of-bands arguments object.
</span><span class="cx">         emitOpcode(op_create_out_of_band_arguments);
</span><span class="cx">         instructions().append(m_argumentsRegister-&gt;index());
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Now declare all variables.
</span><del>-    for (const Identifier&amp; ident : boundParameterProperties)
</del><ins>+    for (const Identifier&amp; ident : boundParameterProperties) {
+        ASSERT(!parameters.hasDefaultParameterValues());
</ins><span class="cx">         createVariable(ident, varKind(ident.impl()), functionSymbolTable);
</span><ins>+    }
</ins><span class="cx">     for (FunctionBodyNode* function : functionNode-&gt;functionStack()) {
</span><span class="cx">         const Identifier&amp; ident = function-&gt;ident();
</span><span class="cx">         createVariable(ident, varKind(ident.impl()), functionSymbolTable);
</span><span class="lines">@@ -421,7 +413,7 @@
</span><span class="cx">         // Variables named &quot;arguments&quot; are never const.
</span><span class="cx">         createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), functionSymbolTable, IgnoreExisting);
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // There are some variables that need to be preinitialized to something other than Undefined:
</span><span class="cx">     //
</span><span class="cx">     // - &quot;arguments&quot;: unless it's used as a function or parameter, this should refer to the
</span><span class="lines">@@ -486,7 +478,7 @@
</span><span class="cx">         
</span><span class="cx">         bool haveParameterNamedArguments = false;
</span><span class="cx">         for (unsigned i = 0; i &lt; parameters.size(); ++i) {
</span><del>-            UniquedStringImpl* name = visibleNameForParameter(parameters.at(i));
</del><ins>+            UniquedStringImpl* name = visibleNameForParameter(parameters.at(i).first);
</ins><span class="cx">             if (name == propertyNames().arguments.impl()) {
</span><span class="cx">                 haveParameterNamedArguments = true;
</span><span class="cx">                 break;
</span><span class="lines">@@ -499,7 +491,7 @@
</span><span class="cx">             m_needToInitializeArguments = true;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     m_newTargetRegister = addVar();
</span><span class="cx">     if (isConstructor()) {
</span><span class="cx">         emitMove(m_newTargetRegister, &amp;m_thisRegister);
</span><span class="lines">@@ -517,10 +509,8 @@
</span><span class="cx">         instructions().append(0);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_lexicalEnvironmentRegister)
-        pushScopedControlFlowContext();
-    m_symbolTableStack.append(SymbolTableStackEntry{ Strong&lt;SymbolTable&gt;(*m_vm, functionSymbolTable), m_lexicalEnvironmentRegister, false, symbolTableConstantIndex });
</del><span class="cx">     m_TDZStack.append(std::make_pair(*parentScopeTDZVariables, false));
</span><ins>+    initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, functionNode, functionSymbolTable, symbolTableConstantIndex, captures);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> BytecodeGenerator::BytecodeGenerator(VM&amp; vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
</span><span class="lines">@@ -564,6 +554,98 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack(
+    FunctionParameters&amp; parameters, FunctionNode* functionNode, SymbolTable* functionSymbolTable, 
+    int symbolTableConstantIndex, const std::function&lt;bool (UniquedStringImpl*)&gt;&amp; captures)
+{
+    Vector&lt;std::pair&lt;Identifier, RefPtr&lt;RegisterID&gt;&gt;&gt; valuesToMoveIntoVars;
+    if (parameters.hasDefaultParameterValues()) {
+        // Refer to the ES6 spec section 9.2.12: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
+        // This implements step 21.
+        VariableEnvironment environment;
+        Vector&lt;Identifier&gt; allParameterNames; 
+        for (unsigned i = 0; i &lt; parameters.size(); i++)
+            parameters.at(i).first-&gt;collectBoundIdentifiers(allParameterNames);
+        IdentifierSet parameterSet;
+        for (auto&amp; ident : allParameterNames) {
+            parameterSet.add(ident.impl());
+            auto addResult = environment.add(ident);
+            addResult.iterator-&gt;value.setIsLet(); // When we have default parameter expressions, parameters act like &quot;let&quot; variables.
+            if (captures(ident.impl()))
+                addResult.iterator-&gt;value.setIsCaptured();
+        }
+        
+        // This implements step 25 of section 9.2.12.
+        pushLexicalScopeInternal(environment, true, nullptr);
+
+        RefPtr&lt;RegisterID&gt; temp = newTemporary();
+        for (unsigned i = 0; i &lt; parameters.size(); i++) {
+            std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt; parameter = parameters.at(i);
+            RefPtr&lt;RegisterID&gt; parameterValue = &amp;registerFor(virtualRegisterForArgument(1 + i));
+            emitMove(temp.get(), parameterValue.get());
+            if (parameter.second) {
+                RefPtr&lt;RegisterID&gt; condition = emitIsUndefined(newTemporary(), parameterValue.get());
+                RefPtr&lt;Label&gt; skipDefaultParameterBecauseNotUndefined = newLabel();
+                emitJumpIfFalse(condition.get(), skipDefaultParameterBecauseNotUndefined.get());
+                emitNode(temp.get(), parameter.second);
+                emitLabel(skipDefaultParameterBecauseNotUndefined.get());
+            }
+
+            parameter.first-&gt;bindValue(*this, temp.get());
+        }
+
+        // Final act of weirdness for default parameters. If a &quot;var&quot; also
+        // has the same name as a parameter, it should start out as the
+        // value of that parameter. Note, though, that they will be distinct
+        // bindings.
+        // This is step 28 of section 9.2.12. 
+        for (auto&amp; entry : functionNode-&gt;varDeclarations()) {
+            if (!entry.value.isVar()) // This is either a parameter or callee.
+                continue;
+
+            if (parameterSet.contains(entry.key)) {
+                Identifier ident = Identifier::fromUid(m_vm, entry.key.get());
+                Variable var = variable(ident);
+                RegisterID* scope = emitResolveScope(nullptr, var);
+                RefPtr&lt;RegisterID&gt; value = emitGetFromScope(newTemporary(), scope, var, DoNotThrowIfNotFound);
+                valuesToMoveIntoVars.append(std::make_pair(ident, value));
+            }
+        }
+
+        // Functions with default parameter expressions must have a separate environment
+        // record for parameters and &quot;var&quot;s. The &quot;var&quot; environment record must have the
+        // parameter environment record as its parent.
+        // See step 28 of section 9.2.12.
+        if (m_lexicalEnvironmentRegister)
+            initializeVarLexicalEnvironment(symbolTableConstantIndex);
+    }
+
+    if (m_lexicalEnvironmentRegister)
+        pushScopedControlFlowContext();
+    m_symbolTableStack.append(SymbolTableStackEntry{ Strong&lt;SymbolTable&gt;(*m_vm, functionSymbolTable), m_lexicalEnvironmentRegister, false, symbolTableConstantIndex });
+
+    // This completes step 28 of section 9.2.12.
+    for (unsigned i = 0; i &lt; valuesToMoveIntoVars.size(); i++) {
+        ASSERT(parameters.hasDefaultParameterValues());
+        Variable var = variable(valuesToMoveIntoVars[i].first);
+        RegisterID* scope = emitResolveScope(nullptr, var);
+        emitPutToScope(scope, var, valuesToMoveIntoVars[i].second.get(), DoNotThrowIfNotFound);
+    }
+
+    if (!parameters.hasDefaultParameterValues()) {
+        ASSERT(!valuesToMoveIntoVars.size());
+        // Initialize destructuring parameters the old way as if we don't have any default parameter values.
+        // If we have default parameter values, we handle this case above.
+        for (unsigned i = 0; i &lt; parameters.size(); i++) {
+            DestructuringPatternNode* pattern = parameters.at(i).first;
+            if (!pattern-&gt;isBindingNode()) {
+                RefPtr&lt;RegisterID&gt; parameterValue = &amp;registerFor(virtualRegisterForArgument(1 + i));
+                pattern-&gt;bindValue(*this, parameterValue.get());
+            }
+        }
+    }
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::initializeNextParameter()
</span><span class="cx"> {
</span><span class="cx">     VirtualRegister reg = virtualRegisterForArgument(m_codeBlock-&gt;numParameters());
</span><span class="lines">@@ -573,6 +655,21 @@
</span><span class="cx">     return &amp;parameter;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::initializeVarLexicalEnvironment(int symbolTableConstantIndex)
+{
+    RELEASE_ASSERT(m_lexicalEnvironmentRegister);
+    m_codeBlock-&gt;setActivationRegister(m_lexicalEnvironmentRegister-&gt;virtualRegister());
+    emitOpcode(op_create_lexical_environment);
+    instructions().append(m_lexicalEnvironmentRegister-&gt;index());
+    instructions().append(scopeRegister()-&gt;index());
+    instructions().append(symbolTableConstantIndex);
+    instructions().append(addConstantValue(jsUndefined())-&gt;index());
+
+    emitOpcode(op_mov);
+    instructions().append(scopeRegister()-&gt;index());
+    instructions().append(m_lexicalEnvironmentRegister-&gt;index());
+}
+
</ins><span class="cx"> UniquedStringImpl* BytecodeGenerator::visibleNameForParameter(DestructuringPatternNode* pattern)
</span><span class="cx"> {
</span><span class="cx">     if (pattern-&gt;isBindingNode()) {
</span><span class="lines">@@ -1258,9 +1355,8 @@
</span><span class="cx">     return m_globalObjectRegister;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
</del><ins>+void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment&amp; environment, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
</ins><span class="cx"> {
</span><del>-    VariableEnvironment&amp; environment = node-&gt;lexicalVariables();
</del><span class="cx">     if (!environment.size())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="lines">@@ -1334,6 +1430,12 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult)
+{
+    VariableEnvironment&amp; environment = node-&gt;lexicalVariables();
+    pushLexicalScopeInternal(environment, canOptimizeTDZChecks, constantSymbolTableResult);
+}
+
</ins><span class="cx"> void BytecodeGenerator::popLexicalScope(VariableEnvironmentNode* node)
</span><span class="cx"> {
</span><span class="cx">     VariableEnvironment&amp; environment = node-&gt;lexicalVariables();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -621,6 +621,9 @@
</span><span class="cx"> 
</span><span class="cx">         OpcodeID lastOpcodeID() const { return m_lastOpcodeID; }
</span><span class="cx"> 
</span><ins>+    private:
+        void pushLexicalScopeInternal(VariableEnvironment&amp;, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult);
+    public:
</ins><span class="cx">         void pushLexicalScope(VariableEnvironmentNode*, bool canOptimizeTDZChecks, RegisterID** constantSymbolTableResult = nullptr);
</span><span class="cx">         void popLexicalScope(VariableEnvironmentNode*);
</span><span class="cx">         void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
</span><span class="lines">@@ -715,6 +718,9 @@
</span><span class="cx">         RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><span class="cx">         RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition&amp; divot, const JSTextPosition&amp; divotStart, const JSTextPosition&amp; divotEnd);
</span><span class="cx"> 
</span><ins>+        void initializeVarLexicalEnvironment(int symbolTableConstantIndex);
+        void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&amp;, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const std::function&lt;bool (UniquedStringImpl*)&gt;&amp; captures);
+
</ins><span class="cx">     public:
</span><span class="cx">         JSString* addStringConstant(const Identifier&amp;);
</span><span class="cx">         JSTemplateRegistryKey* addTemplateRegistryKeyConstant(const TemplateRegistryKey&amp;);
</span><span class="lines">@@ -773,7 +779,6 @@
</span><span class="cx">         Vector&lt;SwitchInfo&gt; m_switchContextStack;
</span><span class="cx">         Vector&lt;std::unique_ptr&lt;ForInContext&gt;&gt; m_forInContextStack;
</span><span class="cx">         Vector&lt;TryContext&gt; m_tryContextStack;
</span><del>-        Vector&lt;std::pair&lt;RefPtr&lt;RegisterID&gt;, const DestructuringPatternNode*&gt;&gt; m_destructuringParameters;
</del><span class="cx">         enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
</span><span class="cx">         Vector&lt;std::pair&lt;FunctionBodyNode*, FunctionVariableType&gt;&gt; m_functionsToInitialize;
</span><span class="cx">         bool m_needToInitializeArguments { false };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -3019,9 +3019,9 @@
</span><span class="cx">     if (generator.vm()-&gt;typeProfiler()) {
</span><span class="cx">         for (size_t i = 0; i &lt; m_parameters-&gt;size(); i++) {
</span><span class="cx">             // FIXME: Handle Destructuring assignments into arguments.
</span><del>-            if (!m_parameters-&gt;at(i)-&gt;isBindingNode())
</del><ins>+            if (!m_parameters-&gt;at(i).first-&gt;isBindingNode())
</ins><span class="cx">                 continue;
</span><del>-            BindingNode* parameter = static_cast&lt;BindingNode*&gt;(m_parameters-&gt;at(i));
</del><ins>+            BindingNode* parameter = static_cast&lt;BindingNode*&gt;(m_parameters-&gt;at(i).first);
</ins><span class="cx">             RegisterID reg(CallFrame::argumentOffset(i));
</span><span class="cx">             generator.emitProfileType(&amp;reg, ProfileTypeBytecodeFunctionArgument, nullptr);
</span><span class="cx">             generator.emitTypeProfilerExpressionInfo(parameter-&gt;divotStart(), parameter-&gt;divotEnd());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -687,11 +687,8 @@
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
</span><span class="cx"> {
</span><ins>+    UNUSED_PARAM(exec);
</ins><span class="cx"> 
</span><del>-    ASSERT_UNUSED(exec, exec-&gt;codeBlock()-&gt;codeType() != FunctionCode
-        || !exec-&gt;codeBlock()-&gt;needsActivation()
-        || exec-&gt;hasActivation());
-
</del><span class="cx">     execCallee-&gt;setCodeBlock(0);
</span><span class="cx"> 
</span><span class="cx">     if (!isHostFunction(execCallee-&gt;calleeAsValue(), globalFuncEval))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -418,7 +418,10 @@
</span><span class="cx">     ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_parserArena) ElementNode(elems, elisions, expr); }
</span><span class="cx"> 
</span><span class="cx">     FormalParameterList createFormalParameterList() { return new (m_parserArena) FunctionParameters(); }
</span><del>-    void appendParameter(FormalParameterList list, DestructuringPattern pattern) { list-&gt;append(pattern); }
</del><ins>+    void appendParameter(FormalParameterList list, DestructuringPattern pattern, ExpressionNode* defaultValue) 
+    { 
+        list-&gt;append(pattern, defaultValue); 
+    }
</ins><span class="cx"> 
</span><span class="cx">     CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_parserArena) CaseClauseNode(expr, statements); }
</span><span class="cx">     ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_parserArena) ClauseListNode(clause); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -1625,12 +1625,20 @@
</span><span class="cx">     public:
</span><span class="cx">         FunctionParameters();
</span><span class="cx">         ALWAYS_INLINE unsigned size() const { return m_patterns.size(); }
</span><del>-        ALWAYS_INLINE DestructuringPatternNode* at(unsigned index) { return m_patterns[index]; }
-        ALWAYS_INLINE void append(DestructuringPatternNode* pattern) { ASSERT(pattern); m_patterns.append(pattern); }
</del><ins>+        ALWAYS_INLINE std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt; at(unsigned index) { return m_patterns[index]; }
+        bool hasDefaultParameterValues() const { return m_hasDefaultParameterValues; }
+        ALWAYS_INLINE void append(DestructuringPatternNode* pattern, ExpressionNode* defaultValue) 
+        { 
+            ASSERT(pattern); 
+            m_patterns.append(std::make_pair(pattern, defaultValue));
+            if (defaultValue)
+                m_hasDefaultParameterValues = true;
+        }
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx"> 
</span><del>-        Vector&lt;DestructuringPatternNode*, 3&gt; m_patterns;
</del><ins>+        Vector&lt;std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt;, 3&gt; m_patterns;
+        bool m_hasDefaultParameterValues { false };
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class FunctionBodyNode final : public StatementNode, public ParserArenaDeletable {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -576,7 +576,7 @@
</span><span class="cx">             }
</span><span class="cx">         } else {
</span><span class="cx">             lastIdent = 0;
</span><del>-            auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), assignmentContext);
</del><ins>+            auto pattern = parseDestructuringPattern(context, destructuringKindFromDeclarationType(declarationType), nullptr, nullptr, assignmentContext);
</ins><span class="cx">             failIfFalse(pattern, &quot;Cannot parse this destructuring pattern&quot;);
</span><span class="cx">             hasInitializer = match(EQUAL);
</span><span class="cx">             failIfTrue(declarationListContext == VarDeclarationContext &amp;&amp; !hasInitializer, &quot;Expected an initializer in destructuring variable declaration&quot;);
</span><span class="lines">@@ -604,21 +604,22 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::createBindingPattern(TreeBuilder&amp; context, DestructuringKind kind, const Identifier&amp; name, int depth, JSToken token, AssignmentContext bindingContext)
</del><ins>+template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::createBindingPattern(TreeBuilder&amp; context, DestructuringKind kind, const Identifier&amp; name, int depth, JSToken token, AssignmentContext bindingContext, const Identifier** duplicateIdentifier)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!name.isNull());
</span><span class="cx">     
</span><span class="cx">     ASSERT(name.impl()-&gt;isAtomic() || name.impl()-&gt;isSymbol());
</span><del>-    if (depth) {
-        if (kind == DestructureToVariables)
-            failIfTrueIfStrict(declareVariable(&amp;name) &amp; DeclarationResult::InvalidStrictMode, &quot;Cannot deconstruct to a variable named '&quot;, name.impl(), &quot;' in strict mode&quot;);
-        else if (kind == DestructureToLet || kind == DestructureToConst) {
-            DeclarationResultMask declarationResult = declareVariable(&amp;name, kind == DestructureToLet ? DeclarationType::LetDeclaration : DeclarationType::ConstDeclaration);
-            if (declarationResult != DeclarationResult::Valid) {
-                failIfTrueIfStrict(declarationResult &amp; DeclarationResult::InvalidStrictMode, &quot;Cannot destructure to a variable named '&quot;, name.impl(), &quot;' in strict mode&quot;);
-                failIfTrue(declarationResult &amp; DeclarationResult::InvalidDuplicateDeclaration, &quot;Cannot declare a lexical variable twice: '&quot;, name.impl(), &quot;'&quot;);
-            }
-        } else if (kind == DestructureToParameters) {
</del><ins>+
+    if (kind == DestructureToVariables)
+        failIfTrueIfStrict(declareVariable(&amp;name) &amp; DeclarationResult::InvalidStrictMode, &quot;Cannot declare a variable named '&quot;, name.impl(), &quot;' in strict mode&quot;);
+    else if (kind == DestructureToLet || kind == DestructureToConst) {
+        DeclarationResultMask declarationResult = declareVariable(&amp;name, kind == DestructureToLet ? DeclarationType::LetDeclaration : DeclarationType::ConstDeclaration);
+        if (declarationResult != DeclarationResult::Valid) {
+            failIfTrueIfStrict(declarationResult &amp; DeclarationResult::InvalidStrictMode, &quot;Cannot destructure to a variable named '&quot;, name.impl(), &quot;' in strict mode&quot;);
+            failIfTrue(declarationResult &amp; DeclarationResult::InvalidDuplicateDeclaration, &quot;Cannot declare a lexical variable twice: '&quot;, name.impl(), &quot;'&quot;);
+        }
+    } else if (kind == DestructureToParameters) {
+        if (depth) {
</ins><span class="cx">             auto bindingResult = declareBoundParameter(&amp;name);
</span><span class="cx">             if (bindingResult == Scope::StrictBindingFailed &amp;&amp; strictMode()) {
</span><span class="cx">                 semanticFailIfTrue(isEvalOrArguments(&amp;name), &quot;Cannot destructure to a parameter name '&quot;, name.impl(), &quot;' in strict mode&quot;);
</span><span class="lines">@@ -635,18 +636,7 @@
</span><span class="cx">                     semanticFail(&quot;Cannot destructure to '&quot;, name.impl(), &quot;' as it has already been declared&quot;);
</span><span class="cx">                 semanticFail(&quot;Cannot destructure to a parameter named '&quot;, name.impl(), &quot;'&quot;);
</span><span class="cx">             }
</span><del>-        }
-
-    } else {
-        if (kind == DestructureToVariables)
-            failIfTrueIfStrict(declareVariable(&amp;name) &amp; DeclarationResult::InvalidStrictMode, &quot;Cannot declare a variable named '&quot;, name.impl(), &quot;' in strict mode&quot;);
-        else if (kind == DestructureToLet || kind == DestructureToConst) {
-            DeclarationResultMask declarationResult = declareVariable(&amp;name, kind == DestructureToLet ? DeclarationType::LetDeclaration : DeclarationType::ConstDeclaration);
-            if (declarationResult != DeclarationResult::Valid) {
-                failIfTrueIfStrict(declarationResult &amp; DeclarationResult::InvalidStrictMode, &quot;Cannot destructure to a variable named '&quot;, name.impl(), &quot;' in strict mode&quot;);
-                failIfTrue(declarationResult &amp; DeclarationResult::InvalidDuplicateDeclaration, &quot;Cannot declare a lexical variable twice: '&quot;, name.impl(), &quot;'&quot;);
-            }
-        } else if (kind == DestructureToParameters) {
</del><ins>+        } else {
</ins><span class="cx">             DeclarationResultMask declarationResult = declareParameter(&amp;name);
</span><span class="cx">             if ((declarationResult &amp; DeclarationResult::InvalidStrictMode) &amp;&amp; strictMode()) {
</span><span class="cx">                 semanticFailIfTrue(isEvalOrArguments(&amp;name), &quot;Cannot destructure to a parameter name '&quot;, name.impl(), &quot;' in strict mode&quot;);
</span><span class="lines">@@ -657,6 +647,13 @@
</span><span class="cx">                     semanticFail(&quot;Cannot declare a parameter named '&quot;, name.impl(), &quot;' in strict mode as it has already been declared&quot;);
</span><span class="cx">                 semanticFail(&quot;Cannot declare a parameter named '&quot;, name.impl(), &quot;' in strict mode&quot;);
</span><span class="cx">             }
</span><ins>+            if (declarationResult &amp; DeclarationResult::InvalidDuplicateDeclaration) {
+                // It's not always an error to define a duplicate parameter.
+                // It's only an error when there are default parameter values or destructuring parameters.
+                // We note this value now so we can check it later.
+                if (duplicateIdentifier)
+                    *duplicateIdentifier = &amp;name;
+            }
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     return context.createBindingLocation(token.m_location, name, token.m_startPosition, token.m_endPosition, bindingContext);
</span><span class="lines">@@ -694,11 +691,11 @@
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="cx"> template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::tryParseDestructuringPatternExpression(TreeBuilder&amp; context, AssignmentContext bindingContext)
</span><span class="cx"> {
</span><del>-    return parseDestructuringPattern(context, DestructureToExpressions, bindingContext);
</del><ins>+    return parseDestructuringPattern(context, DestructureToExpressions, nullptr, nullptr, bindingContext);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::parseDestructuringPattern(TreeBuilder&amp; context, DestructuringKind kind, AssignmentContext bindingContext, int depth)
</del><ins>+template &lt;class TreeBuilder&gt; TreeDestructuringPattern Parser&lt;LexerType&gt;::parseDestructuringPattern(TreeBuilder&amp; context, DestructuringKind kind, const Identifier** duplicateIdentifier, bool* hasDestructuringPattern, AssignmentContext bindingContext, int depth)
</ins><span class="cx"> {
</span><span class="cx">     failIfStackOverflow();
</span><span class="cx">     int nonLHSCount = m_nonLHSCount;
</span><span class="lines">@@ -709,6 +706,9 @@
</span><span class="cx">         auto arrayPattern = context.createArrayPattern(m_token.m_location);
</span><span class="cx">         next();
</span><span class="cx"> 
</span><ins>+        if (hasDestructuringPattern)
+            *hasDestructuringPattern = true;
+
</ins><span class="cx">         bool restElementWasFound = false;
</span><span class="cx"> 
</span><span class="cx">         do {
</span><span class="lines">@@ -724,7 +724,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, bindingContext, depth + 1);
</del><ins>+                auto innerPattern = parseDestructuringPattern(context, kind, 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">@@ -737,12 +737,11 @@
</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, bindingContext, depth + 1);
</del><ins>+            auto innerPattern = parseDestructuringPattern(context, kind, 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="cx">             TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
</span><del>-            failIfTrue(kind == DestructureToParameters &amp;&amp; defaultValue,  &quot;Default values in destructuring parameters are currently not supported&quot;);
</del><span class="cx">             context.appendArrayPatternEntry(arrayPattern, location, innerPattern, defaultValue);
</span><span class="cx">         } while (consume(COMMA));
</span><span class="cx"> 
</span><span class="lines">@@ -757,6 +756,9 @@
</span><span class="cx">         auto objectPattern = context.createObjectPattern(m_token.m_location);
</span><span class="cx">         next();
</span><span class="cx"> 
</span><ins>+        if (hasDestructuringPattern)
+            *hasDestructuringPattern = true;
+
</ins><span class="cx">         do {
</span><span class="cx">             bool wasString = false;
</span><span class="cx"> 
</span><span class="lines">@@ -772,9 +774,9 @@
</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, bindingContext, depth + 1);
</del><ins>+                    innerPattern = parseDestructuringPattern(context, kind, duplicateIdentifier, hasDestructuringPattern, bindingContext, depth + 1);
</ins><span class="cx">                 else
</span><del>-                    innerPattern = createBindingPattern(context, kind, *propertyName, depth, identifierToken, bindingContext);
</del><ins>+                    innerPattern = createBindingPattern(context, kind, *propertyName, depth + 1, identifierToken, bindingContext, duplicateIdentifier);
</ins><span class="cx">             } else {
</span><span class="cx">                 JSTokenType tokenType = m_token.m_type;
</span><span class="cx">                 switch (m_token.m_type) {
</span><span class="lines">@@ -805,13 +807,12 @@
</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, bindingContext, depth + 1);
</del><ins>+                innerPattern = parseDestructuringPattern(context, kind, 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="cx">             failIfFalse(innerPattern, &quot;Cannot parse this destructuring pattern&quot;);
</span><span class="cx">             TreeExpression defaultValue = parseDefaultValueForDestructuringPattern(context);
</span><del>-            failIfTrue(kind == DestructureToParameters &amp;&amp; defaultValue, &quot;Default values in destructuring parameters are currently not supported&quot;);
</del><span class="cx">             ASSERT(propertyName);
</span><span class="cx">             context.appendObjectPatternEntry(objectPattern, location, wasString, *propertyName, innerPattern, defaultValue);
</span><span class="cx">         } while (consume(COMMA));
</span><span class="lines">@@ -831,7 +832,7 @@
</span><span class="cx">             failWithMessage(&quot;Expected a parameter pattern or a ')' in parameter list&quot;);
</span><span class="cx">         }
</span><span class="cx">         failIfTrue(match(LET) &amp;&amp; (kind == DestructureToLet || kind == DestructureToConst), &quot;Can't use 'let' as an identifier name for a LexicalDeclaration&quot;);
</span><del>-        pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token, bindingContext);
</del><ins>+        pattern = createBindingPattern(context, kind, *m_token.m_data.ident, depth, m_token, bindingContext, duplicateIdentifier);
</ins><span class="cx">         next();
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -1446,17 +1447,32 @@
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="cx"> template &lt;class TreeBuilder&gt; bool Parser&lt;LexerType&gt;::parseFormalParameters(TreeBuilder&amp; context, TreeFormalParameterList list, unsigned&amp; parameterCount)
</span><span class="cx"> {
</span><del>-    auto parameter = parseDestructuringPattern(context, DestructureToParameters);
</del><ins>+#define failFromDuplicate() \
+    if (duplicateParameter) {\
+        semanticFailIfTrue(defaultValue, &quot;Duplicate parameter '&quot;, duplicateParameter-&gt;impl(), &quot;' not allowed in function with default parameter values&quot;);\
+        semanticFailIfTrue(hasDestructuringPattern, &quot;Duplicate parameter '&quot;, duplicateParameter-&gt;impl(), &quot;' not allowed in function with destructuring parameters&quot;);\
+    }
+
+    const Identifier* duplicateParameter = nullptr;
+    bool hasDestructuringPattern = false;
+    auto parameter = parseDestructuringPattern(context, DestructureToParameters, &amp;duplicateParameter, &amp;hasDestructuringPattern);
</ins><span class="cx">     failIfFalse(parameter, &quot;Cannot parse parameter pattern&quot;);
</span><del>-    context.appendParameter(list, parameter);
</del><ins>+    auto defaultValue = parseDefaultValueForDestructuringPattern(context);
+    propagateError();
+    failFromDuplicate();
+    context.appendParameter(list, parameter, defaultValue);
</ins><span class="cx">     parameterCount++;
</span><span class="cx">     while (consume(COMMA)) {
</span><del>-        parameter = parseDestructuringPattern(context, DestructureToParameters);
</del><ins>+        parameter = parseDestructuringPattern(context, DestructureToParameters, &amp;duplicateParameter, &amp;hasDestructuringPattern);
</ins><span class="cx">         failIfFalse(parameter, &quot;Cannot parse parameter pattern&quot;);
</span><del>-        context.appendParameter(list, parameter);
</del><ins>+        defaultValue = parseDefaultValueForDestructuringPattern(context);
+        propagateError();
+        failFromDuplicate();
+        context.appendParameter(list, parameter, defaultValue);
</ins><span class="cx">         parameterCount++;
</span><span class="cx">     }
</span><span class="cx">     return true;
</span><ins>+#undef failFromDuplicate
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="lines">@@ -1530,7 +1546,7 @@
</span><span class="cx">                 functionInfo.parameterCount = 1;
</span><span class="cx">                 auto parameter = parseDestructuringPattern(context, DestructureToParameters);
</span><span class="cx">                 failIfFalse(parameter, &quot;Cannot parse parameter pattern&quot;);
</span><del>-                context.appendParameter(parameterList, parameter);
</del><ins>+                context.appendParameter(parameterList, parameter, 0);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1547,9 +1563,13 @@
</span><span class="cx">         functionInfo.parameterCount = 0;
</span><span class="cx">     } else if (mode == SetterMode) {
</span><span class="cx">         failIfTrue(match(CLOSEPAREN), &quot;setter functions must have one parameter&quot;);
</span><del>-        auto parameter = parseDestructuringPattern(context, DestructureToParameters);
</del><ins>+        const Identifier* duplicateParameter = nullptr;
+        auto parameter = parseDestructuringPattern(context, DestructureToParameters, &amp;duplicateParameter);
</ins><span class="cx">         failIfFalse(parameter, &quot;setter functions must have one parameter&quot;);
</span><del>-        context.appendParameter(parameterList, parameter);
</del><ins>+        auto defaultValue = parseDefaultValueForDestructuringPattern(context);
+        propagateError();
+        semanticFailIfTrue(duplicateParameter &amp;&amp; defaultValue, &quot;Duplicate parameter '&quot;, duplicateParameter-&gt;impl(), &quot;' not allowed in function with default parameter values&quot;);
+        context.appendParameter(parameterList, parameter, defaultValue);
</ins><span class="cx">         functionInfo.parameterCount = 1;
</span><span class="cx">         failIfTrue(match(COMMA), &quot;setter functions must have one parameter&quot;);
</span><span class="cx">         consumeOrFail(CLOSEPAREN, &quot;Expected a ')' after a parameter declaration&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -352,6 +352,8 @@
</span><span class="cx">             result |= DeclarationResult::InvalidStrictMode;
</span><span class="cx">         if (isArgumentsIdent)
</span><span class="cx">             m_shadowsArguments = true;
</span><ins>+        if (!addResult.isNewEntry)
+            result |= DeclarationResult::InvalidDuplicateDeclaration;
</ins><span class="cx"> 
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="lines">@@ -1048,8 +1050,8 @@
</span><span class="cx">     template &lt;class TreeBuilder&gt; TreeExpression parseVariableDeclarationList(TreeBuilder&amp;, int&amp; declarations, TreeDestructuringPattern&amp; lastPattern, TreeExpression&amp; lastInitializer, JSTextPosition&amp; identStart, JSTextPosition&amp; initStart, JSTextPosition&amp; initEnd, VarDeclarationListContext, DeclarationType, bool&amp; forLoopConstDoesNotHaveInitializer);
</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><del>-    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&amp;, DestructuringKind, const Identifier&amp;, int depth, JSToken, AssignmentContext);
-    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&amp;, DestructuringKind, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
</del><ins>+    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&amp;, DestructuringKind, const Identifier&amp;, int depth, JSToken, AssignmentContext, const Identifier** duplicateIdentifier);
+    template &lt;class TreeBuilder&gt; NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&amp;, DestructuringKind, const Identifier** duplicateIdentifier = nullptr, bool* hasDestructuringPattern = nullptr, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0);
</ins><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 class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (187350 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-07-24 18:39:41 UTC (rev 187350)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -219,7 +219,7 @@
</span><span class="cx">     int createElementList(int, int) { return ElementsListResult; }
</span><span class="cx">     int createElementList(int, int, int) { return ElementsListResult; }
</span><span class="cx">     int createFormalParameterList() { return FormalParameterListResult; }
</span><del>-    void appendParameter(int, DestructuringPattern) { }
</del><ins>+    void appendParameter(int, DestructuringPattern, int) { }
</ins><span class="cx">     int createClause(int, int) { return ClauseResult; }
</span><span class="cx">     int createClauseList(int) { return ClauseListResult; }
</span><span class="cx">     int createClauseList(int, int) { return ClauseListResult; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresses6defaultparametersjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/es6-default-parameters.js (0 => 187351)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/es6-default-parameters.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/es6-default-parameters.js        2015-07-24 18:40:58 UTC (rev 187351)
</span><span class="lines">@@ -0,0 +1,244 @@
</span><ins>+function assert(cond, msg = &quot;&quot;) {
+    if (!cond)
+        throw new Error(msg);
+}
+noInline(assert);
+
+function shouldThrow(func) {
+    var hadError = false;
+    try {
+        func()
+    } catch (e) {
+        hadError = true;
+    }
+    assert(hadError, &quot;Did not throw&quot;);
+}
+noInline(shouldThrow);
+
+function shouldThrowSyntaxError(str) {
+    var hadError = false;
+    try {
+        eval(str);
+    } catch (e) {
+        if (e instanceof SyntaxError)
+            hadError = true;
+    }
+    assert(hadError, &quot;Did not throw syntax error&quot;);
+}
+noInline(shouldThrowSyntaxError);
+
+function shouldThrowTDZ(func) {
+    var hasThrown = false;
+    try {
+        func();
+    } catch(e) {
+        if (e.name.indexOf(&quot;ReferenceError&quot;) !== -1)
+            hasThrown = true;
+    }
+    assert(hasThrown);
+}
+noInline(shouldThrowTDZ);
+
+function basic(x, y=x) {
+    assert(y === x, &quot;basics don't work.&quot;)
+}
+basic(20);
+basic(&quot;hello&quot;);
+basic({foo: 20});
+basic(undefined);
+
+;(function(){
+    var scopeVariable = {hello: &quot;world&quot;};
+    function basicScope(x = scopeVariable) {
+        assert(x === scopeVariable);
+    }
+    basicScope();
+})();
+
+function basicFunctionCaptureInDefault(theArg = 20, y = function() {return theArg}) {
+    assert(theArg === y(), &quot;y should return x.&quot;);
+    theArg = {};
+    assert(theArg === y(), &quot;y should return x.&quot;);
+}
+basicFunctionCaptureInDefault()
+basicFunctionCaptureInDefault(undefined)
+
+function basicCaptured(x = 20, y = x) {
+    assert(x === y, &quot;y should equal x&quot;);
+    function mutate() { x = &quot;mutation&quot;; }
+    mutate()
+    assert(x !== y, &quot;y should not equal x&quot;);
+}
+basicCaptured()
+basicCaptured(undefined)
+
+function tricky(globalX = (globalX = &quot;x&quot;), y = (globalX = 20)) {
+    assert(globalX === 20);
+    assert(globalX === y);
+}
+shouldThrow(tricky);
+
+function strict(x, y = x) {
+    'use strict';
+    assert(x === y);
+}
+strict(20);
+strict(undefined);
+
+function playground(x = &quot;foo&quot;, y = &quot;bar&quot;) {
+    return {x, y}
+}
+assert(playground().x === &quot;foo&quot;)
+assert(playground(undefined).x === &quot;foo&quot;)
+assert(playground(undefined, 20).x === &quot;foo&quot;)
+assert(playground(null).x === null)
+assert(playground().y === &quot;bar&quot;)
+assert(playground(undefined, undefined).y === &quot;bar&quot;)
+assert(playground(&quot;hello&quot;, undefined).y === &quot;bar&quot;)
+assert(playground(&quot;bar&quot;).x === playground(undefined, undefined).y)
+assert(playground(10).x === 10)
+assert(playground(undefined, 20).y === 20)
+assert(playground(undefined, null).y === null)
+
+function scoping(f = function() { return local;}) {
+    shouldThrow(f);
+    var local = 10;
+    shouldThrow(f);
+}
+scoping();
+
+function augmentsArguments1(x = 20) {
+    assert(x === 20);
+
+    arguments[0] = 10;
+    assert(x === 20);
+
+    x = 15;
+    assert(x === 15);
+    assert(arguments[0] === 10);
+}
+augmentsArguments1(undefined);
+
+function augmentsArguments2(x = 20) {
+    assert(x === 20);
+
+    arguments[0] = 10;
+    assert(x === 20);
+    assert(arguments[0] === 10);
+
+    x = 15;
+    assert(x === 15);
+    assert(arguments[0] === 10);
+
+    function augment() { x = 40 }
+    augment()
+    assert(x === 40);
+    assert(arguments[0] === 10);
+}
+augmentsArguments2(undefined);
+
+function augmentsArguments3(x = 10) {
+    assert(x === 10);
+
+    assert(arguments[0] === undefined);
+    x = 20;
+    assert(arguments[0] === undefined);
+}
+augmentsArguments3();
+
+function augmentsArguments4(x = 10) {
+    &quot;use strict&quot;;
+    assert(x === 10);
+
+    assert(arguments[0] === undefined);
+    x = 20;
+    assert(arguments[0] === undefined);
+}
+augmentsArguments4();
+augmentsArguments4(undefined);
+
+function augmentsArguments5(x = 10) {
+    &quot;use strict&quot;;
+    assert(x === 20);
+
+    assert(arguments[0] === 20);
+    x = 20;
+    assert(arguments[0] === 20);
+}
+augmentsArguments5(20);
+
+;(function () {
+    var outer = &quot;outer&quot;;
+    function foo(a = outer, b = function() { return a; }, c = function(v) { a = v; }) {
+        var a;
+        assert(a === &quot;outer&quot;);
+        a = 20;
+        assert(a === 20);
+        assert(b() === &quot;outer&quot;);
+        c(&quot;hello&quot;);
+        assert(b() === &quot;hello&quot;);
+    }
+
+    function bar(a = outer, b = function() { return a; }, c = function(v) { a = v; }) {
+        with({}) {
+            var a;
+            assert(a === &quot;outer&quot;);
+            a = 20;
+            assert(a === 20);
+            assert(b() === &quot;outer&quot;);
+            c(&quot;hello&quot;);
+            assert(b() === &quot;hello&quot;);
+        }
+    }
+
+    function baz(x = function() { return y; }, y = &quot;y&quot;) {
+        assert(x() === &quot;y&quot;);
+        assert(x() === y);
+        assert(y === y);
+    }
+
+    function jaz(x = function() { return y; }, y = &quot;y&quot;) {
+        return x;
+    }
+
+    function taz(x = 10, y = eval(&quot;x + 1&quot;)) {
+        assert(y === 11);
+    }
+
+    for (var i = 0; i &lt; 1000; i++) {
+        foo();
+        bar();
+        baz();
+        assert(jaz(undefined, 20)() === 20);
+        assert(jaz(undefined, undefined)() === &quot;y&quot;);
+        assert(jaz(undefined, {x: &quot;x&quot;})().x === &quot;x&quot;);
+        taz();
+    }
+})();
+
+// TDZ errors.
+;(function() {
+    function basicError(x = y, y) { }
+    function basicError2(x = x) { }
+    function baz(z = {p: x}, x = z) {}
+    function bar(x = {p: [x]}) {}
+    function jaz(x = eval(&quot;y&quot;), y) { }
+    function kaz(x = eval(&quot;;(function() { return y})();&quot;), y) { }
+    for (var i = 0; i &lt; 1000; i++) {
+        shouldThrowTDZ(basicError);
+        shouldThrowTDZ(basicError2);
+        shouldThrowTDZ(baz);
+        shouldThrowTDZ(bar);
+        shouldThrowTDZ(jaz);
+        shouldThrowTDZ(kaz);
+    }
+})();
+
+
+
+// Syntax errors.
+shouldThrowSyntaxError(&quot;function b(a = 20, a = 40) {}&quot;);
+shouldThrowSyntaxError(&quot;function b(aaaaa = 20,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v, aaaaa = 40) {}&quot;);
+shouldThrowSyntaxError(&quot;function b(a = 20, {a}) {}&quot;);
+shouldThrowSyntaxError(&quot;function b({a, a} = 20) {}&quot;);
+shouldThrowSyntaxError(&quot;function b({a, a} = 20) {}&quot;);
</ins></span></pre>
</div>
</div>

</body>
</html>