Bug 1384299 - Provide better error message when errornous syntax possibly match "yield SOMETHING" outside generators. r=till
authorTooru Fujisawa <arai_a@mac.com>
Thu, 27 Jul 2017 23:17:09 +0900
changeset 420308 dc186bad8bd537919a15722a1a79dd46660f95f1
parent 420307 ef5feef07bed07583c52e434dbc5e4b9a2545deb
child 420309 795aeb51da2b9b2b3667b58ca02e477657253478
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1384299
milestone56.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 1384299 - Provide better error message when errornous syntax possibly match "yield SOMETHING" outside generators. r=till
js/src/frontend/Parser.cpp
js/src/js.msg
js/src/tests/ecma_6/Generators/yield-error.js
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2924,16 +2924,20 @@ Parser<ParseHandler, CharT>::matchOrInse
          *
          * Detect this situation and throw an understandable error.  Otherwise
          * we'd throw a confusing "missing ; before statement" error.
          */
         if (!pc->isAsync() && tokenStream.currentToken().type == TOK_AWAIT) {
             error(JSMSG_AWAIT_OUTSIDE_ASYNC);
             return false;
         }
+        if (!yieldExpressionsSupported() && tokenStream.currentToken().type == TOK_YIELD) {
+            error(JSMSG_YIELD_OUTSIDE_GENERATOR);
+            return false;
+        }
 
         /* Advance the scanner for proper error location reporting. */
         tokenStream.consumeKnownToken(tt, modifier);
         error(JSMSG_SEMI_BEFORE_STMNT);
         return false;
     }
     bool matched;
     if (!tokenStream.matchToken(&matched, TOK_SEMI, modifier))
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -348,16 +348,17 @@ MSG_DEF(JSMSG_UNTERMINATED_REGEXP,     0
 MSG_DEF(JSMSG_UNTERMINATED_STRING,     0, JSEXN_SYNTAXERR, "unterminated string literal")
 MSG_DEF(JSMSG_USELESS_EXPR,            0, JSEXN_TYPEERR, "useless expression")
 MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL,  0, JSEXN_SYNTAXERR, "\"use asm\" is only meaningful in the Directive Prologue of a function body")
 MSG_DEF(JSMSG_VAR_HIDES_ARG,           1, JSEXN_TYPEERR, "variable {0} redeclares argument")
 MSG_DEF(JSMSG_WHILE_AFTER_DO,          0, JSEXN_SYNTAXERR, "missing while after do-loop body")
 MSG_DEF(JSMSG_YIELD_IN_ARROW,          0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
 MSG_DEF(JSMSG_YIELD_IN_DEFAULT,        0, JSEXN_SYNTAXERR, "yield in default expression")
 MSG_DEF(JSMSG_YIELD_IN_METHOD,         0, JSEXN_SYNTAXERR, "non-generator method definitions may not contain yield")
+MSG_DEF(JSMSG_YIELD_OUTSIDE_GENERATOR, 0, JSEXN_SYNTAXERR, "yield expression is only valid in generators")
 MSG_DEF(JSMSG_BAD_COLUMN_NUMBER,       0, JSEXN_RANGEERR, "column number out of range")
 MSG_DEF(JSMSG_COMPUTED_NAME_IN_PATTERN,0, JSEXN_SYNTAXERR, "computed property names aren't supported in this destructuring declaration")
 MSG_DEF(JSMSG_DEFAULT_IN_PATTERN,      0, JSEXN_SYNTAXERR, "destructuring defaults aren't supported in this destructuring declaration")
 MSG_DEF(JSMSG_BAD_NEWTARGET,           0, JSEXN_SYNTAXERR, "new.target only allowed within functions")
 MSG_DEF(JSMSG_ESCAPED_KEYWORD,         0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes")
 
 // asm.js
 MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL,       1, JSEXN_TYPEERR, "asm.js type error: {0}")
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Generators/yield-error.js
@@ -0,0 +1,32 @@
+var BUGNUMBER = 1384299;
+var summary = "yield outside of generators should provide better error";
+
+print(BUGNUMBER + ": " + summary);
+
+let caught = false;
+try {
+    eval("yield 10");
+} catch(e) {
+    assertEq(e.message, "yield expression is only valid in generators");
+    caught = true;
+}
+assertEq(caught, true);
+
+try {
+    eval("function f() { yield 10; }");
+} catch(e) {
+    assertEq(e.message, "yield expression is only valid in generators");
+    caught = true;
+}
+assertEq(caught, true);
+
+try {
+    eval("async function f() { yield 10; }");
+} catch(e) {
+    assertEq(e.message, "yield expression is only valid in generators");
+    caught = true;
+}
+assertEq(caught, true);
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);