Bug 1296814 - Remove Parser::reportBadReturn and report simpler errors that don't use the offset of a node as location. r=arai
authorJeff Walden <jwalden@mit.edu>
Sun, 13 Nov 2016 00:11:39 -0800
changeset 322559 a09a93a0b5a9a3218fb621ee44f6cba5d1f5367e
parent 322558 9ec9d6149b5e8bc091775e67aa921738f0b5624a
child 322560 8035dbcdb2c3a3457dfbdb75752dbc67f4e54303
push id21
push usermaklebus@msu.edu
push dateThu, 01 Dec 2016 06:22:08 +0000
reviewersarai
bugs1296814
milestone52.0a1
Bug 1296814 - Remove Parser::reportBadReturn and report simpler errors that don't use the offset of a node as location. r=arai
js/src/frontend/Parser.cpp
js/src/frontend/Parser.h
js/src/js.msg
js/src/tests/js1_7/geniter/regress-352197.js
js/src/tests/js1_8/genexps/regress-683738.js
testing/xpcshell/selftest.py
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -896,31 +896,16 @@ Parser<ParseHandler>::parse()
     if (foldConstants) {
         if (!FoldConstants(context, &pn, this))
             return null();
     }
 
     return pn;
 }
 
-template <typename ParseHandler>
-bool
-Parser<ParseHandler>::reportBadReturn(Node pn, ParseReportKind kind,
-                                      unsigned errnum, unsigned anonerrnum)
-{
-    JSAutoByteString name;
-    if (JSAtom* atom = pc->functionBox()->function()->name()) {
-        if (!AtomToPrintableString(context, atom, &name))
-            return false;
-    } else {
-        errnum = anonerrnum;
-    }
-    return reportWithNode(kind, pc->sc()->strict(), pn, errnum, name.ptr());
-}
-
 /*
  * Strict mode forbids introducing new definitions for 'eval', 'arguments', or
  * for any strict mode reserved keyword.
  */
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::isValidStrictBinding(PropertyName* name)
 {
@@ -5957,20 +5942,19 @@ Parser<ParseHandler>::returnStatement(Yi
         if (!MatchOrInsertSemicolonAfterNonExpression(tokenStream))
             return null();
     }
 
     Node pn = handler.newReturnStatement(exprNode, TokenPos(begin, pos().end));
     if (!pn)
         return null();
 
+    /* Disallow "return v;" in legacy generators. */
     if (pc->isLegacyGenerator() && exprNode) {
-        /* Disallow "return v;" in legacy generators. */
-        reportBadReturn(pn, ParseError, JSMSG_BAD_GENERATOR_RETURN,
-                        JSMSG_BAD_ANON_GENERATOR_RETURN);
+        errorAt(begin, JSMSG_BAD_GENERATOR_RETURN);
         return null();
     }
 
     return pn;
 }
 
 template <typename ParseHandler>
 typename ParseHandler::Node
@@ -6075,18 +6059,17 @@ Parser<ParseHandler>::yieldExpression(In
 
         if (pc->funHasReturnExpr
 #if JS_HAS_EXPR_CLOSURES
             || pc->functionBox()->function()->isExprBody()
 #endif
             )
         {
             /* As in Python (see PEP-255), disallow return v; in generators. */
-            reportBadReturn(null(), ParseError, JSMSG_BAD_GENERATOR_RETURN,
-                            JSMSG_BAD_ANON_GENERATOR_RETURN);
+            errorAt(begin, JSMSG_BAD_FUNCTION_YIELD);
             return null();
         }
 
         pc->functionBox()->setGeneratorKind(LegacyGenerator);
         addTelemetry(JSCompartment::DeprecatedLegacyGenerator);
 
         MOZ_FALLTHROUGH;
 
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -1432,18 +1432,16 @@ class Parser final : private JS::AutoGCR
     bool checkAssignmentToCall(Node node, unsigned errnum);
 
     Node newNumber(const Token& tok) {
         return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
     }
 
     static Node null() { return ParseHandler::null(); }
 
-    bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum);
-
     JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
 
     TokenPos pos() const { return tokenStream.currentToken().pos; }
 
     bool asmJS(Node list);
 
     void addTelemetry(JSCompartment::DeprecatedLanguageExtension e);
 
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -181,31 +181,31 @@ MSG_DEF(JSMSG_UNKNOWN_FORMAT,          1
 // Frontend
 MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS,     3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}")
 MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE,     0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
 MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG,      0, JSEXN_INTERNALERR, "array initializer too large")
 MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR,    0, JSEXN_SYNTAXERR, "missing keyword 'as' after import *")
 MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD,  1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
 MSG_DEF(JSMSG_ASYNC_GENERATOR,         0, JSEXN_SYNTAXERR, "generator function or method can't be async")
 MSG_DEF(JSMSG_AWAIT_IN_DEFAULT,        0, JSEXN_SYNTAXERR, "await can't be used in default expression")
-MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
 MSG_DEF(JSMSG_BAD_ARROW_ARGS,          0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
 MSG_DEF(JSMSG_BAD_BINDING,             1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
 MSG_DEF(JSMSG_BAD_CONST_DECL,          0, JSEXN_SYNTAXERR, "missing = in const declaration")
 MSG_DEF(JSMSG_BAD_CONTINUE,            0, JSEXN_SYNTAXERR, "continue must be inside loop")
 MSG_DEF(JSMSG_BAD_DESTRUCT_ASS,        0, JSEXN_REFERENCEERR, "invalid destructuring assignment operator")
 MSG_DEF(JSMSG_BAD_DESTRUCT_TARGET,     0, JSEXN_SYNTAXERR, "invalid destructuring target")
 MSG_DEF(JSMSG_BAD_DESTRUCT_PARENS,     0, JSEXN_SYNTAXERR, "destructuring patterns in assignments can't be parenthesized")
 MSG_DEF(JSMSG_BAD_DESTRUCT_DECL,       0, JSEXN_SYNTAXERR, "missing = in destructuring declaration")
 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_GENERATOR_RETURN,    1, JSEXN_TYPEERR,   "generator function {0} returns a value")
+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_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")
--- a/js/src/tests/js1_7/geniter/regress-352197.js
+++ b/js/src/tests/js1_7/geniter/regress-352197.js
@@ -15,17 +15,17 @@ test();
 //-----------------------------------------------------------------------------
 
 function test()
 {
   enterFunc ('test');
   printBugNumber(BUGNUMBER);
   printStatus (summary);
 
-  expect = /TypeError: anonymous generator function returns a value/;
+  expect = /TypeError: can't use 'yield' in a function that can return a value/;
   try
   {
     var gen = eval('(function() { { return 5; } yield 3; })');
     actual = 'No Error';
   }
   catch(ex)
   {
     actual = ex + '';
--- a/js/src/tests/js1_8/genexps/regress-683738.js
+++ b/js/src/tests/js1_8/genexps/regress-683738.js
@@ -15,53 +15,53 @@ test();
 //-----------------------------------------------------------------------------
 
 function test()
 {
   enterFunc ('test');
   printBugNumber(BUGNUMBER);
   printStatus (summary);
 
-  expect = "generator function foo returns a value";
+  expect = "can't use 'yield' in a function that can return a value";
   try
   {
     actual = 'No Error';
     eval("function foo(x) { if (x) { return this; } else { yield 3; } }");
   }
   catch(ex)
   {
     actual = ex.message;
   }
   reportCompare(expect, actual, summary + ": 1");
 
-  expect = "generator function foo returns a value";
+  expect = "generator function can't return a value";
   try
   {
     actual = 'No Error';
     eval("function foo(x) { if (x) { yield 3; } else { return this; } }");
   }
   catch(ex)
   {
     actual = ex.message;
   }
   reportCompare(expect, actual, summary + ": 2");
 
-  expect = "generator function foo returns a value";
+  expect = "can't use 'yield' in a function that can return a value";
   try
   {
     actual = 'No Error';
     eval("function foo(x) { if (x) { return this; } else { (yield 3); } }");
   }
   catch(ex)
   {
     actual = ex.message;
   }
   reportCompare(expect, actual, summary + ": 3");
 
-  expect = "generator function foo returns a value";
+  expect = "generator function can't return a value";
   try
   {
     actual = 'No Error';
     eval("function foo(x) { if (x) { (yield 3); } else { return this; } }");
   }
   catch(ex)
   {
     actual = ex.message;
--- a/testing/xpcshell/selftest.py
+++ b/testing/xpcshell/selftest.py
@@ -1157,17 +1157,17 @@ add_test({
         Check that attempting to load a test file containing an error other
         than a syntax error generates details of the error in the log
         """
         self.writeFile("test_error.js", LOAD_ERROR_OTHER_ERROR)
         self.writeManifest(["test_error.js"])
 
         self.assertTestResult(False)
         self.assertInLog(TEST_FAIL_STRING)
-        self.assertInLog("TypeError: generator function run_test returns a value at")
+        self.assertInLog("TypeError: generator function can't return a value at")
         self.assertInLog("test_error.js:4")
         self.assertNotInLog(TEST_PASS_STRING)
 
     def testDoPrintWhenVerboseNotExplicit(self):
         """
         Check that do_print() and similar calls that generate output do
         not have the output when not run verbosely.
         """