<!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>[197915] 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/197915">197915</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-03-09 18:04:20 -0800 (Wed, 09 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>ES6: Implement lexical scoping for function definitions in strict mode
https://bugs.webkit.org/show_bug.cgi?id=152844

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This patch implements block scoping for function definitions
in strict mode. The implementation works as follows:
        
- If we're in sloppy mode, function declarations work exactly
  as they did before this patch. I.e, function declarations are hoisted
  and declared like &quot;var&quot; variables.
        
- If you're in strict mode and at the top of a function scope or program
  scope, function declarations still work like they used to. They are defined
  like &quot;var&quot; variables. This is necessary for backwards compatibility
  because ES5 strict mode allowed duplicate function declarations at the
  top-most scope of a program/function.
        
- If you're in strict mode and inside a block statement or a switch statement,
  function declarations are now block scoped. All function declarations within
  a block are hoisted to the beginning of the block. They are not hoisted out of the 
  block like they are in sloppy mode. This allows for the following types of
  programs:
  ```
  function foo() {
      function bar() { return 20; }
      {
          function bar() { return 30; }
          bar(); // 30
      }
      bar(); // 20
  }
  ```

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::instantiateLexicalVariables):
(JSC::BytecodeGenerator::emitPrefillStackTDZVariables):
(JSC::BytecodeGenerator::pushLexicalScope):
(JSC::BytecodeGenerator::pushLexicalScopeInternal):
(JSC::BytecodeGenerator::initializeBlockScopedFunctions):
(JSC::BytecodeGenerator::popLexicalScope):
(JSC::BytecodeGenerator::liftTDZCheckIfPossible):
(JSC::BytecodeGenerator::pushTDZVariables):
(JSC::BytecodeGenerator::getVariablesUnderTDZ):
(JSC::BytecodeGenerator::emitNewRegExp):
(JSC::BytecodeGenerator::emitNewFunctionExpressionCommon):
(JSC::BytecodeGenerator::emitNewFunctionExpression):
(JSC::BytecodeGenerator::emitNewArrowFunctionExpression):
* bytecompiler/BytecodeGenerator.h:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createSourceElements):
(JSC::ASTBuilder::features):
(JSC::ASTBuilder::numConstants):
(JSC::ASTBuilder::createFuncDeclStatement):
(JSC::ASTBuilder::createClassDeclStatement):
(JSC::ASTBuilder::createBlockStatement):
(JSC::ASTBuilder::createTryStatement):
(JSC::ASTBuilder::createSwitchStatement):
(JSC::ASTBuilder::Scope::Scope):
(JSC::ASTBuilder::funcDeclarations): Deleted.
* parser/NodeConstructors.h:
(JSC::CaseBlockNode::CaseBlockNode):
(JSC::SwitchNode::SwitchNode):
(JSC::BlockNode::BlockNode):
* parser/Nodes.cpp:
(JSC::ScopeNode::ScopeNode):
(JSC::ScopeNode::singleStatement):
(JSC::ProgramNode::ProgramNode):
(JSC::ModuleProgramNode::ModuleProgramNode):
(JSC::EvalNode::EvalNode):
(JSC::FunctionNode::FunctionNode):
(JSC::VariableEnvironmentNode::VariableEnvironmentNode):
* parser/Nodes.h:
(JSC::VariableEnvironmentNode::VariableEnvironmentNode):
(JSC::VariableEnvironmentNode::lexicalVariables):
(JSC::VariableEnvironmentNode::functionStack):
(JSC::ScopeNode::captures):
(JSC::ScopeNode::varDeclarations):
(JSC::ScopeNode::neededConstants):
(JSC::ProgramNode::startColumn):
(JSC::ProgramNode::endColumn):
(JSC::EvalNode::startColumn):
(JSC::EvalNode::endColumn):
(JSC::ModuleProgramNode::startColumn):
(JSC::ModuleProgramNode::endColumn):
(JSC::ScopeNode::functionStack): Deleted.
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseInner):
(JSC::Parser&lt;LexerType&gt;::didFinishParsing):
(JSC::Parser&lt;LexerType&gt;::parseStatementListItem):
(JSC::Parser&lt;LexerType&gt;::parseSwitchStatement):
(JSC::Parser&lt;LexerType&gt;::parseBlockStatement):
(JSC::Parser&lt;LexerType&gt;::parseStatement):
(JSC::Parser&lt;LexerType&gt;::parseFunctionInfo):
(JSC::getMetadata):
(JSC::Parser&lt;LexerType&gt;::parseFunctionDeclaration):
(JSC::Parser&lt;LexerType&gt;::parseExportDeclaration):
* parser/Parser.h:
(JSC::Scope::declareVariable):
(JSC::Scope::declareFunction):
(JSC::Scope::appendFunction):
(JSC::Scope::takeFunctionDeclarations):
(JSC::Scope::declareLexicalVariable):
(JSC::Parser::currentVariableScope):
(JSC::Parser::currentLexicalDeclarationScope):
(JSC::Parser::currentFunctionScope):
(JSC::Parser::pushScope):
(JSC::Parser::popScopeInternal):
(JSC::Parser::declareVariable):
(JSC::Parser::declareFunction):
(JSC::Parser::hasDeclaredVariable):
(JSC::Parser::isFunctionMetadataNode):
(JSC::Parser&lt;LexerType&gt;::parse):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createFuncDeclStatement):
(JSC::SyntaxChecker::createClassDeclStatement):
(JSC::SyntaxChecker::createBlockStatement):
(JSC::SyntaxChecker::createExprStatement):
(JSC::SyntaxChecker::createIfStatement):
(JSC::SyntaxChecker::createContinueStatement):
(JSC::SyntaxChecker::createTryStatement):
(JSC::SyntaxChecker::createSwitchStatement):
(JSC::SyntaxChecker::createWhileStatement):
(JSC::SyntaxChecker::createWithStatement):
(JSC::SyntaxChecker::createDoWhileStatement):
* parser/VariableEnvironment.h:
(JSC::VariableEnvironmentEntry::isExported):
(JSC::VariableEnvironmentEntry::isImported):
(JSC::VariableEnvironmentEntry::isImportedNamespace):
(JSC::VariableEnvironmentEntry::isFunction):
(JSC::VariableEnvironmentEntry::setIsCaptured):
(JSC::VariableEnvironmentEntry::setIsConst):
(JSC::VariableEnvironmentEntry::setIsExported):
(JSC::VariableEnvironmentEntry::setIsImported):
(JSC::VariableEnvironmentEntry::setIsImportedNamespace):
(JSC::VariableEnvironmentEntry::setIsFunction):
(JSC::VariableEnvironmentEntry::clearIsVar):
(JSC::VariableEnvironment::VariableEnvironment):
(JSC::VariableEnvironment::begin):
(JSC::VariableEnvironment::end):
* tests/es6.yaml:
* tests/stress/block-scoped-function-declarations.js: Added.
(assert):
(test):
(f.foo.bar):
(f.foo.):
(f.foo):
(f):
(assert.foo.):
(assert.foo):
(assert.foo.foo):
(assert.foo.bar):
(assert.foo.switch.case.1):
(assert.foo.switch.case.2):
(assert.foo.switch.foo):
(assert.foo.switch.bar):

LayoutTests:

* js/let-syntax-expected.txt:
* js/parser-syntax-check-expected.txt:
* js/script-tests/parser-syntax-check.js:
(testFailed):
(runTest):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsletsyntaxexpectedtxt">trunk/LayoutTests/js/let-syntax-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsparsersyntaxcheckexpectedtxt">trunk/LayoutTests/js/parser-syntax-check-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsparsersyntaxcheckjs">trunk/LayoutTests/js/script-tests/parser-syntax-check.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodeConstructorsh">trunk/Source/JavaScriptCore/parser/NodeConstructors.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodescpp">trunk/Source/JavaScriptCore/parser/Nodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodesh">trunk/Source/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserVariableEnvironmenth">trunk/Source/JavaScriptCore/parser/VariableEnvironment.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestses6yaml">trunk/Source/JavaScriptCore/tests/es6.yaml</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressblockscopedfunctiondeclarationsjs">trunk/Source/JavaScriptCore/tests/stress/block-scoped-function-declarations.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/LayoutTests/ChangeLog        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-03-09  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        ES6: Implement lexical scoping for function definitions in strict mode
+        https://bugs.webkit.org/show_bug.cgi?id=152844
+
+        Reviewed by Geoffrey Garen.
+
+        * js/let-syntax-expected.txt:
+        * js/parser-syntax-check-expected.txt:
+        * js/script-tests/parser-syntax-check.js:
+        (testFailed):
+        (runTest):
+
</ins><span class="cx"> 2016-03-09  Jer Noble  &lt;jer.noble@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add heuristic for &quot;main content&quot; videos which override user gesture requirements
</span></span></pre></div>
<a id="trunkLayoutTestsjsletsyntaxexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/let-syntax-expected.txt (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/let-syntax-expected.txt        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/LayoutTests/js/let-syntax-expected.txt        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -315,11 +315,11 @@
</span><span class="cx"> SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'x'.
</span><span class="cx"> SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'x'.
</span><span class="cx"> PASS Has syntax error: ''use strict'; function f() { let x; var [x] = 20; }'
</span><del>-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
</del><ins>+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
</ins><span class="cx"> PASS Has syntax error: 'function f() { let x;  function x(){} }'
</span><del>-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
</del><ins>+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
</ins><span class="cx"> PASS Has syntax error: ''use strict'; function f() { let x;  function x(){} }'
</span><span class="cx"> SyntaxError: Cannot declare a let variable twice: 'x'.
</span><span class="cx"> SyntaxError: Cannot declare a let variable twice: 'x'.
</span><span class="lines">@@ -345,11 +345,11 @@
</span><span class="cx"> SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'x'.
</span><span class="cx"> SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'x'.
</span><span class="cx"> PASS Has syntax error: ''use strict'; function f() { const x = 20; var [x] = 20; }'
</span><del>-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
</del><ins>+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
</ins><span class="cx"> PASS Has syntax error: 'function f() { const x = 20;  function x(){} }'
</span><del>-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
</del><ins>+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
</ins><span class="cx"> PASS Has syntax error: ''use strict'; function f() { const x = 20;  function x(){} }'
</span><span class="cx"> SyntaxError: Cannot declare a const variable twice: 'x'.
</span><span class="cx"> SyntaxError: Cannot declare a const variable twice: 'x'.
</span><span class="lines">@@ -375,11 +375,11 @@
</span><span class="cx"> SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'x'.
</span><span class="cx"> SyntaxError: Cannot declare a var variable that shadows a let/const/class variable: 'x'.
</span><span class="cx"> PASS Has syntax error: ''use strict'; function f() { class x{}; var [x] = 20; }'
</span><del>-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
</del><ins>+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
</ins><span class="cx"> PASS Has syntax error: 'function f() { class x{};  function x(){} }'
</span><del>-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
-SyntaxError: Cannot declare a function that shadows a let/const/class variable 'x' in strict mode.
</del><ins>+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
+SyntaxError: Cannot declare a function that shadows a let/const/class/function variable 'x' in strict mode.
</ins><span class="cx"> PASS Has syntax error: ''use strict'; function f() { class x{};  function x(){} }'
</span><span class="cx"> SyntaxError: Cannot declare a class twice: 'x'.
</span><span class="cx"> SyntaxError: Cannot declare a class twice: 'x'.
</span></span></pre></div>
<a id="trunkLayoutTestsjsparsersyntaxcheckexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/parser-syntax-check-expected.txt (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/parser-syntax-check-expected.txt        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/LayoutTests/js/parser-syntax-check-expected.txt        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -628,18 +628,56 @@
</span><span class="cx"> PASS Valid:   &quot;function f() { 'use strict'; function f1(a) { function f2(b) { return b; } return f2(a); } f1(5); }&quot;
</span><span class="cx"> PASS Valid:   &quot;'use strict'; function f1(a) { function f2(b) { function f3(c) { return c; } return f3(b); } return f2(a); } f1(5);&quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { 'use strict'; function f1(a) { function f2(b) { function f3(c) { return c; } return f3(b); } return f2(a); } f1(5); }&quot;
</span><del>-PASS Invalid: &quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } f1(5);&quot;
-PASS Invalid: &quot;function f() { 'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } f1(5); }&quot;
-PASS Invalid: &quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } f1(5);&quot;
-PASS Invalid: &quot;function f() { 'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } f1(5); }&quot;
</del><ins>+PASS Valid:   &quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } f1(5);&quot;
+PASS Valid:   &quot;function f() { 'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } f1(5); }&quot;
+PASS Valid:   &quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } f1(5);&quot;
+PASS Valid:   &quot;function f() { 'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } f1(5); }&quot;
+PASS Valid:   &quot;'use strict'; function f1(a) {}; function f1(a) {};&quot;
+PASS Valid:   &quot;function f() { 'use strict'; function f1(a) {}; function f1(a) {}; }&quot;
+PASS Invalid: &quot;'use strict'; { function f1(a) {}; function f1(a) {}; }&quot;
+PASS Invalid: &quot;function f() { 'use strict'; { function f1(a) {}; function f1(a) {}; } }&quot;
+PASS Invalid: &quot;'use strict'; { let f1; function f1(a) {}; }&quot;
+PASS Invalid: &quot;function f() { 'use strict'; { let f1; function f1(a) {}; } }&quot;
+PASS Invalid: &quot;'use strict'; { function f1(a) {}; let f1; }&quot;
+PASS Invalid: &quot;function f() { 'use strict'; { function f1(a) {}; let f1; } }&quot;
+PASS Invalid: &quot;'use strict'; let f1; function f1(a) {};&quot;
+PASS Invalid: &quot;function f() { 'use strict'; let f1; function f1(a) {}; }&quot;
+PASS Invalid: &quot;'use strict'; function f1(a) {}; let f1; &quot;
+PASS Invalid: &quot;function f() { 'use strict'; function f1(a) {}; let f1;  }&quot;
+PASS Invalid: &quot;let f1; function f1(a) {};&quot;
+PASS Invalid: &quot;function f() { let f1; function f1(a) {}; }&quot;
+PASS Invalid: &quot;let f1; { function f1(a) {}; }&quot;
+PASS Invalid: &quot;function f() { let f1; { function f1(a) {}; } }&quot;
+PASS Invalid: &quot;{ function f1(a) {}; } let f1;&quot;
+PASS Invalid: &quot;function f() { { function f1(a) {}; } let f1; }&quot;
+PASS Valid:   &quot;{ let f1; function f1(a) {}; }&quot;
+PASS Valid:   &quot;function f() { { let f1; function f1(a) {}; } }&quot;
+PASS Valid:   &quot;{  function f1(a) {}; let f1; }&quot;
+PASS Valid:   &quot;function f() { {  function f1(a) {}; let f1; } }&quot;
+PASS Valid:   &quot;switch('foo') { case 1: function foo() {}; break; case 2: function foo() {}; break; }&quot;
+PASS Valid:   &quot;function f() { switch('foo') { case 1: function foo() {}; break; case 2: function foo() {}; break; } }&quot;
+PASS Invalid: &quot;'use strict'; switch('foo') { case 1: function foo() {}; break; case 2: function foo() {}; break; }&quot;
+PASS Invalid: &quot;function f() { 'use strict'; switch('foo') { case 1: function foo() {}; break; case 2: function foo() {}; break; } }&quot;
+PASS Invalid: &quot;'use strict'; switch('foo') { case 1: function foo() {}; break; case 2: let foo; break; }&quot;
+PASS Invalid: &quot;function f() { 'use strict'; switch('foo') { case 1: function foo() {}; break; case 2: let foo; break; } }&quot;
+PASS Invalid: &quot;'use strict'; switch('foo') { case 1: let foo; break; case 2: function foo() {}; break; }&quot;
+PASS Invalid: &quot;function f() { 'use strict'; switch('foo') { case 1: let foo; break; case 2: function foo() {}; break; } }&quot;
+PASS Valid:   &quot;'use strict'; switch('foo') { case 1: { let foo; break; } case 2: function foo() {}; break; }&quot;
+PASS Valid:   &quot;function f() { 'use strict'; switch('foo') { case 1: { let foo; break; } case 2: function foo() {}; break; } }&quot;
+PASS Valid:   &quot;'use strict'; switch('foo') { case 1: { function foo() { }; break; } case 2: function foo() {}; break; }&quot;
+PASS Valid:   &quot;function f() { 'use strict'; switch('foo') { case 1: { function foo() { }; break; } case 2: function foo() {}; break; } }&quot;
+PASS Invalid: &quot;'use strict'; if (true) function foo() { }; &quot;
+PASS Invalid: &quot;function f() { 'use strict'; if (true) function foo() { };  }&quot;
+PASS Valid:   &quot;if (true) function foo() { }; &quot;
+PASS Valid:   &quot;function f() { if (true) function foo() { };  }&quot;
</ins><span class="cx"> PASS Valid:   &quot;var str = &quot;'use strict'; function f1(a) { function f2(b) { return b; } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5);&quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { var str = &quot;'use strict'; function f1(a) { function f2(b) { return b; } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5); }&quot;
</span><span class="cx"> PASS Valid:   &quot;var str = &quot;'use strict'; function f1(a) { function f2(b) { function f3(c) { return c; } return f3(b); } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5);&quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { var str = &quot;'use strict'; function f1(a) { function f2(b) { function f3(c) { return c; } return f3(b); } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5); }&quot;
</span><del>-PASS Invalid: &quot;var str = &quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5);&quot;
-FAIL Invalid: &quot;function f() { var str = &quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5); }&quot; but did not throw
-PASS Invalid: &quot;var str = &quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5);&quot;
-FAIL Invalid: &quot;function f() { var str = &quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5); }&quot; but did not throw
</del><ins>+PASS Valid:   &quot;var str = &quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5);&quot;
+PASS Valid:   &quot;function f() { var str = &quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5); }&quot;
+PASS Valid:   &quot;var str = &quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5);&quot;
+PASS Valid:   &quot;function f() { var str = &quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } return f1(arguments[0]);&quot;; var foo = new Function(str); foo(5); }&quot;
</ins><span class="cx"> PASS Valid:   &quot;if (0) $foo; &quot;
</span><span class="cx"> PASS Valid:   &quot;function f() { if (0) $foo;  }&quot;
</span><span class="cx"> PASS Valid:   &quot;if (0) _foo; &quot;
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsparsersyntaxcheckjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/parser-syntax-check.js (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/LayoutTests/js/script-tests/parser-syntax-check.js        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -2,6 +2,11 @@
</span><span class="cx"> &quot;This test checks that the following expressions or statements are valid ECMASCRIPT code or should throw parse error&quot;
</span><span class="cx"> );
</span><span class="cx"> 
</span><ins>+function testFailed(msg) {
+    description(msg);
+    throw new Error(&quot;Bad!&quot;);
+}
+
</ins><span class="cx"> function runTest(_a, expectSyntaxError)
</span><span class="cx"> {
</span><span class="cx">     var error;
</span><span class="lines">@@ -399,13 +404,32 @@
</span><span class="cx"> 
</span><span class="cx"> valid(&quot;'use strict'; function f1(a) { function f2(b) { return b; } return f2(a); } f1(5);&quot;)
</span><span class="cx"> valid(&quot;'use strict'; function f1(a) { function f2(b) { function f3(c) { return c; } return f3(b); } return f2(a); } f1(5);&quot;)
</span><del>-invalid(&quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } f1(5);&quot;)
-invalid(&quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } f1(5);&quot;)
</del><ins>+valid(&quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } f1(5);&quot;)
+valid(&quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } f1(5);&quot;)
+valid(&quot;'use strict'; function f1(a) {}; function f1(a) {};&quot;)
+invalid(&quot;'use strict'; { function f1(a) {}; function f1(a) {}; }&quot;)
+invalid(&quot;'use strict'; { let f1; function f1(a) {}; }&quot;)
+invalid(&quot;'use strict'; { function f1(a) {}; let f1; }&quot;)
+invalid(&quot;'use strict'; let f1; function f1(a) {};&quot;)
+invalid(&quot;'use strict'; function f1(a) {}; let f1; &quot;)
+invalid(&quot;let f1; function f1(a) {};&quot;)
+invalid(&quot;let f1; { function f1(a) {}; }&quot;)
+invalid(&quot;{ function f1(a) {}; } let f1;&quot;)
+valid(&quot;{ let f1; function f1(a) {}; }&quot;)
+valid(&quot;{  function f1(a) {}; let f1; }&quot;)
+valid(&quot;switch('foo') { case 1: function foo() {}; break; case 2: function foo() {}; break; }&quot;)
+invalid(&quot;'use strict'; switch('foo') { case 1: function foo() {}; break; case 2: function foo() {}; break; }&quot;);
+invalid(&quot;'use strict'; switch('foo') { case 1: function foo() {}; break; case 2: let foo; break; }&quot;);
+invalid(&quot;'use strict'; switch('foo') { case 1: let foo; break; case 2: function foo() {}; break; }&quot;);
+valid(&quot;'use strict'; switch('foo') { case 1: { let foo; break; } case 2: function foo() {}; break; }&quot;);
+valid(&quot;'use strict'; switch('foo') { case 1: { function foo() { }; break; } case 2: function foo() {}; break; }&quot;);
+invalid(&quot;'use strict'; if (true) function foo() { }; &quot;);
+valid(&quot;if (true) function foo() { }; &quot;);
</ins><span class="cx"> 
</span><span class="cx"> valid(&quot;var str = \&quot;'use strict'; function f1(a) { function f2(b) { return b; } return f2(a); } return f1(arguments[0]);\&quot;; var foo = new Function(str); foo(5);&quot;)
</span><span class="cx"> valid(&quot;var str = \&quot;'use strict'; function f1(a) { function f2(b) { function f3(c) { return c; } return f3(b); } return f2(a); } return f1(arguments[0]);\&quot;; var foo = new Function(str); foo(5);&quot;)
</span><del>-invalid(&quot;var str = \&quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } return f1(arguments[0]);\&quot;; var foo = new Function(str); foo(5);&quot;, SyntaxError, undefined)
-invalid(&quot;var str = \&quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } return f1(arguments[0]);\&quot;; var foo = new Function(str); foo(5);&quot;, SyntaxError, undefined)
</del><ins>+valid(&quot;var str = \&quot;'use strict'; function f1(a) { if (a) { function f2(b) { return b; } return f2(a); } else return a; } return f1(arguments[0]);\&quot;; var foo = new Function(str); foo(5);&quot;)
+valid(&quot;var str = \&quot;'use strict'; function f1(a) { function f2(b) { if (b) { function f3(c) { return c; } return f3(b); } else return b; } return f2(a); } return f1(arguments[0]);\&quot;; var foo = new Function(str); foo(5);&quot;)
</ins><span class="cx"> 
</span><span class="cx"> valid(&quot;if (0) $foo; &quot;)
</span><span class="cx"> valid(&quot;if (0) _foo; &quot;)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -1,3 +1,163 @@
</span><ins>+2016-03-09  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        ES6: Implement lexical scoping for function definitions in strict mode
+        https://bugs.webkit.org/show_bug.cgi?id=152844
+
+        Reviewed by Geoffrey Garen.
+
+        This patch implements block scoping for function definitions
+        in strict mode. The implementation works as follows:
+        
+        - If we're in sloppy mode, function declarations work exactly
+          as they did before this patch. I.e, function declarations are hoisted
+          and declared like &quot;var&quot; variables.
+        
+        - If you're in strict mode and at the top of a function scope or program
+          scope, function declarations still work like they used to. They are defined
+          like &quot;var&quot; variables. This is necessary for backwards compatibility
+          because ES5 strict mode allowed duplicate function declarations at the
+          top-most scope of a program/function.
+        
+        - If you're in strict mode and inside a block statement or a switch statement,
+          function declarations are now block scoped. All function declarations within
+          a block are hoisted to the beginning of the block. They are not hoisted out of the 
+          block like they are in sloppy mode. This allows for the following types of
+          programs:
+          ```
+          function foo() {
+              function bar() { return 20; }
+              {
+                  function bar() { return 30; }
+                  bar(); // 30
+              }
+              bar(); // 20
+          }
+          ```
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::instantiateLexicalVariables):
+        (JSC::BytecodeGenerator::emitPrefillStackTDZVariables):
+        (JSC::BytecodeGenerator::pushLexicalScope):
+        (JSC::BytecodeGenerator::pushLexicalScopeInternal):
+        (JSC::BytecodeGenerator::initializeBlockScopedFunctions):
+        (JSC::BytecodeGenerator::popLexicalScope):
+        (JSC::BytecodeGenerator::liftTDZCheckIfPossible):
+        (JSC::BytecodeGenerator::pushTDZVariables):
+        (JSC::BytecodeGenerator::getVariablesUnderTDZ):
+        (JSC::BytecodeGenerator::emitNewRegExp):
+        (JSC::BytecodeGenerator::emitNewFunctionExpressionCommon):
+        (JSC::BytecodeGenerator::emitNewFunctionExpression):
+        (JSC::BytecodeGenerator::emitNewArrowFunctionExpression):
+        * bytecompiler/BytecodeGenerator.h:
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createSourceElements):
+        (JSC::ASTBuilder::features):
+        (JSC::ASTBuilder::numConstants):
+        (JSC::ASTBuilder::createFuncDeclStatement):
+        (JSC::ASTBuilder::createClassDeclStatement):
+        (JSC::ASTBuilder::createBlockStatement):
+        (JSC::ASTBuilder::createTryStatement):
+        (JSC::ASTBuilder::createSwitchStatement):
+        (JSC::ASTBuilder::Scope::Scope):
+        (JSC::ASTBuilder::funcDeclarations): Deleted.
+        * parser/NodeConstructors.h:
+        (JSC::CaseBlockNode::CaseBlockNode):
+        (JSC::SwitchNode::SwitchNode):
+        (JSC::BlockNode::BlockNode):
+        * parser/Nodes.cpp:
+        (JSC::ScopeNode::ScopeNode):
+        (JSC::ScopeNode::singleStatement):
+        (JSC::ProgramNode::ProgramNode):
+        (JSC::ModuleProgramNode::ModuleProgramNode):
+        (JSC::EvalNode::EvalNode):
+        (JSC::FunctionNode::FunctionNode):
+        (JSC::VariableEnvironmentNode::VariableEnvironmentNode):
+        * parser/Nodes.h:
+        (JSC::VariableEnvironmentNode::VariableEnvironmentNode):
+        (JSC::VariableEnvironmentNode::lexicalVariables):
+        (JSC::VariableEnvironmentNode::functionStack):
+        (JSC::ScopeNode::captures):
+        (JSC::ScopeNode::varDeclarations):
+        (JSC::ScopeNode::neededConstants):
+        (JSC::ProgramNode::startColumn):
+        (JSC::ProgramNode::endColumn):
+        (JSC::EvalNode::startColumn):
+        (JSC::EvalNode::endColumn):
+        (JSC::ModuleProgramNode::startColumn):
+        (JSC::ModuleProgramNode::endColumn):
+        (JSC::ScopeNode::functionStack): Deleted.
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseInner):
+        (JSC::Parser&lt;LexerType&gt;::didFinishParsing):
+        (JSC::Parser&lt;LexerType&gt;::parseStatementListItem):
+        (JSC::Parser&lt;LexerType&gt;::parseSwitchStatement):
+        (JSC::Parser&lt;LexerType&gt;::parseBlockStatement):
+        (JSC::Parser&lt;LexerType&gt;::parseStatement):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionInfo):
+        (JSC::getMetadata):
+        (JSC::Parser&lt;LexerType&gt;::parseFunctionDeclaration):
+        (JSC::Parser&lt;LexerType&gt;::parseExportDeclaration):
+        * parser/Parser.h:
+        (JSC::Scope::declareVariable):
+        (JSC::Scope::declareFunction):
+        (JSC::Scope::appendFunction):
+        (JSC::Scope::takeFunctionDeclarations):
+        (JSC::Scope::declareLexicalVariable):
+        (JSC::Parser::currentVariableScope):
+        (JSC::Parser::currentLexicalDeclarationScope):
+        (JSC::Parser::currentFunctionScope):
+        (JSC::Parser::pushScope):
+        (JSC::Parser::popScopeInternal):
+        (JSC::Parser::declareVariable):
+        (JSC::Parser::declareFunction):
+        (JSC::Parser::hasDeclaredVariable):
+        (JSC::Parser::isFunctionMetadataNode):
+        (JSC::Parser&lt;LexerType&gt;::parse):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createFuncDeclStatement):
+        (JSC::SyntaxChecker::createClassDeclStatement):
+        (JSC::SyntaxChecker::createBlockStatement):
+        (JSC::SyntaxChecker::createExprStatement):
+        (JSC::SyntaxChecker::createIfStatement):
+        (JSC::SyntaxChecker::createContinueStatement):
+        (JSC::SyntaxChecker::createTryStatement):
+        (JSC::SyntaxChecker::createSwitchStatement):
+        (JSC::SyntaxChecker::createWhileStatement):
+        (JSC::SyntaxChecker::createWithStatement):
+        (JSC::SyntaxChecker::createDoWhileStatement):
+        * parser/VariableEnvironment.h:
+        (JSC::VariableEnvironmentEntry::isExported):
+        (JSC::VariableEnvironmentEntry::isImported):
+        (JSC::VariableEnvironmentEntry::isImportedNamespace):
+        (JSC::VariableEnvironmentEntry::isFunction):
+        (JSC::VariableEnvironmentEntry::setIsCaptured):
+        (JSC::VariableEnvironmentEntry::setIsConst):
+        (JSC::VariableEnvironmentEntry::setIsExported):
+        (JSC::VariableEnvironmentEntry::setIsImported):
+        (JSC::VariableEnvironmentEntry::setIsImportedNamespace):
+        (JSC::VariableEnvironmentEntry::setIsFunction):
+        (JSC::VariableEnvironmentEntry::clearIsVar):
+        (JSC::VariableEnvironment::VariableEnvironment):
+        (JSC::VariableEnvironment::begin):
+        (JSC::VariableEnvironment::end):
+        * tests/es6.yaml:
+        * tests/stress/block-scoped-function-declarations.js: Added.
+        (assert):
+        (test):
+        (f.foo.bar):
+        (f.foo.):
+        (f.foo):
+        (f):
+        (assert.foo.):
+        (assert.foo):
+        (assert.foo.foo):
+        (assert.foo.bar):
+        (assert.foo.switch.case.1):
+        (assert.foo.switch.case.2):
+        (assert.foo.switch.foo):
+        (assert.foo.switch.bar):
+
</ins><span class="cx"> 2016-03-09  Saam barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Array.isArray support for Proxy
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -566,7 +566,7 @@
</span><span class="cx"> 
</span><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><del>-    m_TDZStack.append(std::make_pair(*parentScopeTDZVariables, false));
</del><ins>+    pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize);
</ins><span class="cx">     initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, functionNode, functionSymbolTable, symbolTableConstantIndex, captures);
</span><span class="cx">     
</span><span class="cx">     // Loading |this| inside an arrow function must be done after initializeDefaultParameterValuesAndSetupFunctionScopeStack()
</span><span class="lines">@@ -582,7 +582,8 @@
</span><span class="cx">         emitPutDerivedConstructorToArrowFunctionContextScope();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize);
</del><ins>+    bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
+    pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
</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">@@ -623,7 +624,7 @@
</span><span class="cx">     }
</span><span class="cx">     codeBlock-&gt;adoptVariables(variables);
</span><span class="cx"> 
</span><del>-    m_TDZStack.append(std::make_pair(*parentScopeTDZVariables, false));
</del><ins>+    pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize);
</ins><span class="cx"> 
</span><span class="cx">     if (codeBlock-&gt;isArrowFunctionContext() &amp;&amp; evalNode-&gt;usesThis())
</span><span class="cx">         emitLoadThisFromArrowFunctionLexicalEnvironment();
</span><span class="lines">@@ -633,7 +634,8 @@
</span><span class="cx">         emitPutThisToArrowFunctionContextScope();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize);
</del><ins>+    bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
+    pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> BytecodeGenerator::BytecodeGenerator(VM&amp; vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode, const VariableEnvironment* parentScopeTDZVariables)
</span><span class="lines">@@ -715,8 +717,9 @@
</span><span class="cx">     else
</span><span class="cx">         constantSymbolTable = addConstantValue(moduleEnvironmentSymbolTable-&gt;cloneScopePart(*m_vm));
</span><span class="cx"> 
</span><del>-    m_TDZStack.append(std::make_pair(lexicalVariables, true));
-    m_symbolTableStack.append(SymbolTableStackEntry { Strong&lt;SymbolTable&gt;(*m_vm, moduleEnvironmentSymbolTable), m_topMostScope, false, constantSymbolTable-&gt;index() });
</del><ins>+    pushTDZVariables(lexicalVariables, TDZCheckOptimization::Optimize);
+    bool isWithScope = false;
+    m_symbolTableStack.append(SymbolTableStackEntry { Strong&lt;SymbolTable&gt;(*m_vm, moduleEnvironmentSymbolTable), m_topMostScope, isWithScope, constantSymbolTable-&gt;index() });
</ins><span class="cx">     emitPrefillStackTDZVariables(lexicalVariables, moduleEnvironmentSymbolTable);
</span><span class="cx"> 
</span><span class="cx">     // makeFunction assumes that there's correct TDZ stack entries.
</span><span class="lines">@@ -1742,7 +1745,7 @@
</span><span class="cx">     {
</span><span class="cx">         ConcurrentJITLocker locker(symbolTable-&gt;m_lock);
</span><span class="cx">         for (auto&amp; entry : lexicalVariables) {
</span><del>-            ASSERT(entry.value.isLet() || entry.value.isConst());
</del><ins>+            ASSERT(entry.value.isLet() || entry.value.isConst() || entry.value.isFunction());
</ins><span class="cx">             ASSERT(!entry.value.isVar());
</span><span class="cx">             SymbolTableEntry symbolTableEntry = symbolTable-&gt;get(locker, entry.key.get());
</span><span class="cx">             ASSERT(symbolTableEntry.isNull());
</span><span class="lines">@@ -1789,6 +1792,9 @@
</span><span class="cx">         if (entry.value.isImported() &amp;&amp; !entry.value.isImportedNamespace())
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><ins>+        if (entry.value.isFunction())
+            continue;
+
</ins><span class="cx">         SymbolTableEntry symbolTableEntry = symbolTable-&gt;get(entry.key.get());
</span><span class="cx">         ASSERT(!symbolTableEntry.isNull());
</span><span class="cx">         VarOffset offset = symbolTableEntry.varOffset();
</span><span class="lines">@@ -1800,10 +1806,17 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType, RegisterID** constantSymbolTableResult)
</del><ins>+void BytecodeGenerator::pushLexicalScope(VariableEnvironmentNode* node, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType, RegisterID** constantSymbolTableResult, bool shouldInitializeBlockScopedFunctions)
</ins><span class="cx"> {
</span><span class="cx">     VariableEnvironment&amp; environment = node-&gt;lexicalVariables();
</span><del>-    pushLexicalScopeInternal(environment, tdzCheckOptimization, nestedScopeType, constantSymbolTableResult, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
</del><ins>+    RegisterID* constantSymbolTableResultTemp = nullptr;
+    pushLexicalScopeInternal(environment, tdzCheckOptimization, nestedScopeType, &amp;constantSymbolTableResultTemp, TDZRequirement::UnderTDZ, ScopeType::LetConstScope, ScopeRegisterType::Block);
+
+    if (shouldInitializeBlockScopedFunctions)
+        initializeBlockScopedFunctions(environment, node-&gt;functionStack(), constantSymbolTableResultTemp);
+
+    if (constantSymbolTableResult &amp;&amp; constantSymbolTableResultTemp)
+        *constantSymbolTableResult = constantSymbolTableResultTemp;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void BytecodeGenerator::pushLexicalScopeInternal(VariableEnvironment&amp; environment, TDZCheckOptimization tdzCheckOptimization, NestedScopeType nestedScopeType,
</span><span class="lines">@@ -1869,15 +1882,69 @@
</span><span class="cx">         pushScopedControlFlowContext();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_symbolTableStack.append(SymbolTableStackEntry{ symbolTable, newScope, false, symbolTableConstantIndex });
-    bool canOptimizeTDZChecks = tdzCheckOptimization == TDZCheckOptimization::Optimize;
</del><ins>+    bool isWithScope = false;
+    m_symbolTableStack.append(SymbolTableStackEntry{ symbolTable, newScope, isWithScope, symbolTableConstantIndex });
</ins><span class="cx">     if (tdzRequirement == TDZRequirement::UnderTDZ)
</span><del>-        m_TDZStack.append(std::make_pair(environment, canOptimizeTDZChecks));
</del><ins>+        pushTDZVariables(environment, tdzCheckOptimization);
</ins><span class="cx"> 
</span><span class="cx">     if (tdzRequirement == TDZRequirement::UnderTDZ)
</span><span class="cx">         emitPrefillStackTDZVariables(environment, symbolTable.get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::initializeBlockScopedFunctions(VariableEnvironment&amp; environment, FunctionStack&amp; functionStack, RegisterID* constantSymbolTable)
+{
+    /*
+     * We must transform block scoped function declarations in strict mode like so:
+     *
+     * function foo() {
+     *     if (c) {
+     *           function foo() { ... }
+     *           if (bar) { ... }
+     *           else { ... }
+     *           function baz() { ... }
+     *     }
+     * }
+     *
+     * to:
+     *
+     * function foo() {
+     *     if (c) {
+     *         let foo = function foo() { ... }
+     *         let baz = function baz() { ... }
+     *         if (bar) { ... }
+     *         else { ... }
+     *     }
+     * }
+     * 
+     * But without the TDZ checks.
+    */
+
+    if (!environment.size()) {
+        RELEASE_ASSERT(!functionStack.size());
+        return;
+    }
+
+    if (!functionStack.size())
+        return;
+
+    SymbolTable* symbolTable = m_symbolTableStack.last().m_symbolTable.get();
+    RegisterID* scope = m_symbolTableStack.last().m_scope;
+    RefPtr&lt;RegisterID&gt; temp = newTemporary();
+    int symbolTableIndex = constantSymbolTable ? constantSymbolTable-&gt;index() : 0;
+    for (FunctionMetadataNode* function : functionStack) {
+        const Identifier&amp; name = function-&gt;ident();
+        auto iter = environment.find(name.impl());
+        RELEASE_ASSERT(iter != environment.end());
+        RELEASE_ASSERT(iter-&gt;value.isFunction());
+        // We purposefully don't hold the symbol table lock around this loop because emitNewFunctionExpressionCommon may GC.
+        SymbolTableEntry entry = symbolTable-&gt;get(name.impl()); 
+        RELEASE_ASSERT(!entry.isNull());
+        emitNewFunctionExpressionCommon(temp.get(), function);
+        bool isLexicallyScoped = true;
+        emitPutToScope(scope, variableForLocalEntry(name, entry, symbolTableIndex, isLexicallyScoped), temp.get(), DoNotThrowIfNotFound, Initialization);
+    }
+}
+
</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 class="lines">@@ -2553,8 +2620,8 @@
</span><span class="cx">     for (unsigned i = m_TDZStack.size(); i--;) {
</span><span class="cx">         VariableEnvironment&amp; environment = m_TDZStack[i].first;
</span><span class="cx">         if (environment.contains(identifier)) {
</span><del>-            bool isSyntacticallyAbleToOptimizeTDZ = m_TDZStack[i].second;
-            if (isSyntacticallyAbleToOptimizeTDZ) {
</del><ins>+            TDZCheckOptimization tdzCheckOptimizationCapability = m_TDZStack[i].second;
+            if (tdzCheckOptimizationCapability == TDZCheckOptimization::Optimize) {
</ins><span class="cx">                 bool wasRemoved = environment.remove(identifier);
</span><span class="cx">                 RELEASE_ASSERT(wasRemoved);
</span><span class="cx">             }
</span><span class="lines">@@ -2563,6 +2630,23 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeGenerator::pushTDZVariables(VariableEnvironment environment, TDZCheckOptimization optimization)
+{
+    if (!environment.size())
+        return;
+
+    Vector&lt;UniquedStringImpl*, 4&gt; functionsToRemove;
+    for (const auto&amp; entry : environment) {
+        if (entry.value.isFunction())
+            functionsToRemove.append(entry.key.get());
+    }
+
+    for (UniquedStringImpl* function : functionsToRemove)
+        environment.remove(function);
+
+    m_TDZStack.append(std::make_pair(WTFMove(environment), optimization));
+}
+
</ins><span class="cx"> void BytecodeGenerator::getVariablesUnderTDZ(VariableEnvironment&amp; result)
</span><span class="cx"> {
</span><span class="cx">     for (auto&amp; pair : m_TDZStack) {
</span><span class="lines">@@ -2683,9 +2767,8 @@
</span><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::emitNewFunctionExpressionCommon(RegisterID* dst, BaseFuncExprNode* func)
</del><ins>+void BytecodeGenerator::emitNewFunctionExpressionCommon(RegisterID* dst, FunctionMetadataNode* function)
</ins><span class="cx"> {
</span><del>-    FunctionMetadataNode* function = func-&gt;metadata();
</del><span class="cx">     unsigned index = m_codeBlock-&gt;addFunctionExpr(makeFunction(function));
</span><span class="cx"> 
</span><span class="cx">     OpcodeID opcodeID = op_new_func_exp;
</span><span class="lines">@@ -2711,14 +2794,14 @@
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func)
</span><span class="cx"> {
</span><del>-    emitNewFunctionExpressionCommon(dst, func);
</del><ins>+    emitNewFunctionExpressionCommon(dst, func-&gt;metadata());
</ins><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitNewArrowFunctionExpression(RegisterID* dst, ArrowFuncExprNode* func)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(func-&gt;metadata()-&gt;parseMode() == SourceParseMode::ArrowFunctionMode);    
</span><del>-    emitNewFunctionExpressionCommon(dst, func);
</del><ins>+    emitNewFunctionExpressionCommon(dst, func-&gt;metadata());
</ins><span class="cx">     return dst;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -709,6 +709,7 @@
</span><span class="cx">         enum class ScopeType { CatchScope, LetConstScope, FunctionNameScope };
</span><span class="cx">         enum class ScopeRegisterType { Var, Block };
</span><span class="cx">         void pushLexicalScopeInternal(VariableEnvironment&amp;, TDZCheckOptimization, NestedScopeType, RegisterID** constantSymbolTableResult, TDZRequirement, ScopeType, ScopeRegisterType);
</span><ins>+        void initializeBlockScopedFunctions(VariableEnvironment&amp;, FunctionStack&amp;, RegisterID* constantSymbolTable);
</ins><span class="cx">         void popLexicalScopeInternal(VariableEnvironment&amp;, TDZRequirement);
</span><span class="cx">         template&lt;typename LookUpVarKindFunctor&gt;
</span><span class="cx">         bool instantiateLexicalVariables(const VariableEnvironment&amp;, SymbolTable*, ScopeRegisterType, LookUpVarKindFunctor);
</span><span class="lines">@@ -716,7 +717,7 @@
</span><span class="cx">         void emitPopScope(RegisterID* dst, RegisterID* scope);
</span><span class="cx">         RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope);
</span><span class="cx">         void emitPushFunctionNameScope(const Identifier&amp; property, RegisterID* value, bool isCaptured);
</span><del>-        void emitNewFunctionExpressionCommon(RegisterID*, BaseFuncExprNode*);
</del><ins>+        void emitNewFunctionExpressionCommon(RegisterID*, FunctionMetadataNode*);
</ins><span class="cx">         
</span><span class="cx">         bool isNewTargetUsedInInnerArrowFunction();
</span><span class="cx">         bool isSuperUsedInInnerArrowFunction();
</span><span class="lines">@@ -725,7 +726,7 @@
</span><span class="cx">     public:
</span><span class="cx">         bool isSuperCallUsedInInnerArrowFunction();
</span><span class="cx">         bool isThisUsedInInnerArrowFunction();
</span><del>-        void pushLexicalScope(VariableEnvironmentNode*, TDZCheckOptimization, NestedScopeType = NestedScopeType::IsNotNested, RegisterID** constantSymbolTableResult = nullptr);
</del><ins>+        void pushLexicalScope(VariableEnvironmentNode*, TDZCheckOptimization, NestedScopeType = NestedScopeType::IsNotNested, RegisterID** constantSymbolTableResult = nullptr, bool shouldInitializeBlockScopedFunctions = true);
</ins><span class="cx">         void popLexicalScope(VariableEnvironmentNode*);
</span><span class="cx">         void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable);
</span><span class="cx">         int labelScopeDepth() const;
</span><span class="lines">@@ -859,7 +860,8 @@
</span><span class="cx">             int m_symbolTableConstantIndex;
</span><span class="cx">         };
</span><span class="cx">         Vector&lt;SymbolTableStackEntry&gt; m_symbolTableStack;
</span><del>-        Vector&lt;std::pair&lt;VariableEnvironment, bool&gt;&gt; m_TDZStack;
</del><ins>+        Vector&lt;std::pair&lt;VariableEnvironment, TDZCheckOptimization&gt;&gt; m_TDZStack;
+        void pushTDZVariables(VariableEnvironment, TDZCheckOptimization);
</ins><span class="cx"> 
</span><span class="cx">         ScopeNode* const m_scopeNode;
</span><span class="cx">         Strong&lt;UnlinkedCodeBlock&gt; m_codeBlock;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -133,7 +133,6 @@
</span><span class="cx"> 
</span><span class="cx">     JSC::SourceElements* createSourceElements() { return new (m_parserArena) JSC::SourceElements(); }
</span><span class="cx"> 
</span><del>-    DeclarationStacks::FunctionStack&amp; funcDeclarations() { return m_scope.m_funcDeclarations; }
</del><span class="cx">     int features() const { return m_scope.m_features; }
</span><span class="cx">     int numConstants() const { return m_scope.m_numConstants; }
</span><span class="cx"> 
</span><span class="lines">@@ -482,7 +481,6 @@
</span><span class="cx">             m_sourceCode-&gt;subExpression(functionInfo.startOffset, functionInfo.endOffset, functionInfo.startLine, functionInfo.bodyStartColumn));
</span><span class="cx">         if (*functionInfo.name == m_vm-&gt;propertyNames-&gt;arguments)
</span><span class="cx">             usesArguments();
</span><del>-        m_scope.m_funcDeclarations.append(decl-&gt;metadata());
</del><span class="cx">         functionInfo.body-&gt;setLoc(functionInfo.startLine, functionInfo.endLine, location.startOffset, location.lineStartOffset);
</span><span class="cx">         return decl;
</span><span class="cx">     }
</span><span class="lines">@@ -496,9 +494,9 @@
</span><span class="cx">         return decl;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    StatementNode* createBlockStatement(const JSTokenLocation&amp; location, JSC::SourceElements* elements, int startLine, int endLine, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    StatementNode* createBlockStatement(const JSTokenLocation&amp; location, JSC::SourceElements* elements, int startLine, int endLine, VariableEnvironment&amp; lexicalVariables, DeclarationStacks::FunctionStack&amp;&amp; functionStack)
</ins><span class="cx">     {
</span><del>-        BlockNode* block = new (m_parserArena) BlockNode(location, elements, lexicalVariables);
</del><ins>+        BlockNode* block = new (m_parserArena) BlockNode(location, elements, lexicalVariables, WTFMove(functionStack));
</ins><span class="cx">         block-&gt;setLoc(startLine, endLine, location.startOffset, location.lineStartOffset);
</span><span class="cx">         return block;
</span><span class="cx">     }
</span><span class="lines">@@ -628,10 +626,10 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    StatementNode* createSwitchStatement(const JSTokenLocation&amp; location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    StatementNode* createSwitchStatement(const JSTokenLocation&amp; location, ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine, VariableEnvironment&amp; lexicalVariables, DeclarationStacks::FunctionStack&amp;&amp; functionStack)
</ins><span class="cx">     {
</span><span class="cx">         CaseBlockNode* cases = new (m_parserArena) CaseBlockNode(firstClauses, defaultClause, secondClauses);
</span><del>-        SwitchNode* result = new (m_parserArena) SwitchNode(location, expr, cases, lexicalVariables);
</del><ins>+        SwitchNode* result = new (m_parserArena) SwitchNode(location, expr, cases, lexicalVariables, WTFMove(functionStack));
</ins><span class="cx">         result-&gt;setLoc(startLine, endLine, location.startOffset, location.lineStartOffset);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="lines">@@ -935,7 +933,6 @@
</span><span class="cx">             , m_numConstants(0)
</span><span class="cx">         {
</span><span class="cx">         }
</span><del>-        DeclarationStacks::FunctionStack m_funcDeclarations;
</del><span class="cx">         int m_features;
</span><span class="cx">         int m_numConstants;
</span><span class="cx">     };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodeConstructorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/NodeConstructors.h (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -964,17 +964,17 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    inline SwitchNode::SwitchNode(const JSTokenLocation&amp; location, ExpressionNode* expr, CaseBlockNode* block, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    inline SwitchNode::SwitchNode(const JSTokenLocation&amp; location, ExpressionNode* expr, CaseBlockNode* block, VariableEnvironment&amp; lexicalVariables, FunctionStack&amp;&amp; functionStack)
</ins><span class="cx">         : StatementNode(location)
</span><del>-        , VariableEnvironmentNode(lexicalVariables)
</del><ins>+        , VariableEnvironmentNode(lexicalVariables, WTFMove(functionStack))
</ins><span class="cx">         , m_expr(expr)
</span><span class="cx">         , m_block(block)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    inline BlockNode::BlockNode(const JSTokenLocation&amp; location, SourceElements* statements, VariableEnvironment&amp; lexicalVariables)
</del><ins>+    inline BlockNode::BlockNode(const JSTokenLocation&amp; location, SourceElements* statements, VariableEnvironment&amp; lexicalVariables, FunctionStack&amp;&amp; functionStack)
</ins><span class="cx">         : StatementNode(location)
</span><del>-        , VariableEnvironmentNode(lexicalVariables)
</del><ins>+        , VariableEnvironmentNode(lexicalVariables, WTFMove(functionStack))
</ins><span class="cx">         , m_statements(statements)
</span><span class="cx">     {
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.cpp (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.cpp        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/Nodes.cpp        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -94,10 +94,10 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ScopeNode::ScopeNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, const SourceCode&amp; source, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp; funcStack, VariableEnvironment&amp; lexicalVariables, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
</del><ins>+ScopeNode::ScopeNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, const SourceCode&amp; source, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp;&amp; funcStack, VariableEnvironment&amp; lexicalVariables, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
</ins><span class="cx">     : StatementNode(endLocation)
</span><span class="cx">     , ParserArenaRoot(parserArena)
</span><del>-    , VariableEnvironmentNode(lexicalVariables)
</del><ins>+    , VariableEnvironmentNode(lexicalVariables, WTFMove(funcStack))
</ins><span class="cx">     , m_startLineNumber(startLocation.line)
</span><span class="cx">     , m_startStartOffset(startLocation.startOffset)
</span><span class="cx">     , m_startLineStartOffset(startLocation.lineStartOffset)
</span><span class="lines">@@ -108,7 +108,6 @@
</span><span class="cx">     , m_statements(children)
</span><span class="cx"> {
</span><span class="cx">     m_varDeclarations.swap(varEnvironment);
</span><del>-    m_functionStack.swap(funcStack);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> StatementNode* ScopeNode::singleStatement() const
</span><span class="lines">@@ -118,8 +117,8 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ ProgramNode -----------------------------
</span><span class="cx"> 
</span><del>-ProgramNode::ProgramNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters*, const SourceCode&amp; source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</del><ins>+ProgramNode::ProgramNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp;&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters*, const SourceCode&amp; source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</ins><span class="cx">     , m_startColumn(startColumn)
</span><span class="cx">     , m_endColumn(endColumn)
</span><span class="cx"> {
</span><span class="lines">@@ -127,8 +126,8 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ ModuleProgramNode -----------------------------
</span><span class="cx"> 
</span><del>-ModuleProgramNode::ModuleProgramNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters*, const SourceCode&amp; source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</del><ins>+ModuleProgramNode::ModuleProgramNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp;&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters*, const SourceCode&amp; source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</ins><span class="cx">     , m_startColumn(startColumn)
</span><span class="cx">     , m_endColumn(endColumn)
</span><span class="cx"> {
</span><span class="lines">@@ -136,8 +135,8 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ EvalNode -----------------------------
</span><span class="cx"> 
</span><del>-EvalNode::EvalNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters*, const SourceCode&amp; source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
-    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, funcStack, lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</del><ins>+EvalNode::EvalNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp;&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters*, const SourceCode&amp; source, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+    : ScopeNode(parserArena, startLocation, endLocation, source, children, varEnvironment, WTFMove(funcStack), lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</ins><span class="cx">     , m_endColumn(endColumn)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -182,8 +181,8 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ FunctionNode -----------------------------
</span><span class="cx"> 
</span><del>-FunctionNode::FunctionNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters* parameters, const SourceCode&amp; sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
-    : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, funcStack, lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</del><ins>+FunctionNode::FunctionNode(ParserArena&amp; parserArena, const JSTokenLocation&amp; startLocation, const JSTokenLocation&amp; endLocation, unsigned startColumn, unsigned endColumn, SourceElements* children, VariableEnvironment&amp; varEnvironment, FunctionStack&amp;&amp; funcStack, VariableEnvironment&amp; lexicalVariables, FunctionParameters* parameters, const SourceCode&amp; sourceCode, CodeFeatures features, InnerArrowFunctionCodeFeatures innerArrowFunctionCodeFeatures, int numConstants)
+    : ScopeNode(parserArena, startLocation, endLocation, sourceCode, children, varEnvironment, WTFMove(funcStack), lexicalVariables, features, innerArrowFunctionCodeFeatures, numConstants)
</ins><span class="cx">     , m_parameters(parameters)
</span><span class="cx">     , m_startColumn(startColumn)
</span><span class="cx">     , m_endColumn(endColumn)
</span><span class="lines">@@ -202,4 +201,10 @@
</span><span class="cx">     m_lexicalVariables.swap(lexicalVariables);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+VariableEnvironmentNode::VariableEnvironmentNode(VariableEnvironment&amp; lexicalVariables, FunctionStack&amp;&amp; functionStack)
+{
+    m_lexicalVariables.swap(lexicalVariables);
+    m_functionStack = WTFMove(functionStack);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -214,16 +214,21 @@
</span><span class="cx"> 
</span><span class="cx">     class VariableEnvironmentNode : public ParserArenaDeletable {
</span><span class="cx">     public:
</span><ins>+        typedef DeclarationStacks::FunctionStack FunctionStack;
+
</ins><span class="cx">         VariableEnvironmentNode()
</span><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         VariableEnvironmentNode(VariableEnvironment&amp; lexicalDeclaredVariables);
</span><ins>+        VariableEnvironmentNode(VariableEnvironment&amp; lexicalDeclaredVariables, FunctionStack&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">         VariableEnvironment&amp; lexicalVariables() { return m_lexicalVariables; }
</span><ins>+        FunctionStack&amp; functionStack() { return m_functionStack; }
</ins><span class="cx"> 
</span><span class="cx">     protected:
</span><span class="cx">         VariableEnvironment m_lexicalVariables;
</span><ins>+        FunctionStack m_functionStack;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class ConstantNode : public ExpressionNode {
</span><span class="lines">@@ -1303,7 +1308,7 @@
</span><span class="cx">     public:
</span><span class="cx">         using ParserArenaDeletable::operator new;
</span><span class="cx"> 
</span><del>-        BlockNode(const JSTokenLocation&amp;, SourceElements*, VariableEnvironment&amp;);
</del><ins>+        BlockNode(const JSTokenLocation&amp;, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">         StatementNode* singleStatement() const;
</span><span class="cx">         StatementNode* lastStatement() const;
</span><span class="lines">@@ -1551,10 +1556,9 @@
</span><span class="cx"> 
</span><span class="cx">     class ScopeNode : public StatementNode, public ParserArenaRoot, public VariableEnvironmentNode {
</span><span class="cx">     public:
</span><del>-        typedef DeclarationStacks::FunctionStack FunctionStack;
</del><span class="cx"> 
</span><span class="cx">         ScopeNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, bool inStrictContext);
</span><del>-        ScopeNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, const SourceCode&amp;, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;, VariableEnvironment&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</del><ins>+        ScopeNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, const SourceCode&amp;, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;&amp;, VariableEnvironment&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</ins><span class="cx"> 
</span><span class="cx">         using ParserArenaRoot::operator new;
</span><span class="cx"> 
</span><span class="lines">@@ -1593,7 +1597,6 @@
</span><span class="cx">         bool captures(const Identifier&amp; ident) { return captures(ident.impl()); }
</span><span class="cx"> 
</span><span class="cx">         VariableEnvironment&amp; varDeclarations() { return m_varDeclarations; }
</span><del>-        FunctionStack&amp; functionStack() { return m_functionStack; }
</del><span class="cx"> 
</span><span class="cx">         int neededConstants()
</span><span class="cx">         {
</span><span class="lines">@@ -1618,14 +1621,13 @@
</span><span class="cx">         InnerArrowFunctionCodeFeatures m_innerArrowFunctionCodeFeatures;
</span><span class="cx">         SourceCode m_source;
</span><span class="cx">         VariableEnvironment m_varDeclarations;
</span><del>-        FunctionStack m_functionStack;
</del><span class="cx">         int m_numConstants;
</span><span class="cx">         SourceElements* m_statements;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     class ProgramNode : public ScopeNode {
</span><span class="cx">     public:
</span><del>-        ProgramNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</del><ins>+        ProgramNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</ins><span class="cx"> 
</span><span class="cx">         unsigned startColumn() const { return m_startColumn; }
</span><span class="cx">         unsigned endColumn() const { return m_endColumn; }
</span><span class="lines">@@ -1640,7 +1642,7 @@
</span><span class="cx"> 
</span><span class="cx">     class EvalNode : public ScopeNode {
</span><span class="cx">     public:
</span><del>-        EvalNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</del><ins>+        EvalNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</ins><span class="cx"> 
</span><span class="cx">         ALWAYS_INLINE unsigned startColumn() const { return 0; }
</span><span class="cx">         unsigned endColumn() const { return m_endColumn; }
</span><span class="lines">@@ -1655,7 +1657,7 @@
</span><span class="cx"> 
</span><span class="cx">     class ModuleProgramNode : public ScopeNode {
</span><span class="cx">     public:
</span><del>-        ModuleProgramNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</del><ins>+        ModuleProgramNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</ins><span class="cx"> 
</span><span class="cx">         unsigned startColumn() const { return m_startColumn; }
</span><span class="cx">         unsigned endColumn() const { return m_endColumn; }
</span><span class="lines">@@ -1897,7 +1899,7 @@
</span><span class="cx"> 
</span><span class="cx">     class FunctionNode final : public ScopeNode {
</span><span class="cx">     public:
</span><del>-        FunctionNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</del><ins>+        FunctionNode(ParserArena&amp;, const JSTokenLocation&amp; start, const JSTokenLocation&amp; end, unsigned startColumn, unsigned endColumn, SourceElements*, VariableEnvironment&amp;, FunctionStack&amp;&amp;, VariableEnvironment&amp;, FunctionParameters*, const SourceCode&amp;, CodeFeatures, InnerArrowFunctionCodeFeatures, int numConstants);
</ins><span class="cx"> 
</span><span class="cx">         FunctionParameters* parameters() const { return m_parameters; }
</span><span class="cx"> 
</span><span class="lines">@@ -2203,7 +2205,7 @@
</span><span class="cx">     public:
</span><span class="cx">         using ParserArenaDeletable::operator new;
</span><span class="cx"> 
</span><del>-        SwitchNode(const JSTokenLocation&amp;, ExpressionNode*, CaseBlockNode*, VariableEnvironment&amp;);
</del><ins>+        SwitchNode(const JSTokenLocation&amp;, ExpressionNode*, CaseBlockNode*, VariableEnvironment&amp;, FunctionStack&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     private:
</span><span class="cx">         void emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -336,17 +336,17 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> #endif // NDEBUG
</span><del>-    didFinishParsing(sourceElements, context.funcDeclarations(), varDeclarations, features, context.numConstants());
</del><ins>+    didFinishParsing(sourceElements, scope-&gt;takeFunctionDeclarations(), varDeclarations, features, context.numConstants());
</ins><span class="cx"> 
</span><span class="cx">     return parseError;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-void Parser&lt;LexerType&gt;::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&amp; funcStack, 
</del><ins>+void Parser&lt;LexerType&gt;::didFinishParsing(SourceElements* sourceElements, DeclarationStacks::FunctionStack&amp;&amp; funcStack, 
</ins><span class="cx">     VariableEnvironment&amp; varDeclarations, CodeFeatures features, int numConstants)
</span><span class="cx"> {
</span><span class="cx">     m_sourceElements = sourceElements;
</span><del>-    m_funcDeclarations.swap(funcStack);
</del><ins>+    m_funcDeclarations = WTFMove(funcStack);
</ins><span class="cx">     m_varDeclarations.swap(varDeclarations);
</span><span class="cx">     m_features = features;
</span><span class="cx">     m_numConstants = numConstants;
</span><span class="lines">@@ -571,6 +571,9 @@
</span><span class="cx">         result = parseClassDeclaration(context);
</span><span class="cx">         break;
</span><span class="cx"> #endif
</span><ins>+    case FUNCTION:
+        result = parseFunctionDeclaration(context);
+        break;
</ins><span class="cx">     default:
</span><span class="cx">         m_statementDepth--; // parseStatement() increments the depth.
</span><span class="cx">         result = parseStatement(context, directive, directiveLiteralLength);
</span><span class="lines">@@ -1424,7 +1427,7 @@
</span><span class="cx">     endSwitch();
</span><span class="cx">     handleProductionOrFail(CLOSEBRACE, &quot;}&quot;, &quot;end&quot;, &quot;body of a 'switch'&quot;);
</span><span class="cx">     
</span><del>-    TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope-&gt;finalizeLexicalEnvironment());
</del><ins>+    TreeStatement result = context.createSwitchStatement(location, expr, firstClauses, defaultClause, secondClauses, startLine, endLine, lexicalScope-&gt;finalizeLexicalEnvironment(), lexicalScope-&gt;takeFunctionDeclarations());
</ins><span class="cx">     popScope(lexicalScope, TreeBuilder::NeedsFreeVariableInfo);
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="lines">@@ -1562,11 +1565,12 @@
</span><span class="cx">     int startOffset = m_token.m_data.offset;
</span><span class="cx">     int start = tokenLine();
</span><span class="cx">     VariableEnvironment emptyEnvironment;
</span><ins>+    DeclarationStacks::FunctionStack emptyFunctionStack;
</ins><span class="cx">     next();
</span><span class="cx">     if (match(CLOSEBRACE)) {
</span><span class="cx">         int endOffset = m_token.m_data.offset;
</span><span class="cx">         next();
</span><del>-        TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()-&gt;finalizeLexicalEnvironment() : emptyEnvironment);
</del><ins>+        TreeStatement result = context.createBlockStatement(location, 0, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()-&gt;finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()-&gt;takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
</ins><span class="cx">         context.setStartOffset(result, startOffset);
</span><span class="cx">         context.setEndOffset(result, endOffset);
</span><span class="cx">         if (shouldPushLexicalScope)
</span><span class="lines">@@ -1578,7 +1582,7 @@
</span><span class="cx">     matchOrFail(CLOSEBRACE, &quot;Expected a closing '}' at the end of a block statement&quot;);
</span><span class="cx">     int endOffset = m_token.m_data.offset;
</span><span class="cx">     next();
</span><del>-    TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()-&gt;finalizeLexicalEnvironment() : emptyEnvironment);
</del><ins>+    TreeStatement result = context.createBlockStatement(location, subtree, start, m_lastTokenEndPosition.line, shouldPushLexicalScope ? currentScope()-&gt;finalizeLexicalEnvironment() : emptyEnvironment, shouldPushLexicalScope ? currentScope()-&gt;takeFunctionDeclarations() : WTFMove(emptyFunctionStack));
</ins><span class="cx">     context.setStartOffset(result, startOffset);
</span><span class="cx">     context.setEndOffset(result, endOffset);
</span><span class="cx">     if (shouldPushLexicalScope)
</span><span class="lines">@@ -1607,8 +1611,10 @@
</span><span class="cx">         result = parseVariableDeclaration(context, DeclarationType::VarDeclaration);
</span><span class="cx">         break;
</span><span class="cx">     case FUNCTION:
</span><del>-        failIfFalseIfStrict(m_statementDepth == 1, &quot;Strict mode does not allow function declarations in a lexically nested statement&quot;);
-        result = parseFunctionDeclaration(context);
</del><ins>+        if (!strictMode())
+            result = parseFunctionDeclaration(context);
+        else
+            failWithMessage(&quot;Function declarations are only allowed inside blocks or switch statements in strict mode&quot;);
</ins><span class="cx">         break;
</span><span class="cx">     case SEMICOLON: {
</span><span class="cx">         JSTokenLocation location(tokenLocation());
</span><span class="lines">@@ -2121,6 +2127,9 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static NO_RETURN_DUE_TO_CRASH FunctionMetadataNode* getMetadata(ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;) { RELEASE_ASSERT_NOT_REACHED(); }
+static FunctionMetadataNode* getMetadata(ParserFunctionInfo&lt;ASTBuilder&gt;&amp; info) { return info.body; }
+
</ins><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="cx"> template &lt;class TreeBuilder&gt; TreeStatement Parser&lt;LexerType&gt;::parseFunctionDeclaration(TreeBuilder&amp; context, ExportType exportType)
</span><span class="cx"> {
</span><span class="lines">@@ -2137,15 +2146,20 @@
</span><span class="cx">     failIfFalse((parseFunctionInfo(context, FunctionNeedsName, parseMode, true, ConstructorKind::None, SuperBinding::NotNeeded, functionKeywordStart, functionInfo, FunctionDefinitionType::Declaration)), &quot;Cannot parse this function&quot;);
</span><span class="cx">     failIfFalse(functionInfo.name, &quot;Function statements must have a name&quot;);
</span><span class="cx"> 
</span><del>-    DeclarationResultMask declarationResult = declareVariable(functionInfo.name);
</del><ins>+    std::pair&lt;DeclarationResultMask, ScopeRef&gt; functionDeclaration = declareFunction(functionInfo.name);
+    DeclarationResultMask declarationResult = functionDeclaration.first;
</ins><span class="cx">     failIfTrueIfStrict(declarationResult &amp; DeclarationResult::InvalidStrictMode, &quot;Cannot declare a function named '&quot;, functionInfo.name-&gt;impl(), &quot;' in strict mode&quot;);
</span><span class="cx">     if (declarationResult &amp; DeclarationResult::InvalidDuplicateDeclaration)
</span><del>-        internalFailWithMessage(false, &quot;Cannot declare a function that shadows a let/const/class variable '&quot;, functionInfo.name-&gt;impl(), &quot;' in strict mode&quot;);
</del><ins>+        internalFailWithMessage(false, &quot;Cannot declare a function that shadows a let/const/class/function variable '&quot;, functionInfo.name-&gt;impl(), &quot;' in strict mode&quot;);
</ins><span class="cx">     if (exportType == ExportType::Exported) {
</span><span class="cx">         semanticFailIfFalse(exportName(*functionInfo.name), &quot;Cannot export a duplicate function name: '&quot;, functionInfo.name-&gt;impl(), &quot;'&quot;);
</span><span class="cx">         currentScope()-&gt;moduleScopeData().exportBinding(*functionInfo.name);
</span><span class="cx">     }
</span><del>-    return context.createFuncDeclStatement(location, functionInfo);
</del><ins>+
+    TreeStatement result = context.createFuncDeclStatement(location, functionInfo);
+    if (TreeBuilder::CreatesAST)
+        functionDeclaration.second-&gt;appendFunction(getMetadata(functionInfo));
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><span class="lines">@@ -2767,8 +2781,11 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (localName) {
</span><del>-            if (match(FUNCTION))
</del><ins>+            if (match(FUNCTION)) {
+                DepthManager statementDepth(&amp;m_statementDepth);
+                m_statementDepth = 1;
</ins><span class="cx">                 result = parseFunctionDeclaration(context);
</span><ins>+            }
</ins><span class="cx"> #if ENABLE(ES6_CLASS_SYNTAX)
</span><span class="cx">             else {
</span><span class="cx">                 ASSERT(match(CLASSTOKEN));
</span><span class="lines">@@ -2878,9 +2895,12 @@
</span><span class="cx">             result = parseVariableDeclaration(context, DeclarationType::LetDeclaration, ExportType::Exported);
</span><span class="cx">             break;
</span><span class="cx"> 
</span><del>-        case FUNCTION:
</del><ins>+        case FUNCTION: {
+            DepthManager statementDepth(&amp;m_statementDepth);
+            m_statementDepth = 1;
</ins><span class="cx">             result = parseFunctionDeclaration(context, ExportType::Exported);
</span><span class="cx">             break;
</span><ins>+        }
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(ES6_CLASS_SYNTAX)
</span><span class="cx">         case CLASSTOKEN:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -368,6 +368,37 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    DeclarationResultMask declareFunction(const Identifier* ident, bool declareAsVar)
+    {
+        ASSERT(m_allowsVarDeclarations || m_allowsLexicalDeclarations);
+        DeclarationResultMask result = DeclarationResult::Valid;
+        bool isValidStrictMode = !isEvalOrArgumentsIdentifier(m_vm, ident);
+        if (!isValidStrictMode)
+            result |= DeclarationResult::InvalidStrictMode;
+        m_isValidStrictMode = m_isValidStrictMode &amp;&amp; isValidStrictMode;
+        auto addResult = declareAsVar ? m_declaredVariables.add(ident-&gt;impl()) : m_lexicalVariables.add(ident-&gt;impl());
+        addResult.iterator-&gt;value.setIsFunction();
+        if (declareAsVar) {
+            addResult.iterator-&gt;value.setIsVar();
+            if (m_lexicalVariables.contains(ident-&gt;impl()))
+                result |= DeclarationResult::InvalidDuplicateDeclaration;
+        } else {
+            addResult.iterator-&gt;value.setIsLet();
+            ASSERT_WITH_MESSAGE(!m_declaredVariables.size(), &quot;We should only declare a function as a lexically scoped variable in scopes where var declarations aren't allowed. I.e, in strict mode and not at the top-level scope of a function or program.&quot;);
+            if (!addResult.isNewEntry) 
+                result |= DeclarationResult::InvalidDuplicateDeclaration;
+        }
+        return result;
+    }
+
+    void appendFunction(FunctionMetadataNode* node)
+    { 
+        ASSERT(node);
+        m_functionDeclarations.append(node);
+    }
+    DeclarationStacks::FunctionStack&amp;&amp; takeFunctionDeclarations() { return WTFMove(m_functionDeclarations); }
+    
+
</ins><span class="cx">     DeclarationResultMask declareLexicalVariable(const Identifier* ident, bool isConstant, DeclarationImportType importType = DeclarationImportType::NotImported)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(m_allowsLexicalDeclarations);
</span><span class="lines">@@ -691,6 +722,7 @@
</span><span class="cx">     IdentifierSet m_closedVariableCandidates;
</span><span class="cx">     IdentifierSet m_writtenVariables;
</span><span class="cx">     RefPtr&lt;ModuleScopeData&gt; m_moduleScopeData { };
</span><ins>+    DeclarationStacks::FunctionStack m_functionDeclarations;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> typedef Vector&lt;Scope, 10&gt; ScopeStack;
</span><span class="lines">@@ -923,6 +955,18 @@
</span><span class="cx">         return ScopeRef(&amp;m_scopeStack, i);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ScopeRef currentLexicalDeclarationScope()
+    {
+        unsigned i = m_scopeStack.size() - 1;
+        ASSERT(i &lt; m_scopeStack.size());
+        while (!m_scopeStack[i].allowsLexicalDeclarations()) {
+            i--;
+            ASSERT(i &lt; m_scopeStack.size());
+        }
+
+        return ScopeRef(&amp;m_scopeStack, i);
+    }
+
</ins><span class="cx">     ScopeRef currentFunctionScope()
</span><span class="cx">     {
</span><span class="cx">         unsigned i = m_scopeStack.size() - 1;
</span><span class="lines">@@ -959,7 +1003,7 @@
</span><span class="cx">         m_scopeStack.append(Scope(m_vm, isFunction, isGenerator, isStrict, isArrowFunction));
</span><span class="cx">         return currentScope();
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     void popScopeInternal(ScopeRef&amp; scope, bool shouldTrackClosedVariables)
</span><span class="cx">     {
</span><span class="cx">         ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
</span><span class="lines">@@ -1001,22 +1045,30 @@
</span><span class="cx">         if (type == DeclarationType::VarDeclaration)
</span><span class="cx">             return currentVariableScope()-&gt;declareVariable(ident);
</span><span class="cx"> 
</span><del>-        unsigned i = m_scopeStack.size() - 1;
-        ASSERT(i &lt; m_scopeStack.size());
</del><span class="cx">         ASSERT(type == DeclarationType::LetDeclaration || type == DeclarationType::ConstDeclaration);
</span><del>-
</del><span class="cx">         // Lexical variables declared at a top level scope that shadow arguments or vars are not allowed.
</span><span class="cx">         if (m_statementDepth == 1 &amp;&amp; (hasDeclaredParameter(*ident) || hasDeclaredVariable(*ident)))
</span><span class="cx">             return DeclarationResult::InvalidDuplicateDeclaration;
</span><span class="cx"> 
</span><del>-        while (!m_scopeStack[i].allowsLexicalDeclarations()) {
-            i--;
-            ASSERT(i &lt; m_scopeStack.size());
</del><ins>+        return currentLexicalDeclarationScope()-&gt;declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration, importType);
+    }
+
+    std::pair&lt;DeclarationResultMask, ScopeRef&gt; declareFunction(const Identifier* ident)
+    {
+        if (m_statementDepth == 1 || !strictMode()) {
+            // Functions declared at the top-most scope (both in sloppy and strict mode) are declared as vars
+            // for backwards compatibility. This allows us to declare functions with the same name more than once.
+            // In sloppy mode, we always declare functions as vars.
+            bool declareAsVar = true;
+            ScopeRef variableScope = currentVariableScope();
+            return std::make_pair(variableScope-&gt;declareFunction(ident, declareAsVar), variableScope);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return m_scopeStack[i].declareLexicalVariable(ident, type == DeclarationType::ConstDeclaration, importType);
</del><ins>+        bool declareAsVar = false;
+        ScopeRef lexicalVariableScope = currentLexicalDeclarationScope();
+        return std::make_pair(lexicalVariableScope-&gt;declareFunction(ident, declareAsVar), lexicalVariableScope);
</ins><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     NEVER_INLINE bool hasDeclaredVariable(const Identifier&amp; ident)
</span><span class="cx">     {
</span><span class="cx">         unsigned i = m_scopeStack.size() - 1;
</span><span class="lines">@@ -1061,7 +1113,7 @@
</span><span class="cx">     Parser();
</span><span class="cx">     String parseInner(const Identifier&amp;, SourceParseMode);
</span><span class="cx"> 
</span><del>-    void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&amp;, VariableEnvironment&amp;, CodeFeatures, int);
</del><ins>+    void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&amp;&amp;, VariableEnvironment&amp;, CodeFeatures, int);
</ins><span class="cx"> 
</span><span class="cx">     // Used to determine type of error to report.
</span><span class="cx">     bool isFunctionMetadataNode(ScopeNode*) { return false; }
</span><span class="lines">@@ -1543,7 +1595,7 @@
</span><span class="cx">                                     endColumn,
</span><span class="cx">                                     m_sourceElements,
</span><span class="cx">                                     m_varDeclarations,
</span><del>-                                    m_funcDeclarations,
</del><ins>+                                    WTFMove(m_funcDeclarations),
</ins><span class="cx">                                     currentScope()-&gt;finalizeLexicalEnvironment(),
</span><span class="cx">                                     m_parameters,
</span><span class="cx">                                     *m_source,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> #include &quot;YarrSyntaxChecker.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><del>-    
</del><ins>+
</ins><span class="cx"> class SyntaxChecker {
</span><span class="cx"> public:
</span><span class="cx">     struct BinaryExprContext {
</span><span class="lines">@@ -230,7 +230,7 @@
</span><span class="cx">     int createFuncDeclStatement(const JSTokenLocation&amp;, const ParserFunctionInfo&lt;SyntaxChecker&gt;&amp;) { return StatementResult; }
</span><span class="cx">     int createClassDeclStatement(const JSTokenLocation&amp;, ClassExpression,
</span><span class="cx">         const JSTextPosition&amp;, const JSTextPosition&amp;, int, int) { return StatementResult; }
</span><del>-    int createBlockStatement(const JSTokenLocation&amp;, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
</del><ins>+    int createBlockStatement(const JSTokenLocation&amp;, int, int, int, VariableEnvironment&amp;, DeclarationStacks::FunctionStack&amp;&amp;) { return StatementResult; }
</ins><span class="cx">     int createExprStatement(const JSTokenLocation&amp;, int, int, int) { return StatementResult; }
</span><span class="cx">     int createIfStatement(const JSTokenLocation&amp;, int, int, int, int) { return StatementResult; }
</span><span class="cx">     int createIfStatement(const JSTokenLocation&amp;, int, int, int, int, int) { return StatementResult; }
</span><span class="lines">@@ -245,7 +245,7 @@
</span><span class="cx">     int createContinueStatement(const JSTokenLocation&amp;, int, int) { return StatementResult; }
</span><span class="cx">     int createContinueStatement(const JSTokenLocation&amp;, const Identifier*, int, int) { return StatementResult; }
</span><span class="cx">     int createTryStatement(const JSTokenLocation&amp;, int, int, int, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
</span><del>-    int createSwitchStatement(const JSTokenLocation&amp;, int, int, int, int, int, int, VariableEnvironment&amp;) { return StatementResult; }
</del><ins>+    int createSwitchStatement(const JSTokenLocation&amp;, int, int, int, int, int, int, VariableEnvironment&amp;, DeclarationStacks::FunctionStack&amp;&amp;) { return StatementResult; }
</ins><span class="cx">     int createWhileStatement(const JSTokenLocation&amp;, int, int, int, int) { return StatementResult; }
</span><span class="cx">     int createWithStatement(const JSTokenLocation&amp;, int, int, int, int, int, int) { return StatementResult; }
</span><span class="cx">     int createDoWhileStatement(const JSTokenLocation&amp;, int, int, int, int) { return StatementResult; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserVariableEnvironmenth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/VariableEnvironment.h (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/VariableEnvironment.h        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/parser/VariableEnvironment.h        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx">     ALWAYS_INLINE bool isExported() const { return m_bits &amp; IsExported; }
</span><span class="cx">     ALWAYS_INLINE bool isImported() const { return m_bits &amp; IsImported; }
</span><span class="cx">     ALWAYS_INLINE bool isImportedNamespace() const { return m_bits &amp; IsImportedNamespace; }
</span><ins>+    ALWAYS_INLINE bool isFunction() const { return m_bits &amp; IsFunction; }
</ins><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void setIsCaptured() { m_bits |= IsCaptured; }
</span><span class="cx">     ALWAYS_INLINE void setIsConst() { m_bits |= IsConst; }
</span><span class="lines">@@ -48,18 +49,20 @@
</span><span class="cx">     ALWAYS_INLINE void setIsExported() { m_bits |= IsExported; }
</span><span class="cx">     ALWAYS_INLINE void setIsImported() { m_bits |= IsImported; }
</span><span class="cx">     ALWAYS_INLINE void setIsImportedNamespace() { m_bits |= IsImportedNamespace; }
</span><ins>+    ALWAYS_INLINE void setIsFunction() { m_bits |= IsFunction; }
</ins><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void clearIsVar() { m_bits &amp;= ~IsVar; }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    enum Traits {
</del><ins>+    enum Traits : uint8_t {
</ins><span class="cx">         IsCaptured = 1 &lt;&lt; 0,
</span><span class="cx">         IsConst = 1 &lt;&lt; 1,
</span><span class="cx">         IsVar = 1 &lt;&lt; 2,
</span><span class="cx">         IsLet = 1 &lt;&lt; 3,
</span><span class="cx">         IsExported = 1 &lt;&lt; 4,
</span><span class="cx">         IsImported = 1 &lt;&lt; 5,
</span><del>-        IsImportedNamespace = 1 &lt;&lt; 6
</del><ins>+        IsImportedNamespace = 1 &lt;&lt; 6,
+        IsFunction = 1 &lt;&lt; 7
</ins><span class="cx">     };
</span><span class="cx">     uint8_t m_bits { 0 };
</span><span class="cx"> };
</span><span class="lines">@@ -72,6 +75,15 @@
</span><span class="cx"> private:
</span><span class="cx">     typedef HashMap&lt;RefPtr&lt;UniquedStringImpl&gt;, VariableEnvironmentEntry, IdentifierRepHash, HashTraits&lt;RefPtr&lt;UniquedStringImpl&gt;&gt;, VariableEnvironmentEntryHashTraits&gt; Map;
</span><span class="cx"> public:
</span><ins>+    VariableEnvironment()
+    { }
+    VariableEnvironment(VariableEnvironment&amp;&amp; other)
+        : m_map(WTFMove(other.m_map))
+        , m_isEverythingCaptured(other.m_isEverythingCaptured)
+    { }
+    VariableEnvironment(const VariableEnvironment&amp; other) = default;
+    VariableEnvironment&amp; operator=(const VariableEnvironment&amp; other) = default;
+
</ins><span class="cx">     ALWAYS_INLINE Map::iterator begin() { return m_map.begin(); }
</span><span class="cx">     ALWAYS_INLINE Map::iterator end() { return m_map.end(); }
</span><span class="cx">     ALWAYS_INLINE Map::const_iterator begin() const { return m_map.begin(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestses6yaml"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/es6.yaml (197914 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/es6.yaml        2016-03-10 01:55:34 UTC (rev 197914)
+++ trunk/Source/JavaScriptCore/tests/es6.yaml        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -753,7 +753,7 @@
</span><span class="cx"> - path: es6/arrow_functions_no_prototype_property.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/block-level_function_declaration.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/destructuring_computed_properties.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/destructuring_defaults_in_parameters_separate_scope.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressblockscopedfunctiondeclarationsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/block-scoped-function-declarations.js (0 => 197915)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/block-scoped-function-declarations.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/block-scoped-function-declarations.js        2016-03-10 02:04:20 UTC (rev 197915)
</span><span class="lines">@@ -0,0 +1,227 @@
</span><ins>+&quot;use strict&quot;;
+
+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;)
+}
+
+function test(f) {
+    for (let i = 0; i &lt; 500; i++)
+        f();
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        function bar() { return 25; }
+        assert(bar() === 25);
+        {
+            function bar() { return 30; }
+            assert(bar() === 30);
+        }
+        assert(bar() === 25);
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        assert(bar() === 25);
+        {
+            assert(bar() === 30);
+            function bar() { return 30; }
+        }
+        assert(bar() === 25);
+
+        function bar() { return 25; }
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        function foo() { return bar(); }
+        function bar() { return 25; }
+        assert(bar() === 25);
+        assert(foo() === 25);
+        {
+            function bar() { return 30; }
+            function foo() { return 25; }
+            assert(bar() === 30);
+            assert(foo() === 25);
+        }
+        assert(bar() === 25);
+        assert(foo() === 25);
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        assert(bar() === 25);
+        assert(foo() === 25);
+        {
+            function bar() { return 30; }
+            function foo() { return 25; }
+            assert(bar() === 30);
+            assert(foo() === 25);
+        }
+        assert(bar() === 25);
+        assert(foo() === 25);
+
+        function foo() { return bar(); }
+        function bar() { return 25; }
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        let isDefault = false;
+        switch ('foo') {
+        case 1:
+            function foo() { return 25; }
+            break;
+        case 2:
+            function bar() { return 30; }
+            break;
+        default:
+            isDefault = true;
+            assert(foo() === 25);
+            assert(bar() === 30);
+            break;
+        }
+        assert(isDefault);
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        let is1 = false;
+        switch (1) {
+        case 1:
+            is1 = true;
+            function foo() { return 25; }
+            assert(foo() === 25);
+            assert(bar() === 30);
+            break;
+        case 2:
+            function bar() { return 30; }
+            break;
+        }
+        assert(is1);
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        function foo() { return 25; }
+        function bar() { return &quot;bar&quot;; }
+        let is2 = false;
+        switch (2) {
+        case 1: {
+            function foo() { return 30; }
+            break;
+        }
+        case 2:
+            is2 = true;
+            function bar() { return 30; }
+            assert(bar() === 30);
+            assert(foo() === 25);
+            break;
+        }
+        assert(is2);
+        assert(bar() === &quot;bar&quot;);
+        assert(foo() === 25);
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        function foo() { return 25; }
+        function bar() { return &quot;bar&quot;; }
+        let capture = () =&gt; foo + &quot;&quot; + bar;
+        let is2 = false;
+        switch (2) {
+        case 1: {
+            function foo() { return 30; }
+            break;
+        }
+        case 2:
+            is2 = true;
+            function bar() { return 30; }
+            let capture = () =&gt; bar;
+            assert(bar() === 30);
+            assert(foo() === 25);
+            break;
+        }
+        assert(is2);
+        assert(bar() === &quot;bar&quot;);
+        assert(foo() === 25);
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        let f1;
+        let f2 = foo;
+        function foo() { }
+        if (true) {
+            f1 = foo;
+            function foo() { }
+        }
+        assert(!!f1 &amp;&amp; !!f2);
+        assert(f1 !== f2);
+    }
+    test(foo);
+    assert(called);
+}
+
+{
+    let called = false;
+    function foo() {
+        called = true;
+        let f1;
+        let f2 = foo;
+        function foo() { }
+        let capture = () =&gt; foo;
+        if (true) {
+            f1 = foo;
+            function foo() { }
+            let capture = () =&gt; foo;
+        }
+        assert(!!f1 &amp;&amp; !!f2);
+        assert(f1 !== f2);
+    }
+    test(foo);
+    assert(called);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>