Repository: jshint/jshint
Pull request #3396 (2019-05-04 06:55:53)

Correct binding power of AwaitExpression
This is intended to resolve gh-3395. I had to fix a previously-unreported issue with the `singleGroups` option to get there.

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

Coverage remained the same at 100.0% when pulling **3ce6a99e5563a167f81b4230bfd0e3bdf28a816c on jugglinmike:async-functions-binding-power** into **02f20b23bafb1aacbde41bfcdafe23e419c955d3 on jshint:master**.

rwaldron: Manually re-running the single failed build in appveyor. Once that's finished, this is 👍 
rwaldron: 💚 

Patch:
diff --git a/src/jshint.js b/src/jshint.js
index cd88e19e..d3d95e23 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -3173,6 +3173,12 @@ var JSHINT = (function() {
       ret = first = last = exprs[0];
 
       if (!isNecessary) {
+        // async functions are identified after parsing due to the complexity
+        // of disambiguating the `async` keyword.
+        if (!triggerFnExpr) {
+          triggerFnExpr = ret.id === "async";
+        }
+
         isNecessary =
           // Used to distinguish from an ExpressionStatement which may not
           // begin with the `{` and `function` tokens
@@ -5292,7 +5298,7 @@ var JSHINT = (function() {
         error("E024", this, "await");
       }
 
-      expression(context, 0);
+      expression(context, 10);
       return this;
     } else {
       this.exps = false;


Test patch:
diff --git a/tests/unit/options.js b/tests/unit/options.js
index ece32ae7..2f91f57e 100644
--- a/tests/unit/options.js
+++ b/tests/unit/options.js
@@ -3425,6 +3425,86 @@ singleGroups.exponentiation = function (test) {
   test.done();
 };
 
+singleGroups.asyncFunction = function (test) {
+  TestRun(test, "Async Function Expression")
+    .test([
+      "(async function() {})();",
+      "(async function a() {})();"
+    ], { singleGroups: true, esversion: 8 });
+
+  TestRun(test, "Async Generator Function Expression")
+    .test([
+      "(async function * () { yield; })();",
+      "(async function * a() { yield; })();"
+    ], { singleGroups: true, esversion: 9 });
+
+
+  TestRun(test, "Async Arrow Function")
+    .test([
+      "(async () => {})();",
+      "(async x => x)();"
+    ], { singleGroups: true, esversion: 8 });
+
+  TestRun(test, "async identifier")
+    .addError(1, 1, "Unnecessary grouping operator.")
+    .addError(2, 1, "Unnecessary grouping operator.")
+    .test([
+      "(async());",
+      "(async(x, y, z));"
+    ], { singleGroups: true, esversion: 8 });
+
+  test.done();
+};
+
+singleGroups.await = function (test) {
+  TestRun(test, "MultiplicativeExpression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 2) * 3;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "ExponentiationExpression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 2) ** 3;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "CallExpression")
+    .test([
+      "(async function() {",
+      "  (await 2)();",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "EqualityExpression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .addError(3, 3, "Unnecessary grouping operator.")
+    .addError(4, 3, "Unnecessary grouping operator.")
+    .addError(5, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 2) == 2;",
+      "  (await 2) != 2;",
+      "  (await 2) === 2;",
+      "  (await 2) !== 2;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  TestRun(test, "Expression")
+    .addError(2, 3, "Unnecessary grouping operator.")
+    .test([
+      "(async function() {",
+      "  (await 0), 0;",
+      "})();"
+    ], { singleGroups: true, expr: true, esversion: 8 });
+
+  test.done();
+};
+
 singleGroups.objectLiterals = function (test) {
   var code = [
     "({}).method();",
diff --git a/tests/unit/parser.js b/tests/unit/parser.js
index cf1a9284..7386f845 100644
--- a/tests/unit/parser.js
+++ b/tests/unit/parser.js
@@ -9591,6 +9591,16 @@ exports.asyncFunctions.awaitOperator = function (test) {
       "};",
     ], { esversion: 8 });
 
+  // Regression test for gh-3395
+  TestRun(test, "within object initializer")
+    .test([
+      "void async function() {",
+      "  void {",
+      "    x: await 0,",
+      "  };",
+      "};"
+    ], { esversion: 8 });
+
   test.done();
 };