Skip to content

Commit

Permalink
Fix missing parentheses on async inside for..of (#10781)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed May 6, 2021
1 parent 7a6af71 commit 877e64c
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 1 deletion.
17 changes: 17 additions & 0 deletions changelog_unreleased/javascript/10781.md
@@ -0,0 +1,17 @@
#### Fix missing parentheses on `async` inside `for..of` (#10781 by @fisker)

<!-- prettier-ignore -->
```jsx
// Input
for ((async) of []);

// Prettier stable
for (async of []);

// Prettier stable (second format)
SyntaxError: Unexpected token, expected "=>" (1:15)
> 1 | for (async of []);

// Prettier main
for ((async) of []);
```
11 changes: 11 additions & 0 deletions src/language-js/needs-parens.js
Expand Up @@ -63,6 +63,17 @@ function needsParens(path, options) {
) {
return true;
}

// `for (async of []);` is invalid
if (
name === "left" &&
node.name === "async" &&
parent.type === "ForOfStatement" &&
!parent.await
) {
return true;
}

return false;
}

Expand Down
44 changes: 44 additions & 0 deletions tests/format/js/for-of/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`async-identifier.js [espree] format 1`] = `
"Unexpected token [ (6:23)
4 |
5 | async function f() {
> 6 | for await (async of []);
| ^
7 | for await ((async) of []);
8 | for await ((foo) of async);
9 | for await ((foo) of []) async;"
`;
exports[`async-identifier.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
for ((async) of []);
for ((foo) of async);
for ((foo) of []) async;
async function f() {
for await (async of []);
for await ((async) of []);
for await ((foo) of async);
for await ((foo) of []) async;
}
=====================================output=====================================
for ((async) of []);
for (foo of async);
for (foo of []) async;
async function f() {
for await (async of []);
for await (async of []);
for await (foo of async);
for await (foo of []) async;
}
================================================================================
`;
10 changes: 10 additions & 0 deletions tests/format/js/for-of/async-identifier.js
@@ -0,0 +1,10 @@
for ((async) of []);
for ((foo) of async);
for ((foo) of []) async;

async function f() {
for await (async of []);
for await ((async) of []);
for await ((foo) of async);
for await ((foo) of []) async;
}
3 changes: 3 additions & 0 deletions tests/format/js/for-of/jsfmt.spec.js
@@ -0,0 +1,3 @@
run_spec(__dirname, ["babel", "flow", "typescript"], {
errors: { espree: ["async-identifier.js"] },
});
Expand Up @@ -6,18 +6,42 @@ exports[`snippet: #0 [babel] format 1`] = `
| ^"
`;

exports[`snippet: #0 [babel] format 2`] = `
"The left-hand side of a for-of loop may not be 'async'. (1:6)
> 1 | for (async of []);
| ^"
`;

exports[`snippet: #0 [babel-flow] format 1`] = `
"The left-hand side of a for-of loop may not start with 'let'. (1:6)
> 1 | for (let.foo of []);
| ^"
`;

exports[`snippet: #0 [babel-flow] format 2`] = `
"The left-hand side of a for-of loop may not be 'async'. (1:6)
> 1 | for (async of []);
| ^"
`;

exports[`snippet: #0 [babel-ts] format 1`] = `
"The left-hand side of a for-of loop may not start with 'let'. (1:6)
> 1 | for (let.foo of []);
| ^"
`;

exports[`snippet: #0 [babel-ts] format 2`] = `
"The left-hand side of a for-of loop may not be 'async'. (1:6)
> 1 | for (async of []);
| ^"
`;

exports[`snippet: #0 [espree] format 1`] = `
"Unexpected token [ (1:15)
> 1 | for (async of []);
| ^"
`;

exports[`snippet: #0 [flow] format 1`] = `
"Unexpected token \`.\`, expected an identifier (1:9)
> 1 | for (let.foo of []);
Expand Down
21 changes: 20 additions & 1 deletion tests/format/misc/errors/js/for-of/jsfmt.spec.js
Expand Up @@ -9,7 +9,7 @@ run_spec(
},
[
"babel",
// Espree didn't throw https://github.com/acornjs/acorn/issues/1009
// `espree` didn't throw https://github.com/acornjs/acorn/issues/1009
// "espree",
"meriyah",
"flow",
Expand All @@ -18,3 +18,22 @@ run_spec(
"babel-ts",
]
);

run_spec(
{
dirname: __dirname,
snippets: ["for (async of []);"],
},
[
"babel",
"espree",
// `meriyah` didn't throw https://github.com/meriyah/meriyah/issues/190
// "meriyah",
// `flow` didn't throw https://github.com/facebook/flow/issues/8651
// "flow",
// `typescript` didn't throw
// "typescript",
"babel-flow",
"babel-ts",
]
);

0 comments on commit 877e64c

Please sign in to comment.