Skip to content

Commit 213fa63

Browse files
committed
feat(es/minifier): Fine grained effect analysis of class
1 parent fe38342 commit 213fa63

19 files changed

Lines changed: 243 additions & 281 deletions

File tree

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1 @@
11
//// [assignParameterPropertyToPropertyDeclarationES2022.ts]
2-
class F {
3-
Inner = class extends F {
4-
p2 = this.p1;
5-
};
6-
p1 = 0;
7-
}
8-
class G {
9-
p1;
10-
Inner = class extends G {
11-
p2 = this.p1;
12-
};
13-
constructor(p1){
14-
this.p1 = p1;
15-
}
16-
}
Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1 @@
11
//// [assignParameterPropertyToPropertyDeclarationESNext.ts]
2-
class F {
3-
Inner = class extends F {
4-
p2 = this.p1;
5-
};
6-
p1 = 0;
7-
}
8-
class G {
9-
p1;
10-
Inner = class extends G {
11-
p2 = this.p1;
12-
};
13-
constructor(p1){
14-
this.p1 = p1;
15-
}
16-
}
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
//// [classStaticBlock15.ts]
2-
var _C__1;
3-
console.log(_C__1);
2+
console.log(void 0);
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
//// [classStaticBlock15.ts]
2-
var _C__1;
3-
console.log(_C__1);
2+
console.log(void 0);
Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,2 @@
11
//// [superSymbolIndexedAccess3.ts]
2-
var symbol = Symbol.for('myThing');
3-
class Foo {
4-
[symbol]() {
5-
return 0;
6-
}
7-
}
8-
class Bar extends Foo {
9-
[symbol]() {
10-
return super[Bar]();
11-
}
12-
}
2+
Symbol.for('myThing');

crates/swc/tests/tsc-references/uniqueSymbols.2.minified.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,4 @@ class C0 {
5454
this.a = s, this.b = N.s, this.c = N.s, this.d = s, this.e = N.s, this.f = N.s;
5555
}
5656
}
57-
o[s], o[N.s], o[N.s], f(s), f(N.s), f(N.s), g(s), g(N.s), g(N.s), s, N.s, N.s, 2 * Math.random() && s, 2 * Math.random() && N.s, 2 * Math.random() && N.s, s, N.s;
58-
class C1 {
59-
static{
60-
N.s, N.s;
61-
}
62-
}
57+
o[s], o[N.s], o[N.s], f(s), f(N.s), f(N.s), g(s), g(N.s), g(N.s), s, N.s, N.s, 2 * Math.random() && s, 2 * Math.random() && N.s, 2 * Math.random() && N.s, s, N.s, N.s, N.s;

crates/swc/tests/tsc-references/uniqueSymbolsDeclarations.2.minified.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,4 @@ class C0 {
5454
this.a = s, this.b = N.s, this.c = N.s, this.d = s, this.e = N.s, this.f = N.s;
5555
}
5656
}
57-
o[s], o[N.s], o[N.s], f(s), f(N.s), f(N.s), g(s), g(N.s), g(N.s), s, N.s, N.s, 2 * Math.random() && s, 2 * Math.random() && N.s, 2 * Math.random() && N.s, s, N.s;
58-
class C1 {
59-
static{
60-
N.s, N.s;
61-
}
62-
}
57+
o[s], o[N.s], o[N.s], f(s), f(N.s), f(N.s), g(s), g(N.s), g(N.s), s, N.s, N.s, 2 * Math.random() && s, 2 * Math.random() && N.s, 2 * Math.random() && N.s, s, N.s, N.s, N.s;

crates/swc_ecma_minifier/src/compress/optimize/mod.rs

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use swc_ecma_ast::*;
1010
use swc_ecma_transforms_base::rename::contains_eval;
1111
use swc_ecma_transforms_optimization::debug_assert_valid;
1212
use swc_ecma_utils::{
13-
prepend_stmts, prop_name_from_ident, ExprCtx, ExprExt, ExprFactory, IdentUsageFinder, IsEmpty,
14-
ModuleItemLike, StmtLike, Type, Value,
13+
prepend_stmts, prop_name_from_ident, ExprCtx, ExprExt, ExprFactory, IsEmpty, ModuleItemLike,
14+
StmtLike, Type, Value,
1515
};
1616
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith, VisitWith};
1717
#[cfg(feature = "debug")]
@@ -677,26 +677,11 @@ impl Optimizer<'_> {
677677
}
678678

679679
Expr::Class(cls) => {
680-
// Do not remove class if it's self-referencing
681-
if let Some(id) = &cls.ident {
682-
if IdentUsageFinder::find(id, &cls.class.body) {
683-
return Some(cls.take().into());
684-
}
685-
}
686-
687-
if cls
688-
.class
689-
.body
690-
.iter()
691-
.any(|m| m.as_static_block().iter().any(|s| !s.body.is_empty()))
692-
{
693-
// there's nothing we can do about it
694-
return Some(cls.take().into());
695-
}
696-
697-
let Some(side_effects) =
698-
extract_class_side_effect(self.ctx.expr_ctx, &mut cls.class)
699-
else {
680+
let Some(side_effects) = extract_class_side_effect(
681+
self.ctx.expr_ctx,
682+
cls.ident.as_ref(),
683+
&mut cls.class,
684+
) else {
700685
return Some(cls.take().into());
701686
};
702687

crates/swc_ecma_minifier/src/compress/optimize/unused.rs

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -535,32 +535,6 @@ impl Optimizer<'_> {
535535

536536
match decl {
537537
Decl::Class(ClassDecl { ident, class, .. }) => {
538-
if ident.sym == "arguments" {
539-
return;
540-
}
541-
542-
// Fix https://github.com/swc-project/swc/issues/5588
543-
let may_have_side_effect = class.body.iter().any(|m| match m {
544-
ClassMember::ClassProp(ClassProp {
545-
is_static: true,
546-
value: Some(_),
547-
..
548-
})
549-
| ClassMember::PrivateProp(PrivateProp {
550-
is_static: true,
551-
value: Some(_),
552-
..
553-
}) => true,
554-
ClassMember::StaticBlock(StaticBlock {
555-
body: BlockStmt { stmts, .. },
556-
..
557-
}) if !stmts.is_empty() => true,
558-
_ => false,
559-
});
560-
if may_have_side_effect {
561-
return;
562-
}
563-
564538
// If it is not used, drop it.
565539
if self
566540
.data
@@ -569,7 +543,8 @@ impl Optimizer<'_> {
569543
.map(|v| v.usage_count == 0 && v.property_mutation_count == 0)
570544
.unwrap_or(false)
571545
{
572-
let Some(side_effects) = extract_class_side_effect(self.ctx.expr_ctx, class)
546+
let Some(side_effects) =
547+
extract_class_side_effect(self.ctx.expr_ctx, Some(ident), class)
573548
else {
574549
return;
575550
};

crates/swc_ecma_minifier/src/compress/optimize/util.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ use swc_common::{util::take::Take, Mark, SyntaxContext, DUMMY_SP};
1010
use swc_ecma_ast::*;
1111
use swc_ecma_transforms_base::perf::{Parallel, ParallelExt};
1212
use swc_ecma_utils::{
13-
collect_decls, contains_this_expr, prop_name_from_ident, ExprCtx, ExprExt, Remapper,
13+
collect_decls, contains_this_expr, prop_name_from_ident, ExprCtx, ExprExt, IdentUsageFinder,
14+
Remapper,
1415
};
1516
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};
1617
use tracing::debug;
1718

1819
use super::{Ctx, Optimizer};
19-
use crate::HEAVY_TASK_PARALLELS;
20+
use crate::{compress::util::contains_super, HEAVY_TASK_PARALLELS};
2021

2122
impl<'b> Optimizer<'b> {
2223
pub(super) fn normalize_expr(&mut self, e: &mut Expr) {
@@ -164,10 +165,11 @@ impl Drop for WithCtx<'_, '_> {
164165
}
165166
}
166167

167-
pub(crate) fn extract_class_side_effect(
168+
pub(crate) fn extract_class_side_effect<'a>(
168169
expr_ctx: ExprCtx,
169-
c: &mut Class,
170-
) -> Option<Vec<&mut Box<Expr>>> {
170+
ident: Option<&'a Ident>,
171+
c: &'a mut Class,
172+
) -> Option<Vec<&'a mut Box<Expr>>> {
171173
let mut res = Vec::new();
172174
if let Some(e) = &mut c.super_class {
173175
if e.may_have_side_effects(expr_ctx) {
@@ -195,9 +197,16 @@ pub(crate) fn extract_class_side_effect(
195197

196198
if let Some(v) = &mut p.value {
197199
if p.is_static && v.may_have_side_effects(expr_ctx) {
198-
if contains_this_expr(v) {
200+
if contains_this_expr(v) || contains_super(v) {
199201
return None;
200202
}
203+
204+
if let Some(id) = ident {
205+
if IdentUsageFinder::find(id, v) {
206+
return None;
207+
}
208+
}
209+
201210
res.push(v);
202211
}
203212
}
@@ -208,12 +217,44 @@ pub(crate) fn extract_class_side_effect(
208217
..
209218
}) => {
210219
if v.may_have_side_effects(expr_ctx) {
211-
if contains_this_expr(v) {
220+
if contains_this_expr(v) || contains_super(v) {
212221
return None;
213222
}
223+
224+
if let Some(id) = ident {
225+
if IdentUsageFinder::find(id, v) {
226+
return None;
227+
}
228+
}
229+
214230
res.push(v);
215231
}
216232
}
233+
ClassMember::StaticBlock(s) => {
234+
if s.body.stmts.len() > 1 {
235+
return None;
236+
}
237+
238+
let first = if let Some(stmt) = s.body.stmts.get_mut(0) {
239+
&mut stmt.as_mut_expr()?.expr
240+
} else {
241+
continue;
242+
};
243+
244+
if first.may_have_side_effects(expr_ctx) {
245+
if contains_this_expr(first) || contains_super(first) {
246+
return None;
247+
}
248+
249+
if let Some(id) = ident {
250+
if IdentUsageFinder::find(id, first) {
251+
return None;
252+
}
253+
}
254+
255+
res.push(first);
256+
}
257+
}
217258

218259
_ => {}
219260
}

0 commit comments

Comments
 (0)