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;
|
return this.m + n + 12;
|
||||||
}
|
}
|
||||||
var impl = {
|
var impl = {
|
||||||
|
a: 12,
|
||||||
explicitVoid2: function() {
|
explicitVoid2: function() {
|
||||||
return _this.a;
|
return _this.a;
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
|
use rustc_hash::FxHashSet;
|
||||||
use swc_atoms::{js_word, JsWord};
|
use swc_atoms::{js_word, JsWord};
|
||||||
use swc_common::{util::take::Take, DUMMY_SP};
|
use swc_common::{util::take::Take, DUMMY_SP};
|
||||||
use swc_ecma_ast::*;
|
use swc_ecma_ast::*;
|
||||||
use swc_ecma_usage_analyzer::util::is_global_var_with_pure_property_access;
|
use swc_ecma_usage_analyzer::util::is_global_var_with_pure_property_access;
|
||||||
use swc_ecma_utils::{contains_ident_ref, ExprExt};
|
use swc_ecma_utils::{contains_ident_ref, ExprExt};
|
||||||
|
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
|
||||||
|
|
||||||
use super::Optimizer;
|
use super::Optimizer;
|
||||||
#[cfg(feature = "debug")]
|
#[cfg(feature = "debug")]
|
||||||
@ -785,11 +787,17 @@ impl Optimizer<'_> {
|
|||||||
return None;
|
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| {
|
let should_preserve_property = |sym: &JsWord| {
|
||||||
if let "toString" = &**sym {
|
if let "toString" = &**sym {
|
||||||
return true;
|
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 {
|
let should_preserve = |key: &PropName| match key {
|
||||||
PropName::Ident(k) => should_preserve_property(&k.sym),
|
PropName::Ident(k) => should_preserve_property(&k.sym),
|
||||||
@ -824,3 +832,34 @@ impl Optimizer<'_> {
|
|||||||
None
|
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