Repository: jshint/jshint
Pull request #3427 (2019-09-15 19:12:01)

Re-implement `yield` parsing improvements
@caitp @rwaldron This is the latest in the series of rewrites (the prior patches along these lines were 6759ac902928c32e0c798134abe1fbd1353ad3a3 and gh-3419).

Since the first commit intentionally regresses functionality, we should definitely use a merge commit to land this branch.


Commit messages:

>     [[FIX]] Improve parsing of `yield`
>
>     Re-implement the improvements reverted by the previous commit. Use
>     distinct logic to differentiate this new implementation, including the
>     following substantive improvements:
>
>     - Correct the reported location of warning W093 ("Did you mean to return
>       a conditional instead of an assignment?")
>     - Permit the use of `yield` as an identifier outside of strict mode and
>       generator function bodies
>     - Remove inaccurate restriction on `yield` within Mozilla generator
>       functions
>     - Forward the context when parsing computed property names
>
>     [[CHORE]] Revert `yield` expression improvements
>
>     JSHint's parsing of `yield` expressions is derived from code first
>     contributed by GitHub user "usrbincc." That user could not be reached to
>     sign JSHint's Contributor License Agreement. Revert the user's
>     contribution to the application logic (preserving the corresponding
>     MIT-licensed test code) so that it may be re-written under the terms of
>     the Contributor License Agreement.
>
>     Revert the changes introduced by
>     88c862df3dba9e2cfa1e44d4be909099d8306c97

coveralls: 
[![Coverage Status](https://coveralls.io/builds/25724252/badge)](https://coveralls.io/builds/25724252)

Coverage decreased (-0.07%) to 99.933% when pulling **56bb87166200313b46084bcce7a96e2b8c067692 on jugglinmike:revert-yield-6** into **38285cd78346ff0194e5b080af565f3143476255 on jshint:master**.

jugglinmike: I've rebased this against the `v2.11.0` branch so that we can trial it via a release candidate.
jugglinmike: @rwaldron I'm thinking that since no one is actively working on the `v2.11.0` feature branch, I should rebase that on `master` before we merge this. What do you think?
rwaldron: @jugglinmike I trust your intuition 👍 
jugglinmike: That's much appreciated, Rick. This is rebased and ready for review.

Patch:
diff --git a/src/jshint.js b/src/jshint.js
index 277fc078..a4c99f61 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -179,6 +179,10 @@ var JSHINT = (function() {
       return false;
     }
 
+    if (token.id === "yield" && (!(context & prodParams.yield))) {
+      return state.isStrict();
+    }
+
     return true;
   }
 
@@ -892,9 +896,11 @@ var JSHINT = (function() {
     if (next.id === "in" && context & prodParams.noin) {
       return true;
     }
+
     if (next.id === ";" || next.id === "}" || next.id === ":") {
       return true;
     }
+
     if (next.infix === curr.infix || curr.ltBoundary === "after" ||
       next.ltBoundary === "before") {
       return curr.line !== startLine(next);
@@ -1022,26 +1028,21 @@ var JSHINT = (function() {
     }
   }
 
-  function nobreakcomma(left, right) {
-    if (left.line !== startLine(right)) {
-      if (!state.option.laxcomma) {
-        if (parseComma.first) {
-          warning("I001");
-          parseComma.first = false;
-        }
-        warning("W014", left, right.value);
-      }
-    }
-  }
-
   function parseComma(opts) {
     opts = opts || {};
 
     if (!opts.peek) {
-      nobreakcomma(state.tokens.curr, state.tokens.next);
+      if (state.tokens.curr.line !== startLine(state.tokens.next)) {
+        if (!state.option.laxcomma) {
+          if (parseComma.first) {
+            warning("I001");
+            parseComma.first = false;
+          }
+          warning("W014", state.tokens.curr, state.tokens.next.value);
+        }
+      }
+
       advance(",");
-    } else {
-      nobreakcomma(state.tokens.prev, state.tokens.curr);
     }
 
     if (state.tokens.next.identifier && !(opts.property && state.inES5())) {
@@ -1239,7 +1240,7 @@ var JSHINT = (function() {
    *                     support cases where further refinement is necessary)
    */
   function type(s, f) {
-    var x = delim(s);
+    var x = symbol(s, 0);
     x.type = s;
     x.nud = f;
     return x;
@@ -1617,13 +1618,11 @@ var JSHINT = (function() {
    * @param {function} [f] - a function to be invoked that consumes the
    *                         right-hand side of the operator (see the `infix`
    *                         function)
-   * @param {number} p - the left-binding power of the token as used by the
-   *                     Pratt parsing semantics
    *
    * @returns {object} - the object describing the JSHint symbol (provided to
    *                     support cases where further refinement is necessary)
    */
-  function assignop(s, f, p) {
+  function assignop(s, f) {
     var x = infix(s, typeof f === "function" ? f : function(context, left, that) {
       that.left = left;
 
@@ -1632,10 +1631,11 @@ var JSHINT = (function() {
       that.right = expression(context, 10);
 
       return that;
-    }, p);
+    }, 20);
 
     x.exps = true;
     x.assign = true;
+
     return x;
   }
 
@@ -1676,7 +1676,8 @@ var JSHINT = (function() {
    *                     support cases where further refinement is necessary)
    */
   function bitwiseassignop(s) {
-    return assignop(s, function(context, left, that) {
+    symbol(s, 20).exps = true;
+    return infix(s, function(context, left, that) {
       if (state.option.bitwise) {
         warning("W016", that, that.id);
       }
@@ -2352,15 +2353,15 @@ var JSHINT = (function() {
     return this;
   });
 
-  assignop("=", "assign", 20);
-  assignop("+=", "assignadd", 20);
-  assignop("-=", "assignsub", 20);
-  assignop("*=", "assignmult", 20);
-  assignop("/=", "assigndiv", 20).nud = function() {
+  assignop("=", "assign");
+  assignop("+=", "assignadd");
+  assignop("-=", "assignsub");
+  assignop("*=", "assignmult");
+  assignop("/=", "assigndiv").nud = function() {
     /* istanbul ignore next */
     error("E014");
   };
-  assignop("%=", "assignmod", 20);
+  assignop("%=", "assignmod");
   assignop("**=", function(context, left, that) {
     if (!state.inES7()) {
       warning("W119", that, "Exponentiation operator", "7");
@@ -2373,7 +2374,7 @@ var JSHINT = (function() {
     that.right = expression(context, 10);
 
     return that;
-  }, 20);
+  });
 
   bitwiseassignop("&=");
   bitwiseassignop("|=");
@@ -3609,7 +3610,7 @@ var JSHINT = (function() {
       "(context)"   : null,
       "(scope)"     : null,
       "(comparray)" : null,
-      "(generator)" : null,
+      "(yielded)"   : null,
       "(arrow)"     : null,
       "(async)"     : null,
       "(params)"    : null
@@ -3732,6 +3733,12 @@ var JSHINT = (function() {
     } else {
       context &= ~prodParams.async;
     }
+
+    if (isGenerator) {
+      context |= prodParams.yield;
+    } else if (!isArrow) {
+      context &= ~prodParams.yield;
+    }
     context &= ~prodParams.preAsync;
 
     state.option = Object.create(state.option);
@@ -3742,7 +3749,6 @@ var JSHINT = (function() {
       "(context)":   state.funct,
       "(arrow)":     isArrow,
       "(method)":    isMethod,
-      "(generator)": isGenerator,
       "(async)":     isAsync
     });
 
@@ -3784,6 +3790,8 @@ var JSHINT = (function() {
     }
 
     if (isArrow) {
+      context &= ~prodParams.yield;
+
       if (!state.inES6(true)) {
         warning("W119", state.tokens.curr, "arrow function syntax (=>)", "6");
       }
@@ -3795,8 +3803,7 @@ var JSHINT = (function() {
 
     block(context, false, true, true, isArrow);
 
-    if (!state.option.noyield && isGenerator &&
-        state.funct["(generator)"] !== "yielded") {
+    if (!state.option.noyield && isGenerator && !state.funct["(yielded)"]) {
       warning("W124", state.tokens.curr);
     }
 
@@ -3999,7 +4006,7 @@ var JSHINT = (function() {
           }
 
           if (state.tokens.next.id === "[") {
-            i = computedPropertyName();
+            i = computedPropertyName(context);
           } else {
             i = propertyName(context);
 
@@ -4701,6 +4708,10 @@ var JSHINT = (function() {
       type: generator ? "generator" : null
     });
 
+    if (generator && nameToken && nameToken.value === "yield") {
+      error("E024", nameToken, "yield");
+    }
+
     if (nameToken && (f["(name)"] === "arguments" || f["(name)"] === "eval") &&
       f["(isStrict)"]) {
       error("E008", nameToken);
@@ -5311,7 +5322,7 @@ var JSHINT = (function() {
         if (this.first &&
             this.first.type === "(punctuator)" && this.first.value === "=" &&
             !this.first.paren && !state.option.boss) {
-          warningAt("W093", this.first.line, this.first.character);
+          warning("W093", this.first);
         }
 
         if (state.option.noreturnawait && context & prodParams.async &&
@@ -5406,14 +5417,20 @@ var JSHINT = (function() {
     return state.syntax["(identifier)"].nud.apply(this, arguments);
   })));
 
-  (function(x) {
-    x.exps = true;
-    x.lbp = x.rbp = 25;
-    x.ltBoundary = "after";
-  }(prefix("yield", function(context) {
+  (function(yieldSymbol) {
+    yieldSymbol.rbp = yieldSymbol.lbp = 25;
+    yieldSymbol.exps = true;
+    yieldSymbol.ltBoundary = "after";
+  })(prefix("yield", function(context) {
     if (state.inMoz()) {
       return mozYield.call(this, context);
     }
+
+    if (!(context & prodParams.yield)) {
+      this.exps = false;
+      return state.syntax["(identifier)"].nud.apply(this, arguments);
+    }
+
     var prev = state.tokens.prev;
 
     // If the parameters of the current function scope have not been defined,
@@ -5427,15 +5444,10 @@ var JSHINT = (function() {
       error("E061", this);
     }
 
-    if (state.inES6(true) && !state.funct["(generator)"]) {
-      // If it's a yield within a catch clause inside a generator then that's ok
-      if (!("(catch)" === state.funct["(name)"] && state.funct["(context)"]["(generator)"])) {
-        error("E046", state.tokens.curr, "yield");
-      }
-    } else if (!state.inES6()) {
+    if (!state.inES6()) {
       warning("W104", state.tokens.curr, "yield", "6");
     }
-    state.funct["(generator)"] = "yielded";
+    state.funct["(yielded)"] = true;
 
     if (state.tokens.next.value === "*") {
       advance("*");
@@ -5450,7 +5462,7 @@ var JSHINT = (function() {
 
         if (this.first.type === "(punctuator)" && this.first.value === "=" &&
             !this.first.paren && !state.option.boss) {
-          warningAt("W093", this.first.line, this.first.character);
+          warning("W093", this.first);
         }
       } else if (state.tokens.next.led) {
         if (state.tokens.next.id !== ",") {
@@ -5460,7 +5472,7 @@ var JSHINT = (function() {
     }
 
     return this;
-  })));
+  }));
 
   /**
    * Parsing logic for non-standard Mozilla implementation of `yield`
@@ -5468,13 +5480,10 @@ var JSHINT = (function() {
    */
   var mozYield = function(context) {
     var prev = state.tokens.prev;
-    if (state.inES6(true) && !state.funct["(generator)"]) {
-      // If it's a yield within a catch clause inside a generator then that's ok
-      if (!("(catch)" === state.funct["(name)"] && state.funct["(context)"]["(generator)"])) {
-        error("E046", state.tokens.curr, "yield");
-      }
+    if (state.inES6(true) && !(context & prodParams.yield)) {
+      error("E046", state.tokens.curr, "yield");
     }
-    state.funct["(generator)"] = "yielded";
+    state.funct["(yielded)"] = true;
     var delegatingYield = false;
 
     if (state.tokens.next.value === "*") {
@@ -5492,12 +5501,11 @@ var JSHINT = (function() {
 
         if (this.first.type === "(punctuator)" && this.first.value === "=" &&
             !this.first.paren && !state.option.boss) {
-          warningAt("W093", this.first.line, this.first.character);
+          warning("W093", this.first);
         }
       }
-
       if (state.tokens.next.id !== ")" &&
-          (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === "yield")) {
+          (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()))) {
         error("E050", this);
       }
     } else if (!state.option.asi) {
diff --git a/src/prod-params.js b/src/prod-params.js
index 61cc8c0f..c9842c36 100644
--- a/src/prod-params.js
+++ b/src/prod-params.js
@@ -39,5 +39,10 @@ module.exports = {
    * Enabled when any exception thrown by the expression will be caught by a
    * TryStatement.
    */
-  tryClause: 32
+  tryClause: 32,
+
+  /**
+   * Enabled when parsing the body of a generator function.
+   */
+  yield: 64
 };


Test patch:
diff --git a/tests/test262/expectations.txt b/tests/test262/expectations.txt
index 37e9238b..468e0aab 100644
--- a/tests/test262/expectations.txt
+++ b/tests/test262/expectations.txt
@@ -157,7 +157,6 @@ test/language/global-code/import.js(default)
 test/language/global-code/import.js(strict mode)
 test/language/global-code/return.js(default)
 test/language/global-code/return.js(strict mode)
-test/language/global-code/yield-non-strict.js(default)
 test/language/identifiers/part-digits-via-escape-hex.js(default)
 test/language/identifiers/part-digits-via-escape-hex.js(strict mode)
 test/language/identifiers/val-dollar-sign-via-escape-hex.js(default)
@@ -228,13 +227,11 @@ test/language/expressions/template-literal/invalid-hexidecimal-character-escape-
 test/language/expressions/template-literal/invalid-legacy-octal-escape-sequence.js(default)
 test/language/expressions/template-literal/tv-utf16-escape-sequence.js(default)
 test/language/expressions/template-literal/tv-utf16-escape-sequence.js(strict mode)
-test/language/expressions/function/param-dflt-yield-non-strict.js(default)
 test/language/expressions/function/scope-param-rest-elem-var-close.js(default)
 test/language/expressions/function/scope-param-rest-elem-var-open.js(default)
 test/language/expressions/generators/scope-param-rest-elem-var-close.js(default)
 test/language/expressions/generators/scope-param-rest-elem-var-open.js(default)
 test/language/expressions/generators/yield-as-function-expression-binding-identifier.js(default)
-test/language/expressions/generators/yield-as-identifier-in-nested-function.js(default)
 test/language/expressions/generators/yield-as-logical-or-expression.js(default)
 test/language/expressions/generators/yield-as-logical-or-expression.js(strict mode)
 test/language/expressions/generators/yield-star-after-newline.js(default)
@@ -245,28 +242,17 @@ test/language/expressions/object/scope-gen-meth-param-rest-elem-var-close.js(def
 test/language/expressions/object/scope-gen-meth-param-rest-elem-var-open.js(default)
 test/language/expressions/object/scope-meth-param-rest-elem-var-close.js(default)
 test/language/expressions/object/scope-meth-param-rest-elem-var-open.js(default)
-test/language/expressions/object/yield-non-strict-access.js(default)
-test/language/expressions/object/yield-non-strict-syntax.js(default)
-test/language/expressions/object/method-definition/generator-prop-name-yield-expr.js(default)
-test/language/expressions/object/method-definition/generator-prop-name-yield-id.js(default)
-test/language/expressions/object/method-definition/name-param-id-yield.js(default)
-test/language/expressions/object/method-definition/name-param-init-yield.js(default)
-test/language/expressions/object/method-definition/name-prop-name-yield-expr.js(default)
-test/language/expressions/object/method-definition/name-prop-name-yield-id.js(default)
 test/language/expressions/object/method-definition/yield-as-expression-with-rhs.js(default)
 test/language/expressions/object/method-definition/yield-as-expression-with-rhs.js(strict mode)
 test/language/expressions/object/method-definition/yield-as-expression-without-rhs.js(default)
 test/language/expressions/object/method-definition/yield-as-expression-without-rhs.js(strict mode)
 test/language/expressions/object/method-definition/yield-as-function-expression-binding-identifier.js(default)
-test/language/expressions/object/method-definition/yield-as-identifier-in-nested-function.js(default)
 test/language/expressions/object/method-definition/yield-as-logical-or-expression.js(default)
 test/language/expressions/object/method-definition/yield-as-logical-or-expression.js(strict mode)
 test/language/expressions/object/method-definition/yield-star-after-newline.js(default)
 test/language/expressions/object/method-definition/yield-star-after-newline.js(strict mode)
 test/language/expressions/arrow-function/scope-param-rest-elem-var-close.js(default)
 test/language/expressions/arrow-function/scope-param-rest-elem-var-open.js(default)
-test/language/expressions/arrow-function/syntax/arrowparameters-bindingidentifier-yield.js(default)
-test/language/expressions/arrow-function/syntax/arrowparameters-cover-formalparameters-yield.js(default)
 test/language/expressions/arrow-function/syntax/early-errors/asi-restriction-invalid-parenless-parameters-expression-body.js(default)
 test/language/expressions/arrow-function/syntax/early-errors/asi-restriction-invalid-parenless-parameters-expression-body.js(strict mode)
 test/language/expressions/arrow-function/syntax/early-errors/asi-restriction-invalid-parenless-parameters.js(default)
@@ -315,8 +301,6 @@ test/language/statements/if/if-stmt-else-gen.js(strict mode)
 test/language/statements/generators/scope-param-rest-elem-var-close.js(default)
 test/language/statements/generators/scope-param-rest-elem-var-open.js(default)
 test/language/statements/generators/yield-as-function-expression-binding-identifier.js(default)
-test/language/statements/generators/yield-as-generator-declaration-binding-identifier.js(default)
-test/language/statements/generators/yield-as-identifier-in-nested-function.js(default)
 test/language/statements/generators/yield-as-logical-or-expression.js(default)
 test/language/statements/generators/yield-as-logical-or-expression.js(strict mode)
 test/language/statements/generators/yield-star-after-newline.js(default)
@@ -332,8 +316,6 @@ test/language/statements/labeled/decl-gen.js(default)
 test/language/statements/labeled/decl-gen.js(strict mode)
 test/language/statements/labeled/decl-let.js(default)
 test/language/statements/labeled/decl-let.js(strict mode)
-test/language/statements/labeled/value-yield-non-strict.js(default)
-test/language/statements/function/param-dflt-yield-non-strict.js(default)
 test/language/statements/function/scope-param-rest-elem-var-close.js(default)
 test/language/statements/function/scope-param-rest-elem-var-open.js(default)
 test/language/statements/return/S12.9_A1_T1.js(default)
@@ -1189,17 +1171,11 @@ test/language/statements/async-generator/dflt-params-ref-later.js(default)
 test/language/statements/async-generator/dflt-params-ref-later.js(strict mode)
 test/language/statements/async-generator/dflt-params-ref-self.js(default)
 test/language/statements/async-generator/dflt-params-ref-self.js(strict mode)
-test/language/statements/async-generator/yield-identifier-non-strict.js(default)
-test/language/statements/async-generator/yield-identifier-spread-non-strict.js(default)
 
 test/language/expressions/generators/dflt-params-ref-later.js(default)
 test/language/expressions/generators/dflt-params-ref-later.js(strict mode)
 test/language/expressions/generators/dflt-params-ref-self.js(default)
 test/language/expressions/generators/dflt-params-ref-self.js(strict mode)
-test/language/expressions/generators/named-yield-identifier-non-strict.js(default)
-test/language/expressions/generators/named-yield-identifier-spread-non-strict.js(default)
-test/language/expressions/generators/yield-identifier-non-strict.js(default)
-test/language/expressions/generators/yield-identifier-spread-non-strict.js(default)
 test/language/expressions/async-generator/dflt-params-ref-later.js(default)
 test/language/expressions/async-generator/dflt-params-ref-later.js(strict mode)
 test/language/expressions/async-generator/dflt-params-ref-self.js(default)
@@ -1208,23 +1184,16 @@ test/language/expressions/async-generator/named-dflt-params-ref-later.js(default
 test/language/expressions/async-generator/named-dflt-params-ref-later.js(strict mode)
 test/language/expressions/async-generator/named-dflt-params-ref-self.js(default)
 test/language/expressions/async-generator/named-dflt-params-ref-self.js(strict mode)
-test/language/expressions/async-generator/named-yield-identifier-non-strict.js(default)
-test/language/expressions/async-generator/named-yield-identifier-spread-non-strict.js(default)
-test/language/expressions/async-generator/yield-identifier-non-strict.js(default)
-test/language/expressions/async-generator/yield-identifier-spread-non-strict.js(default)
 test/language/expressions/function/dflt-params-ref-later.js(default)
 test/language/expressions/function/dflt-params-ref-later.js(strict mode)
 test/language/expressions/function/dflt-params-ref-self.js(default)
 test/language/expressions/function/dflt-params-ref-self.js(strict mode)
-test/language/expressions/object/accessor-name-computed-yield-id.js(default)
 test/language/expressions/object/accessor-name-literal-string-unicode-escape.js(default)
 test/language/expressions/object/accessor-name-literal-string-unicode-escape.js(strict mode)
 test/language/expressions/object/method-definition/async-gen-meth-dflt-params-ref-later.js(default)
 test/language/expressions/object/method-definition/async-gen-meth-dflt-params-ref-later.js(strict mode)
 test/language/expressions/object/method-definition/async-gen-meth-dflt-params-ref-self.js(default)
 test/language/expressions/object/method-definition/async-gen-meth-dflt-params-ref-self.js(strict mode)
-test/language/expressions/object/method-definition/async-gen-yield-identifier-non-strict.js(default)
-test/language/expressions/object/method-definition/async-gen-yield-identifier-spread-non-strict.js(default)
 test/language/expressions/object/method-definition/async-meth-dflt-params-ref-later.js(default)
 test/language/expressions/object/method-definition/async-meth-dflt-params-ref-later.js(strict mode)
 test/language/expressions/object/method-definition/async-meth-dflt-params-ref-self.js(default)
@@ -1233,8 +1202,6 @@ test/language/expressions/object/method-definition/gen-meth-dflt-params-ref-late
 test/language/expressions/object/method-definition/gen-meth-dflt-params-ref-later.js(strict mode)
 test/language/expressions/object/method-definition/gen-meth-dflt-params-ref-self.js(default)
 test/language/expressions/object/method-definition/gen-meth-dflt-params-ref-self.js(strict mode)
-test/language/expressions/object/method-definition/gen-yield-identifier-non-strict.js(default)
-test/language/expressions/object/method-definition/gen-yield-identifier-spread-non-strict.js(default)
 test/language/expressions/object/method-definition/meth-dflt-params-ref-later.js(default)
 test/language/expressions/object/method-definition/meth-dflt-params-ref-later.js(strict mode)
 test/language/expressions/object/method-definition/meth-dflt-params-ref-self.js(default)
@@ -1256,8 +1223,6 @@ test/language/statements/generators/dflt-params-ref-later.js(default)
 test/language/statements/generators/dflt-params-ref-later.js(strict mode)
 test/language/statements/generators/dflt-params-ref-self.js(default)
 test/language/statements/generators/dflt-params-ref-self.js(strict mode)
-test/language/statements/generators/yield-identifier-non-strict.js(default)
-test/language/statements/generators/yield-identifier-spread-non-strict.js(default)
 
 test/language/export/escaped-as-export-specifier.js(default)
 test/language/export/escaped-as-export-specifier.js(strict mode)
@@ -1594,7 +1559,6 @@ test/annexB/language/comments/single-line-html-close-unicode-separators.js(stric
 test/annexB/language/function-code/function-redeclaration-block.js(default)
 test/intl402/Intl/getCanonicalLocales/non-iana-canon.js(default)
 test/intl402/Intl/getCanonicalLocales/non-iana-canon.js(strict mode)
-test/language/expressions/arrow-function/param-dflt-yield-id-non-strict.js(default)
 test/language/expressions/class/constructor-this-tdz-during-initializers.js(default)
 test/language/expressions/class/constructor-this-tdz-during-initializers.js(strict mode)
 test/language/expressions/dynamic-import/always-create-new-promise.js(default)
@@ -1729,18 +1693,6 @@ test/language/statements/class/static-classelementname-abrupt-completion.js(defa
 test/language/statements/class/static-classelementname-abrupt-completion.js(strict mode)
 test/language/statements/for/let-block-with-newline.js(default)
 test/language/statements/for/let-identifier-with-newline.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-array-elem-init-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-array-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-array-elem-nested-obj-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-array-elem-target-yield-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-array-rest-nested-array-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-array-rest-nested-obj-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-array-rest-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-obj-id-init-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-obj-prop-elem-init-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-obj-prop-elem-target-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-obj-prop-nested-array-yield-ident-valid.js(default)
-test/language/statements/for-await-of/async-func-decl-dstr-obj-prop-nested-obj-yield-ident-valid.js(default)
 test/language/statements/for-await-of/async-func-decl-dstr-obj-rest-to-property-with-setter.js(default)
 test/language/statements/for-await-of/async-func-decl-dstr-obj-rest-to-property-with-setter.js(strict mode)
 test/language/statements/for-await-of/async-func-decl-dstr-obj-rest-to-property.js(default)
@@ -1767,7 +1719,6 @@ test/language/statements/for-of/let-block-with-newline.js(default)
 test/language/statements/for-of/let-identifier-with-newline.js(default)
 test/language/statements/if/let-block-with-newline.js(default)
 test/language/statements/if/let-identifier-with-newline.js(default)
-test/language/statements/labeled/value-yield-non-strict-escaped.js(default)
 test/language/statements/while/let-block-with-newline.js(default)
 test/language/statements/while/let-identifier-with-newline.js(default)
 test/language/statements/with/let-block-with-newline.js(default)
@@ -1829,7 +1780,6 @@ test/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-style-short.js(def
 test/intl402/RelativeTimeFormat/prototype/formatToParts/en-us-style-short.js(strict mode)
 test/intl402/RelativeTimeFormat/prototype/formatToParts/value-tonumber.js(default)
 test/intl402/RelativeTimeFormat/prototype/formatToParts/value-tonumber.js(strict mode)
-test/language/expressions/assignment/dstr/array-elem-init-yield-ident-valid.js(default)
 test/language/expressions/assignment/dstr/array-elem-iter-rtrn-close-err.js(default)
 test/language/expressions/assignment/dstr/array-elem-iter-rtrn-close-err.js(strict mode)
 test/language/expressions/assignment/dstr/array-elem-iter-thrw-close-err.js(default)
@@ -1838,11 +1788,8 @@ test/language/expressions/assignment/dstr/array-elem-iter-thrw-close.js(default)
 test/language/expressions/assignment/dstr/array-elem-iter-thrw-close.js(strict mode)
 test/language/expressions/assignment/dstr/array-elem-nested-array-yield-expr.js(default)
 test/language/expressions/assignment/dstr/array-elem-nested-array-yield-expr.js(strict mode)
-test/language/expressions/assignment/dstr/array-elem-nested-array-yield-ident-valid.js(default)
-test/language/expressions/assignment/dstr/array-elem-nested-obj-yield-ident-valid.js(default)
 test/language/expressions/assignment/dstr/array-elem-target-yield-expr.js(default)
 test/language/expressions/assignment/dstr/array-elem-target-yield-expr.js(strict mode)
-test/language/expressions/assignment/dstr/array-elem-target-yield-valid.js(default)
 test/language/expressions/assignment/dstr/array-elem-trlg-iter-list-thrw-close-err.js(default)
 test/language/expressions/assignment/dstr/array-elem-trlg-iter-list-thrw-close-err.js(strict mode)
 test/language/expressions/assignment/dstr/array-elem-trlg-iter-list-thrw-close.js(default)
@@ -1873,19 +1820,10 @@ test/language/expressions/assignment/dstr/array-rest-nested-array-iter-thrw-clos
 test/language/expressions/assignment/dstr/array-rest-nested-array-iter-thrw-close-skip.js(strict mode)
 test/language/expressions/assignment/dstr/array-rest-nested-array-yield-expr.js(default)
 test/language/expressions/assignment/dstr/array-rest-nested-array-yield-expr.js(strict mode)
-test/language/expressions/assignment/dstr/array-rest-nested-array-yield-ident-valid.js(default)
-test/language/expressions/assignment/dstr/array-rest-nested-obj-yield-ident-valid.js(default)
 test/language/expressions/assignment/dstr/array-rest-yield-expr.js(default)
 test/language/expressions/assignment/dstr/array-rest-yield-expr.js(strict mode)
-test/language/expressions/assignment/dstr/array-rest-yield-ident-valid.js(default)
-test/language/expressions/assignment/dstr/obj-id-identifier-yield-ident-valid.js(default)
-test/language/expressions/assignment/dstr/obj-id-init-yield-ident-valid.js(default)
-test/language/expressions/assignment/dstr/obj-prop-elem-init-yield-ident-valid.js(default)
 test/language/expressions/assignment/dstr/obj-prop-elem-target-yield-expr.js(default)
 test/language/expressions/assignment/dstr/obj-prop-elem-target-yield-expr.js(strict mode)
-test/language/expressions/assignment/dstr/obj-prop-elem-target-yield-ident-valid.js(default)
-test/language/expressions/assignment/dstr/obj-prop-nested-array-yield-ident-valid.js(default)
-test/language/expressions/assignment/dstr/obj-prop-nested-obj-yield-ident-valid.js(default)
 test/language/expressions/assignment/dstr/obj-rest-to-property-with-setter.js(default)
 test/language/expressions/assignment/dstr/obj-rest-to-property-with-setter.js(strict mode)
 test/language/expressions/assignment/dstr/obj-rest-to-property.js(default)
@@ -8402,7 +8340,6 @@ test/language/statements/class/method-static/dflt-params-ref-later.js(default)
 test/language/statements/class/method-static/dflt-params-ref-later.js(strict mode)
 test/language/statements/class/method-static/dflt-params-ref-self.js(default)
 test/language/statements/class/method-static/dflt-params-ref-self.js(strict mode)
-test/language/statements/for-of/dstr/array-elem-init-yield-ident-valid.js(default)
 test/language/statements/for-of/dstr/array-elem-iter-rtrn-close-err.js(default)
 test/language/statements/for-of/dstr/array-elem-iter-rtrn-close-err.js(strict mode)
 test/language/statements/for-of/dstr/array-elem-iter-thrw-close-err.js(default)
@@ -8411,11 +8348,8 @@ test/language/statements/for-of/dstr/array-elem-iter-thrw-close.js(default)
 test/language/statements/for-of/dstr/array-elem-iter-thrw-close.js(strict mode)
 test/language/statements/for-of/dstr/array-elem-nested-array-yield-expr.js(default)
 test/language/statements/for-of/dstr/array-elem-nested-array-yield-expr.js(strict mode)
-test/language/statements/for-of/dstr/array-elem-nested-array-yield-ident-valid.js(default)
-test/language/statements/for-of/dstr/array-elem-nested-obj-yield-ident-valid.js(default)
 test/language/statements/for-of/dstr/array-elem-target-yield-expr.js(default)
 test/language/statements/for-of/dstr/array-elem-target-yield-expr.js(strict mode)
-test/language/statements/for-of/dstr/array-elem-target-yield-valid.js(default)
 test/language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close-err.js(default)
 test/language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close-err.js(strict mode)
 test/language/statements/for-of/dstr/array-elem-trlg-iter-list-thrw-close.js(default)
@@ -8446,19 +8380,10 @@ test/language/statements/for-of/dstr/array-rest-nested-array-iter-thrw-close-ski
 test/language/statements/for-of/dstr/array-rest-nested-array-iter-thrw-close-skip.js(strict mode)
 test/language/statements/for-of/dstr/array-rest-nested-array-yield-expr.js(default)
 test/language/statements/for-of/dstr/array-rest-nested-array-yield-expr.js(strict mode)
-test/language/statements/for-of/dstr/array-rest-nested-array-yield-ident-valid.js(default)
-test/language/statements/for-of/dstr/array-rest-nested-obj-yield-ident-valid.js(default)
 test/language/statements/for-of/dstr/array-rest-yield-expr.js(default)
 test/language/statements/for-of/dstr/array-rest-yield-expr.js(strict mode)
-test/language/statements/for-of/dstr/array-rest-yield-ident-valid.js(default)
-test/language/statements/for-of/dstr/obj-id-identifier-yield-ident-valid.js(default)
-test/language/statements/for-of/dstr/obj-id-init-yield-ident-valid.js(default)
-test/language/statements/for-of/dstr/obj-prop-elem-init-yield-ident-valid.js(default)
 test/language/statements/for-of/dstr/obj-prop-elem-target-yield-expr.js(default)
 test/language/statements/for-of/dstr/obj-prop-elem-target-yield-expr.js(strict mode)
-test/language/statements/for-of/dstr/obj-prop-elem-target-yield-ident-valid.js(default)
-test/language/statements/for-of/dstr/obj-prop-nested-array-yield-ident-valid.js(default)
-test/language/statements/for-of/dstr/obj-prop-nested-obj-yield-ident-valid.js(default)
 test/language/statements/for-of/dstr/obj-rest-to-property-with-setter.js(default)
 test/language/statements/for-of/dstr/obj-rest-to-property-with-setter.js(strict mode)
 test/language/statements/for-of/dstr/obj-rest-to-property.js(default)
diff --git a/tests/unit/core.js b/tests/unit/core.js
index 2ebb3c72..ba126e69 100644
--- a/tests/unit/core.js
+++ b/tests/unit/core.js
@@ -391,7 +391,7 @@ exports.returnStatement = function (test) {
   var src = fs.readFileSync(__dirname + '/fixtures/return.js', 'utf8');
 
   TestRun(test)
-    .addError(3, 15, "Did you mean to return a conditional instead of an assignment?")
+    .addError(3, 14, "Did you mean to return a conditional instead of an assignment?")
     .addError(38, 5, "Line breaking error 'return'.")
     .addError(38, 11, "Missing semicolon.")
     .addError(39, 7, "Unnecessary semicolon.")
diff --git a/tests/unit/options.js b/tests/unit/options.js
index 0ea9b95a..d1b8687b 100644
--- a/tests/unit/options.js
+++ b/tests/unit/options.js
@@ -1689,8 +1689,8 @@ exports.boss = function (test) {
     .addError(25, 25, 'Expected a conditional expression and instead saw an assignment.')
 
     // GH-670
-    .addError(28, 13, "Did you mean to return a conditional instead of an assignment?")
-    .addError(32, 15, "Did you mean to return a conditional instead of an assignment?")
+    .addError(28, 12, "Did you mean to return a conditional instead of an assignment?")
+    .addError(32, 14, "Did you mean to return a conditional instead of an assignment?")
     .test(src, {es3: true});
 
   // But if you are the boss, all is good
diff --git a/tests/unit/parser.js b/tests/unit/parser.js
index ce0077b7..96eb8f24 100644
--- a/tests/unit/parser.js
+++ b/tests/unit/parser.js
@@ -4193,8 +4193,10 @@ exports["mozilla generator as esnext"] = function (test) {
     "  print(g.next());"
   ];
   TestRun(test)
-    .addError(4, 5,
-     "Yield expressions may only occur within generator functions.")
+    .addError(4, 5, "Expected an assignment or function call and instead saw an expression.")
+    .addError(4, 10, "Missing semicolon.")
+    .addError(4, 11, "Expected an assignment or function call and instead saw an expression.")
+    .addError(4, 5, "'yield' is not defined.")
     .test(code, {esnext: true, unused: true, undef: true, predef: ["print", "Iterator"]});
 
   TestRun(test)
@@ -4373,7 +4375,10 @@ exports["mozilla generator as es5"] = function (test) {
     "  print(g.next());"
   ];
   TestRun(test)
-    .addError(4, 5, "'yield' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
+    .addError(4, 5, "Expected an assignment or function call and instead saw an expression.")
+    .addError(4, 10, "Missing semicolon.")
+    .addError(4, 11, "Expected an assignment or function call and instead saw an expression.")
+    .addError(4, 5, "'yield' is not defined.")
     .addError(5, 5, "'destructuring assignment' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
     .addError(9, 6, "'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
     .test(code, {unused: true, undef: true, predef: ["print", "Iterator"]}); // es5
@@ -4396,7 +4401,10 @@ exports["mozilla generator as legacy JS"] = function (test) {
     "  print(g.next());"
   ];
   TestRun(test)
-    .addError(4, 5, "'yield' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
+    .addError(4, 5, "Expected an assignment or function call and instead saw an expression.")
+    .addError(4, 10, "Missing semicolon.")
+    .addError(4, 11, "Expected an assignment or function call and instead saw an expression.")
+    .addError(4, 5, "'yield' is not defined.")
     .addError(5, 5, "'destructuring assignment' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
     .addError(9, 6, "'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
     .test(code, {es3: true, unused: true, undef: true, predef: ["print", "Iterator"]});
@@ -4583,7 +4591,10 @@ exports["moz-style array comprehension as esnext"] = function (test) {
     "print('evens:', evens);"
   ];
   TestRun(test)
-    .addError(3, 5, "Yield expressions may only occur within generator functions.")
+    .addError(3, 5, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 10, "Missing semicolon.")
+    .addError(3, 11, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 5, "'yield' is not defined.")
     .addError(6, 20, "Expected 'for' and instead saw 'i'.")
     .addError(6, 30, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")
     .addError(7, 14, "Expected 'for' and instead saw 'i'.")
@@ -4636,7 +4647,10 @@ exports["moz-style array comprehension as es5"] = function (test) {
   ];
   TestRun(test)
     .addError(2, 8, "'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
-    .addError(3, 5, "'yield' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
+    .addError(3, 5, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 10, "Missing semicolon.")
+    .addError(3, 11, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 5, "'yield' is not defined.")
     .addError(6, 19, "'array comprehension' is only available in Mozilla JavaScript extensions (use moz option).")
     .addError(6, 20, "Expected 'for' and instead saw 'i'.")
     .addError(6, 30, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")
@@ -4663,7 +4677,10 @@ exports["array comprehension as legacy JS"] = function (test) {
   ];
   TestRun(test)
     .addError(2, 8, "'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
-    .addError(3, 5, "'yield' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
+    .addError(3, 5, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 10, "Missing semicolon.")
+    .addError(3, 11, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 5, "'yield' is not defined.")
     .addError(6, 19, "'array comprehension' is only available in Mozilla JavaScript extensions (use moz option).")
     .addError(7, 13, "'array comprehension' is only available in Mozilla JavaScript extensions (use moz option).")
     .test(code, {es3: true, unused: true, undef: true, predef: ["print"]});
@@ -4686,7 +4703,11 @@ exports["moz-style array comprehension as legacy JS"] = function (test) {
   ];
   TestRun(test)
     .addError(2, 8, "'let' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
-    .addError(3, 5, "'yield' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).")
+    .addError(3, 5, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 10, "Missing semicolon.")
+    .addError(3, 11, "Expected an assignment or function call and instead saw an expression.")
+    .addError(3, 5, "'yield' is not defined.")
+
     .addError(6, 19, "'array comprehension' is only available in Mozilla JavaScript extensions (use moz option).")
     .addError(6, 20, "Expected 'for' and instead saw 'i'.")
     .addError(6, 30, "'for each' is only available in Mozilla JavaScript extensions (use moz option).")
@@ -5994,7 +6015,7 @@ exports["regression test for crash from GH-964"] = function (test) {
 
   TestRun(test)
     .addError(2, 23, "Bad assignment.")
-    .addError(2, 24, "Did you mean to return a conditional instead of an assignment?")
+    .addError(2, 23, "Did you mean to return a conditional instead of an assignment?")
     .test(code);
 
   test.done();
@@ -7580,9 +7601,9 @@ exports["test 'yield' in compound expressions."] = function (test) {
   var run = TestRun(test);
 
   run
-    .addError(22, 15, "Did you mean to return a conditional instead of an assignment?")
+    .addError(22, 14, "Did you mean to return a conditional instead of an assignment?")
     .addError(23, 22, "Invalid position for 'yield' expression (consider wrapping in parenthesis).")
-    .addError(31, 15, "Did you mean to return a conditional instead of an assignment?")
+    .addError(31, 14, "Did you mean to return a conditional instead of an assignment?")
     .addError(32, 20, "Invalid position for 'yield' expression (consider wrapping in parenthesis).")
     .addError(32, 17, "Bad operand.")
     .addError(51, 10, "Invalid position for 'yield' expression (consider wrapping in parenthesis).")
@@ -7615,17 +7636,17 @@ exports["test 'yield' in compound expressions."] = function (test) {
     .test(code, {maxerr: 1000, expr: true, esnext: true});
 
   run = TestRun(test)
-    .addError(22, 15, "Did you mean to return a conditional instead of an assignment?")
-    .addError(31, 15, "Did you mean to return a conditional instead of an assignment?");
+    .addError(22, 14, "Did you mean to return a conditional instead of an assignment?")
+    .addError(31, 14, "Did you mean to return a conditional instead of an assignment?");
 
   // These are line-column pairs for the Mozilla paren errors.
   var needparen = [
     // comma
     [ 5,  5], [ 6,  8], [ 7,  5], [11,  5], [12,  8], [13,  5],
     // yield in yield
-    [18, 11], [19, 17], [19, 11], [20, 11], [20,  5], [21, 11], [21,  5], [21, 26], [22, 22],
-    [23, 22], [23, 11], [27, 11], [28, 17], [28, 11], [29, 11], [29,  5], [30, 11], [30,  5],
-    [30, 24], [31, 22], [32, 11], [32, 20],
+    [20, 11], [20,  5], [21, 11], [21,  5],
+    [23, 22], [29, 11], [29,  5], [30, 11], [30,  5],
+    [32, 11], [32, 20],
     // infix
     [51, 10], [53, 10], [54, 16], [57, 10], [58,  5], [59, 10], [60,  5], [60, 14],
     // prefix
@@ -7766,6 +7787,14 @@ exports["test 'yield' in invalid positions"] = function (test) {
   TestRun(test, "asi (ignoring warnings)")
     .test(code, { esversion: 6, expr: true, asi: true });
 
+  TestRun(test, "name of a generator expression")
+    .addError(1, 13, "Unexpected 'yield'.")
+    .test([
+      "(function * yield() {",
+      "  yield;",
+      "})();"
+    ], { esversion: 6 });
+
   test.done();
 };
 
@@ -9810,6 +9839,9 @@ exports.asyncFunctions.awaitOperator = function (test) {
       "void async function() {",
       "  void {",
       "    x: await 0,",
+      "    [await 0]: 0,",
+      "    get [await 0]() {},",
+      "    set [await 0](_) {},",
       "  };",
       "};"
     ], { esversion: 8 });
@@ -10062,7 +10094,10 @@ exports.asyncGenerators.classMethod = function (test) {
 
   TestRun(test, "Illegal constructor")
     .addError(1, 19, "Unexpected 'constructor'.")
-    .addError(1,44, "Yield expressions may only occur within generator functions.")
+    .addError(1, 44, "Expected an identifier and instead saw 'yield' (a reserved word).")
+    .addError(1, 44, "Expected an assignment or function call and instead saw an expression.")
+    .addError(1, 49, "Missing semicolon.")
+    .addError(1, 50, "Expected an assignment or function call and instead saw an expression.")
     .test("class C { async * constructor() { await 0; yield 0; } }", { esversion: 9 });
 
   test.done();