From 121b5fefbc17932816f69c88edc14f8387c493e9 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Wed, 15 Jan 2025 22:32:10 +0800 Subject: [PATCH] fix(es/ts_strip): Handle ASI hazard in return statement (#9882) **Related issue:** - Closes /~https://github.com/swc-project/swc/issues/9878 --- .changeset/curly-poems-dance.md | 5 ++ crates/swc_fast_ts_strip/src/lib.rs | 60 ++++++++++++++++--- .../tests/fixture/issue-9878.js | 18 ++++++ .../tests/fixture/issue-9878.transform.js | 9 +++ .../tests/fixture/issue-9878.ts | 18 ++++++ 5 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 .changeset/curly-poems-dance.md create mode 100644 crates/swc_fast_ts_strip/tests/fixture/issue-9878.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/issue-9878.transform.js create mode 100644 crates/swc_fast_ts_strip/tests/fixture/issue-9878.ts diff --git a/.changeset/curly-poems-dance.md b/.changeset/curly-poems-dance.md new file mode 100644 index 000000000000..b9337603b288 --- /dev/null +++ b/.changeset/curly-poems-dance.md @@ -0,0 +1,5 @@ +--- +swc_fast_ts_strip: minor +--- + +fix(es/ts_strip): Handle ASI hazard in return statement diff --git a/crates/swc_fast_ts_strip/src/lib.rs b/crates/swc_fast_ts_strip/src/lib.rs index 7c2f37aa3e50..930157f4e23a 100644 --- a/crates/swc_fast_ts_strip/src/lib.rs +++ b/crates/swc_fast_ts_strip/src/lib.rs @@ -15,10 +15,11 @@ use swc_ecma_ast::{ Constructor, Decl, DefaultDecl, DoWhileStmt, EsVersion, ExportAll, ExportDecl, ExportDefaultDecl, ExportSpecifier, FnDecl, ForInStmt, ForOfStmt, ForStmt, GetterProp, IfStmt, ImportDecl, ImportSpecifier, NamedExport, ObjectPat, Param, Pat, PrivateMethod, PrivateProp, - Program, SetterProp, Stmt, TsAsExpr, TsConstAssertion, TsEnumDecl, TsExportAssignment, - TsImportEqualsDecl, TsIndexSignature, TsInstantiation, TsModuleDecl, TsModuleName, - TsNamespaceDecl, TsNonNullExpr, TsParamPropParam, TsSatisfiesExpr, TsTypeAliasDecl, TsTypeAnn, - TsTypeAssertion, TsTypeParamDecl, TsTypeParamInstantiation, VarDeclarator, WhileStmt, + Program, ReturnStmt, SetterProp, Stmt, TsAsExpr, TsConstAssertion, TsEnumDecl, + TsExportAssignment, TsImportEqualsDecl, TsIndexSignature, TsInstantiation, TsModuleDecl, + TsModuleName, TsNamespaceDecl, TsNonNullExpr, TsParamPropParam, TsSatisfiesExpr, + TsTypeAliasDecl, TsTypeAnn, TsTypeAssertion, TsTypeParamDecl, TsTypeParamInstantiation, + VarDeclarator, WhileStmt, }; use swc_ecma_parser::{ lexer::Lexer, @@ -610,11 +611,6 @@ impl Visit for TsStrip { } fn visit_arrow_expr(&mut self, n: &ArrowExpr) { - #[inline(always)] - fn is_new_line(c: char) -> bool { - matches!(c, '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}') - } - 'type_params: { // ```TypeScript // let f = async < @@ -692,6 +688,48 @@ impl Visit for TsStrip { n.body.visit_with(self); } + fn visit_return_stmt(&mut self, n: &ReturnStmt) { + let Some(arg) = n.arg.as_deref() else { + return; + }; + + arg.visit_with(self); + + if let Some(arrow_expr) = arg.as_arrow() { + if arrow_expr.is_async { + // We have already handled type parameters in `visit_arrow_expr`. + return; + } + + // ```TypeScript + // return + // (v: T) => v; + // ``` + // + // ```TypeScript + // return ( + // v ) => v; + // ``` + + if let Some(tp) = &arrow_expr.type_params { + let l_paren = self.get_next_token(tp.span.hi); + debug_assert_eq!(l_paren.token, Token::LParen); + + let slice = self.get_src_slice(tp.span.with_hi(l_paren.span.lo)); + + if !slice.chars().any(is_new_line) { + return; + } + + let l_paren_pos = l_paren.span.lo; + let l_lt_pos = tp.span.lo; + + self.add_overwrite(l_paren_pos, b' '); + self.add_overwrite(l_lt_pos, b'('); + } + } + } + fn visit_binding_ident(&mut self, n: &BindingIdent) { n.visit_children_with(self); @@ -1303,6 +1341,10 @@ impl Visit for TsStrip { } } +#[inline(always)] +fn is_new_line(c: char) -> bool { + matches!(c, '\u{000A}' | '\u{000D}' | '\u{2028}' | '\u{2029}') +} trait IsTsDecl { fn is_ts_declare(&self) -> bool; } diff --git a/crates/swc_fast_ts_strip/tests/fixture/issue-9878.js b/crates/swc_fast_ts_strip/tests/fixture/issue-9878.js new file mode 100644 index 000000000000..b200909d5d5b --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/issue-9878.js @@ -0,0 +1,18 @@ +function f() { + return ( + x )=>x; +} + +function f2() { + return ( + + x )=>x; +} + + +function f3() { + return ( + + x + )=>x; +} \ No newline at end of file diff --git a/crates/swc_fast_ts_strip/tests/fixture/issue-9878.transform.js b/crates/swc_fast_ts_strip/tests/fixture/issue-9878.transform.js new file mode 100644 index 000000000000..9f663419aa98 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/issue-9878.transform.js @@ -0,0 +1,9 @@ +function f() { + return (x)=>x; +} +function f2() { + return (x)=>x; +} +function f3() { + return (x)=>x; +} diff --git a/crates/swc_fast_ts_strip/tests/fixture/issue-9878.ts b/crates/swc_fast_ts_strip/tests/fixture/issue-9878.ts new file mode 100644 index 000000000000..c6fed4606be5 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/issue-9878.ts @@ -0,0 +1,18 @@ +function f() { + return + (x: T)=>x; +} + +function f2() { + return + (x: T)=>x; +} + + +function f3() { + return + (x: T): Promise< + T>=>x; +} \ No newline at end of file