mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 09:38:16 +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;
|
return MyClass.prototype.fn = function() {}, MyClass;
|
||||||
}();
|
}();
|
||||||
(function() {
|
0..toExponential();
|
||||||
return 0;
|
|
||||||
})().toExponential();
|
|
||||||
|
@ -2,10 +2,7 @@ import * as swcHelpers from "@swc/helpers";
|
|||||||
var M, ANY2 = [
|
var M, ANY2 = [
|
||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
], obj1 = {
|
], A = function() {
|
||||||
x: "",
|
|
||||||
y: function() {}
|
|
||||||
}, A = function() {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
function A() {
|
function A() {
|
||||||
swcHelpers.classCallCheck(this, A);
|
swcHelpers.classCallCheck(this, A);
|
||||||
@ -17,4 +14,4 @@ var M, ANY2 = [
|
|||||||
M1.n = n;
|
M1.n = n;
|
||||||
}(M || (M = {}));
|
}(M || (M = {}));
|
||||||
var objA = new A();
|
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;
|
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);
|
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 = [
|
var M, ANY2 = [
|
||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
], obj1 = {
|
], A = function() {
|
||||||
x: function(s) {},
|
|
||||||
y: function(s1) {}
|
|
||||||
}, A = function() {
|
|
||||||
"use strict";
|
"use strict";
|
||||||
function A() {
|
function A() {
|
||||||
swcHelpers.classCallCheck(this, A);
|
swcHelpers.classCallCheck(this, A);
|
||||||
@ -17,4 +14,4 @@ var M, ANY2 = [
|
|||||||
M1.n = n;
|
M1.n = n;
|
||||||
}(M || (M = {}));
|
}(M || (M = {}));
|
||||||
var objA = new A();
|
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;
|
return C.prototype.m = function(x) {}, C.m = function(x) {}, C;
|
||||||
}();
|
}();
|
||||||
C.m(), new C().m(), new C().p();
|
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
|
set -eux
|
||||||
|
|
||||||
export RUST_LOG=swc_ecma_minifier=trace,swc_ecma_transforms_optimization=trace
|
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_ast::*;
|
||||||
use swc_ecma_utils::{contains_this_expr, ident::IdentLike};
|
use swc_ecma_utils::{contains_this_expr, ident::IdentLike};
|
||||||
|
|
||||||
@ -98,6 +99,13 @@ where
|
|||||||
if let Prop::KeyValue(p) = &**prop {
|
if let Prop::KeyValue(p) = &**prop {
|
||||||
let value = match &*p.value {
|
let value = match &*p.value {
|
||||||
Expr::Lit(..) => p.value.clone(),
|
Expr::Lit(..) => p.value.clone(),
|
||||||
|
Expr::Fn(..) | Expr::Arrow(..) => {
|
||||||
|
if self.options.hoist_props {
|
||||||
|
p.value.clone()
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -182,19 +190,27 @@ where
|
|||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
if let Expr::Ident(obj) = &*member.obj {
|
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()) {
|
if let Some(value) = self.vars_for_prop_hoisting.remove(&obj.to_id()) {
|
||||||
member.obj = value;
|
member.obj = value;
|
||||||
self.changed = true;
|
self.changed = true;
|
||||||
tracing::debug!("hoist_props: Inlined a property");
|
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)
|
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 {
|
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.
|
// Don't create top-level variables.
|
||||||
if !param_ids.is_empty() && self.ctx.in_top_level() {
|
if !param_ids.is_empty() && self.ctx.in_top_level() {
|
||||||
for pid in param_ids {
|
for pid in param_ids {
|
||||||
if let Some(usage) = self.data.vars.get(&pid.to_id()) {
|
if let Some(usage) = self.data.vars.get(&pid.to_id()) {
|
||||||
if usage.ref_count > 1 || usage.assign_count > 0 || usage.inline_prevented {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,6 +604,12 @@ where
|
|||||||
|
|
||||||
for param in param_ids {
|
for param in param_ids {
|
||||||
if captured.contains(¶m.to_id()) {
|
if captured.contains(¶m.to_id()) {
|
||||||
|
if cfg!(feature = "debug") {
|
||||||
|
tracing::trace!(
|
||||||
|
"iife: [x] Cannot inline because of the capture of {}",
|
||||||
|
param
|
||||||
|
);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -639,10 +678,6 @@ where
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if contains_this_expr(body) || contains_arguments(body) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,12 +771,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (idx, param) in params.iter().enumerate() {
|
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 {
|
exprs.push(Box::new(Expr::Assign(AssignExpr {
|
||||||
span: DUMMY_SP.apply_mark(self.marks.non_top_level),
|
span: DUMMY_SP.apply_mark(self.marks.non_top_level),
|
||||||
op: op!("="),
|
op: op!("="),
|
||||||
left: PatOrExpr::Pat(Box::new(Pat::Ident(param.clone().into()))),
|
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/dead_code_constant_boolean_should_warn_more_strict/input.js
|
||||||
dead_code/global_fns/input.js
|
dead_code/global_fns/input.js
|
||||||
dead_code/issue_2749/input.js
|
dead_code/issue_2749/input.js
|
||||||
|
dead_code/issue_2860_2/input.js
|
||||||
dead_code/issue_718/input.js
|
dead_code/issue_718/input.js
|
||||||
dead_code/return_assignment/input.js
|
dead_code/return_assignment/input.js
|
||||||
dead_code/unsafe_builtin/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/direct_access_1/input.js
|
||||||
hoist_props/hoist_class/input.js
|
hoist_props/hoist_class/input.js
|
||||||
hoist_props/hoist_class_with_new/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_3/input.js
|
||||||
hoist_props/issue_2473_4/input.js
|
hoist_props/issue_2473_4/input.js
|
||||||
hoist_props/issue_2508_1/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_2692/input.js
|
||||||
dead_code/issue_2701/input.js
|
dead_code/issue_2701/input.js
|
||||||
dead_code/issue_2860_1/input.js
|
dead_code/issue_2860_1/input.js
|
||||||
dead_code/issue_2860_2/input.js
|
|
||||||
dead_code/issue_2929/input.js
|
dead_code/issue_2929/input.js
|
||||||
dead_code/throw_assignment/input.js
|
dead_code/throw_assignment/input.js
|
||||||
dead_code/try_catch_finally/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/direct_access_3/input.js
|
||||||
hoist_props/does_not_hoist_objects_with_computed_props/input.js
|
hoist_props/does_not_hoist_objects_with_computed_props/input.js
|
||||||
hoist_props/hoist_function_with_call/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_2462/input.js
|
||||||
hoist_props/issue_2473_1/input.js
|
hoist_props/issue_2473_1/input.js
|
||||||
hoist_props/issue_2473_2/input.js
|
hoist_props/issue_2473_2/input.js
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
"dead_code": true,
|
"dead_code": true,
|
||||||
"evaluate": true,
|
"evaluate": true,
|
||||||
"inline": true,
|
"inline": true,
|
||||||
"passes": 3,
|
"passes": 4,
|
||||||
"reduce_vars": true
|
"reduce_vars": true
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1 @@
|
|||||||
var obj_foo = 1,
|
console.log(1, 27);
|
||||||
obj_cube = function (x) {
|
|
||||||
return x * x * x;
|
|
||||||
};
|
|
||||||
console.log(obj_foo, obj_cube(3));
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
console.log(1, ((x = 3), x * x * x));
|
|
||||||
var x;
|
var x;
|
||||||
|
console.log(1, 27);
|
||||||
|
Loading…
Reference in New Issue
Block a user