mirror of
https://github.com/swc-project/swc.git
synced 2024-11-24 10:12:42 +03:00
fix(es/minifier): Do not drop properties used via this
(#7785)
**Related issue:** - Closes #7783.
This commit is contained in:
parent
e90b555790
commit
552d9aa344
71
crates/swc/tests/fixture/issues-7xxx/7783/input/.swcrc
Normal file
71
crates/swc/tests/fixture/issues-7xxx/7783/input/.swcrc
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "ecmascript",
|
||||
"jsx": true
|
||||
},
|
||||
"target": "es2015",
|
||||
"loose": false,
|
||||
"minify": {
|
||||
"compress": {
|
||||
"arguments": false,
|
||||
"arrows": true,
|
||||
"booleans": true,
|
||||
"booleans_as_integers": false,
|
||||
"collapse_vars": true,
|
||||
"comparisons": true,
|
||||
"computed_props": true,
|
||||
"conditionals": true,
|
||||
"dead_code": true,
|
||||
"directives": true,
|
||||
"drop_console": false,
|
||||
"drop_debugger": true,
|
||||
"evaluate": true,
|
||||
"expression": false,
|
||||
"hoist_funs": false,
|
||||
"hoist_props": true,
|
||||
"hoist_vars": false,
|
||||
"if_return": true,
|
||||
"join_vars": true,
|
||||
"keep_classnames": false,
|
||||
"keep_fargs": true,
|
||||
"keep_fnames": false,
|
||||
"keep_infinity": false,
|
||||
"loops": true,
|
||||
"negate_iife": true,
|
||||
"properties": true,
|
||||
"reduce_funcs": false,
|
||||
"reduce_vars": false,
|
||||
"side_effects": true,
|
||||
"switches": true,
|
||||
"typeofs": true,
|
||||
"unsafe": false,
|
||||
"unsafe_arrows": false,
|
||||
"unsafe_comps": false,
|
||||
"unsafe_Function": false,
|
||||
"unsafe_math": false,
|
||||
"unsafe_symbols": false,
|
||||
"unsafe_methods": false,
|
||||
"unsafe_proto": false,
|
||||
"unsafe_regexp": false,
|
||||
"unsafe_undefined": false,
|
||||
"unused": true,
|
||||
"const_to_let": true,
|
||||
"pristine_globals": true
|
||||
},
|
||||
"mangle": {
|
||||
"toplevel": false,
|
||||
"keep_classnames": false,
|
||||
"keep_fnames": false,
|
||||
"keep_private_props": false,
|
||||
"ie8": false,
|
||||
"safari10": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"type": "es6"
|
||||
},
|
||||
"minify": true,
|
||||
"isModule": true
|
||||
}
|
14
crates/swc/tests/fixture/issues-7xxx/7783/input/1.js
Normal file
14
crates/swc/tests/fixture/issues-7xxx/7783/input/1.js
Normal file
@ -0,0 +1,14 @@
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>{foo.a}</div>
|
||||
)
|
||||
}
|
||||
|
||||
const foo = {
|
||||
get a() {
|
||||
return `a ${this.b}`;
|
||||
},
|
||||
get b() {
|
||||
return `b`;
|
||||
}
|
||||
}
|
1
crates/swc/tests/fixture/issues-7xxx/7783/output/1.js
Normal file
1
crates/swc/tests/fixture/issues-7xxx/7783/output/1.js
Normal file
@ -0,0 +1 @@
|
||||
export default function e(){return React.createElement("div",null,foo.a)}let foo={get a(){return`a ${this.b}`},get b(){return"b"}};
|
@ -28,6 +28,7 @@ function implicitThis(n) {
|
||||
return this.m + n + 12;
|
||||
}
|
||||
var impl = {
|
||||
a: 12,
|
||||
explicitVoid2: function() {
|
||||
return _this.a;
|
||||
},
|
||||
|
@ -1,8 +1,10 @@
|
||||
use rustc_hash::FxHashSet;
|
||||
use swc_atoms::{js_word, JsWord};
|
||||
use swc_common::{util::take::Take, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_usage_analyzer::util::is_global_var_with_pure_property_access;
|
||||
use swc_ecma_utils::{contains_ident_ref, ExprExt};
|
||||
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
|
||||
|
||||
use super::Optimizer;
|
||||
#[cfg(feature = "debug")]
|
||||
@ -785,11 +787,17 @@ impl Optimizer<'_> {
|
||||
return None;
|
||||
}
|
||||
|
||||
let properties_used_via_this = {
|
||||
let mut v = ThisPropertyVisitor::default();
|
||||
obj.visit_with(&mut v);
|
||||
v.properties
|
||||
};
|
||||
|
||||
let should_preserve_property = |sym: &JsWord| {
|
||||
if let "toString" = &**sym {
|
||||
return true;
|
||||
}
|
||||
!usage.accessed_props.contains_key(sym)
|
||||
!usage.accessed_props.contains_key(sym) && !properties_used_via_this.contains(sym)
|
||||
};
|
||||
let should_preserve = |key: &PropName| match key {
|
||||
PropName::Ident(k) => should_preserve_property(&k.sym),
|
||||
@ -824,3 +832,34 @@ impl Optimizer<'_> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ThisPropertyVisitor {
|
||||
properties: FxHashSet<JsWord>,
|
||||
|
||||
should_abort: bool,
|
||||
}
|
||||
|
||||
impl Visit for ThisPropertyVisitor {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_member_expr(&mut self, e: &MemberExpr) {
|
||||
if self.should_abort {
|
||||
return;
|
||||
}
|
||||
|
||||
e.visit_children_with(self);
|
||||
|
||||
if let Expr::This(..) = &*e.obj {
|
||||
match &e.prop {
|
||||
MemberProp::Ident(p) => {
|
||||
self.properties.insert(p.sym.clone());
|
||||
}
|
||||
MemberProp::Computed(_) => {
|
||||
self.should_abort = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
export default function Home() {
|
||||
return React.createElement("div", null, foo.a);
|
||||
}
|
||||
const foo = {
|
||||
get a() {
|
||||
return `a ${this.b}`;
|
||||
},
|
||||
get b() {
|
||||
return `b`;
|
||||
}
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
export default function Home() {
|
||||
return React.createElement("div", null, foo.a);
|
||||
}
|
||||
const foo = {
|
||||
get a () {
|
||||
return `a ${this.b}`;
|
||||
},
|
||||
get b () {
|
||||
return "b";
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user