Bug 1336783 - Part 2: Remove Parser::checkStrictBinding. r=jwalden
authorTooru Fujisawa <arai_a@mac.com>
Wed, 15 Feb 2017 23:53:05 +0900
changeset 342995 761227e357b95f345ec43df0b2be4cba88393ef4
parent 342994 476a938ee2abc89377b9451295735919c51259f9
child 342996 cbcd8c6fe6bb6ddbb38bbdf72f6365a0faeb56f2
push id87011
push userarai_a@mac.com
push dateWed, 15 Feb 2017 14:54:02 +0000
treeherdermozilla-inbound@aeca66c82a3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1336783
milestone54.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 1336783 - Part 2: Remove Parser::checkStrictBinding. r=jwalden
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -926,54 +926,16 @@ ParserBase::isValidStrictBinding(Propert
            name != context->names().arguments &&
            name != context->names().let &&
            name != context->names().static_ &&
            name != context->names().yield &&
            !IsStrictReservedWord(name);
 }
 
 /*
- * Check that it is permitted to introduce a binding for |name|. Use |pos| for
- * reporting error locations.
- */
-template <typename ParseHandler>
-bool
-Parser<ParseHandler>::checkStrictBinding(PropertyName* name, TokenPos pos)
-{
-    if (!pc->sc()->needStrictChecks())
-        return true;
-
-    if (name == context->names().arguments)
-        return strictModeErrorAt(pos.begin, JSMSG_BAD_BINDING, "arguments");
-
-    if (name == context->names().eval)
-        return strictModeErrorAt(pos.begin, JSMSG_BAD_BINDING, "eval");
-
-    if (name == context->names().let) {
-        errorAt(pos.begin, JSMSG_RESERVED_ID, "let");
-        return false;
-    }
-
-    if (name == context->names().static_) {
-        errorAt(pos.begin, JSMSG_RESERVED_ID, "static");
-        return false;
-    }
-
-    if (name == context->names().yield) {
-        errorAt(pos.begin, JSMSG_RESERVED_ID, "yield");
-        return false;
-    }
-
-    if (IsStrictReservedWord(name))
-        return strictModeErrorAt(pos.begin, JSMSG_RESERVED_ID, ReservedWordToCharZ(name));
-
-    return true;
-}
-
-/*
  * Returns true if all parameter names are valid strict mode binding names and
  * no duplicate parameter names are present.
  */
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::hasValidSimpleStrictParameterNames()
 {
     MOZ_ASSERT(pc->isFunctionBox() && pc->functionBox()->hasSimpleParameterList());
@@ -1044,19 +1006,16 @@ Parser<ParseHandler>::notePositionalForm
         ReportOutOfMemory(context);
         return false;
     }
 
     Node paramNode = newName(name);
     if (!paramNode)
         return false;
 
-    if (!checkStrictBinding(name, pos()))
-        return false;
-
     handler.addFunctionFormalParameter(fn, paramNode);
     return true;
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::noteDestructuredPositionalFormalParameter(Node fn, Node destruct)
 {
@@ -1307,19 +1266,16 @@ bool
 Parser<ParseHandler>::noteDeclaredName(HandlePropertyName name, DeclarationKind kind,
                                        TokenPos pos)
 {
     // The asm.js validator does all its own symbol-table management so, as an
     // optimization, avoid doing any work here.
     if (pc->useAsmOrInsideUseAsm())
         return true;
 
-    if (!checkStrictBinding(name, pos))
-        return false;
-
     switch (kind) {
       case DeclarationKind::Var:
       case DeclarationKind::BodyLevelFunction:
       case DeclarationKind::ForOfVar: {
         Maybe<DeclarationKind> redeclaredKind;
         if (!tryDeclareVar(name, kind, &redeclaredKind))
             return false;
 
@@ -3521,18 +3477,36 @@ Parser<ParseHandler>::functionFormalPara
     // Whereas the |yield| in the function body is always parsed as a name.
     YieldHandling bodyYieldHandling = GetYieldHandling(pc->generatorKind(), pc->asyncKind());
     Node body = functionBody(inHandling, bodyYieldHandling, kind, bodyType);
     if (!body)
         return false;
 
     if ((kind != Method && !IsConstructorKind(kind)) && fun->explicitName()) {
         RootedPropertyName propertyName(context, fun->explicitName()->asPropertyName());
-        if (!checkStrictBinding(propertyName, handler.getPosition(pn)))
-            return false;
+        // `await` cannot be checked at this point because of different context.
+        // It should already be checked before this point.
+        if (propertyName != context->names().await) {
+            YieldHandling nameYieldHandling;
+            if (kind == Expression) {
+                // Named lambda has binding inside it.
+                nameYieldHandling = bodyYieldHandling;
+            } else {
+                // Otherwise YieldHandling cannot be checked at this point
+                // because of different context.
+                // It should already be checked before this point.
+                nameYieldHandling = YieldIsName;
+            }
+
+            if (!checkBindingIdentifier(propertyName, handler.getPosition(pn).begin,
+                                        nameYieldHandling))
+            {
+                return false;
+            }
+        }
     }
 
     if (bodyType == StatementListBody) {
         bool matched;
         if (!tokenStream.matchToken(&matched, TOK_RC, TokenStream::Operand))
             return false;
         if (!matched) {
             error(JSMSG_CURLY_AFTER_BODY);
@@ -4091,16 +4065,19 @@ Parser<FullParseHandler>::checkDestructu
         // Destructuring patterns in declarations must only contain
         // unparenthesized names.
         if (!handler.isUnparenthesizedName(expr)) {
             errorAt(expr->pn_pos.begin, JSMSG_NO_VARIABLE_NAME);
             return false;
         }
 
         RootedPropertyName name(context, expr->name());
+        // `yield` is already checked, so pass YieldIsName to skip that check.
+        if (!checkBindingIdentifier(name, expr->pn_pos.begin, YieldIsName))
+            return false;
         return noteDeclaredName(name, *maybeDecl, expr->pn_pos);
     }
 
     // Otherwise this is an expression in destructuring outside a declaration.
     if (handler.isNameAnyParentheses(expr)) {
         if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(expr, context)) {
             if (!strictModeErrorAt(expr->pn_pos.begin, JSMSG_BAD_STRICT_ASSIGN, chars))
                 return false;
@@ -8028,17 +8005,17 @@ Parser<ParseHandler>::comprehensionFor(G
 
     uint32_t begin = pos().begin;
 
     MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
 
     // FIXME: Destructuring binding (bug 980828).
 
     MUST_MATCH_TOKEN_FUNC(TokenKindIsPossibleIdentifier, JSMSG_NO_VARIABLE_NAME);
-    RootedPropertyName name(context, tokenStream.currentName());
+    RootedPropertyName name(context, bindingIdentifier(YieldIsKeyword));
     if (name == context->names().let) {
         error(JSMSG_LET_COMP_BINDING);
         return null();
     }
     TokenPos namePos = pos();
     Node lhs = newName(name);
     if (!lhs)
         return null();
@@ -8551,22 +8528,26 @@ Parser<ParseHandler>::newName(PropertyNa
 template <typename ParseHandler>
 PropertyName*
 Parser<ParseHandler>::checkLabelOrIdentifierReference(PropertyName* ident,
                                                       uint32_t offset,
                                                       YieldHandling yieldHandling)
 {
     if (ident == context->names().yield) {
         if (yieldHandling == YieldIsKeyword ||
-            pc->sc()->strict() ||
             versionNumber() >= JSVERSION_1_7)
         {
             errorAt(offset, JSMSG_RESERVED_ID, "yield");
             return nullptr;
         }
+        if (pc->sc()->needStrictChecks()) {
+            if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "yield"))
+                return nullptr;
+        }
+
         return ident;
     }
 
     if (ident == context->names().await) {
         if (awaitIsKeyword()) {
             errorAt(offset, JSMSG_RESERVED_ID, "await");
             return nullptr;
         }
@@ -8578,30 +8559,59 @@ Parser<ParseHandler>::checkLabelOrIdenti
         return nullptr;
     }
 
     if (IsFutureReservedWord(ident)) {
         errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(ident));
         return nullptr;
     }
 
-    if (pc->sc()->strict()) {
+    if (pc->sc()->needStrictChecks()) {
         if (IsStrictReservedWord(ident)) {
-            errorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(ident));
-            return nullptr;
+            if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, ReservedWordToCharZ(ident)))
+                return nullptr;
+            return ident;
         }
 
         if (ident == context->names().let) {
-            errorAt(offset, JSMSG_RESERVED_ID, "let");
-            return nullptr;
+            if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "let"))
+                return nullptr;
+            return ident;
         }
 
         if (ident == context->names().static_) {
-            errorAt(offset, JSMSG_RESERVED_ID, "static");
-            return nullptr;
+            if (!strictModeErrorAt(offset, JSMSG_RESERVED_ID, "static"))
+                return nullptr;
+            return ident;
+        }
+    }
+
+    return ident;
+}
+
+template <typename ParseHandler>
+PropertyName*
+Parser<ParseHandler>::checkBindingIdentifier(PropertyName* ident,
+                                             uint32_t offset,
+                                             YieldHandling yieldHandling)
+{
+    if (!checkLabelOrIdentifierReference(ident, offset, yieldHandling))
+        return nullptr;
+
+    if (pc->sc()->needStrictChecks()) {
+        if (ident == context->names().arguments) {
+            if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "arguments"))
+                return nullptr;
+            return ident;
+        }
+
+        if (ident == context->names().eval) {
+            if (!strictModeErrorAt(offset, JSMSG_BAD_STRICT_ASSIGN, "eval"))
+                return nullptr;
+            return ident;
         }
     }
 
     return ident;
 }
 
 template <typename ParseHandler>
 PropertyName*
@@ -8616,33 +8626,17 @@ Parser<ParseHandler>::labelOrIdentifierR
 
     return checkLabelOrIdentifierReference(tokenStream.currentName(), pos().begin, yieldHandling);
 }
 
 template <typename ParseHandler>
 PropertyName*
 Parser<ParseHandler>::bindingIdentifier(YieldHandling yieldHandling)
 {
-    PropertyName* ident = labelOrIdentifierReference(yieldHandling);
-    if (!ident)
-        return nullptr;
-
-    if (pc->sc()->strict()) {
-        if (ident == context->names().arguments) {
-            error(JSMSG_BAD_STRICT_ASSIGN, "arguments");
-            return nullptr;
-        }
-
-        if (ident == context->names().eval) {
-            error(JSMSG_BAD_STRICT_ASSIGN, "eval");
-            return nullptr;
-        }
-    }
-
-    return ident;
+    return checkBindingIdentifier(tokenStream.currentName(), pos().begin, yieldHandling);
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::identifierReference(Handle<PropertyName*> name)
 {
     Node pn = newName(name);
     if (!pn)
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -1325,16 +1325,20 @@ class Parser final : public ParserBase, 
     enum ClassContext { ClassStatement, ClassExpression };
     Node classDefinition(YieldHandling yieldHandling, ClassContext classContext,
                          DefaultHandling defaultHandling);
 
     PropertyName* checkLabelOrIdentifierReference(PropertyName* ident,
                                                   uint32_t offset,
                                                   YieldHandling yieldHandling);
 
+    PropertyName* checkBindingIdentifier(PropertyName* ident,
+                                         uint32_t offset,
+                                         YieldHandling yieldHandling);
+
     PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling);
 
     PropertyName* labelIdentifier(YieldHandling yieldHandling) {
         return labelOrIdentifierReference(yieldHandling);
     }
 
     PropertyName* identifierReference(YieldHandling yieldHandling) {
         return labelOrIdentifierReference(yieldHandling);
@@ -1392,17 +1396,16 @@ class Parser final : public ParserBase, 
     };
 
     bool isValidSimpleAssignmentTarget(Node node,
                                        FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
 
   private:
     bool checkIncDecOperand(Node operand, uint32_t operandOffset);
     bool checkStrictAssignment(Node lhs);
-    bool checkStrictBinding(PropertyName* name, TokenPos pos);
 
     bool hasValidSimpleStrictParameterNames();
 
     void reportRedeclaration(HandlePropertyName name, DeclarationKind kind, TokenPos pos);
     bool notePositionalFormalParameter(Node fn, HandlePropertyName name,
                                        bool disallowDuplicateParams, bool* duplicatedParam);
     bool noteDestructuredPositionalFormalParameter(Node fn, Node destruct);
     mozilla::Maybe<DeclarationKind> isVarRedeclaredInEval(HandlePropertyName name,