Files
oxc-project__oxc/tasks/coverage/misc/fail/oxc-22684.js
Boshen beb46d31fa fix(parser): commit to module goal on decorated exports (#22941)
## Summary

In unambiguous (`.js`) sources, `@foo export default class C { x = await + 1 }` reported a spurious `A module cannot have multiple default exports`.

A leading decorator makes the statement start with `@`, not `export`, so the eager Module-goal switch from #22684 didn't fire. The `await` identifier in the field initializer then triggered the unambiguous-mode top-level-await reparse, which re-ran `parse_statement_list_item` and recorded the `export default` a second time.

## Fix

- Commit to the Module goal in `parse_export_declaration` — the single place both leading and decorated exports flow through — so the export body parses under `Await` on the first pass, matching a non-decorated leading `export` (`ExportDeclaration` is unambiguously a `ModuleItem`, ECMA-262 §16.2.3).
- Skip the reparse for module declarations (`!stmt.is_module_declaration()`): an `export` / `import` is recorded on the first pass and is goal-independent, so reparsing only double-records it.

This also simplifies `parse_directives_and_statements`: the mutable `track_await_reparse` flag and the inline eager-commit block are removed; committing is now driven by `!ctx.has_await()`.

`await` stays correctly reserved in the module, so the input is still a syntax error (`The keyword 'await' is reserved`) — just no longer a *spurious* duplicate-export one. `tasks/coverage/misc/fail/oxc-22684.js` covers this.

Conformance: zero snapshot drift outside the new `misc` fixture.

Follow-up to #22684.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-04 04:05:46 +00:00

11 lines
447 B
JavaScript

// https://github.com/oxc-project/oxc/pull/22684
// `await` is reserved in a module, so this is a (correct) error. The point of
// this test is that the decorated `export default` must be recorded only once:
// it must NOT also report a spurious "A module cannot have multiple default
// exports". The `await` identifier is what previously triggered the reparse
// that double-recorded the export.
@foo
export default class C {
x = await + 1;
}