Bug 1359575 - Report SyntaxError if GeneratorDeclaration/AsyncFunctionDeclaration is redeclared in block-scope. r=shu
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 15 May 2017 12:08:59 -0700
changeset 406654 cb4c204b5fcd8bd7c6f2ea3e8d6f82dccf247df1
parent 406653 c63d8286d4548cd385947dc8c4895800b1e793f2
child 406655 0fe9a65a0786e52a8a4f5c72ee633f2df998ac6b
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1359575
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1359575 - Report SyntaxError if GeneratorDeclaration/AsyncFunctionDeclaration is redeclared in block-scope. r=shu
js/src/frontend/NameAnalysisTypes.h
js/src/frontend/Parser.cpp
--- a/js/src/frontend/NameAnalysisTypes.h
+++ b/js/src/frontend/NameAnalysisTypes.h
@@ -75,16 +75,17 @@ enum class DeclarationKind : uint8_t
     Var,
     ForOfVar,
     Let,
     Const,
     Import,
     BodyLevelFunction,
     ModuleBodyLevelFunction,
     LexicalFunction,
+    SloppyLexicalFunction,
     VarForAnnexBLexicalFunction,
     SimpleCatchParameter,
     CatchParameter
 };
 
 static inline BindingKind
 DeclarationKindToBindingKind(DeclarationKind kind)
 {
@@ -98,16 +99,17 @@ DeclarationKindToBindingKind(Declaration
       case DeclarationKind::BodyLevelFunction:
       case DeclarationKind::ModuleBodyLevelFunction:
       case DeclarationKind::VarForAnnexBLexicalFunction:
       case DeclarationKind::ForOfVar:
         return BindingKind::Var;
 
       case DeclarationKind::Let:
       case DeclarationKind::LexicalFunction:
+      case DeclarationKind::SloppyLexicalFunction:
       case DeclarationKind::SimpleCatchParameter:
       case DeclarationKind::CatchParameter:
         return BindingKind::Let;
 
       case DeclarationKind::Const:
         return BindingKind::Const;
 
       case DeclarationKind::Import:
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -118,16 +118,17 @@ DeclarationKindString(DeclarationKind ki
         return "let";
       case DeclarationKind::Const:
         return "const";
       case DeclarationKind::Import:
         return "import";
       case DeclarationKind::BodyLevelFunction:
       case DeclarationKind::ModuleBodyLevelFunction:
       case DeclarationKind::LexicalFunction:
+      case DeclarationKind::SloppyLexicalFunction:
         return "function";
       case DeclarationKind::VarForAnnexBLexicalFunction:
         return "annex b var";
       case DeclarationKind::ForOfVar:
         return "var in for-of";
       case DeclarationKind::SimpleCatchParameter:
       case DeclarationKind::CatchParameter:
         return "catch parameter";
@@ -1321,17 +1322,17 @@ ParseContext::tryDeclareVarHelper(Handle
             } else if (!DeclarationKindIsParameter(declaredKind)) {
                 // Annex B.3.5 allows redeclaring simple (non-destructured)
                 // catch parameters with var declarations, except when it
                 // appears in a for-of.
                 bool annexB35Allowance = declaredKind == DeclarationKind::SimpleCatchParameter &&
                                          kind != DeclarationKind::ForOfVar;
 
                 // Annex B.3.3 allows redeclaring functions in the same block.
-                bool annexB33Allowance = declaredKind == DeclarationKind::LexicalFunction &&
+                bool annexB33Allowance = declaredKind == DeclarationKind::SloppyLexicalFunction &&
                                          kind == DeclarationKind::VarForAnnexBLexicalFunction &&
                                          scope == innermostScope();
 
                 if (!annexB35Allowance && !annexB33Allowance) {
                     *redeclaredKind = Some(declaredKind);
                     *prevPos = p->value()->pos();
                     return true;
                 }
@@ -1482,29 +1483,42 @@ Parser<ParseHandler, CharT>::noteDeclare
 
         if (!pc->functionScope().addDeclaredName(pc, p, name, kind, pos.begin))
             return false;
 
         break;
       }
 
       case DeclarationKind::LexicalFunction: {
+        ParseContext::Scope* scope = pc->innermostScope();
+        if (AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name)) {
+            reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
+            return false;
+        } else {
+            if (!scope->addDeclaredName(pc, p, name, kind, pos.begin))
+                return false;
+        }
+
+        break;
+      }
+
+      case DeclarationKind::SloppyLexicalFunction: {
         // Functions in block have complex allowances in sloppy mode for being
         // labelled that other lexical declarations do not have. Those checks
         // are more complex than calling checkLexicalDeclarationDirectlyWithin-
         // Block and are done in checkFunctionDefinition.
 
         ParseContext::Scope* scope = pc->innermostScope();
         if (AddDeclaredNamePtr p = scope->lookupDeclaredNameForAdd(name)) {
             // It is usually an early error if there is another declaration
             // with the same name in the same scope.
             //
-            // In sloppy mode, lexical functions may redeclare other lexical
+            // Sloppy lexical functions may redeclare other sloppy lexical
             // functions for web compatibility reasons.
-            if (pc->sc()->strict() || p->value()->kind() != DeclarationKind::LexicalFunction) {
+            if (p->value()->kind() != DeclarationKind::SloppyLexicalFunction) {
                 reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
                 return false;
             }
         } else {
             if (!scope->addDeclaredName(pc, p, name, kind, pos.begin))
                 return false;
         }
 
@@ -3852,47 +3866,46 @@ Parser<ParseHandler, CharT>::functionStm
         tokenStream.ungetToken();
     } else {
         /* Unnamed function expressions are forbidden in statement context. */
         error(JSMSG_UNNAMED_FUNCTION_STMT);
         return null();
     }
 
     // Note the declared name and check for early errors.
-    bool tryAnnexB = false;
+    DeclarationKind kind;
     if (declaredInStmt) {
         MOZ_ASSERT(declaredInStmt->kind() != StatementKind::Label);
         MOZ_ASSERT(StatementKindIsBraced(declaredInStmt->kind()));
 
-        if (!pc->sc()->strict() && generatorKind == NotGenerator && asyncKind == SyncFunction) {
-            // Under sloppy mode, try Annex B.3.3 semantics. If making an
-            // additional 'var' binding of the same name does not throw an
-            // early error, do so. This 'var' binding would be assigned
-            // the function object when its declaration is reached, not at
-            // the start of the block.
-            //
-            // This semantics is implemented upon Scope exit in
-            // Scope::propagateAndMarkAnnexBFunctionBoxes.
-            tryAnnexB = true;
-        }
-
-        if (!noteDeclaredName(name, DeclarationKind::LexicalFunction, pos()))
-            return null();
+        kind = !pc->sc()->strict() && generatorKind == NotGenerator && asyncKind == SyncFunction
+               ? DeclarationKind::SloppyLexicalFunction
+               : DeclarationKind::LexicalFunction;
     } else {
-        DeclarationKind kind = pc->atModuleLevel()
-                               ? DeclarationKind::ModuleBodyLevelFunction
-                               : DeclarationKind::BodyLevelFunction;
-        if (!noteDeclaredName(name, kind, pos()))
-            return null();
-    }
+        kind = pc->atModuleLevel()
+               ? DeclarationKind::ModuleBodyLevelFunction
+               : DeclarationKind::BodyLevelFunction;
+    }
+
+    if (!noteDeclaredName(name, kind, pos()))
+        return null();
 
     Node pn = handler.newFunctionStatement(pos());
     if (!pn)
         return null();
 
+    // Under sloppy mode, try Annex B.3.3 semantics. If making an additional
+    // 'var' binding of the same name does not throw an early error, do so.
+    // This 'var' binding would be assigned the function object when its
+    // declaration is reached, not at the start of the block.
+    //
+    // This semantics is implemented upon Scope exit in
+    // Scope::propagateAndMarkAnnexBFunctionBoxes.
+    bool tryAnnexB = kind == DeclarationKind::SloppyLexicalFunction;
+
     YieldHandling newYieldHandling = GetYieldHandling(generatorKind);
     return functionDefinition(pn, toStringStart, InAllowed, newYieldHandling, name, Statement,
                               generatorKind, asyncKind, tryAnnexB);
 }
 
 template <template <typename CharT> class ParseHandler, typename CharT>
 typename ParseHandler<CharT>::Node
 Parser<ParseHandler, CharT>::functionExpr(uint32_t toStringStart, InvokedPrediction invoked,