fix(parser): reject async modifiers on class fields (#26486)

`class C { async x; }` was accepted in JavaScript and TypeScript, silently discarding `async` from the resulting field. Reject the modifier after parsing a class field, once fields have been distinguished from methods.

Async methods, fields named `async`, and newline-separated fields remain valid.
This commit is contained in:
camc314
2026-09-09 13:04:01 +00:00
parent 9b1aff8c0c
commit 2dcee2f216
11 changed files with 49 additions and 13 deletions
+8
View File
@@ -712,6 +712,14 @@ impl<'a, C: Config> ParserImpl<'a, C> {
return self.fatal_error(error);
}
// `async` is valid on methods, but not fields.
self.verify_modifiers(
modifiers,
ModifierKinds::all_except([ModifierKind::Async]),
false,
diagnostics::modifier_cannot_be_used_here,
);
let r#abstract = modifiers.contains(ModifierKind::Abstract);
let r#type = if r#abstract {
PropertyDefinitionType::TSAbstractPropertyDefinition
+1
View File
@@ -0,0 +1 @@
class C { async x; }
+1
View File
@@ -0,0 +1 @@
class C { async x; }
@@ -0,0 +1,7 @@
class C {
async
x;
static async
y;
}
@@ -0,0 +1,7 @@
class C {
async
x: number;
static async
y: number;
}
+2 -2
View File
@@ -1,3 +1,3 @@
codegen_misc Summary:
AST Parsed : 91/91 (100.00%)
Positive Passed: 91/91 (100.00%)
AST Parsed : 93/93 (100.00%)
Positive Passed: 93/93 (100.00%)
+2 -2
View File
@@ -1,3 +1,3 @@
formatter_misc Summary:
AST Parsed : 91/91 (100.00%)
Positive Passed: 91/91 (100.00%)
AST Parsed : 93/93 (100.00%)
Positive Passed: 93/93 (100.00%)
+2 -2
View File
@@ -1,3 +1,3 @@
lexer_misc Summary:
AST Parsed : 286/286 (100.00%)
Positive Passed: 286/286 (100.00%)
AST Parsed : 290/290 (100.00%)
Positive Passed: 290/290 (100.00%)
+15 -3
View File
@@ -1,7 +1,7 @@
parser_misc Summary:
AST Parsed : 91/91 (100.00%)
Positive Passed: 91/91 (100.00%)
Negative Passed: 195/195 (100.00%)
AST Parsed : 93/93 (100.00%)
Positive Passed: 93/93 (100.00%)
Negative Passed: 197/197 (100.00%)
× Cannot assign to 'arguments' in strict mode
╭─[misc/fail/arguments-eval-ambient.ts:2:13]
@@ -190,6 +190,18 @@ Negative Passed: 195/195 (100.00%)
· ─────
╰────
× 'async' modifier cannot be used here.
╭─[misc/fail/async-field.js:1:11]
1 │ class C { async x; }
· ─────
╰────
× 'async' modifier cannot be used here.
╭─[misc/fail/async-field.ts:1:11]
1 │ class C { async x; }
· ─────
╰────
× `await` is only allowed within async functions and at the top levels of modules
╭─[misc/fail/auto-accessor-initializer-await.js:3:18]
2 │ class C {
+2 -2
View File
@@ -1,6 +1,6 @@
semantic_misc Summary:
AST Parsed : 91/91 (100.00%)
Positive Passed: 87/91 (95.60%)
AST Parsed : 93/93 (100.00%)
Positive Passed: 89/93 (95.70%)
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 : 91/91 (100.00%)
Positive Passed: 91/91 (100.00%)
AST Parsed : 93/93 (100.00%)
Positive Passed: 93/93 (100.00%)