diff --git a/.changeset/few-bats-battle.md b/.changeset/few-bats-battle.md new file mode 100644 index 000000000000..433cbc9f0f32 --- /dev/null +++ b/.changeset/few-bats-battle.md @@ -0,0 +1,5 @@ +--- +swc_fast_ts_strip: patch +--- + +fix(es/typescript): Strip declare export in strip-only mode diff --git a/crates/swc_fast_ts_strip/src/lib.rs b/crates/swc_fast_ts_strip/src/lib.rs index fdc303235ba7..68cd118c05e5 100644 --- a/crates/swc_fast_ts_strip/src/lib.rs +++ b/crates/swc_fast_ts_strip/src/lib.rs @@ -12,12 +12,12 @@ use swc_common::{ }; use swc_ecma_ast::{ ArrowExpr, BindingIdent, Class, ClassDecl, ClassMethod, ClassProp, Decl, DoWhileStmt, - EsVersion, ExportAll, ExportDecl, ExportSpecifier, FnDecl, ForInStmt, ForOfStmt, ForStmt, - IfStmt, ImportDecl, ImportSpecifier, NamedExport, Param, Pat, Program, Stmt, TsAsExpr, - TsConstAssertion, TsEnumDecl, TsExportAssignment, TsImportEqualsDecl, TsIndexSignature, - TsInstantiation, TsInterfaceDecl, TsModuleDecl, TsModuleName, TsNamespaceDecl, TsNonNullExpr, + EsVersion, ExportAll, ExportDecl, ExportDefaultDecl, ExportSpecifier, FnDecl, ForInStmt, + ForOfStmt, ForStmt, IfStmt, ImportDecl, ImportSpecifier, NamedExport, Param, Pat, Program, + Stmt, TsAsExpr, TsConstAssertion, TsEnumDecl, TsExportAssignment, TsImportEqualsDecl, + TsIndexSignature, TsInstantiation, TsModuleDecl, TsModuleName, TsNamespaceDecl, TsNonNullExpr, TsParamPropParam, TsSatisfiesExpr, TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, - TsTypeParamDecl, TsTypeParamInstantiation, VarDecl, WhileStmt, + TsTypeParamDecl, TsTypeParamInstantiation, WhileStmt, }; use swc_ecma_parser::{ lexer::Lexer, @@ -532,16 +532,6 @@ impl Visit for TsStrip { n.visit_children_with(self); } - fn visit_class_decl(&mut self, n: &ClassDecl) { - if n.declare { - self.add_replacement(n.span()); - self.fix_asi(n.span()); - return; - } - - n.visit_children_with(self); - } - fn visit_class_method(&mut self, n: &ClassMethod) { if n.function.body.is_none() || n.is_abstract { self.add_replacement(n.span); @@ -636,19 +626,33 @@ impl Visit for TsStrip { } fn visit_export_decl(&mut self, n: &ExportDecl) { - match n.decl { - swc_ecma_ast::Decl::TsInterface(_) - | swc_ecma_ast::Decl::TsTypeAlias(_) - | swc_ecma_ast::Decl::TsEnum(_) - | swc_ecma_ast::Decl::TsModule(_) => { - self.add_replacement(n.span); - self.fix_asi(n.span); - } + if n.decl.is_ts_declare() { + self.add_replacement(n.span); + self.fix_asi(n.span); + return; + } - _ => { - n.visit_children_with(self); - } + n.visit_children_with(self); + } + + fn visit_export_default_decl(&mut self, n: &ExportDefaultDecl) { + if n.decl.is_ts_interface_decl() { + self.add_replacement(n.span); + self.fix_asi(n.span); + return; } + + n.visit_children_with(self); + } + + fn visit_decl(&mut self, n: &Decl) { + if n.is_ts_declare() { + self.add_replacement(n.span()); + self.fix_asi(n.span()); + return; + } + + n.visit_children_with(self); } fn visit_fn_decl(&mut self, n: &FnDecl) { @@ -756,21 +760,6 @@ impl Visit for TsStrip { n.expr.visit_children_with(self); } - fn visit_ts_enum_decl(&mut self, e: &TsEnumDecl) { - if e.declare { - self.add_replacement(e.span); - self.fix_asi(e.span); - return; - } - - HANDLER.with(|handler| { - handler.span_err( - e.span, - "TypeScript enum is not supported in strip-only mode", - ); - }); - } - fn visit_ts_export_assignment(&mut self, n: &TsExportAssignment) { HANDLER.with(|handler| { handler.span_err( @@ -805,18 +794,16 @@ impl Visit for TsStrip { n.expr.visit_children_with(self); } - fn visit_ts_interface_decl(&mut self, n: &TsInterfaceDecl) { - self.add_replacement(n.span); - self.fix_asi(n.span); + fn visit_ts_enum_decl(&mut self, e: &TsEnumDecl) { + HANDLER.with(|handler| { + handler.span_err( + e.span, + "TypeScript enum is not supported in strip-only mode", + ); + }); } fn visit_ts_module_decl(&mut self, n: &TsModuleDecl) { - if n.declare || matches!(n.id, TsModuleName::Str(..)) { - self.add_replacement(n.span); - self.fix_asi(n.span); - return; - } - HANDLER.with(|handler| { handler.span_err( n.span(), @@ -826,12 +813,6 @@ impl Visit for TsStrip { } fn visit_ts_namespace_decl(&mut self, n: &TsNamespaceDecl) { - if n.declare { - self.add_replacement(n.span); - self.fix_asi(n.span); - return; - } - HANDLER.with(|handler| { handler.span_err( n.span(), @@ -904,25 +885,15 @@ impl Visit for TsStrip { self.add_replacement(span(n.span.lo, n.span.hi)); } - fn visit_var_decl(&mut self, n: &VarDecl) { - if n.declare { - self.add_replacement(n.span); - self.fix_asi(n.span); - return; - } - - n.visit_children_with(self); - } - fn visit_if_stmt(&mut self, n: &IfStmt) { n.visit_children_with(self); - if n.cons.is_ts_stmt() { + if n.cons.is_ts_declare() { self.add_overwrite(n.cons.span_lo(), b';'); } if let Some(alt) = &n.alt { - if alt.is_ts_stmt() { + if alt.is_ts_declare() { self.add_overwrite(alt.span_lo(), b';'); } } @@ -931,7 +902,7 @@ impl Visit for TsStrip { fn visit_for_stmt(&mut self, n: &ForStmt) { n.visit_children_with(self); - if n.body.is_ts_stmt() { + if n.body.is_ts_declare() { self.add_overwrite(n.body.span_lo(), b';'); } } @@ -939,7 +910,7 @@ impl Visit for TsStrip { fn visit_for_in_stmt(&mut self, n: &ForInStmt) { n.visit_children_with(self); - if n.body.is_ts_stmt() { + if n.body.is_ts_declare() { self.add_overwrite(n.body.span_lo(), b';'); } } @@ -947,7 +918,7 @@ impl Visit for TsStrip { fn visit_for_of_stmt(&mut self, n: &ForOfStmt) { n.visit_children_with(self); - if n.body.is_ts_stmt() { + if n.body.is_ts_declare() { self.add_overwrite(n.body.span_lo(), b';'); } } @@ -955,7 +926,7 @@ impl Visit for TsStrip { fn visit_while_stmt(&mut self, n: &WhileStmt) { n.visit_children_with(self); - if n.body.is_ts_stmt() { + if n.body.is_ts_declare() { self.add_overwrite(n.body.span_lo(), b';'); } } @@ -963,26 +934,38 @@ impl Visit for TsStrip { fn visit_do_while_stmt(&mut self, n: &DoWhileStmt) { n.visit_children_with(self); - if n.body.is_ts_stmt() { + if n.body.is_ts_declare() { self.add_overwrite(n.body.span_lo(), b';'); } } } -trait IsTsStmt { - fn is_ts_stmt(&self) -> bool; +trait IsTsDecl { + fn is_ts_declare(&self) -> bool; } -impl IsTsStmt for Stmt { - fn is_ts_stmt(&self) -> bool { +impl IsTsDecl for Decl { + fn is_ts_declare(&self) -> bool { match self { - Stmt::Decl(Decl::TsInterface { .. } | Decl::TsTypeAlias(..)) => true, - Stmt::Decl(Decl::TsModule(n)) => n.declare || matches!(n.id, TsModuleName::Str(..)), - Stmt::Decl(Decl::TsEnum(e)) => e.declare, + Self::TsInterface { .. } | Self::TsTypeAlias(..) => true, + + Self::TsModule(module) => module.declare || matches!(module.id, TsModuleName::Str(..)), + Self::TsEnum(ref r#enum) => r#enum.declare, + + Self::Var(ref var) => var.declare, + Self::Fn(FnDecl { declare: true, .. }) + | Self::Class(ClassDecl { declare: true, .. }) => true, _ => false, } } } + +impl IsTsDecl for Stmt { + fn is_ts_declare(&self) -> bool { + self.as_decl().map_or(false, IsTsDecl::is_ts_declare) + } +} + trait U8Helper { fn is_utf8_char_boundary(&self) -> bool; } diff --git a/crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr b/crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr index 2efbeccbfe87..a7bcfdc15e70 100644 --- a/crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr +++ b/crates/swc_fast_ts_strip/tests/errors/enums.swc-stderr @@ -3,3 +3,9 @@ 1 | enum Foo { } : ^^^^^^^^^^^^ `---- + x TypeScript enum is not supported in strip-only mode + ,-[3:1] + 2 | + 3 | export enum Bar { } + : ^^^^^^^^^^^^ + `---- diff --git a/crates/swc_fast_ts_strip/tests/errors/enums.ts b/crates/swc_fast_ts_strip/tests/errors/enums.ts index dfa841058431..9a599b12b341 100644 --- a/crates/swc_fast_ts_strip/tests/errors/enums.ts +++ b/crates/swc_fast_ts_strip/tests/errors/enums.ts @@ -1 +1,3 @@ -enum Foo { } \ No newline at end of file +enum Foo { } + +export enum Bar { } \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr b/crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr index 20b6f1cdb834..6400d96291e3 100644 --- a/crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr +++ b/crates/swc_fast_ts_strip/tests/errors/modules.swc-stderr @@ -3,3 +3,9 @@ 1 | module aModuleKeywordNamespace { } : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- + x TypeScript namespace declaration is not supported in strip-only mode + ,-[3:1] + 2 | + 3 | export module aModuleKeywordExportedNamespace { } + : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + `---- diff --git a/crates/swc_fast_ts_strip/tests/errors/modules.ts b/crates/swc_fast_ts_strip/tests/errors/modules.ts index ad71f09e7580..9274355d33c0 100644 --- a/crates/swc_fast_ts_strip/tests/errors/modules.ts +++ b/crates/swc_fast_ts_strip/tests/errors/modules.ts @@ -1 +1,3 @@ -module aModuleKeywordNamespace { } \ No newline at end of file +module aModuleKeywordNamespace { } + +export module aModuleKeywordExportedNamespace { } \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr b/crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr index ae5fe90b0de2..1de76bce5e24 100644 --- a/crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr +++ b/crates/swc_fast_ts_strip/tests/errors/namespaces.swc-stderr @@ -3,3 +3,9 @@ 1 | namespace Foo { } : ^^^^^^^^^^^^^^^^^ `---- + x TypeScript namespace declaration is not supported in strip-only mode + ,-[3:1] + 2 | + 3 | export namespace Bar { } + : ^^^^^^^^^^^^^^^^^ + `---- diff --git a/crates/swc_fast_ts_strip/tests/errors/namespaces.ts b/crates/swc_fast_ts_strip/tests/errors/namespaces.ts index f10df856e654..c19c32771565 100644 --- a/crates/swc_fast_ts_strip/tests/errors/namespaces.ts +++ b/crates/swc_fast_ts_strip/tests/errors/namespaces.ts @@ -1 +1,3 @@ -namespace Foo { } \ No newline at end of file +namespace Foo { } + +export namespace Bar { } diff --git a/crates/swc_fast_ts_strip/tests/fixture/export-declare.js b/crates/swc_fast_ts_strip/tests/fixture/export-declare.js new file mode 100644 index 000000000000..0d240f761365 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/export-declare.js @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/crates/swc_fast_ts_strip/tests/fixture/export-declare.transform.js b/crates/swc_fast_ts_strip/tests/fixture/export-declare.transform.js new file mode 100644 index 000000000000..2234b9cae16d --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/export-declare.transform.js @@ -0,0 +1 @@ +export { }; diff --git a/crates/swc_fast_ts_strip/tests/fixture/export-declare.ts b/crates/swc_fast_ts_strip/tests/fixture/export-declare.ts new file mode 100644 index 000000000000..5a7bbfec2c84 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/export-declare.ts @@ -0,0 +1,8 @@ +export declare class Foo {} +export declare interface Bar {} +export declare type Baz = {}; +export declare enum Qux {} +export declare const Quux = 0; +export declare function Corge(): void; +export declare namespace Grault {} +export declare module Garply {} diff --git a/crates/swc_fast_ts_strip/tests/fixture/export-interface.js b/crates/swc_fast_ts_strip/tests/fixture/export-interface.js new file mode 100644 index 000000000000..505658fb3c19 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/export-interface.js @@ -0,0 +1,2 @@ + + diff --git a/crates/swc_fast_ts_strip/tests/fixture/export-interface.transform.js b/crates/swc_fast_ts_strip/tests/fixture/export-interface.transform.js new file mode 100644 index 000000000000..2234b9cae16d --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/export-interface.transform.js @@ -0,0 +1 @@ +export { }; diff --git a/crates/swc_fast_ts_strip/tests/fixture/export-interface.ts b/crates/swc_fast_ts_strip/tests/fixture/export-interface.ts new file mode 100644 index 000000000000..35f2a916931b --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/export-interface.ts @@ -0,0 +1,2 @@ +export default interface Foo {} +export interface Bar {}