fix(parser): reset auto-accessor initializer context (#25384)

## Summary

- Align auto-accessor initializer parsing with class-field initializer grammar.
- Add regressions for `in` in a `for` initializer and disallowed inherited `await`/`yield` contexts.

## Root cause

The auto-accessor path only enabled `new.target`. It therefore inherited outer `~In`, `Await`, and `Yield` grammar contexts: `a in b` could not parse in a `for` initializer, while `await` and `yield` could incorrectly parse from enclosing async/generator functions. The fix applies the same `In | NewTarget` addition and `Yield | Await` removal already used for class fields, while retaining AssignmentExpression parsing.

## References

- [ECMAScript `FieldDefinition` grammar](https://tc39.es/ecma262/#prod-FieldDefinition)
- [ECMAScript `Initializer` grammar](https://tc39.es/ecma262/#prod-Initializer)
- [TC39 decorators proposal: class auto-accessors](https://github.com/tc39/proposal-decorators#introduction)
This commit is contained in:
camc314 committed 2026-08-07 23:03:24 +00:00
1 parent 6fb7f47605
commit 9e93ba6908
9 files changed
+51 -13

No files matched your search

+5 -2
View File
@@ -418,9 +418,12 @@ impl<'a, C: Config> ParserImpl<'a, C> {
decorators: ArenaVec<'a, Decorator<'a>>,
) -> ClassElement<'a> {
let type_annotation = if self.is_ts { self.parse_ts_type_annotation() } else { None };
// `new.target` is allowed in a class accessor field initializer.
let value = self.eat(Kind::Eq).then(|| {
self.context_add(Context::NewTarget, Self::parse_assignment_expression_or_higher)
self.context(
Context::In | Context::NewTarget,
Context::Yield | Context::Await,
Self::parse_assignment_expression_or_higher,
)
});
self.asi();
let r#type = if modifiers.contains(ModifierKind::Abstract) {
@@ -0,0 +1,5 @@
async function f() {
class C {
accessor x = await 1;
}
}
@@ -0,0 +1,5 @@
function* f() {
class C {
accessor x = yield 1;
}
}
@@ -0,0 +1,7 @@
for (
class C {
field = a in b;
accessor x = a in b;
};
;
) {}
+2 -2
View File
@@ -1,3 +1,3 @@
codegen_misc Summary:
AST Parsed : 75/75 (100.00%)
Positive Passed: 75/75 (100.00%)
AST Parsed : 76/76 (100.00%)
Positive Passed: 76/76 (100.00%)
+2 -2
View File
@@ -1,3 +1,3 @@
formatter_misc Summary:
AST Parsed : 75/75 (100.00%)
Positive Passed: 75/75 (100.00%)
AST Parsed : 76/76 (100.00%)
Positive Passed: 76/76 (100.00%)
+21 -3
View File
@@ -1,7 +1,7 @@
parser_misc Summary:
AST Parsed : 75/75 (100.00%)
Positive Passed: 75/75 (100.00%)
Negative Passed: 156/156 (100.00%)
AST Parsed : 76/76 (100.00%)
Positive Passed: 76/76 (100.00%)
Negative Passed: 158/158 (100.00%)
× Cannot assign to 'arguments' in strict mode
╭─[misc/fail/arguments-eval-ambient.ts:2:13]
@@ -136,6 +136,24 @@ Negative Passed: 156/156 (100.00%)
╰────
note: Classes are always strict mode code
× `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 {
3 │ accessor x = await 1;
· ─────
4 │ }
╰────
help: Either remove this `await` or add the `async` keyword to the enclosing function
× A 'yield' expression is only allowed in a generator body.
╭─[misc/fail/auto-accessor-initializer-yield.js:3:18]
2 │ class C {
3 │ accessor x = yield 1;
· ─────
4 │ }
╰────
help: Either remove this `yield` or change the enclosing function to a generator function (`function*`)
× Cannot use await in class static initialization block
╭─[misc/fail/await-expr-in-block-in-class-static-block.mjs:4:7]
3 │ {
+2 -2
View File
@@ -1,6 +1,6 @@
semantic_misc Summary:
AST Parsed : 75/75 (100.00%)
Positive Passed: 71/75 (94.67%)
AST Parsed : 76/76 (100.00%)
Positive Passed: 72/76 (94.74%)
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 : 75/75 (100.00%)
Positive Passed: 75/75 (100.00%)
AST Parsed : 76/76 (100.00%)
Positive Passed: 76/76 (100.00%)