Bug 1296814 - Simplify increment/decrement operand checking. r=anba
authorJeff Walden <jwalden@mit.edu>
Mon, 14 Nov 2016 14:05:11 -0800
changeset 323510 05a3ca69cea33b3860c3141ee3c9ddd52258f42b
parent 323509 1ca3b35d540cca151eefdd78927dbf72ea170000
child 323511 38a15e0978e0e54fe1255eb62350e9f89d5ac25f
push id30978
push usercbook@mozilla.com
push dateMon, 21 Nov 2016 14:44:46 +0000
treeherdermozilla-central@0534254e9a40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanba
bugs1296814
milestone53.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 1296814 - Simplify increment/decrement operand checking. r=anba
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/js.msg
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -7834,38 +7834,42 @@ Parser<ParseHandler>::reportIfNotValidSi
     }
 
     reportWithNode(ParseError, pc->sc()->strict(), target, errnum, extra);
     return false;
 }
 
 template <typename ParseHandler>
 bool
-Parser<ParseHandler>::checkAndMarkAsIncOperand(Node target, AssignmentFlavor flavor)
-{
-    MOZ_ASSERT(flavor == IncrementAssignment || flavor == DecrementAssignment);
-
-    // Check.
-    if (!reportIfNotValidSimpleAssignmentTarget(target, flavor))
-        return false;
-
-    // Mark.
+Parser<ParseHandler>::checkAndMarkAsIncOperand(Node target)
+{
     if (handler.isNameAnyParentheses(target)) {
-        // Assignment to arguments/eval is allowed outside strict mode code,
-        // but it's dodgy.  Report a strict warning (error, if werror was set).
-        if (!reportIfArgumentsEvalTarget(target))
-            return false;
+        if (const char* chars = handler.nameIsArgumentsEvalAnyParentheses(target, context)) {
+            if (!reportWithNode(ParseStrictError, pc->sc()->strict(), target,
+                                JSMSG_BAD_STRICT_ASSIGN, chars))
+            {
+                return false;
+            }
+        }
+    } else if (handler.isPropertyAccess(target)) {
+        // Permitted: no additional testing/fixup needed.
     } else if (handler.isFunctionCall(target)) {
         // Assignment to function calls is forbidden in ES6.  We're still
         // somewhat concerned about sites using this in dead code, so forbid it
         // only in strict mode code (or if the werror option has been set), and
         // otherwise warn.
         if (!reportWithNode(ParseStrictError, pc->sc()->strict(), target, JSMSG_BAD_INCOP_OPERAND))
             return false;
-    }
+    } else {
+        reportWithNode(ParseError, pc->sc()->strict(), target, JSMSG_BAD_INCOP_OPERAND);
+        return false;
+    }
+
+    MOZ_ASSERT(isValidSimpleAssignmentTarget(target, PermitAssignmentToFunctionCalls),
+               "inconsistent increment/decrement operand validation");
     return true;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
 Parser<ParseHandler>::unaryOpExpr(YieldHandling yieldHandling, ParseNodeKind kind, JSOp op,
                                   uint32_t begin)
 {
@@ -7922,18 +7926,17 @@ Parser<ParseHandler>::unaryExpr(YieldHan
       case TOK_DEC:
       {
         TokenKind tt2;
         if (!tokenStream.getToken(&tt2, TokenStream::Operand))
             return null();
         Node pn2 = memberExpr(yieldHandling, TripledotProhibited, tt2);
         if (!pn2)
             return null();
-        AssignmentFlavor flavor = (tt == TOK_INC) ? IncrementAssignment : DecrementAssignment;
-        if (!checkAndMarkAsIncOperand(pn2, flavor))
+        if (!checkAndMarkAsIncOperand(pn2))
             return null();
         return handler.newUpdate((tt == TOK_INC) ? PNK_PREINCREMENT : PNK_PREDECREMENT,
                                  begin,
                                  pn2);
       }
 
       case TOK_DELETE: {
         uint32_t exprOffset;
@@ -7984,18 +7987,17 @@ Parser<ParseHandler>::unaryExpr(YieldHan
         if (!pn)
             return null();
 
         /* Don't look across a newline boundary for a postfix incop. */
         if (!tokenStream.peekTokenSameLine(&tt))
             return null();
         if (tt == TOK_INC || tt == TOK_DEC) {
             tokenStream.consumeKnownToken(tt);
-            AssignmentFlavor flavor = (tt == TOK_INC) ? IncrementAssignment : DecrementAssignment;
-            if (!checkAndMarkAsIncOperand(pn, flavor))
+            if (!checkAndMarkAsIncOperand(pn))
                 return null();
             return handler.newUpdate((tt == TOK_INC) ? PNK_POSTINCREMENT : PNK_POSTDECREMENT,
                                      begin,
                                      pn);
         }
         return pn;
       }
     }
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -1368,17 +1368,17 @@ class Parser final : private JS::AutoGCR
 
     bool isValidSimpleAssignmentTarget(Node node,
                                        FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
 
   private:
     bool reportIfArgumentsEvalTarget(Node nameNode);
     bool reportIfNotValidSimpleAssignmentTarget(Node target, AssignmentFlavor flavor);
 
-    bool checkAndMarkAsIncOperand(Node kid, AssignmentFlavor flavor);
+    bool checkAndMarkAsIncOperand(Node kid);
     bool checkStrictAssignment(Node lhs);
     bool checkStrictBinding(PropertyName* name, TokenPos pos);
 
     bool hasValidSimpleStrictParameterNames();
 
     bool isValidStrictBinding(PropertyName* name);
 
     void reportRedeclaration(HandlePropertyName name, DeclarationKind kind, TokenPos pos);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -198,17 +198,17 @@ MSG_DEF(JSMSG_BAD_DESTRUCT_DECL,       0
 MSG_DEF(JSMSG_BAD_DUP_ARGS,            0, JSEXN_SYNTAXERR, "duplicate argument names not allowed in this context")
 MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP,       0, JSEXN_SYNTAXERR, "invalid for each loop")
 MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE,        0, JSEXN_SYNTAXERR, "invalid for-in/of left-hand side")
 MSG_DEF(JSMSG_LEXICAL_DECL_DEFINES_LET,0, JSEXN_SYNTAXERR, "a lexical declaration can't define a 'let' binding")
 MSG_DEF(JSMSG_LET_STARTING_FOROF_LHS,  0, JSEXN_SYNTAXERR, "an expression X in 'for (X of Y)' must not start with 'let'")
 MSG_DEF(JSMSG_BAD_FUNCTION_YIELD,      0, JSEXN_TYPEERR,   "can't use 'yield' in a function that can return a value")
 MSG_DEF(JSMSG_BAD_GENERATOR_RETURN,    0, JSEXN_TYPEERR,   "generator function can't return a value")
 MSG_DEF(JSMSG_BAD_GENEXP_BODY,         1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression")
-MSG_DEF(JSMSG_BAD_INCOP_OPERAND,       0, JSEXN_REFERENCEERR, "invalid increment/decrement operand")
+MSG_DEF(JSMSG_BAD_INCOP_OPERAND,       0, JSEXN_SYNTAXERR, "invalid increment/decrement operand")
 MSG_DEF(JSMSG_BAD_METHOD_DEF,          0, JSEXN_SYNTAXERR, "bad method definition")
 MSG_DEF(JSMSG_BAD_OCTAL,               1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
 MSG_DEF(JSMSG_BAD_OPERAND,             1, JSEXN_SYNTAXERR, "invalid {0} operand")
 MSG_DEF(JSMSG_BAD_POW_LEFTSIDE,        0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'")
 MSG_DEF(JSMSG_BAD_PROP_ID,             0, JSEXN_SYNTAXERR, "invalid property id")
 MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD,     1, JSEXN_SYNTAXERR, "{0} not in function")
 MSG_DEF(JSMSG_BAD_STRICT_ASSIGN,       1, JSEXN_SYNTAXERR, "'{0}' can't be defined or assigned to in strict mode code")
 MSG_DEF(JSMSG_BAD_SWITCH,              0, JSEXN_SYNTAXERR, "invalid switch statement")