Bug 1296814 - Move FunctionDeclaration-as-consequent/alternative handling out of Parser::functionStmt into Parser::consequentOrAlternative. r=anba
authorJeff Walden <jwalden@mit.edu>
Tue, 08 Nov 2016 10:35:11 -0800
changeset 322553 c770f757dbc645e8a300406d5a9f4021a61ba958
parent 322552 7b5162f3e8c63ccf2f9055f7b88f75c3a4ce4e91
child 322554 d2ee58a58aa76762f06903a48c505370776ca913
push id21
push usermaklebus@msu.edu
push dateThu, 01 Dec 2016 06:22:08 +0000
reviewersanba
bugs1296814
milestone52.0a1
Bug 1296814 - Move FunctionDeclaration-as-consequent/alternative handling out of Parser::functionStmt into Parser::consequentOrAlternative. r=anba
js/src/frontend/Parser.cpp
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -3563,31 +3563,16 @@ Parser<ParseHandler>::functionFormalPara
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling,
                                    FunctionAsyncKind asyncKind)
 {
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
 
-    // Annex B.3.4 says we can parse function declarations unbraced under if
-    // or else as if it were braced. That is, |if (x) function f() {}| is
-    // parsed as |if (x) { function f() {} }|.
-    Maybe<ParseContext::Statement> synthesizedStmtForAnnexB;
-    Maybe<ParseContext::Scope> synthesizedScopeForAnnexB;
-    if (!pc->sc()->strict()) {
-        ParseContext::Statement* stmt = pc->innermostStatement();
-        if (stmt && stmt->kind() == StatementKind::If) {
-            synthesizedStmtForAnnexB.emplace(pc, StatementKind::Block);
-            synthesizedScopeForAnnexB.emplace(this);
-            if (!synthesizedScopeForAnnexB->init(pc))
-                return null();
-        }
-    }
-
     RootedPropertyName name(context);
     GeneratorKind generatorKind = asyncKind == AsyncFunction ? StarGenerator : NotGenerator;
     TokenKind tt;
     if (!tokenStream.getToken(&tt))
         return null();
 
     if (tt == TOK_MUL) {
         if (asyncKind != SyncFunction) {
@@ -3608,30 +3593,18 @@ Parser<ParseHandler>::functionStmt(Yield
         tokenStream.ungetToken();
     } else {
         /* Unnamed function expressions are forbidden in statement context. */
         error(JSMSG_UNNAMED_FUNCTION_STMT);
         return null();
     }
 
     YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind);
-    Node fun = functionDefinition(InAllowed, newYieldHandling, name, Statement, generatorKind,
-                                  asyncKind, PredictUninvoked);
-    if (!fun)
-        return null();
-
-    if (synthesizedStmtForAnnexB) {
-        Node synthesizedStmtList = handler.newStatementList(handler.getPosition(fun));
-        if (!synthesizedStmtList)
-            return null();
-        handler.addStatementToList(synthesizedStmtList, fun);
-        return finishLexicalScope(*synthesizedScopeForAnnexB, synthesizedStmtList);
-    }
-
-    return fun;
+    return functionDefinition(InAllowed, newYieldHandling, name, Statement, generatorKind,
+                              asyncKind, PredictUninvoked);
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::functionExpr(InvokedPrediction invoked, FunctionAsyncKind asyncKind)
 {
     MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FUNCTION));
 
@@ -5246,23 +5219,42 @@ template <class ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::consequentOrAlternative(YieldHandling yieldHandling)
 {
     TokenKind next;
     if (!tokenStream.peekToken(&next, TokenStream::Operand))
         return null();
 
     if (next == TOK_FUNCTION) {
-        // Apply Annex B.3.4 in non-strict code to allow FunctionDeclaration as
-        // the consequent/alternative of an |if| or |else|.  Parser::statement
-        // will report the strict mode error.
+        // Annex B.3.4 says that unbraced function declarations under if/else
+        // in non-strict code act as if they were braced. That is,
+        // |if (x) function f() {}| is parsed as |if (x) { function f() {} }|.
         if (!pc->sc()->strict()) {
             tokenStream.consumeKnownToken(next, TokenStream::Operand);
-            return functionStmt(yieldHandling, NameRequired);
-        }
+
+            ParseContext::Statement stmt(pc, StatementKind::Block);
+            ParseContext::Scope scope(this);
+            if (!scope.init(pc))
+                return null();
+
+            TokenPos funcPos = pos();
+            Node fun = functionStmt(yieldHandling, NameRequired);
+            if (!fun)
+                return null();
+
+            Node block = handler.newStatementList(funcPos);
+            if (!block)
+                return null();
+
+            handler.addStatementToList(block, fun);
+            return finishLexicalScope(scope, block);
+        }
+
+        // Function declarations are a syntax error in strict mode code.
+        // Parser::statement reports that error.
     }
 
     return statement(yieldHandling);
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::ifStatement(YieldHandling yieldHandling)