feat(es/minifier): Implement more rules for hoist_props (#4262)

This commit is contained in:
Donny/강동윤 2022-04-06 20:01:45 +09:00 committed by GitHub
parent 35ad940ca5
commit 1f5cac4d41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 80 additions and 51 deletions

View File

@ -11,6 +11,4 @@ var MyClass = function() {
}
return MyClass.prototype.fn = function() {}, MyClass;
}();
(function() {
return 0;
})().toExponential();
0..toExponential();

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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 $@

View File

@ -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()
}
}
}
}

View File

@ -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(&param.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,
})));
}
}

View File

@ -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

View File

@ -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

View File

@ -2,6 +2,6 @@
"dead_code": true,
"evaluate": true,
"inline": true,
"passes": 3,
"passes": 4,
"reduce_vars": true
}

View File

@ -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);

View File

@ -1,2 +1,2 @@
console.log(1, ((x = 3), x * x * x));
var x;
console.log(1, 27);