From fed20bb039cf9f53adfcf93e467f418c5e958f45 Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Fri, 15 Nov 2019 12:46:55 -0800 Subject: [PATCH] Fix: require-await crash on global await (#12571) --- lib/rules/require-await.js | 8 + .../typescript-parsers/global-await.js | 162 ++++++ .../typescript-parsers/global-for-await-of.js | 470 ++++++++++++++++++ tests/lib/rules/require-await.js | 16 +- 4 files changed, 655 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/parsers/typescript-parsers/global-await.js create mode 100644 tests/fixtures/parsers/typescript-parsers/global-for-await-of.js diff --git a/lib/rules/require-await.js b/lib/rules/require-await.js index 0aa6fce7e19..22c111b6dc8 100644 --- a/lib/rules/require-await.js +++ b/lib/rules/require-await.js @@ -89,9 +89,17 @@ module.exports = { "ArrowFunctionExpression:exit": exitFunction, AwaitExpression() { + if (!scopeInfo) { + return; + } + scopeInfo.hasAwait = true; }, ForOfStatement(node) { + if (!scopeInfo) { + return; + } + if (node.await) { scopeInfo.hasAwait = true; } diff --git a/tests/fixtures/parsers/typescript-parsers/global-await.js b/tests/fixtures/parsers/typescript-parsers/global-await.js new file mode 100644 index 00000000000..d68af6fc6cc --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/global-await.js @@ -0,0 +1,162 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser v2.6.1 + * Source code: + * await foo(); + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AwaitExpression", + argument: { + type: "CallExpression", + callee: { + type: "Identifier", + name: "foo", + range: [6, 9], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 9 + } + } + }, + arguments: [], + optional: false, + range: [6, 11], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 11 + } + } + }, + range: [0, 11], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 11 + } + } + }, + range: [0, 12], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 12 + } + } + } + ], + sourceType: "module", + range: [0, 12], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 12 + } + }, + tokens: [ + { + type: "Identifier", + value: "await", + range: [0, 5], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 5 + } + } + }, + { + type: "Identifier", + value: "foo", + range: [6, 9], + loc: { + start: { + line: 1, + column: 6 + }, + end: { + line: 1, + column: 9 + } + } + }, + { + type: "Punctuator", + value: "(", + range: [9, 10], + loc: { + start: { + line: 1, + column: 9 + }, + end: { + line: 1, + column: 10 + } + } + }, + { + type: "Punctuator", + value: ")", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10 + }, + end: { + line: 1, + column: 11 + } + } + }, + { + type: "Punctuator", + value: ";", + range: [11, 12], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 12 + } + } + } + ], + comments: [] +}); diff --git a/tests/fixtures/parsers/typescript-parsers/global-for-await-of.js b/tests/fixtures/parsers/typescript-parsers/global-for-await-of.js new file mode 100644 index 00000000000..2f61b833b22 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/global-for-await-of.js @@ -0,0 +1,470 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser v2.6.1 + * Source code: +for await (let num of asyncIterable) { + console.log(num); +} + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ForOfStatement", + left: { + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + id: { + type: "Identifier", + name: "num", + range: [15, 18], + loc: { + start: { + line: 1, + column: 15 + }, + end: { + line: 1, + column: 18 + } + } + }, + init: null, + range: [15, 18], + loc: { + start: { + line: 1, + column: 15 + }, + end: { + line: 1, + column: 18 + } + } + } + ], + kind: "let", + range: [11, 18], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 18 + } + } + }, + right: { + type: "Identifier", + name: "asyncIterable", + range: [22, 35], + loc: { + start: { + line: 1, + column: 22 + }, + end: { + line: 1, + column: 35 + } + } + }, + body: { + type: "BlockStatement", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "MemberExpression", + object: { + type: "Identifier", + name: "console", + range: [41, 48], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 9 + } + } + }, + property: { + type: "Identifier", + name: "log", + range: [49, 52], + loc: { + start: { + line: 2, + column: 10 + }, + end: { + line: 2, + column: 13 + } + } + }, + computed: false, + optional: false, + range: [41, 52], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 13 + } + } + }, + arguments: [ + { + type: "Identifier", + name: "num", + range: [53, 56], + loc: { + start: { + line: 2, + column: 14 + }, + end: { + line: 2, + column: 17 + } + } + } + ], + optional: false, + range: [41, 57], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 18 + } + } + }, + range: [41, 58], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 19 + } + } + } + ], + range: [37, 60], + loc: { + start: { + line: 1, + column: 37 + }, + end: { + line: 3, + column: 1 + } + } + }, + await: true, + range: [0, 60], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 3, + column: 1 + } + } + } + ], + sourceType: "module", + range: [0, 60], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 3, + column: 1 + } + }, + tokens: [ + { + type: "Keyword", + value: "for", + range: [0, 3], + loc: { + start: { + line: 1, + column: 0 + }, + end: { + line: 1, + column: 3 + } + } + }, + { + type: "Identifier", + value: "await", + range: [4, 9], + loc: { + start: { + line: 1, + column: 4 + }, + end: { + line: 1, + column: 9 + } + } + }, + { + type: "Punctuator", + value: "(", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10 + }, + end: { + line: 1, + column: 11 + } + } + }, + { + type: "Keyword", + value: "let", + range: [11, 14], + loc: { + start: { + line: 1, + column: 11 + }, + end: { + line: 1, + column: 14 + } + } + }, + { + type: "Identifier", + value: "num", + range: [15, 18], + loc: { + start: { + line: 1, + column: 15 + }, + end: { + line: 1, + column: 18 + } + } + }, + { + type: "Identifier", + value: "of", + range: [19, 21], + loc: { + start: { + line: 1, + column: 19 + }, + end: { + line: 1, + column: 21 + } + } + }, + { + type: "Identifier", + value: "asyncIterable", + range: [22, 35], + loc: { + start: { + line: 1, + column: 22 + }, + end: { + line: 1, + column: 35 + } + } + }, + { + type: "Punctuator", + value: ")", + range: [35, 36], + loc: { + start: { + line: 1, + column: 35 + }, + end: { + line: 1, + column: 36 + } + } + }, + { + type: "Punctuator", + value: "{", + range: [37, 38], + loc: { + start: { + line: 1, + column: 37 + }, + end: { + line: 1, + column: 38 + } + } + }, + { + type: "Identifier", + value: "console", + range: [41, 48], + loc: { + start: { + line: 2, + column: 2 + }, + end: { + line: 2, + column: 9 + } + } + }, + { + type: "Punctuator", + value: ".", + range: [48, 49], + loc: { + start: { + line: 2, + column: 9 + }, + end: { + line: 2, + column: 10 + } + } + }, + { + type: "Identifier", + value: "log", + range: [49, 52], + loc: { + start: { + line: 2, + column: 10 + }, + end: { + line: 2, + column: 13 + } + } + }, + { + type: "Punctuator", + value: "(", + range: [52, 53], + loc: { + start: { + line: 2, + column: 13 + }, + end: { + line: 2, + column: 14 + } + } + }, + { + type: "Identifier", + value: "num", + range: [53, 56], + loc: { + start: { + line: 2, + column: 14 + }, + end: { + line: 2, + column: 17 + } + } + }, + { + type: "Punctuator", + value: ")", + range: [56, 57], + loc: { + start: { + line: 2, + column: 17 + }, + end: { + line: 2, + column: 18 + } + } + }, + { + type: "Punctuator", + value: ";", + range: [57, 58], + loc: { + start: { + line: 2, + column: 18 + }, + end: { + line: 2, + column: 19 + } + } + }, + { + type: "Punctuator", + value: "}", + range: [59, 60], + loc: { + start: { + line: 3, + column: 0 + }, + end: { + line: 3, + column: 1 + } + } + } + ], + comments: [] +}); diff --git a/tests/lib/rules/require-await.js b/tests/lib/rules/require-await.js index 7b43f326662..55c305e7861 100644 --- a/tests/lib/rules/require-await.js +++ b/tests/lib/rules/require-await.js @@ -41,7 +41,21 @@ ruleTester.run("require-await", rule, { "function foo() { doSomething() }", // for-await-of - "async function foo() { for await (x of xs); }" + "async function foo() { for await (x of xs); }", + + // global await + { + code: "await foo()", + parser: require.resolve("../../fixtures/parsers/typescript-parsers/global-await") + }, + { + code: ` + for await (let num of asyncIterable) { + console.log(num); + } + `, + parser: require.resolve("../../fixtures/parsers/typescript-parsers/global-for-await-of") + } ], invalid: [ {