From 287b11831b51490399e1d750f7e3f774d4d6e2b0 Mon Sep 17 00:00:00 2001 From: Stuart Cook Date: Mon, 26 Apr 2021 19:55:00 +1000 Subject: [PATCH] Prevent ForOfStatement from printing the forbidden sequence "for ( async of" --- .../babel-generator/src/generators/statements.ts | 16 +++++++++++++--- .../test/fixtures/edgecase/for-async-of/input.js | 7 +++++++ .../fixtures/edgecase/for-async-of/output.js | 7 +++++++ 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 packages/babel-generator/test/fixtures/edgecase/for-async-of/input.js create mode 100644 packages/babel-generator/test/fixtures/edgecase/for-async-of/output.js diff --git a/packages/babel-generator/src/generators/statements.ts b/packages/babel-generator/src/generators/statements.ts index 24ca879d9686..3fa8e33c6701 100644 --- a/packages/babel-generator/src/generators/statements.ts +++ b/packages/babel-generator/src/generators/statements.ts @@ -82,16 +82,26 @@ export function WhileStatement(this: Printer, node: t.WhileStatement) { this.printBlock(node); } -const buildForXStatement = function (op) { - return function (node: any) { +const buildForXStatement = function (op: "in" | "of") { + return function (this: Printer, node: t.ForInStatement | t.ForOfStatement) { this.word("for"); this.space(); - if (op === "of" && node.await) { + if (op === "of" && (node as t.ForOfStatement).await) { this.word("await"); this.space(); } this.token("("); + + // ECMAScript specifically forbids a for-of loop from starting with the + // token sequence "for ( async of", because it would be ambiguous with + // "for (async of => {};;)", so we need to add extra parentheses. + const leftNeedsParens = + op === "of" && t.isIdentifier(node.left) && node.left.name === "async"; + + if (leftNeedsParens) this.token("("); this.print(node.left, node); + if (leftNeedsParens) this.token(")"); + this.space(); this.word(op); this.space(); diff --git a/packages/babel-generator/test/fixtures/edgecase/for-async-of/input.js b/packages/babel-generator/test/fixtures/edgecase/for-async-of/input.js new file mode 100644 index 000000000000..934747c7b4f9 --- /dev/null +++ b/packages/babel-generator/test/fixtures/edgecase/for-async-of/input.js @@ -0,0 +1,7 @@ +for ((async) of []); + +for ((async) of async) async; + +for (\u0061sync of []); + +for (async in []); diff --git a/packages/babel-generator/test/fixtures/edgecase/for-async-of/output.js b/packages/babel-generator/test/fixtures/edgecase/for-async-of/output.js new file mode 100644 index 000000000000..c5734919e906 --- /dev/null +++ b/packages/babel-generator/test/fixtures/edgecase/for-async-of/output.js @@ -0,0 +1,7 @@ +for ((async) of []); + +for ((async) of async) async; + +for ((async) of []); + +for (async in []); \ No newline at end of file