preserve function identity in reduce_vars

fixes #2450
This commit is contained in:
alexlamsl 2017-11-07 13:47:49 +08:00
parent 38bfb73f06
commit 012046b8b1
2 changed files with 95 additions and 15 deletions

View File

@ -623,7 +623,8 @@ merge(Compressor.prototype, {
function mark_escaped(d, node, value, level) {
var parent = tw.parent(level);
if (value instanceof AST_Constant || value instanceof AST_Function) return;
if (value instanceof AST_Constant) return;
if (level > 0 && value instanceof AST_Function) return;
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|| parent instanceof AST_Call && node !== parent.expression
|| parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
@ -4216,6 +4217,17 @@ merge(Compressor.prototype, {
return self;
});
function recursive_ref(compressor, def) {
var node;
for (var i = 0; node = compressor.parent(i); i++) {
if (node instanceof AST_Lambda) {
var name = node.name;
if (name && name.definition() === def) break;
}
}
return node;
}
OPT(AST_SymbolRef, function(self, compressor){
var def = self.resolve_defines(compressor);
if (def) {
@ -4241,21 +4253,14 @@ merge(Compressor.prototype, {
if (fixed instanceof AST_Defun) {
d.fixed = fixed = make_node(AST_Function, fixed, fixed);
}
if (fixed && d.single_use) {
var recurse;
if (fixed instanceof AST_Function) {
for (var i = 0; recurse = compressor.parent(i); i++) {
if (recurse instanceof AST_Lambda) {
var name = recurse.name;
if (name && name.definition() === d) break;
}
}
}
if (!recurse) {
if (fixed
&& d.single_use
&& !(fixed instanceof AST_Function
&& (d.escaped && d.scope !== self.scope
|| recursive_ref(compressor, d)))) {
var value = fixed.optimize(compressor);
return value === fixed ? fixed.clone(true) : value;
}
}
if (fixed && d.should_replace === undefined) {
var init;
if (fixed instanceof AST_This) {

View File

@ -3845,3 +3845,78 @@ recursive_inlining_5: {
"foo 0",
]
}
issue_2450_1: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {}
function g() {
return f;
}
console.log(g() === g());
}
expect: {
function f() {}
function g() {
return f;
}
console.log(g() === g());
}
expect_stdout: "true"
}
issue_2450_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function g() {
function f() {}
return f;
}
console.log(g() === g());
}
expect: {
function g() {
return function() {};
}
console.log(g() === g());
}
expect_stdout: "false"
}
issue_2450_3: {
options = {
reduce_vars: true,
unused: true,
}
input: {
var x = (function() {
function test() {
return "foo";
}
return function b() {
return [1, test];
}
})();
console.log(x()[1] === x()[1]);
}
expect: {
var x = (function() {
function test() {
return "foo";
}
return function() {
return [1, test];
}
})();
console.log(x()[1] === x()[1]);
}
expect_stdout: "true"
}