fix multiple nested function substitutions (#2458)

fixes #2449
This commit is contained in:
Alex Lam S.L
2017-11-09 23:30:00 +08:00
committed by GitHub
parent 246d9d4e83
commit 1127a2caf3
5 changed files with 64 additions and 24 deletions

View File

@@ -313,19 +313,14 @@ merge(Compressor.prototype, {
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
var d = node.definition(); var d = node.definition();
d.references.push(node); d.references.push(node);
var value;
if (d.fixed === undefined || !safe_to_read(d) || d.single_use == "m") { if (d.fixed === undefined || !safe_to_read(d) || d.single_use == "m") {
d.fixed = false; d.fixed = false;
} else if (d.fixed) { } else if (d.fixed) {
var value = node.fixed_value(); value = node.fixed_value();
if (value && ref_once(d)) { if (value && ref_once(d)) {
if (value instanceof AST_Lambda) { d.single_use = value instanceof AST_Lambda
d.single_use = d.scope === node.scope || d.scope === node.scope && value.is_constant_expression();
&& !(d.orig[0] instanceof AST_SymbolFunarg)
|| value.is_constant_expression(node.scope);
} else {
d.single_use = d.scope === node.scope
&& value.is_constant_expression();
}
} else { } else {
d.single_use = false; d.single_use = false;
} }
@@ -335,10 +330,9 @@ merge(Compressor.prototype, {
} else { } else {
d.fixed = false; d.fixed = false;
} }
} else {
mark_escaped(d, node, value, 0);
} }
} }
mark_escaped(d, node, value, 0);
} }
if (node instanceof AST_SymbolCatch) { if (node instanceof AST_SymbolCatch) {
node.definition().fixed = false; node.definition().fixed = false;
@@ -385,10 +379,7 @@ merge(Compressor.prototype, {
d.fixed = node; d.fixed = node;
loop_ids[d.id] = in_loop; loop_ids[d.id] = in_loop;
mark(d, true); mark(d, true);
if (ref_once(d)) { d.single_use = ref_once(d);
d.single_use = d.scope === d.references[0].scope
|| node.is_constant_expression(d.references[0].scope);
}
} }
var save_ids = safe_ids; var save_ids = safe_ids;
safe_ids = Object.create(null); safe_ids = Object.create(null);
@@ -2209,7 +2200,10 @@ merge(Compressor.prototype, {
&& !self.variables.has(def.name)) { && !self.variables.has(def.name)) {
if (scope) { if (scope) {
var scope_def = scope.find_variable(node); var scope_def = scope.find_variable(node);
if (def.undeclared ? !scope_def : scope_def === def) return true; if (def.undeclared ? !scope_def : scope_def === def) {
result = "f";
return true;
}
} }
result = false; result = false;
} }
@@ -4256,11 +4250,20 @@ merge(Compressor.prototype, {
if (fixed instanceof AST_Defun) { if (fixed instanceof AST_Defun) {
d.fixed = fixed = make_node(AST_Function, fixed, fixed); d.fixed = fixed = make_node(AST_Function, fixed, fixed);
} }
if (fixed if (d.single_use && fixed instanceof AST_Function) {
&& d.single_use if (d.escaped && d.scope !== self.scope || recursive_ref(compressor, d)) {
&& !(fixed instanceof AST_Function d.single_use = false;
&& (d.escaped && d.scope !== self.scope } else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) {
|| recursive_ref(compressor, d)))) { d.single_use = fixed.is_constant_expression(self.scope);
if (d.single_use == "f") {
var scope = self.scope;
do {
if (scope.name) scope.name.definition().single_use = false;
} while (scope = scope.parent_scope);
}
}
}
if (d.single_use && fixed) {
var value = fixed.optimize(compressor); var value = fixed.optimize(compressor);
return value === fixed ? fixed.clone(true) : value; return value === fixed ? fixed.clone(true) : value;
} }

View File

@@ -3036,6 +3036,7 @@ issue_2437: {
conditionals: true, conditionals: true,
inline: true, inline: true,
join_vars: true, join_vars: true,
passes: 2,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
sequences: true, sequences: true,

View File

@@ -1113,7 +1113,7 @@ issue_2105_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
inline: true, inline: true,
passes: 2, passes: 3,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
@@ -1153,7 +1153,7 @@ issue_2105_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
inline: true, inline: true,
passes: 2, passes: 3,
properties: true, properties: true,
pure_getters: "strict", pure_getters: "strict",
reduce_vars: true, reduce_vars: true,

View File

@@ -513,7 +513,7 @@ issue_2428: {
options = { options = {
collapse_vars: true, collapse_vars: true,
inline: true, inline: true,
passes: 2, passes: 3,
pure_getters: "strict", pure_getters: "strict",
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,

View File

@@ -3714,6 +3714,7 @@ recursive_inlining_2: {
recursive_inlining_3: { recursive_inlining_3: {
options = { options = {
passes: 2,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -3989,3 +3990,38 @@ issue_2450_5: {
"true", "true",
] ]
} }
issue_2449: {
options = {
passes: 10,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
function f() {
return a;
}
function g() {
return f();
}
(function() {
var a = "FAIL";
if (a == a) console.log(g());
})();
}
expect: {
var a = "PASS";
function g() {
return function() {
return a;
}();
}
(function() {
var a = "FAIL";
if (a == a) console.log(g());
})();
}
expect_stdout: "PASS"
}