fix(parser): reject TypeScript default exports in JavaScript (#28440)

Restrict default-exported interfaces and abstract classes to TypeScript
sources.

Validated with scoped Rust checks, full conformance, parser bindings,
allocation tracking.

AI-assisted (Codex).
This commit is contained in:
Boshen authored and GitHub committed 2026-10-30 17:17:30 +08:00
1 parent dbf84827f7
commit c97c43c997
5 files changed
+21 -5

No files matched your search

+2 -2
View File
@@ -753,7 +753,7 @@ impl<'a, C: Config> ParserImpl<'a, C> {
let next = self.lexer.peek_token();
if !next.is_on_new_line() {
// export default abstract class C {}
if kind == Kind::Abstract && next.kind() == Kind::Class {
if self.is_ts && kind == Kind::Abstract && next.kind() == Kind::Class {
self.bump_any();
let modifiers = Modifiers::new_single(ModifierKind::Abstract, modifier_start);
return ExportDefaultDeclarationKind::ClassDeclaration(
@@ -778,7 +778,7 @@ impl<'a, C: Config> ParserImpl<'a, C> {
return ExportDefaultDeclarationKind::FunctionDeclaration(func);
}
// export default interface I {}
if kind == Kind::Interface {
if self.is_ts && kind == Kind::Interface {
self.bump_any();
for decorator in &decorators {
self.error(diagnostics::decorators_are_not_valid_here(decorator.span));
@@ -0,0 +1 @@
export default abstract class C {}
@@ -0,0 +1 @@
export default interface I {}
+2 -2
View File
@@ -1,3 +1,3 @@
lexer_misc Summary:
AST Parsed : 393/393 (100.00%)
Positive Passed: 393/393 (100.00%)
AST Parsed : 395/395 (100.00%)
Positive Passed: 395/395 (100.00%)
+15 -1
View File
@@ -1,7 +1,7 @@
parser_misc Summary:
AST Parsed : 130/130 (100.00%)
Positive Passed: 130/130 (100.00%)
Negative Passed: 265/265 (100.00%)
Negative Passed: 267/267 (100.00%)
× TS(1275): 'accessor' modifier can only appear on a property declaration.
╭─[misc/fail/accessor-modifier-abstract-method.ts:1:29]
@@ -1192,6 +1192,20 @@ Negative Passed: 265/265 (100.00%)
· ──────
╰────
× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[misc/fail/js-export-default-abstract-class.js:1:24]
1 │ export default abstract class C {}
· ▲
╰────
help: Try inserting a semicolon here
× Expected a semicolon or an implicit semicolon after a statement, but found none
╭─[misc/fail/js-export-default-interface.js:1:25]
1 │ export default interface I {}
· ▲
╰────
help: Try inserting a semicolon here
× Adjacent JSX elements must be wrapped in an enclosing tag.
╭─[misc/fail/jsx-adjacent-elements.jsx:3:3]
2 │ <div />