fix(semantic): reject await and yield in rest parameter defaults (#26359)

The parameter check only recognized `FormalParameter`, allowing `await` and `yield` in destructuring defaults inside rest parameters:

```js
async function f(...[x = await 0]) {}
function* g(...[x = yield 0]) {}
```

Include `FormalParameterRest` so both cases report the existing parameter diagnostic. The check still stops at nested functions, where `await` and `yield` can be valid.
This commit is contained in:
camc314 committed 2026-09-06 08:36:56 +00:00
1 parent 4b89c7bd55
commit 457ed57ff2
10 files changed
+46 -14

No files matched your search

@@ -1296,9 +1296,16 @@ pub fn check_unary_expression(unary_expr: &UnaryExpression, ctx: &SemanticBuilde
}
fn is_in_formal_parameters(ctx: &SemanticBuilder<'_>) -> bool {
for node_kind in ctx.ancestry().ancestor_kinds() {
let mut ancestors = ctx.ancestry().ancestor_kinds().peekable();
while let Some(node_kind) = ancestors.next() {
match node_kind {
AstKind::FormalParameter(_) => return true,
// Only the rest binding belongs to the parameter; decorators use the surrounding context.
AstKind::BindingRestElement(_)
if matches!(ancestors.peek(), Some(AstKind::FormalParameterRest(_))) =>
{
return true;
}
AstKind::Program(_) | AstKind::Function(_) | AstKind::ArrowFunctionExpression(_) => {
break;
}
@@ -0,0 +1,2 @@
async function f(...[x = await 0]) {}
function* g(...[x = yield 0]) {}
@@ -0,0 +1,5 @@
const p = Promise.resolve(() => {});
class C {
async rest(@(await p) ...args: unknown[]) {}
}
export {};
@@ -0,0 +1,2 @@
async function f(...[x = async () => await 0]) {}
function* g(...[x = function* () { yield 0; }]) {}
+2 -2
View File
@@ -1,3 +1,3 @@
codegen_misc Summary:
AST Parsed : 81/81 (100.00%)
Positive Passed: 81/81 (100.00%)
AST Parsed : 83/83 (100.00%)
Positive Passed: 83/83 (100.00%)
+2 -2
View File
@@ -1,3 +1,3 @@
formatter_misc Summary:
AST Parsed : 81/81 (100.00%)
Positive Passed: 81/81 (100.00%)
AST Parsed : 83/83 (100.00%)
Positive Passed: 83/83 (100.00%)
+2 -2
View File
@@ -1,6 +1,6 @@
lexer_misc Summary:
AST Parsed : 250/250 (100.00%)
Positive Passed: 248/250 (99.20%)
AST Parsed : 253/253 (100.00%)
Positive Passed: 251/253 (99.21%)
Tokens: tasks/coverage/misc/pass/oxc-2674.tsx
Tokens: tasks/coverage/misc/pass/swc-7187.ts
+19 -3
View File
@@ -1,7 +1,7 @@
parser_misc Summary:
AST Parsed : 81/81 (100.00%)
Positive Passed: 81/81 (100.00%)
Negative Passed: 169/169 (100.00%)
AST Parsed : 83/83 (100.00%)
Positive Passed: 83/83 (100.00%)
Negative Passed: 170/170 (100.00%)
× Cannot assign to 'arguments' in strict mode
╭─[misc/fail/arguments-eval-ambient.ts:2:13]
@@ -4292,6 +4292,22 @@ Negative Passed: 169/169 (100.00%)
╰────
help: Expected an identifier, like `...rest`.
× await expression not allowed in formal parameter
╭─[misc/fail/rest-parameter-default-await-yield.js:1:26]
1 │ async function f(...[x = await 0]) {}
· ───┬───
· ╰── await expression not allowed in formal parameter
2 │ function* g(...[x = yield 0]) {}
╰────
× yield expression not allowed in formal parameter
╭─[misc/fail/rest-parameter-default-await-yield.js:2:21]
1 │ async function f(...[x = await 0]) {}
2 │ function* g(...[x = yield 0]) {}
· ───┬───
· ╰── yield expression not allowed in formal parameter
╰────
× 'using' declarations are not allowed at the top level of a script
╭─[misc/fail/script-top-level-using.js:2:1]
1 │ // 'using' is not allowed at top level in scripts
+2 -2
View File
@@ -1,6 +1,6 @@
semantic_misc Summary:
AST Parsed : 81/81 (100.00%)
Positive Passed: 77/81 (95.06%)
AST Parsed : 83/83 (100.00%)
Positive Passed: 79/83 (95.18%)
semantic Error: tasks/coverage/misc/pass/declare-let-private.ts
Bindings mismatch:
after transform: ScopeId(0): ["private"]
@@ -1,3 +1,3 @@
transformer_misc Summary:
AST Parsed : 81/81 (100.00%)
Positive Passed: 81/81 (100.00%)
AST Parsed : 83/83 (100.00%)
Positive Passed: 83/83 (100.00%)