<!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>[201122] 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/201122">201122</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-05-18 18:27:49 -0700 (Wed, 18 May 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Function with default parameter values that are arrow functions that capture this isn't working
https://bugs.webkit.org/show_bug.cgi?id=157786
&lt;rdar://problem/26327329&gt;

Reviewed by Geoffrey Garen.

To make the scopes ordered properly, I needed to initialize the arrow
function lexical environment before initializing default parameter values.
I also made the code easier to reason about by never reusing the function's
var lexical environment for the arrow function lexical environment. The
reason for this is that that code was wrong, and we just didn't have code to
that properly tested it. It was easy for that code to be wrong because
sometimes the function's lexical environment isn't the top-most scope
(namely, when a function's parameter list is non-simple) and sometimes
it is (when the function's parameter list is simple).

Also, because a function's default parameter values may capture the
'arguments' variable inside an arrow function, I needed to take care
to initialize the 'arguments' variable as part of whichever scope
is the top-most scope. It's either the function's var environment
if the parameter list is simple, or it's the function's parameter
environment if the parameter list is non-simple.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
(JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
(JSC::BytecodeGenerator::initializeParameters):
(JSC::BytecodeGenerator::initializeVarLexicalEnvironment):
(JSC::BytecodeGenerator::visibleNameForParameter):
* bytecompiler/BytecodeGenerator.h:
* tests/stress/arrow-functions-as-default-parameter-values.js: Added.
(assert):
(test):
(test.foo):
* tests/stress/op-push-name-scope-crashes-profiler.js:
(test):</pre>

<h3>Modified Paths</h3>
<ul>
<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="#trunkSourceJavaScriptCoretestsstressoppushnamescopecrashesprofilerjs">trunk/Source/JavaScriptCore/tests/stress/op-push-name-scope-crashes-profiler.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressarrowfunctionsasdefaultparametervaluesjs">trunk/Source/JavaScriptCore/tests/stress/arrow-functions-as-default-parameter-values.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (201121 => 201122)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-05-19 01:01:21 UTC (rev 201121)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-05-19 01:27:49 UTC (rev 201122)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2016-05-18  Saam barati  &lt;sbarati@apple.com&gt;
+
+        Function with default parameter values that are arrow functions that capture this isn't working
+        https://bugs.webkit.org/show_bug.cgi?id=157786
+        &lt;rdar://problem/26327329&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        To make the scopes ordered properly, I needed to initialize the arrow 
+        function lexical environment before initializing default parameter values.
+        I also made the code easier to reason about by never reusing the function's
+        var lexical environment for the arrow function lexical environment. The
+        reason for this is that that code was wrong, and we just didn't have code to
+        that properly tested it. It was easy for that code to be wrong because
+        sometimes the function's lexical environment isn't the top-most scope
+        (namely, when a function's parameter list is non-simple) and sometimes
+        it is (when the function's parameter list is simple).
+
+        Also, because a function's default parameter values may capture the
+        'arguments' variable inside an arrow function, I needed to take care
+        to initialize the 'arguments' variable as part of whichever scope
+        is the top-most scope. It's either the function's var environment
+        if the parameter list is simple, or it's the function's parameter
+        environment if the parameter list is non-simple.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack):
+        (JSC::BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded):
+        (JSC::BytecodeGenerator::initializeParameters):
+        (JSC::BytecodeGenerator::initializeVarLexicalEnvironment):
+        (JSC::BytecodeGenerator::visibleNameForParameter):
+        * bytecompiler/BytecodeGenerator.h:
+        * tests/stress/arrow-functions-as-default-parameter-values.js: Added.
+        (assert):
+        (test):
+        (test.foo):
+        * tests/stress/op-push-name-scope-crashes-profiler.js:
+        (test):
+
</ins><span class="cx"> 2016-05-18  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         r199812 broke test262
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (201121 => 201122)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-05-19 01:01:21 UTC (rev 201121)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-05-19 01:27:49 UTC (rev 201122)
</span><span class="lines">@@ -321,15 +321,15 @@
</span><span class="cx">         emitPushFunctionNameScope(functionNode-&gt;ident(), &amp;m_calleeRegister, markAsCaptured);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (shouldCaptureSomeOfTheThings) {
</del><ins>+    if (shouldCaptureSomeOfTheThings)
</ins><span class="cx">         m_lexicalEnvironmentRegister = addVar();
</span><del>-        // 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 (isSimpleParameterList)
-            initializeVarLexicalEnvironment(symbolTableConstantIndex);
-    }
</del><span class="cx"> 
</span><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 (isSimpleParameterList)
+        initializeVarLexicalEnvironment(symbolTableConstantIndex, functionSymbolTable, shouldCaptureSomeOfTheThings);
+
</ins><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="lines">@@ -452,19 +452,6 @@
</span><span class="cx">         instructions().append(m_argumentsRegister-&gt;index());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    for (FunctionMetadataNode* function : functionNode-&gt;functionStack()) {
-        const Identifier&amp; ident = function-&gt;ident();
-        createVariable(ident, varKind(ident.impl()), functionSymbolTable);
-        m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
-    }
-    for (auto&amp; entry : functionNode-&gt;varDeclarations()) {
-        ASSERT(!entry.value.isLet() &amp;&amp; !entry.value.isConst());
-        if (!entry.value.isVar()) // This is either a parameter or callee.
-            continue;
-        // Variables named &quot;arguments&quot; are never const.
-        createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), functionSymbolTable, IgnoreExisting);
-    }
-
</del><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,6 +473,7 @@
</span><span class="cx">     
</span><span class="cx">     // This is our final act of weirdness. &quot;arguments&quot; is overridden by everything except the
</span><span class="cx">     // callee. We add it to the symbol table if it's not already there and it's not an argument.
</span><ins>+    bool shouldCreateArgumentsVariableInParameterScope = false;
</ins><span class="cx">     if (needsArguments) {
</span><span class="cx">         // If &quot;arguments&quot; is overridden by a function or destructuring parameter name, then it's
</span><span class="cx">         // OK for us to call createVariable() because it won't change anything. It's also OK for
</span><span class="lines">@@ -504,8 +492,10 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        bool shouldCreateArgumensVariable = !haveParameterNamedArguments &amp;&amp; !m_codeBlock-&gt;isArrowFunction();
+        shouldCreateArgumentsVariableInParameterScope = shouldCreateArgumensVariable &amp;&amp; !isSimpleParameterList;
</ins><span class="cx">         // Do not create arguments variable in case of Arrow function. Value will be loaded from parent scope
</span><del>-        if (!haveParameterNamedArguments &amp;&amp; !m_codeBlock-&gt;isArrowFunction()) {
</del><ins>+        if (shouldCreateArgumensVariable &amp;&amp; !shouldCreateArgumentsVariableInParameterScope) {
</ins><span class="cx">             createVariable(
</span><span class="cx">                 propertyNames().arguments, varKind(propertyNames().arguments.impl()), functionSymbolTable);
</span><span class="cx"> 
</span><span class="lines">@@ -513,6 +503,21 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    for (FunctionMetadataNode* function : functionNode-&gt;functionStack()) {
+        const Identifier&amp; ident = function-&gt;ident();
+        createVariable(ident, varKind(ident.impl()), functionSymbolTable);
+        m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
+    }
+    for (auto&amp; entry : functionNode-&gt;varDeclarations()) {
+        ASSERT(!entry.value.isLet() &amp;&amp; !entry.value.isConst());
+        if (!entry.value.isVar()) // This is either a parameter or callee.
+            continue;
+        if (shouldCreateArgumentsVariableInParameterScope &amp;&amp; entry.key.get() == propertyNames().arguments.impl())
+            continue;
+        createVariable(Identifier::fromUid(m_vm, entry.key.get()), varKind(entry.key.get()), functionSymbolTable, IgnoreExisting);
+    }
+
+
</ins><span class="cx">     m_newTargetRegister = addVar();
</span><span class="cx">     switch (parseMode) {
</span><span class="cx">     case SourceParseMode::GeneratorWrapperFunctionMode: {
</span><span class="lines">@@ -569,10 +574,17 @@
</span><span class="cx">             emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (needsToUpdateArrowFunctionContext() &amp;&amp; !codeBlock-&gt;isArrowFunction()) {
+        initializeArrowFunctionContextScopeIfNeeded();
+        emitPutThisToArrowFunctionContextScope();
+        emitPutNewTargetToArrowFunctionContextScope();
+        emitPutDerivedConstructorToArrowFunctionContextScope();
+    }
+
</ins><span class="cx">     // All &quot;addVar()&quot;s needs to happen before &quot;initializeDefaultParameterValuesAndSetupFunctionScopeStack()&quot; is called
</span><span class="cx">     // because a function's default parameter ExpressionNodes will use temporary registers.
</span><span class="cx">     pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize);
</span><del>-    initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures);
</del><ins>+    initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope);
</ins><span class="cx">     
</span><span class="cx">     // If we don't have  default parameter expression, then loading |this| inside an arrow function must be done
</span><span class="cx">     // after initializeDefaultParameterValuesAndSetupFunctionScopeStack() because that function sets up the
</span><span class="lines">@@ -585,13 +597,6 @@
</span><span class="cx">             emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (needsToUpdateArrowFunctionContext() &amp;&amp; !codeBlock-&gt;isArrowFunction()) {
-        initializeArrowFunctionContextScopeIfNeeded(functionSymbolTable);
-        emitPutThisToArrowFunctionContextScope();
-        emitPutNewTargetToArrowFunctionContextScope();
-        emitPutDerivedConstructorToArrowFunctionContextScope();
-    }
-
</del><span class="cx">     bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
</span><span class="cx">     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
</span><span class="cx"> }
</span><span class="lines">@@ -805,9 +810,10 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::initializeDefaultParameterValuesAndSetupFunctionScopeStack(
</span><span class="cx">     FunctionParameters&amp; parameters, bool isSimpleParameterList, FunctionNode* functionNode, SymbolTable* functionSymbolTable, 
</span><del>-    int symbolTableConstantIndex, const std::function&lt;bool (UniquedStringImpl*)&gt;&amp; captures)
</del><ins>+    int symbolTableConstantIndex, const std::function&lt;bool (UniquedStringImpl*)&gt;&amp; captures, bool shouldCreateArgumentsVariableInParameterScope)
</ins><span class="cx"> {
</span><span class="cx">     Vector&lt;std::pair&lt;Identifier, RefPtr&lt;RegisterID&gt;&gt;&gt; valuesToMoveIntoVars;
</span><ins>+    ASSERT(!(isSimpleParameterList &amp;&amp; shouldCreateArgumentsVariableInParameterScope));
</ins><span class="cx">     if (!isSimpleParameterList) {
</span><span class="cx">         // Refer to the ES6 spec section 9.2.12: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
</span><span class="cx">         // This implements step 21.
</span><span class="lines">@@ -815,6 +821,8 @@
</span><span class="cx">         Vector&lt;Identifier&gt; allParameterNames; 
</span><span class="cx">         for (unsigned i = 0; i &lt; parameters.size(); i++)
</span><span class="cx">             parameters.at(i).first-&gt;collectBoundIdentifiers(allParameterNames);
</span><ins>+        if (shouldCreateArgumentsVariableInParameterScope)
+            allParameterNames.append(propertyNames().arguments);
</ins><span class="cx">         IdentifierSet parameterSet;
</span><span class="cx">         for (auto&amp; ident : allParameterNames) {
</span><span class="cx">             parameterSet.add(ident.impl());
</span><span class="lines">@@ -823,10 +831,15 @@
</span><span class="cx">             if (captures(ident.impl()))
</span><span class="cx">                 addResult.iterator-&gt;value.setIsCaptured();
</span><span class="cx">         }
</span><del>-        
</del><span class="cx">         // This implements step 25 of section 9.2.12.
</span><span class="cx">         pushLexicalScopeInternal(environment, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</span><span class="cx"> 
</span><ins>+        if (shouldCreateArgumentsVariableInParameterScope) {
+            Variable argumentsVariable = variable(propertyNames().arguments); 
+            initializeVariable(argumentsVariable, m_argumentsRegister);
+            liftTDZCheckIfPossible(argumentsVariable);
+        }
+
</ins><span class="cx">         RefPtr&lt;RegisterID&gt; temp = newTemporary();
</span><span class="cx">         for (unsigned i = 0; i &lt; parameters.size(); i++) {
</span><span class="cx">             std::pair&lt;DestructuringPatternNode*, ExpressionNode*&gt; parameter = parameters.at(i);
</span><span class="lines">@@ -867,16 +880,10 @@
</span><span class="cx">         // record for parameters and &quot;var&quot;s. The &quot;var&quot; environment record must have the
</span><span class="cx">         // parameter environment record as its parent.
</span><span class="cx">         // See step 28 of section 9.2.12.
</span><del>-        if (m_lexicalEnvironmentRegister)
-            initializeVarLexicalEnvironment(symbolTableConstantIndex);
</del><ins>+        bool hasCapturedVariables = !!m_lexicalEnvironmentRegister; 
+        initializeVarLexicalEnvironment(symbolTableConstantIndex, functionSymbolTable, hasCapturedVariables);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_lexicalEnvironmentRegister)
-        pushScopedControlFlowContext();
-    m_symbolTableStack.append(SymbolTableStackEntry{ functionSymbolTable, m_lexicalEnvironmentRegister, false, symbolTableConstantIndex });
-
-    m_varScopeSymbolTableIndex = m_symbolTableStack.size() - 1;
-
</del><span class="cx">     // This completes step 28 of section 9.2.12.
</span><span class="cx">     for (unsigned i = 0; i &lt; valuesToMoveIntoVars.size(); i++) {
</span><span class="cx">         ASSERT(!isSimpleParameterList);
</span><span class="lines">@@ -886,43 +893,16 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded(SymbolTable* symbolTable)
</del><ins>+void BytecodeGenerator::initializeArrowFunctionContextScopeIfNeeded()
</ins><span class="cx"> {
</span><del>-    if (m_arrowFunctionContextLexicalEnvironmentRegister != nullptr)
-        return;
-    
-    if (m_lexicalEnvironmentRegister != nullptr) {
-        m_arrowFunctionContextLexicalEnvironmentRegister = m_lexicalEnvironmentRegister;
-        
-        if (!m_codeBlock-&gt;isArrowFunction()) {
-            ScopeOffset offset;
-            
-            ConcurrentJITLocker locker(ConcurrentJITLocker::NoLockingNecessary);
-            if (isThisUsedInInnerArrowFunction()) {
-                offset = symbolTable-&gt;takeNextScopeOffset(locker);
-                symbolTable-&gt;set(locker, propertyNames().thisIdentifier.impl(), SymbolTableEntry(VarOffset(offset)));
-            }
</del><ins>+    ASSERT(!m_arrowFunctionContextLexicalEnvironmentRegister);
</ins><span class="cx"> 
</span><del>-            if (m_codeType == FunctionCode &amp;&amp; isNewTargetUsedInInnerArrowFunction()) {
-                offset = symbolTable-&gt;takeNextScopeOffset();
-                symbolTable-&gt;set(locker, propertyNames().newTargetLocalPrivateName.impl(), SymbolTableEntry(VarOffset(offset)));
-            }
-            
-            if (isConstructor() &amp;&amp; constructorKind() == ConstructorKind::Derived &amp;&amp; isSuperUsedInInnerArrowFunction()) {
-                offset = symbolTable-&gt;takeNextScopeOffset(locker);
-                symbolTable-&gt;set(locker, propertyNames().derivedConstructorPrivateName.impl(), SymbolTableEntry(VarOffset(offset)));
-            }
-        }
-
-        return;
-    }
-
</del><span class="cx">     VariableEnvironment environment;
</span><span class="cx"> 
</span><span class="cx">     if (isThisUsedInInnerArrowFunction()) {
</span><span class="cx">         auto addResult = environment.add(propertyNames().thisIdentifier);
</span><span class="cx">         addResult.iterator-&gt;value.setIsCaptured();
</span><del>-        addResult.iterator-&gt;value.setIsConst();
</del><ins>+        addResult.iterator-&gt;value.setIsLet();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (m_codeType == FunctionCode &amp;&amp; isNewTargetUsedInInnerArrowFunction()) {
</span><span class="lines">@@ -972,18 +952,25 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::initializeVarLexicalEnvironment(int symbolTableConstantIndex)
</del><ins>+void BytecodeGenerator::initializeVarLexicalEnvironment(int symbolTableConstantIndex, SymbolTable* functionSymbolTable, bool hasCapturedVariables)
</ins><span class="cx"> {
</span><del>-    RELEASE_ASSERT(m_lexicalEnvironmentRegister);
-    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());
</del><ins>+    if (hasCapturedVariables) {
+        RELEASE_ASSERT(m_lexicalEnvironmentRegister);
+        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());
</ins><span class="cx"> 
</span><del>-    emitOpcode(op_mov);
-    instructions().append(scopeRegister()-&gt;index());
-    instructions().append(m_lexicalEnvironmentRegister-&gt;index());
</del><ins>+        emitOpcode(op_mov);
+        instructions().append(scopeRegister()-&gt;index());
+        instructions().append(m_lexicalEnvironmentRegister-&gt;index());
+
+        pushScopedControlFlowContext();
+    }
+    bool isWithScope = false;
+    m_symbolTableStack.append(SymbolTableStackEntry{ functionSymbolTable, m_lexicalEnvironmentRegister, isWithScope, symbolTableConstantIndex });
+    m_varScopeSymbolTableIndex = m_symbolTableStack.size() - 1;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> UniquedStringImpl* BytecodeGenerator::visibleNameForParameter(DestructuringPatternNode* pattern)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (201121 => 201122)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-05-19 01:01:21 UTC (rev 201121)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-05-19 01:27:49 UTC (rev 201122)
</span><span class="lines">@@ -856,9 +856,9 @@
</span><span class="cx">         void emitLogShadowChickenTailIfNecessary();
</span><span class="cx"> 
</span><span class="cx">         void initializeParameters(FunctionParameters&amp;);
</span><del>-        void initializeVarLexicalEnvironment(int symbolTableConstantIndex);
-        void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&amp;, bool isSimpleParameterList, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const std::function&lt;bool (UniquedStringImpl*)&gt;&amp; captures);
-        void initializeArrowFunctionContextScopeIfNeeded(SymbolTable* = nullptr);
</del><ins>+        void initializeVarLexicalEnvironment(int symbolTableConstantIndex, SymbolTable* functionSymbolTable, bool hasCapturedVariables);
+        void initializeDefaultParameterValuesAndSetupFunctionScopeStack(FunctionParameters&amp;, bool isSimpleParameterList, FunctionNode*, SymbolTable*, int symbolTableConstantIndex, const std::function&lt;bool (UniquedStringImpl*)&gt;&amp; captures, bool shouldCreateArgumentsVariableInParameterScope);
+        void initializeArrowFunctionContextScopeIfNeeded();
</ins><span class="cx"> 
</span><span class="cx">     public:
</span><span class="cx">         JSString* addStringConstant(const Identifier&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarrowfunctionsasdefaultparametervaluesjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/arrow-functions-as-default-parameter-values.js (0 => 201122)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/arrow-functions-as-default-parameter-values.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/arrow-functions-as-default-parameter-values.js        2016-05-19 01:27:49 UTC (rev 201122)
</span><span class="lines">@@ -0,0 +1,128 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;)
+}
+function test(f, n = 1000) {
+    for (let i = 0; i &lt; n; i++)
+        f();
+}
+
+test(function() {
+    function foo(x = ()=&gt;this) {
+        return x();
+    }
+    let o = {};
+    assert(foo.call(o) === o);
+})
+
+test(function() {
+    function foo(x = ()=&gt;arguments) {
+        assert(x() === arguments);
+    }
+    foo();
+})
+
+test(function() {
+    function foo({x = ()=&gt;arguments}) {
+        assert(x() === arguments);
+    }
+    foo({x:undefined});
+})
+
+test(function() {
+    function foo(x = ()=&gt;arguments) {
+        let a = x();
+        assert(a.length === 3);
+        assert(a[0] === undefined);
+        assert(a[1] === 20);
+        assert(a[2] === 40);
+    }
+    foo(undefined, 20, 40);
+})
+
+test(function() {
+    function foo(x = ()=&gt;new.target) {
+        assert(x() === foo);
+    }
+    new foo(undefined);
+})
+
+test(function() {
+    function foo({x = ()=&gt;new.target}) {
+        assert(x() === foo);
+    }
+    new foo({});
+})
+
+test(function() {
+    function foo(x = ()=&gt;arguments) {
+        var arguments;
+        assert(x() === arguments);
+    }
+    foo(undefined);
+});
+
+test(function() {
+    function foo(x = ()=&gt;arguments) {
+        var arguments = 25;
+        assert(x() === arguments);
+    }
+    foo(undefined);
+});
+
+test(function() {
+    function foo(x = (y = ()=&gt;arguments)=&gt;y()) {
+        assert(x() === arguments);
+    }
+    foo(undefined);
+});
+
+test(function() {
+    function foo({x = (y = ()=&gt;arguments)=&gt;y()}) {
+        assert(x() === arguments);
+    }
+    foo({});
+});
+
+test(function() {
+    function foo(x = (y = ()=&gt;this)=&gt;y()) {
+        return x();
+    }
+    let o = {};
+    foo.call(o);
+});
+
+test(function() {
+    function foo(x = (y = ()=&gt;new.target)=&gt;y()) {
+        assert(x() === foo);
+    }
+    new foo();
+});
+
+test(function() {
+    function foo(x = (y = ()=&gt;new.target)=&gt;y()) {
+        assert(x() === undefined);
+    }
+    foo();
+});
+
+// FIXME: Our parser throws a syntax error here but it should not.
+// https://bugs.webkit.org/show_bug.cgi?id=157872
+/*
+test(function() {
+    class C {
+        constructor() { this._x = 45; }
+        get foo() { return this._x;}
+    }
+    class D extends C {
+        //constructor(x = ()=&gt;super.foo) {
+        //    super();
+        //    assert(x() === 45);
+        //}
+        x(x = ()=&gt;super.foo) {
+            return x();
+        }
+    }
+    //(new D).x();
+});
+*/
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressoppushnamescopecrashesprofilerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/op-push-name-scope-crashes-profiler.js (201121 => 201122)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/op-push-name-scope-crashes-profiler.js        2016-05-19 01:01:21 UTC (rev 201121)
+++ trunk/Source/JavaScriptCore/tests/stress/op-push-name-scope-crashes-profiler.js        2016-05-19 01:27:49 UTC (rev 201122)
</span><span class="lines">@@ -8,10 +8,10 @@
</span><span class="cx">      })(arguments[0]);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-for (var i = 0; i &lt; 10000; ++i) {
</del><ins>+for (var i = 0; i &lt; 1000; ++i) {
</ins><span class="cx">     counter = 0;
</span><span class="cx">     test(100);
</span><span class="cx">     if (counter !== 101) {
</span><span class="cx">         throw &quot;Oops, test(100) = &quot; + test(100) + &quot;, expected 101.&quot;;
</span><span class="cx">     }
</span><del>-}
</del><span class="cx">\ No newline at end of file
</span><ins>+}
</ins></span></pre>
</div>
</div>

</body>
</html>