Skip to content

Commit 9154bbc

Browse files
authoredNov 20, 2022
fix(es/minifier): Avoid dropping statements which has side-effects (#6476)
1 parent e59ccfc commit 9154bbc

File tree

13 files changed

+157
-20
lines changed

13 files changed

+157
-20
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
11
//// [objectSpreadSetonlyAccessor.ts]
2+
({
3+
...{
4+
set foo (_v){}
5+
}
6+
});

‎crates/swc_atoms/words.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1369,3 +1369,4 @@ ychannelselector
13691369
yield
13701370
zoomAndPan
13711371
zoomandpan
1372+
__proto__

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

+17-9
Original file line numberDiff line numberDiff line change
@@ -1918,15 +1918,23 @@ where
19181918
#[cfg(feature = "debug")]
19191919
let start = dump(&n.expr, true);
19201920

1921-
let expr = self.ignore_return_value(&mut n.expr);
1922-
n.expr = expr.map(Box::new).unwrap_or_else(|| {
1923-
report_change!("visit_mut_expr_stmt: Dropped an expression statement");
1924-
1925-
#[cfg(feature = "debug")]
1926-
dump_change_detail!("Removed {}", start);
1927-
1928-
undefined(DUMMY_SP)
1929-
});
1921+
// Fix https://github.com/swc-project/swc/issues/6422
1922+
let is_object_lit_with_spread = n
1923+
.expr
1924+
.as_object()
1925+
.map(|object_lit| object_lit.props.iter().any(|prop| prop.is_spread()))
1926+
.unwrap_or(false);
1927+
1928+
if !is_object_lit_with_spread {
1929+
let expr = self.ignore_return_value(&mut n.expr);
1930+
n.expr = expr.map(Box::new).unwrap_or_else(|| {
1931+
report_change!("visit_mut_expr_stmt: Dropped an expression statement");
1932+
#[cfg(feature = "debug")]
1933+
dump_change_detail!("Removed {}", start);
1934+
1935+
undefined(DUMMY_SP)
1936+
});
1937+
}
19301938
} else {
19311939
match &mut *n.expr {
19321940
Expr::Seq(e) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"collapse_vars": true,
3+
"unused": true,
4+
"toplevel": true
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
let getter_effect = 'FAIL';
2+
let setter_effect = 'FAIL';
3+
let proto = {
4+
get foo() {
5+
getter_effect = 'PASS';
6+
},
7+
set bar(value) {
8+
setter_effect = 'PASS';
9+
}
10+
};
11+
let obj1 = {
12+
__proto__: proto
13+
};
14+
let obj2 = {
15+
__proto__: proto
16+
};
17+
let unused = obj1.foo;
18+
obj2.bar = 0;
19+
20+
assert.strictEqual(getter_effect, 'PASS');
21+
assert.strictEqual(setter_effect, 'PASS');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
let getter_effect = 'FAIL';
2+
let setter_effect = 'FAIL';
3+
let proto = {
4+
get foo () {
5+
getter_effect = 'PASS';
6+
},
7+
set bar (value){
8+
setter_effect = 'PASS';
9+
}
10+
};
11+
({
12+
__proto__: proto
13+
}).foo;
14+
({
15+
__proto__: proto
16+
}).bar = 0;
17+
assert.strictEqual(getter_effect, 'PASS');
18+
assert.strictEqual(setter_effect, 'PASS');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"toplevel": true,
3+
"unused": true
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import assert from 'assert'
2+
let result = 'FAIL';
3+
const unused = {
4+
...{
5+
get prop() {
6+
result = 'PASS';
7+
}
8+
}
9+
};
10+
assert.strictEqual(result, 'PASS');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import assert from 'assert';
2+
let result = 'FAIL';
3+
({
4+
...{
5+
get prop () {
6+
result = 'PASS';
7+
}
8+
}
9+
});
10+
assert.strictEqual(result, 'PASS');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"toplevel": true,
3+
"unused": true
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import assert from 'assert'
2+
let result = 0;
3+
const unused = {
4+
...{
5+
get prop() {
6+
result = 1;
7+
}
8+
},
9+
[assert.strictEqual(result, 1)]: null,
10+
[result = 2]: null,
11+
[assert.strictEqual(result, 2)]: null,
12+
...{
13+
get prop() {
14+
result = 3;
15+
}
16+
}
17+
};
18+
assert.strictEqual(result, 3);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import assert from 'assert';
2+
let result = 0;
3+
({
4+
...{
5+
get prop () {
6+
result = 1;
7+
}
8+
},
9+
[assert.strictEqual(result, 1)]: null,
10+
[result = 2]: null,
11+
[assert.strictEqual(result, 2)]: null,
12+
...{
13+
get prop () {
14+
result = 3;
15+
}
16+
}
17+
});
18+
assert.strictEqual(result, 3);

‎crates/swc_ecma_utils/src/lib.rs

+26-11
Original file line numberDiff line numberDiff line change
@@ -1375,18 +1375,33 @@ pub trait ExprExt {
13751375
}
13761376
}
13771377
Expr::Object(obj) => {
1378-
let is_static_accessor = |prop: &PropOrSpread| {
1379-
if let PropOrSpread::Prop(prop) = prop {
1380-
if let Prop::Getter(_) | Prop::Setter(_) = &**prop {
1381-
true
1382-
} else {
1383-
false
1384-
}
1385-
} else {
1386-
false
1387-
}
1378+
let can_have_side_effect = |prop: &PropOrSpread| match prop {
1379+
PropOrSpread::Spread(_) => true,
1380+
PropOrSpread::Prop(prop) => match prop.as_ref() {
1381+
Prop::Getter(_)
1382+
| Prop::Setter(_)
1383+
| Prop::Method(_)
1384+
| Prop::Shorthand(Ident {
1385+
sym: js_word!("__proto__"),
1386+
..
1387+
})
1388+
| Prop::KeyValue(KeyValueProp {
1389+
key:
1390+
PropName::Ident(Ident {
1391+
sym: js_word!("__proto__"),
1392+
..
1393+
})
1394+
| PropName::Str(Str {
1395+
value: js_word!("__proto__"),
1396+
..
1397+
})
1398+
| PropName::Computed(_),
1399+
..
1400+
}) => true,
1401+
_ => false,
1402+
},
13881403
};
1389-
if obj.props.iter().any(is_static_accessor) {
1404+
if obj.props.iter().any(can_have_side_effect) {
13901405
return true;
13911406
}
13921407
}

1 commit comments

Comments
 (1)

github-actions[bot] commented on Nov 20, 2022

@github-actions[bot]

Benchmark

Benchmark suite Current: 9154bbc Previous: 15ad2c2 Ratio
es/full/bugs-1 389841 ns/iter (± 22054) 346117 ns/iter (± 22474) 1.13
es/full/minify/libraries/antd 2094374257 ns/iter (± 82448426) 1957955351 ns/iter (± 56659346) 1.07
es/full/minify/libraries/d3 502630299 ns/iter (± 27607030) 444712150 ns/iter (± 38663654) 1.13
es/full/minify/libraries/echarts 1873070557 ns/iter (± 758763072) 1615751824 ns/iter (± 115715877) 1.16
es/full/minify/libraries/jquery 125668872 ns/iter (± 7586107) 110708257 ns/iter (± 5102303) 1.14
es/full/minify/libraries/lodash 161579804 ns/iter (± 21023829) 133833754 ns/iter (± 14042922) 1.21
es/full/minify/libraries/moment 88708545 ns/iter (± 29765105) 65244200 ns/iter (± 7197779) 1.36
es/full/minify/libraries/react 26280308 ns/iter (± 4046363) 25592873 ns/iter (± 2133927) 1.03
es/full/minify/libraries/terser 374533985 ns/iter (± 18064188) 368397583 ns/iter (± 23963737) 1.02
es/full/minify/libraries/three 652642002 ns/iter (± 31323109) 635544587 ns/iter (± 23540994) 1.03
es/full/minify/libraries/typescript 4136959214 ns/iter (± 252717032) 3664030287 ns/iter (± 95819033) 1.13
es/full/minify/libraries/victory 927628403 ns/iter (± 61741347) 863451822 ns/iter (± 31194415) 1.07
es/full/minify/libraries/vue 178428798 ns/iter (± 9735215) 165269128 ns/iter (± 11804335) 1.08
es/full/codegen/es3 35629 ns/iter (± 8609) 34763 ns/iter (± 1305) 1.02
es/full/codegen/es5 38103 ns/iter (± 6502) 34587 ns/iter (± 1230) 1.10
es/full/codegen/es2015 36890 ns/iter (± 5849) 34433 ns/iter (± 1937) 1.07
es/full/codegen/es2016 34100 ns/iter (± 6093) 34382 ns/iter (± 2122) 0.99
es/full/codegen/es2017 38119 ns/iter (± 7737) 34724 ns/iter (± 1535) 1.10
es/full/codegen/es2018 37150 ns/iter (± 6840) 34589 ns/iter (± 2727) 1.07
es/full/codegen/es2019 36291 ns/iter (± 6934) 34779 ns/iter (± 956) 1.04
es/full/codegen/es2020 36868 ns/iter (± 5595) 34435 ns/iter (± 1021) 1.07
es/full/all/es3 225387040 ns/iter (± 24353389) 208946945 ns/iter (± 17927599) 1.08
es/full/all/es5 213631035 ns/iter (± 17082855) 196987775 ns/iter (± 14151792) 1.08
es/full/all/es2015 169123795 ns/iter (± 9833735) 155192235 ns/iter (± 10338814) 1.09
es/full/all/es2016 171026993 ns/iter (± 15511849) 156039736 ns/iter (± 14142708) 1.10
es/full/all/es2017 169572869 ns/iter (± 12352684) 152429291 ns/iter (± 9867532) 1.11
es/full/all/es2018 164007453 ns/iter (± 10050642) 151556223 ns/iter (± 12155126) 1.08
es/full/all/es2019 164051983 ns/iter (± 11626394) 149367814 ns/iter (± 13828712) 1.10
es/full/all/es2020 161819590 ns/iter (± 14091917) 141622508 ns/iter (± 8817046) 1.14
es/full/parser 822178 ns/iter (± 111880) 735960 ns/iter (± 41686) 1.12
es/full/base/fixer 28915 ns/iter (± 4716) 26506 ns/iter (± 1048) 1.09
es/full/base/resolver_and_hygiene 97233 ns/iter (± 11134) 95434 ns/iter (± 18794) 1.02
serialization of ast node 244 ns/iter (± 32) 220 ns/iter (± 11) 1.11
serialization of serde 228 ns/iter (± 28) 221 ns/iter (± 3) 1.03

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.