Skip to content

Commit

Permalink
fix(es/typescript): Handle ASI hazards in fast type strip
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed Nov 3, 2024
1 parent 1ccbbf0 commit 844ba71
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 15 deletions.
103 changes: 88 additions & 15 deletions crates/swc_fast_ts_strip/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,17 @@ impl Visit for TsStrip {
}

'type_params: {
// ```TypeScript
// let f = async <
// T
// >(v: T) => v;
// ```

// ```TypeScript
// let f = async (
//
// v ) => v;
// ```
if let Some(tp) = &n.type_params {
self.add_replacement(tp.span);

Expand Down Expand Up @@ -673,7 +684,12 @@ impl Visit for TsStrip {
return;
}

self.strip_class_modifier(n.span.lo, n.key.span_lo());
// TODO(AST): constructor can not be optional
debug_assert!(!n.is_optional);

if n.accessibility.is_some() {
self.strip_class_modifier(n.span.lo, n.key.span_lo());
}

n.visit_children_with(self);
}
Expand All @@ -684,20 +700,43 @@ impl Visit for TsStrip {
return;
}

let has_modifier = n.is_override || n.accessibility.is_some();

// @foo public m(): void {}
let start_pos = n
.function
.decorators
.last()
.map_or(n.span.lo, |d| d.span.hi);

self.strip_class_modifier(start_pos, n.key.span_lo());
if has_modifier {
self.strip_class_modifier(start_pos, n.key.span_lo());
}

if n.is_optional {
let mark_index = self.get_next_token_index(n.key.span_hi());
self.strip_optional_mark(mark_index);
}

// `public [foo]()`
// `; [foo]()`
//
// `public *foo()`
// `; *foo()`
//
// `public in()`
// `; in()`
if (has_modifier && !n.is_static)
&& (n.key.is_computed()
|| n.function.is_generator
|| n.key
.as_ident()
.filter(|k| matches!(k.sym.as_ref(), "in" | "instanceof"))
.is_some())
{
self.add_overwrite(start_pos, b';');
}

n.visit_children_with(self);
}

Expand All @@ -707,9 +746,12 @@ impl Visit for TsStrip {
return;
}

let has_modifier = n.readonly || n.is_override || n.accessibility.is_some();
let start_pos = n.decorators.last().map_or(n.span.lo, |d| d.span.hi);

self.strip_class_modifier(start_pos, n.key.span_lo());
if has_modifier {
self.strip_class_modifier(start_pos, n.key.span_lo());
}

if n.is_optional {
let mark_index = self.get_next_token_index(n.key.span_hi());
Expand All @@ -720,23 +762,51 @@ impl Visit for TsStrip {
self.strip_definite_mark(mark_index);
}

if n.value.is_none() && n.key.as_ident().filter(|k| k.sym == "static").is_some() {
if let Some(type_ann) = &n.type_ann {
self.add_overwrite(type_ann.span.lo, b';');
if n.value.is_none() {
if let Some(key) = n.key.as_ident() {
if matches!(key.sym.as_ref(), "get" | "set" | "static") {
// `get: number`
// `get; `
if let Some(type_ann) = &n.type_ann {
self.add_overwrite(type_ann.span.lo, b';');
}
}
}
}

// `private [foo]`
// `; [foo]`
//
// `private in`
// `; in`
if !n.is_static
&& has_modifier
&& (n.key.is_computed()
|| n.key
.as_ident()
.filter(|k| matches!(k.sym.as_ref(), "in" | "instanceof"))
.is_some())
{
self.add_overwrite(start_pos, b';');
}

n.visit_children_with(self);
}

fn visit_private_method(&mut self, n: &PrivateMethod) {
let start_pos = n
.function
.decorators
.last()
.map_or(n.span.lo, |d| d.span.hi);

self.strip_class_modifier(start_pos, n.key.span.lo);
debug_assert!(!n.is_override);
debug_assert!(!n.is_abstract);

// Is `private #foo()` valid?
if n.accessibility.is_some() {
let start_pos = n
.function
.decorators
.last()
.map_or(n.span.lo, |d| d.span.hi);

self.strip_class_modifier(start_pos, n.key.span.lo);
}

if n.is_optional {
let mark_index = self.get_next_token_index(n.key.span.hi);
Expand All @@ -747,9 +817,12 @@ impl Visit for TsStrip {
}

fn visit_private_prop(&mut self, n: &PrivateProp) {
let start_pos = n.decorators.last().map_or(n.span.lo, |d| d.span.hi);
debug_assert!(!n.is_override);

self.strip_class_modifier(start_pos, n.key.span.lo);
if n.readonly || n.accessibility.is_some() {
let start_pos = n.decorators.last().map_or(n.span.lo, |d| d.span.hi);
self.strip_class_modifier(start_pos, n.key.span.lo);
}

if n.is_optional {
let mark_index = self.get_next_token_index(n.key.span.hi);
Expand Down
40 changes: 40 additions & 0 deletions crates/swc_fast_ts_strip/tests/fixture/issue-9681.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class A {
foo = 1
; ["bar"] = 2;

x = 1
; ["y"](){}

z = 1
static ["w"](){}
}

class Test {
x = 1
; *f() {}
}

class Test2 {
out = 'out'
; in
name
}

class Test3 {
out = 'out'
; in
name;

x = 'x'
; instanceof
String
}

class Test4 {
set;
a(x) {}
get;
b() {}
static;
c(x) {}
}
33 changes: 33 additions & 0 deletions crates/swc_fast_ts_strip/tests/fixture/issue-9681.transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class A {
foo = 1;
["bar"] = 2;
x = 1;
["y"]() {}
z = 1;
static ["w"]() {}
}
class Test {
x = 1;
*f() {}
}
class Test2 {
out = 'out';
in;
name;
}
class Test3 {
out = 'out';
in;
name;
x = 'x';
instanceof;
String;
}
class Test4 {
set;
a(x) {}
get;
b() {}
static;
c(x) {}
}
40 changes: 40 additions & 0 deletions crates/swc_fast_ts_strip/tests/fixture/issue-9681.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class A {
foo = 1
private ["bar"] = 2;

x = 1
public ["y"](){}

z = 1
public static ["w"](){}
}

class Test {
x = 1
public *f() {}
}

class Test2 {
out = 'out'
public in
public name
}

class Test3 {
out = 'out'
public in: any
name;

x = 'x'
public instanceof: any
String: any
}

class Test4 {
set: any
a(x) {}
get: any
b() {}
static: any
c(x) {}
}

0 comments on commit 844ba71

Please sign in to comment.