From 07cb64151b1244997b6680130f225cc8cb481308 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Thu, 9 Nov 2017 20:04:59 +0800 Subject: [PATCH] fix multiple nested function substitutions fixes #2449 --- lib/compress.js | 45 ++++++++++++++++++---------------- test/compress/collapse_vars.js | 1 + test/compress/drop-unused.js | 4 +-- test/compress/functions.js | 2 +- test/compress/reduce_vars.js | 36 +++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 24 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 6354197d39f..d649b6f476e 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -313,19 +313,14 @@ merge(Compressor.prototype, { if (node instanceof AST_SymbolRef) { var d = node.definition(); d.references.push(node); + var value; if (d.fixed === undefined || !safe_to_read(d) || d.single_use == "m") { d.fixed = false; } else if (d.fixed) { - var value = node.fixed_value(); + value = node.fixed_value(); if (value && ref_once(d)) { - if (value instanceof AST_Lambda) { - d.single_use = d.scope === node.scope - && !(d.orig[0] instanceof AST_SymbolFunarg) - || value.is_constant_expression(node.scope); - } else { - d.single_use = d.scope === node.scope - && value.is_constant_expression(); - } + d.single_use = value instanceof AST_Lambda + || d.scope === node.scope && value.is_constant_expression(); } else { d.single_use = false; } @@ -335,10 +330,9 @@ merge(Compressor.prototype, { } else { d.fixed = false; } - } else { - mark_escaped(d, node, value, 0); } } + mark_escaped(d, node, value, 0); } if (node instanceof AST_SymbolCatch) { node.definition().fixed = false; @@ -385,10 +379,7 @@ merge(Compressor.prototype, { d.fixed = node; loop_ids[d.id] = in_loop; mark(d, true); - if (ref_once(d)) { - d.single_use = d.scope === d.references[0].scope - || node.is_constant_expression(d.references[0].scope); - } + d.single_use = ref_once(d); } var save_ids = safe_ids; safe_ids = Object.create(null); @@ -2210,7 +2201,10 @@ merge(Compressor.prototype, { && !self.variables.has(def.name)) { if (scope) { 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; } @@ -4257,11 +4251,20 @@ merge(Compressor.prototype, { if (fixed instanceof AST_Defun) { d.fixed = fixed = make_node(AST_Function, fixed, fixed); } - if (fixed - && d.single_use - && !(fixed instanceof AST_Function - && (d.escaped && d.scope !== self.scope - || recursive_ref(compressor, d)))) { + if (d.single_use && fixed instanceof AST_Function) { + if (d.escaped && d.scope !== self.scope || recursive_ref(compressor, d)) { + d.single_use = false; + } else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) { + 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); return value === fixed ? fixed.clone(true) : value; } diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index fe8e409749c..34489717ce7 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -3036,6 +3036,7 @@ issue_2437: { conditionals: true, inline: true, join_vars: true, + passes: 2, reduce_vars: true, side_effects: true, sequences: true, diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index af6a7a476c2..ebb0b8fa89e 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -1113,7 +1113,7 @@ issue_2105_1: { options = { collapse_vars: true, inline: true, - passes: 2, + passes: 3, reduce_vars: true, side_effects: true, unused: true, @@ -1153,7 +1153,7 @@ issue_2105_2: { options = { collapse_vars: true, inline: true, - passes: 2, + passes: 3, properties: true, pure_getters: "strict", reduce_vars: true, diff --git a/test/compress/functions.js b/test/compress/functions.js index 3c2ccce3c35..c5aab171923 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -513,7 +513,7 @@ issue_2428: { options = { collapse_vars: true, inline: true, - passes: 2, + passes: 3, pure_getters: "strict", reduce_vars: true, side_effects: true, diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 8afea850bd8..d7c5601a968 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -3714,6 +3714,7 @@ recursive_inlining_2: { recursive_inlining_3: { options = { + passes: 2, reduce_vars: true, unused: true, } @@ -3989,3 +3990,38 @@ issue_2450_5: { "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" +}