handle pure_funcs under inline & reduce_vars correctly (#3066)

fixes #3065
This commit is contained in:
Alex Lam S.L
2018-04-10 02:46:38 +08:00
committed by GitHub
parent 87857b0f1b
commit 183da16896
3 changed files with 116 additions and 6 deletions

View File

@@ -685,7 +685,8 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
pass `pure_funcs: [ 'Math.floor' ]` to let it know that this pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
function won't produce any side effect, in which case the whole function won't produce any side effect, in which case the whole
statement would get discarded. The current implementation adds some statement would get discarded. The current implementation adds some
overhead (compression will be slower). overhead (compression will be slower). Make sure symbols under `pure_funcs`
are also under `mangle.reserved` to avoid mangling.
- `pure_getters` (default: `"strict"`) -- If you pass `true` for - `pure_getters` (default: `"strict"`) -- If you pass `true` for
this, UglifyJS will assume that object property access this, UglifyJS will assume that object property access

View File

@@ -4573,7 +4573,8 @@ merge(Compressor.prototype, {
} }
} }
var stat = is_func && fn.body[0]; var stat = is_func && fn.body[0];
if (compressor.option("inline") && stat instanceof AST_Return) { var can_inline = compressor.option("inline") && !self.is_expr_pure(compressor);
if (can_inline && stat instanceof AST_Return) {
var value = stat.value; var value = stat.value;
if (!value || value.is_constant_expression()) { if (!value || value.is_constant_expression()) {
if (value) { if (value) {
@@ -4587,7 +4588,7 @@ merge(Compressor.prototype, {
} }
if (is_func) { if (is_func) {
var def, value, scope, in_loop, level = -1; var def, value, scope, in_loop, level = -1;
if (compressor.option("inline") if (can_inline
&& !fn.uses_arguments && !fn.uses_arguments
&& !fn.uses_eval && !fn.uses_eval
&& !(fn.name && fn instanceof AST_Function) && !(fn.name && fn instanceof AST_Function)
@@ -5460,11 +5461,12 @@ merge(Compressor.prototype, {
return make_node(AST_Infinity, self).optimize(compressor); return make_node(AST_Infinity, self).optimize(compressor);
} }
} }
if (compressor.option("reduce_vars") var parent = compressor.parent();
&& is_lhs(self, compressor.parent()) !== self) { if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
var d = self.definition(); var d = self.definition();
var fixed = self.fixed_value(); var fixed = self.fixed_value();
var single_use = d.single_use; var single_use = d.single_use
&& !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
if (single_use && fixed instanceof AST_Lambda) { if (single_use && fixed instanceof AST_Lambda) {
if (d.scope !== self.scope if (d.scope !== self.scope
&& (!compressor.option("reduce_funcs") && (!compressor.option("reduce_funcs")

View File

@@ -535,3 +535,110 @@ issue_2705_6: {
"/* */new(/* */a()||b())(c(),d());", "/* */new(/* */a()||b())(c(),d());",
] ]
} }
issue_3065_1: {
options = {
inline: true,
pure_funcs: [ "pureFunc" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function modifyWrapper(a, f, wrapper) {
wrapper.a = a;
wrapper.f = f;
return wrapper;
}
function pureFunc(fun) {
return modifyWrapper(1, fun, function(a) {
return fun(a);
});
}
var unused = pureFunc(function(x) {
return x;
});
}
expect: {}
}
issue_3065_2: {
rename = true
options = {
inline: true,
pure_funcs: [ "pureFunc" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
mangle = {
reserved: [ "pureFunc" ],
toplevel: true,
}
input: {
function modifyWrapper(a, f, wrapper) {
wrapper.a = a;
wrapper.f = f;
return wrapper;
}
function pureFunc(fun) {
return modifyWrapper(1, fun, function(a) {
return fun(a);
});
}
var unused = pureFunc(function(x) {
return x;
});
}
expect: {}
}
issue_3065_3: {
options = {
pure_funcs: [ "debug" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
function debug(msg) {
console.log(msg);
}
debug(function() {
console.log("PASS");
return "FAIL";
}());
}
expect: {
(function() {
console.log("PASS");
})();
}
}
issue_3065_4: {
options = {
pure_funcs: [ "debug" ],
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var debug = function(msg) {
console.log(msg);
};
debug(function() {
console.log("PASS");
return "FAIL";
}());
}
expect: {
(function() {
console.log("PASS");
})();
}
}