Skip to content

Commit e3022ab

Browse files
committed
fix(minifier): keep classes that have static initializer that have side effects
1 parent d79f4ec commit e3022ab

File tree

2 files changed

+26
-22
lines changed

2 files changed

+26
-22
lines changed

crates/oxc_minifier/src/peephole/remove_unused_declaration.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,23 +130,21 @@ mod test {
130130
test_options("class C { foo }", "", &options);
131131
test_options("class C { foo = bar }", "", &options);
132132
test_options("class C { foo = 1 }", "", &options);
133-
test_options("class C { static foo = bar }", "bar", &options);
133+
// TODO: would be nice if this is removed but the one with `this` is kept.
134+
test_same_options("class C { static foo = bar }", &options);
135+
test_same_options("class C { static foo = this.bar = {} }", &options);
134136
test_options("class C { static foo = 1 }", "", &options);
135137
test_options("class C { [foo] = bar }", "foo", &options);
136138
test_options("class C { [foo] = 1 }", "foo", &options);
137-
test_options("class C { static [foo] = bar }", "foo, bar", &options);
139+
test_same_options("class C { static [foo] = bar }", &options);
138140
test_options("class C { static [foo] = 1 }", "foo", &options);
139141

140142
// accessor
141143
test_options("class C { accessor foo = 1 }", "", &options);
142144
test_options("class C { accessor [foo] = 1 }", "foo", &options);
143145

144146
// order
145-
test_options(
146-
"class _ extends A { static [B] = C; static [D]() {} }",
147-
"A, B, C, D",
148-
&options,
149-
);
147+
test_options("class _ extends A { [B] = C; [D]() {} }", "A, B, D", &options);
150148

151149
// decorators
152150
test_same_options("class C { @dec foo() {} }", &options);

crates/oxc_minifier/src/peephole/remove_unused_expression.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -674,20 +674,29 @@ impl<'a> PeepholeOptimizations {
674674
{
675675
return None;
676676
}
677-
// Keep the entire class if non-empty static block exists.
677+
// Keep the entire class if there are class level side effects.
678678
for e in &c.body.body {
679679
match e {
680680
e if e.has_decorator() => return None,
681681
ClassElement::TSIndexSignature(_) => return None,
682-
ClassElement::StaticBlock(block) => {
683-
if !block.body.is_empty() {
684-
return None;
685-
}
682+
ClassElement::StaticBlock(block) if !block.body.is_empty() => return None,
683+
ClassElement::PropertyDefinition(prop)
684+
if prop.r#static
685+
&& prop.value.as_ref().is_some_and(|v| v.may_have_side_effects(ctx)) =>
686+
{
687+
return None;
688+
}
689+
ClassElement::AccessorProperty(prop)
690+
if prop.r#static
691+
&& prop.value.as_ref().is_some_and(|v| v.may_have_side_effects(ctx)) =>
692+
{
693+
return None;
686694
}
687695
_ => {}
688696
}
689697
}
690698

699+
// Otherwise extract the expressions.
691700
let mut exprs = ctx.ast.vec();
692701

693702
if let Some(e) = &mut c.super_class {
@@ -721,9 +730,8 @@ impl<'a> PeepholeOptimizations {
721730
ClassElement::PropertyDefinition(def) => def.value.take(),
722731
ClassElement::AccessorProperty(def) => def.value.take(),
723732
} {
724-
if init.may_have_side_effects(ctx) {
725-
exprs.push(init);
726-
}
733+
// Already checked side effects above.
734+
exprs.push(init);
727735
}
728736
}
729737
}
@@ -1115,23 +1123,21 @@ mod test {
11151123
test_options("(class { foo })", "", &options);
11161124
test_options("(class { foo = bar })", "", &options);
11171125
test_options("(class { foo = 1 })", "", &options);
1118-
test_options("(class { static foo = bar })", "bar", &options);
1126+
// TODO: would be nice if this is removed but the one with `this` is kept.
1127+
test_same_options("(class { static foo = bar })", &options);
1128+
test_same_options("(class { static foo = this.bar = {} })", &options);
11191129
test_options("(class { static foo = 1 })", "", &options);
11201130
test_options("(class { [foo] = bar })", "foo", &options);
11211131
test_options("(class { [foo] = 1 })", "foo", &options);
1122-
test_options("(class { static [foo] = bar })", "foo, bar", &options);
1132+
test_same_options("(class { static [foo] = bar })", &options);
11231133
test_options("(class { static [foo] = 1 })", "foo", &options);
11241134

11251135
// accessor
11261136
test_options("(class { accessor foo = 1 })", "", &options);
11271137
test_options("(class { accessor [foo] = 1 })", "foo", &options);
11281138

11291139
// order
1130-
test_options(
1131-
"(class extends A { static [B] = C; static [D]() {} })",
1132-
"A, B, C, D",
1133-
&options,
1134-
);
1140+
test_options("(class extends A { [B] = C; [D]() {} })", "A, B, D", &options);
11351141

11361142
// decorators
11371143
test_same_options("(class { @dec foo() {} })", &options);

0 commit comments

Comments
 (0)