Fix missing parentheses around throw expression (#20028)

Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
Lazizbek Ergashevandfisker authored and GitHub committed 2026-09-11 18:10:50 +08:00
1 parent c150b07c07
commit 60a1d7ec78
7 files changed
+301 -14

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
#### Keep necessary parentheses around `throw` expression (#20028 by @lazerg)
<!-- prettier-ignore -->
```jsx
// Input
(throw error);
// Prettier stable
throw error;
// Prettier main
(throw error);
```
@@ -62,7 +62,8 @@ function needsParentheses(path, options) {
node.type === "ObjectExpression" || node.type === "ObjectExpression" ||
node.type === "FunctionExpression" || node.type === "FunctionExpression" ||
node.type === "ClassExpression" || node.type === "ClassExpression" ||
node.type === "DoExpression" node.type === "DoExpression" ||
(node.type === "UnaryExpression" && node.operator === "throw")
) { ) {
const expression = path.findAncestor( const expression = path.findAncestor(
(node) => node.type === "ExpressionStatement", (node) => node.type === "ExpressionStatement",
@@ -287,10 +287,6 @@ function foo() {
); );
} }
(do {});
(do {} + 1);
(1 + do {});
() => do {};
(do { (do {
switch(0) { switch(0) {
@@ -358,11 +354,6 @@ function foo() {
); );
} }
(do {});
(do {}) + 1;
1 + do {};
() => do {};
(do { (do {
switch (0) { switch (0) {
case 0: case 0:
@@ -34,10 +34,6 @@ function foo() {
); );
} }
(do {});
(do {} + 1);
(1 + do {});
() => do {};
(do { (do {
switch(0) { switch(0) {
@@ -0,0 +1,216 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`do-expression.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80 (default) |
=====================================input======================================
(do {});
(async do {});
(throw error);
(do {}) || fallback;
(async do {}) || fallback;
(throw error) || fallback;
(do {}).message;
(async do {}).message;
(throw error).message;
// Head, bug
((do {}), _);
((async do {}), _);
((throw error), _);
// Tail
(_, (do {}));
(_, (async do {}));
(_, (throw error));
// Middle
(
_,
(do {}),
(async do {}),
(throw error),
_
);
(do {}) + 1;
(async do {}) + 1;
(throw error) + 1;
1 + do {};
1 + async do {};
1 + throw error;
() => do {};
() => async do {};
() => throw error;
if (condition) (do {});
if (condition) (async do {});
if (condition) (throw error);
for (;;) (do {});
for (;;) (async do {});
for (;;) (throw error);
label: (do {});
label: (async do {});
label: (throw error);
value = do {};
value = async do {};
value = throw error;
=====================================output=====================================
(do {});
(async do {});
(throw error);
(do {}) || fallback;
(async do {}) || fallback;
(throw error) || fallback;
(do {}).message;
(async do {}).message;
(throw error).message;
// Head, bug
((do {}), _);
((async do {}), _);
((throw error), _);
// Tail
(_, do {});
(_, async do {});
(_, throw error);
// Middle
(_, do {}, async do {}, throw error, _);
(do {}) + 1;
(async do {}) + 1;
(throw error) + 1;
1 + do {};
1 + async do {};
1 + throw error;
() => do {};
() => async do {};
() => throw error;
if (condition) (do {});
if (condition) (async do {});
if (condition) (throw error);
for (;;) (do {});
for (;;) (async do {});
for (;;) (throw error);
label: (do {});
label: (async do {});
label: (throw error);
value = do {};
value = async do {};
value = throw error;
================================================================================
`;
exports[`do-expression.js format[acorn] 1`] = `
"Unexpected token (1:2)
> 1 | (do {});
| ^
2 | (async do {});
3 | (throw error);
4 |
Cause: Unexpected token (1:1)"
`;
exports[`do-expression.js format[espree] 1`] = `
"Unexpected token do (1:2)
> 1 | (do {});
| ^
2 | (async do {});
3 | (throw error);
4 |
Cause: Unexpected token do"
`;
exports[`do-expression.js format[flow] 1`] = `
"Unexpected token \`do\` (1:2)
> 1 | (do {});
| ^
2 | (async do {});
3 | (throw error);
4 |
Cause: Unexpected token \`do\` (1:1)"
`;
exports[`do-expression.js format[hermes] 1`] = `
"invalid expression (1:2)
> 1 | (do {});
| ^
2 | (async do {});
3 | (throw error);
4 |
Cause: invalid expression (1:1)
(do {});
^"
`;
exports[`do-expression.js format[meriyah] 1`] = `
"Unexpected token: 'do' (1:2)
> 1 | (do {});
| ^^
2 | (async do {});
3 | (throw error);
4 |
Cause: [1:1-1:3]: Unexpected token: 'do'"
`;
exports[`do-expression.js format[oxc] 1`] = `
"Unexpected token (1:2)
> 1 | (do {});
| ^^
2 | (async do {});
3 | (throw error);
4 |"
`;
exports[`do-expression.js format[oxc-ts] 1`] = `
"Unexpected token (1:2)
> 1 | (do {});
| ^^
2 | (async do {});
3 | (throw error);
4 |"
`;
exports[`do-expression.js format[typescript] 1`] = `
"Expression expected. (1:2)
> 1 | (do {});
| ^
2 | (async do {});
3 | (throw error);
4 |
Cause: Expression expected."
`;
exports[`do-expression.js format[yuku] 1`] = `
"'do' is reserved and cannot be used as an identifier (1:2)
> 1 | (do {});
| ^^
2 | (async do {});
3 | (throw error);
4 |"
`;
exports[`do-expression.js format[yuku-ts] 1`] = `
"'do' is reserved and cannot be used as an identifier (1:2)
> 1 | (do {});
| ^^
2 | (async do {});
3 | (throw error);
4 |"
`;
@@ -0,0 +1,56 @@
(do {});
(async do {});
(throw error);
(do {}) || fallback;
(async do {}) || fallback;
(throw error) || fallback;
(do {}).message;
(async do {}).message;
(throw error).message;
// Head, bug
((do {}), _);
((async do {}), _);
((throw error), _);
// Tail
(_, (do {}));
(_, (async do {}));
(_, (throw error));
// Middle
(
_,
(do {}),
(async do {}),
(throw error),
_
);
(do {}) + 1;
(async do {}) + 1;
(throw error) + 1;
1 + do {};
1 + async do {};
1 + throw error;
() => do {};
() => async do {};
() => throw error;
if (condition) (do {});
if (condition) (async do {});
if (condition) (throw error);
for (;;) (do {});
for (;;) (async do {});
for (;;) (throw error);
label: (do {});
label: (async do {});
label: (throw error);
value = do {};
value = async do {};
value = throw error;
@@ -0,0 +1,14 @@
runFormatTest(import.meta, ["babel", "flow", "typescript"], {
errors: {
acorn: ["do-expression.js"],
espree: ["do-expression.js"],
meriyah: ["do-expression.js"],
oxc: ["do-expression.js"],
"oxc-ts": ["do-expression.js"],
yuku: ["do-expression.js"],
"yuku-ts": ["do-expression.js"],
typescript: ["do-expression.js"],
flow: ["do-expression.js"],
hermes: ["do-expression.js"],
},
});