implement function inlining (#2053)
- empty body - single `AST_Return` - single `AST_SimpleStatement` - avoid `/*#__PURE__*/` Miscellaneous - enhance single-use function substitution fixes #281
This commit is contained in:
@@ -63,6 +63,7 @@ function Compressor(options, false_by_default) {
|
||||
hoist_vars : false,
|
||||
ie8 : false,
|
||||
if_return : !false_by_default,
|
||||
inline : !false_by_default,
|
||||
join_vars : !false_by_default,
|
||||
keep_fargs : true,
|
||||
keep_fnames : false,
|
||||
@@ -2943,24 +2944,9 @@ merge(Compressor.prototype, {
|
||||
|
||||
OPT(AST_Call, function(self, compressor){
|
||||
var exp = self.expression;
|
||||
if (compressor.option("reduce_vars")
|
||||
&& exp instanceof AST_SymbolRef) {
|
||||
var def = exp.definition();
|
||||
if (compressor.option("reduce_vars") && exp instanceof AST_SymbolRef) {
|
||||
var fixed = exp.fixed_value();
|
||||
if (fixed instanceof AST_Defun) {
|
||||
def.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true);
|
||||
}
|
||||
if (fixed instanceof AST_Function) {
|
||||
exp = fixed;
|
||||
if (compressor.option("unused")
|
||||
&& def.references.length == 1
|
||||
&& !(def.scope.uses_arguments
|
||||
&& def.orig[0] instanceof AST_SymbolFunarg)
|
||||
&& !def.scope.uses_eval
|
||||
&& compressor.find_parent(AST_Scope) === exp.parent_scope) {
|
||||
self.expression = exp;
|
||||
}
|
||||
}
|
||||
if (fixed instanceof AST_Function) exp = fixed;
|
||||
}
|
||||
if (compressor.option("unused")
|
||||
&& exp instanceof AST_Function
|
||||
@@ -3171,13 +3157,61 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
if (exp instanceof AST_Function) {
|
||||
if (exp.body[0] instanceof AST_Return) {
|
||||
var value = exp.body[0].value;
|
||||
var stat = exp.body[0];
|
||||
if (compressor.option("inline") && stat instanceof AST_Return) {
|
||||
var value = stat && stat.value;
|
||||
if (!value || value.is_constant_expression()) {
|
||||
var args = self.args.concat(value || make_node(AST_Undefined, self));
|
||||
return make_sequence(self, args).transform(compressor);
|
||||
}
|
||||
}
|
||||
if (compressor.option("inline")
|
||||
&& !exp.name
|
||||
&& exp.body.length == 1
|
||||
&& !exp.uses_arguments
|
||||
&& !exp.uses_eval
|
||||
&& !self.has_pure_annotation(compressor)) {
|
||||
var body;
|
||||
if (stat instanceof AST_Return) {
|
||||
body = stat.value.clone(true);
|
||||
} else if (stat instanceof AST_SimpleStatement) {
|
||||
body = [];
|
||||
merge_sequence(body, stat.body.clone(true));
|
||||
merge_sequence(body, make_node(AST_Undefined, self));
|
||||
body = make_sequence(self, body);
|
||||
}
|
||||
if (body) {
|
||||
var fn = exp.clone();
|
||||
fn.argnames = [];
|
||||
fn.body = [
|
||||
make_node(AST_Var, self, {
|
||||
definitions: exp.argnames.map(function(sym, i) {
|
||||
return make_node(AST_VarDef, sym, {
|
||||
name: sym,
|
||||
value: self.args[i] || make_node(AST_Undefined, self)
|
||||
});
|
||||
})
|
||||
})
|
||||
];
|
||||
if (self.args.length > exp.argnames.length) {
|
||||
fn.body.push(make_node(AST_SimpleStatement, self, {
|
||||
body: make_sequence(self, self.args.slice(exp.argnames.length))
|
||||
}));
|
||||
}
|
||||
fn.body.push(make_node(AST_Return, self, {
|
||||
value: body
|
||||
}));
|
||||
body = fn.transform(compressor).body;
|
||||
if (body.length == 0) return make_node(AST_Undefined, self);
|
||||
if (body.length == 1 && body[0] instanceof AST_Return) {
|
||||
if (!body[0].value) return make_node(AST_Undefined, self);
|
||||
body = best_of(compressor, body[0].value, self);
|
||||
} else {
|
||||
body = self;
|
||||
}
|
||||
if (body !== self) return body;
|
||||
}
|
||||
}
|
||||
if (compressor.option("side_effects") && all(exp.body, is_empty)) {
|
||||
var args = self.args.concat(make_node(AST_Undefined, self));
|
||||
return make_sequence(self, args).transform(compressor);
|
||||
@@ -3836,12 +3870,22 @@ merge(Compressor.prototype, {
|
||||
return make_node(AST_Infinity, self).optimize(compressor);
|
||||
}
|
||||
}
|
||||
if (compressor.option("evaluate")
|
||||
&& compressor.option("reduce_vars")
|
||||
if (compressor.option("reduce_vars")
|
||||
&& is_lhs(self, compressor.parent()) !== self) {
|
||||
var d = self.definition();
|
||||
var fixed = self.fixed_value();
|
||||
if (fixed) {
|
||||
if (fixed instanceof AST_Defun) {
|
||||
d.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true);
|
||||
}
|
||||
if (compressor.option("unused")
|
||||
&& fixed instanceof AST_Function
|
||||
&& d.references.length == 1
|
||||
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
|
||||
&& !d.scope.uses_eval
|
||||
&& compressor.find_parent(AST_Scope) === fixed.parent_scope) {
|
||||
return fixed;
|
||||
}
|
||||
if (compressor.option("evaluate") && fixed) {
|
||||
if (d.should_replace === undefined) {
|
||||
var init = fixed.evaluate(compressor);
|
||||
if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
|
||||
|
||||
Reference in New Issue
Block a user