diff --git a/packages/babel-generator/src/node/parentheses.ts b/packages/babel-generator/src/node/parentheses.ts index 26789bf13d10..867419aa467d 100644 --- a/packages/babel-generator/src/node/parentheses.ts +++ b/packages/babel-generator/src/node/parentheses.ts @@ -276,6 +276,15 @@ export function LogicalExpression(node: any, parent: any): boolean { } } +export function Identifier(node: t.Identifier, parent: t.Node): boolean { + // 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. + return ( + node.name === "async" && t.isForOfStatement(parent) && node === parent.left + ); +} + // Walk up the print stack to determine if our node can come first // in statement. function isFirstInStatement( 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