handle pure_funcs under inline & reduce_vars correctly (#3066)
fixes #3065
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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");
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user