Skip to content

Commit

Permalink
Add case for respecting side-effect of getter and setter
Browse files Browse the repository at this point in the history
  • Loading branch information
hyf0 committed Nov 18, 2022
1 parent e8f930d commit eb5745d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 10 deletions.
1 change: 1 addition & 0 deletions crates/swc_atoms/words.txt
Expand Up @@ -1369,3 +1369,4 @@ ychannelselector
yield
zoomAndPan
zoomandpan
__proto__
2 changes: 2 additions & 0 deletions crates/swc_ecma_minifier/src/compress/optimize/mod.rs
Expand Up @@ -1918,6 +1918,7 @@ where
#[cfg(feature = "debug")]
let start = dump(&n.expr, true);

// Fix https://github.com/swc-project/swc/issues/6422
let is_object_lit_with_spread = n
.expr
.as_object()
Expand Down Expand Up @@ -2572,6 +2573,7 @@ where
if can_be_removed {
self.changed = true;
report_change!("unused: Dropping an expression without side effect");
tracing::debug!("unused: Dropping \n{}\n", dump(&*expr, false));
dump_change_detail!("unused: Dropping \n{}\n", dump(&*expr, false));
*s = Stmt::Empty(EmptyStmt { span: DUMMY_SP });
return;
Expand Down
@@ -0,0 +1,5 @@
{
"collapse_vars": true,
"unused": true,
"toplevel": true
}
21 changes: 21 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/6422/1/input.js
@@ -0,0 +1,21 @@
let getter_effect = 'FAIL';
let setter_effect = 'FAIL';
let proto = {
get foo() {
getter_effect = 'PASS';
},
set bar(value) {
setter_effect = 'PASS';
}
};
let obj1 = {
__proto__: proto
};
let obj2 = {
__proto__: proto
};
let unused = obj1.foo;
obj2.bar = 0;

assert.strictEqual(getter_effect, 'PASS');
assert.strictEqual(setter_effect, 'PASS');
18 changes: 18 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/issues/6422/1/output.js
@@ -0,0 +1,18 @@
let getter_effect = 'FAIL';
let setter_effect = 'FAIL';
let proto = {
get foo () {
getter_effect = 'PASS';
},
set bar (value){
setter_effect = 'PASS';
}
};
({
__proto__: proto
}).foo;
({
__proto__: proto
}).bar = 0;
assert.strictEqual(getter_effect, 'PASS');
assert.strictEqual(setter_effect, 'PASS');
31 changes: 21 additions & 10 deletions crates/swc_ecma_utils/src/lib.rs
Expand Up @@ -1375,18 +1375,29 @@ pub trait ExprExt {
}
}
Expr::Object(obj) => {
let is_static_accessor = |prop: &PropOrSpread| {
if let PropOrSpread::Prop(prop) = prop {
if let Prop::Getter(_) | Prop::Setter(_) = &**prop {
true
} else {
false
}
} else {
false
let is_prop_could_has_side_effect = |prop: &PropOrSpread| {
match prop {
// ({ ...{ __proto__: { get foo() { a = 1; } } } }).foo
PropOrSpread::Spread(_) => true,
PropOrSpread::Prop(prop) => match prop.as_ref() {
Prop::Shorthand(ident) => ident.sym == js_word!("__proto__"),
Prop::KeyValue(KeyValueProp { key, value, .. }) => match key {
PropName::Ident(ident) => {
ident.sym == js_word!("__proto__")
}
PropName::Str(str) => str.value == js_word!("__proto__"),
PropName::Computed(_) => true,
_ => false,
},
Prop::Getter(..) | Prop::Setter(..) => true,
Prop::Method(prop) => true,
Prop::Assign(_) => {
unreachable!("This is **invalid** for object literal")
}
},
}
};
if obj.props.iter().any(is_static_accessor) {
if obj.props.iter().any(is_prop_could_has_side_effect) {
return true;
}
}
Expand Down

0 comments on commit eb5745d

Please sign in to comment.