diff --git a/.changeset/polite-tools-lie.md b/.changeset/polite-tools-lie.md new file mode 100644 index 00000000000..a40ab95d6b4 --- /dev/null +++ b/.changeset/polite-tools-lie.md @@ -0,0 +1,5 @@ +--- +swc_fast_ts_strip: patch +--- + +fix(es/typescript): Fix ASI in expression for TypeScript strip diff --git a/crates/swc_fast_ts_strip/src/lib.rs b/crates/swc_fast_ts_strip/src/lib.rs index 36880b166c9..ac851cb54b0 100644 --- a/crates/swc_fast_ts_strip/src/lib.rs +++ b/crates/swc_fast_ts_strip/src/lib.rs @@ -389,13 +389,21 @@ impl TsStrip { .. } = &self.tokens[index - 1]; - let index = self.get_prev_token_index(span.hi); + let index = self.get_prev_token_index(span.hi - BytePos(1)); if index == self.tokens.len() - 1 { // Skip if the token is the last token. return; } - let TokenAndSpan { token, .. } = &self.tokens[index + 1]; + let TokenAndSpan { + token, + had_line_break, + .. + } = &self.tokens[index + 1]; + + if !*had_line_break { + return; + } // Add a semicolon if the next token is `[`, `(`, `/`, `+`, or `-` match token { @@ -413,6 +421,23 @@ impl TsStrip { _ => {} } } + + fn fix_asi_in_expr(&mut self, span: Span) { + let index = self.get_prev_token_index(span.hi - BytePos(1)); + if index == self.tokens.len() - 1 { + return; + } + + if let TokenAndSpan { + // Only `([` affect ASI. + token: Token::LParen | Token::LBracket, + had_line_break: true, + .. + } = &self.tokens[index + 1] + { + self.add_overwrite(span.lo, b';'); + } + } } impl Visit for TsStrip { @@ -708,6 +733,16 @@ impl Visit for TsStrip { fn visit_ts_as_expr(&mut self, n: &TsAsExpr) { self.add_replacement(span(n.expr.span().hi, n.span.hi)); + let TokenAndSpan { + token, + span: as_span, + .. + } = self.get_next_token(n.expr.span_hi()); + debug_assert_eq!( + token, + &Token::Word(Word::Ident(IdentLike::Known(KnownIdent::As))) + ); + self.fix_asi_in_expr(span(as_span.lo, n.span.hi)); n.expr.visit_children_with(self); } @@ -820,6 +855,17 @@ impl Visit for TsStrip { fn visit_ts_satisfies_expr(&mut self, n: &TsSatisfiesExpr) { self.add_replacement(span(n.expr.span().hi, n.span.hi)); + let TokenAndSpan { + token, + span: as_span, + .. + } = self.get_next_token(n.expr.span_hi()); + debug_assert_eq!( + token, + &Token::Word(Word::Ident(IdentLike::Known(KnownIdent::Satisfies))) + ); + self.fix_asi_in_expr(span(as_span.lo, n.span.hi)); + n.expr.visit_children_with(self); } diff --git a/crates/swc_fast_ts_strip/tests/fixture/issue-9355.js b/crates/swc_fast_ts_strip/tests/fixture/issue-9355.js new file mode 100644 index 00000000000..baa2f5f894e --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/issue-9355.js @@ -0,0 +1,20 @@ +const x1 = 10 ; +(1) + +const x2 = (10); +(1) + +const x3 = 10 ; +(1) + +const x4 = (10); +(1) + +const y = 10 + + 1 + +const z = 10 + / 1 + +const w = 10 ; +[1]; diff --git a/crates/swc_fast_ts_strip/tests/fixture/issue-9355.transform.js b/crates/swc_fast_ts_strip/tests/fixture/issue-9355.transform.js new file mode 100644 index 00000000000..bc5a37b4e35 --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/issue-9355.transform.js @@ -0,0 +1,14 @@ +const x1 = 10; +1; +const x2 = 10; +1; +const x3 = 10; +1; +const x4 = 10; +1; +const y = 10 + 1; +const z = 10 / 1; +const w = 10; +[ + 1 +]; diff --git a/crates/swc_fast_ts_strip/tests/fixture/issue-9355.ts b/crates/swc_fast_ts_strip/tests/fixture/issue-9355.ts new file mode 100644 index 00000000000..bb396d8ab9d --- /dev/null +++ b/crates/swc_fast_ts_strip/tests/fixture/issue-9355.ts @@ -0,0 +1,20 @@ +const x1 = 10 as any +(1) + +const x2 = (10)as any +(1) + +const x3 = 10 satisfies any +(1) + +const x4 = (10)satisfies any +(1) + +const y = 10 as any + + 1 + +const z = 10 as any + / 1 + +const w = 10 as any +[1];