mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 13:51:19 +03:00
feat(es/minifier): Implement more rules for hoist_props
(#4262)
This commit is contained in:
parent
35ad940ca5
commit
1f5cac4d41
@ -11,6 +11,4 @@ var MyClass = function() {
|
||||
}
|
||||
return MyClass.prototype.fn = function() {}, MyClass;
|
||||
}();
|
||||
(function() {
|
||||
return 0;
|
||||
})().toExponential();
|
||||
0..toExponential();
|
||||
|
@ -2,10 +2,7 @@ import * as swcHelpers from "@swc/helpers";
|
||||
var M, ANY2 = [
|
||||
"",
|
||||
""
|
||||
], obj1 = {
|
||||
x: "",
|
||||
y: function() {}
|
||||
}, A = function() {
|
||||
], A = function() {
|
||||
"use strict";
|
||||
function A() {
|
||||
swcHelpers.classCallCheck(this, A);
|
||||
@ -17,4 +14,4 @@ var M, ANY2 = [
|
||||
M1.n = n;
|
||||
}(M || (M = {}));
|
||||
var objA = new A();
|
||||
ANY2[0], obj1.y, objA.a, M.n, A.foo(), ANY2[0], obj1.y, objA.a, M.n;
|
||||
ANY2[0], objA.a, M.n, A.foo(), ANY2[0], objA.a, M.n;
|
||||
|
@ -10,9 +10,3 @@ var C = function() {
|
||||
return C.prototype.foo = function(x) {}, C;
|
||||
}();
|
||||
c.foo(), c.foo(1), i(), i(1), i.foo(1), i.foo(1, 2), a(), a(1), a.foo(), a.foo(1);
|
||||
var b = {
|
||||
foo: function(x) {},
|
||||
a: function(x, y) {},
|
||||
b: function(x) {}
|
||||
};
|
||||
b.foo(), b.foo(1), b.a(1), b.a(1, 2), b.b(), b.b(1);
|
||||
|
@ -2,10 +2,7 @@ import * as swcHelpers from "@swc/helpers";
|
||||
var M, ANY2 = [
|
||||
"",
|
||||
""
|
||||
], obj1 = {
|
||||
x: function(s) {},
|
||||
y: function(s1) {}
|
||||
}, A = function() {
|
||||
], A = function() {
|
||||
"use strict";
|
||||
function A() {
|
||||
swcHelpers.classCallCheck(this, A);
|
||||
@ -17,4 +14,4 @@ var M, ANY2 = [
|
||||
M1.n = n;
|
||||
}(M || (M = {}));
|
||||
var objA = new A();
|
||||
ANY2[0], obj1.x, obj1.y, objA.a, M.n, A.foo(), ANY2[0], objA.a, M.n;
|
||||
ANY2[0], objA.a, M.n, A.foo(), ANY2[0], objA.a, M.n;
|
||||
|
@ -7,8 +7,3 @@ var C = function() {
|
||||
return C.prototype.m = function(x) {}, C.m = function(x) {}, C;
|
||||
}();
|
||||
C.m(), new C().m(), new C().p();
|
||||
var obj = {
|
||||
m: function(x) {},
|
||||
p: function(x) {}
|
||||
};
|
||||
obj.m(), obj.p();
|
||||
|
@ -8,4 +8,4 @@
|
||||
set -eux
|
||||
|
||||
export RUST_LOG=swc_ecma_minifier=trace,swc_ecma_transforms_optimization=trace
|
||||
cargo test $@ --features debug --features swc_ecma_transforms_optimization/debug --test compress
|
||||
cargo test --features debug --features swc_ecma_transforms_optimization/debug --test compress $@
|
@ -1,3 +1,4 @@
|
||||
use swc_common::DUMMY_SP;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_utils::{contains_this_expr, ident::IdentLike};
|
||||
|
||||
@ -98,6 +99,13 @@ where
|
||||
if let Prop::KeyValue(p) = &**prop {
|
||||
let value = match &*p.value {
|
||||
Expr::Lit(..) => p.value.clone(),
|
||||
Expr::Fn(..) | Expr::Arrow(..) => {
|
||||
if self.options.hoist_props {
|
||||
p.value.clone()
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
@ -182,19 +190,27 @@ where
|
||||
_ => return,
|
||||
};
|
||||
if let Expr::Ident(obj) = &*member.obj {
|
||||
if let MemberProp::Ident(prop) = &member.prop {
|
||||
if let Some(mut value) = self
|
||||
.simple_props
|
||||
.get(&(obj.to_id(), prop.sym.clone()))
|
||||
.cloned()
|
||||
{
|
||||
if let Expr::Fn(f) = &mut *value {
|
||||
f.function.span = DUMMY_SP;
|
||||
}
|
||||
|
||||
tracing::debug!("hoist_props: Inlining `{}.{}`", obj.sym, prop.sym);
|
||||
self.changed = true;
|
||||
*e = *value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value) = self.vars_for_prop_hoisting.remove(&obj.to_id()) {
|
||||
member.obj = value;
|
||||
self.changed = true;
|
||||
tracing::debug!("hoist_props: Inlined a property");
|
||||
return;
|
||||
}
|
||||
|
||||
if let MemberProp::Ident(prop) = &member.prop {
|
||||
if let Some(value) = self.simple_props.get(&(obj.to_id(), prop.sym.clone())) {
|
||||
tracing::debug!("hoist_props: Inlining `{}.{}`", obj.sym, prop.sym);
|
||||
self.changed = true;
|
||||
*e = *value.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -553,12 +553,45 @@ where
|
||||
self.lits.contains_key(id) || self.vars_for_inlining.contains_key(id)
|
||||
}
|
||||
|
||||
fn is_return_arg_simple_enough_for_iife_eval(&self, e: &Expr) -> bool {
|
||||
match e {
|
||||
Expr::Lit(..) | Expr::Ident(..) => true,
|
||||
|
||||
Expr::Bin(BinExpr {
|
||||
op: op!("&&") | op!("||") | op!("??"),
|
||||
..
|
||||
}) => false,
|
||||
|
||||
Expr::Bin(e) => {
|
||||
self.is_return_arg_simple_enough_for_iife_eval(&e.left)
|
||||
&& self.is_return_arg_simple_enough_for_iife_eval(&e.right)
|
||||
}
|
||||
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn can_inline_fn_like(&self, param_ids: &[Ident], body: &BlockStmt) -> bool {
|
||||
if contains_this_expr(body) || contains_arguments(body) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if body.stmts.len() == 1 {
|
||||
if let Stmt::Return(ReturnStmt { arg: Some(arg), .. }) = &body.stmts[0] {
|
||||
if self.is_return_arg_simple_enough_for_iife_eval(arg) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't create top-level variables.
|
||||
if !param_ids.is_empty() && self.ctx.in_top_level() {
|
||||
for pid in param_ids {
|
||||
if let Some(usage) = self.data.vars.get(&pid.to_id()) {
|
||||
if usage.ref_count > 1 || usage.assign_count > 0 || usage.inline_prevented {
|
||||
if cfg!(feature = "debug") {
|
||||
tracing::trace!("iife: [x] Cannot inline because of usage of {}", pid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -571,6 +604,12 @@ where
|
||||
|
||||
for param in param_ids {
|
||||
if captured.contains(¶m.to_id()) {
|
||||
if cfg!(feature = "debug") {
|
||||
tracing::trace!(
|
||||
"iife: [x] Cannot inline because of the capture of {}",
|
||||
param
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -639,10 +678,6 @@ where
|
||||
return false;
|
||||
}
|
||||
|
||||
if contains_this_expr(body) || contains_arguments(body) {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
@ -736,12 +771,13 @@ where
|
||||
}
|
||||
|
||||
for (idx, param) in params.iter().enumerate() {
|
||||
if let Some(arg) = args.get_mut(idx) {
|
||||
let arg = args.get_mut(idx).map(|arg| arg.expr.take());
|
||||
if let Some(arg) = arg {
|
||||
exprs.push(Box::new(Expr::Assign(AssignExpr {
|
||||
span: DUMMY_SP.apply_mark(self.marks.non_top_level),
|
||||
op: op!("="),
|
||||
left: PatOrExpr::Pat(Box::new(Pat::Ident(param.clone().into()))),
|
||||
right: arg.expr.take(),
|
||||
right: arg,
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ dead_code/dead_code_constant_boolean_should_warn_more/input.js
|
||||
dead_code/dead_code_constant_boolean_should_warn_more_strict/input.js
|
||||
dead_code/global_fns/input.js
|
||||
dead_code/issue_2749/input.js
|
||||
dead_code/issue_2860_2/input.js
|
||||
dead_code/issue_718/input.js
|
||||
dead_code/return_assignment/input.js
|
||||
dead_code/unsafe_builtin/input.js
|
||||
@ -333,9 +334,6 @@ hoist_props/contains_this_2/input.js
|
||||
hoist_props/direct_access_1/input.js
|
||||
hoist_props/hoist_class/input.js
|
||||
hoist_props/hoist_class_with_new/input.js
|
||||
hoist_props/issue_2377_1/input.js
|
||||
hoist_props/issue_2377_2/input.js
|
||||
hoist_props/issue_2377_3/input.js
|
||||
hoist_props/issue_2473_3/input.js
|
||||
hoist_props/issue_2473_4/input.js
|
||||
hoist_props/issue_2508_1/input.js
|
||||
|
@ -292,7 +292,6 @@ dead_code/issue_2666/input.js
|
||||
dead_code/issue_2692/input.js
|
||||
dead_code/issue_2701/input.js
|
||||
dead_code/issue_2860_1/input.js
|
||||
dead_code/issue_2860_2/input.js
|
||||
dead_code/issue_2929/input.js
|
||||
dead_code/throw_assignment/input.js
|
||||
dead_code/try_catch_finally/input.js
|
||||
@ -624,6 +623,9 @@ hoist_props/direct_access_2/input.js
|
||||
hoist_props/direct_access_3/input.js
|
||||
hoist_props/does_not_hoist_objects_with_computed_props/input.js
|
||||
hoist_props/hoist_function_with_call/input.js
|
||||
hoist_props/issue_2377_1/input.js
|
||||
hoist_props/issue_2377_2/input.js
|
||||
hoist_props/issue_2377_3/input.js
|
||||
hoist_props/issue_2462/input.js
|
||||
hoist_props/issue_2473_1/input.js
|
||||
hoist_props/issue_2473_2/input.js
|
||||
|
@ -2,6 +2,6 @@
|
||||
"dead_code": true,
|
||||
"evaluate": true,
|
||||
"inline": true,
|
||||
"passes": 3,
|
||||
"passes": 4,
|
||||
"reduce_vars": true
|
||||
}
|
||||
|
@ -1,5 +1 @@
|
||||
var obj_foo = 1,
|
||||
obj_cube = function (x) {
|
||||
return x * x * x;
|
||||
};
|
||||
console.log(obj_foo, obj_cube(3));
|
||||
console.log(1, 27);
|
||||
|
@ -1,2 +1,2 @@
|
||||
console.log(1, ((x = 3), x * x * x));
|
||||
var x;
|
||||
console.log(1, 27);
|
||||
|
Loading…
Reference in New Issue
Block a user