diff --git a/lib/compress.js b/lib/compress.js index ba7c10f4..9185f048 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1009,6 +1009,10 @@ merge(Compressor.prototype, { } } + function get_rvalue(expr) { + return expr[expr instanceof AST_Assign ? "right" : "value"]; + } + function get_lvalues(expr) { var lvalues = Object.create(null); if (expr instanceof AST_Unary) return lvalues; @@ -1019,7 +1023,7 @@ merge(Compressor.prototype, { lvalues[sym.name] = lvalues[sym.name] || is_lhs(node, tw.parent()); } }); - expr[expr instanceof AST_Assign ? "right" : "value"].walk(tw); + get_rvalue(expr).walk(tw); return lvalues; } @@ -1044,6 +1048,8 @@ merge(Compressor.prototype, { found = true; if (node instanceof AST_VarDef) { remove(node.name.definition().orig, node.name); + node.value = null; + return node; } return in_list ? MAP.skip : null; } @@ -1052,16 +1058,13 @@ merge(Compressor.prototype, { case 0: return null; case 1: return node.expressions[0]; } - if (node instanceof AST_Definitions && node.definitions.length == 0 - || node instanceof AST_SimpleStatement && !node.body) { - return null; - } + if (node instanceof AST_SimpleStatement && !node.body) return null; })); } function value_has_side_effects(expr) { if (expr instanceof AST_Unary) return false; - return expr[expr instanceof AST_Assign ? "right" : "value"].has_side_effects(compressor); + return get_rvalue(expr).has_side_effects(compressor); } function references_in_scope(def) { @@ -2303,61 +2306,63 @@ merge(Compressor.prototype, { // this scope (not in nested scopes). var scope = this; var tw = new TreeWalker(function(node, descend){ - if (node !== self) { - if (node instanceof AST_Defun) { - if (!drop_funcs && scope === self) { - var node_def = node.name.definition(); + if (node === self) return; + if (node instanceof AST_Defun) { + if (!drop_funcs && scope === self) { + var node_def = node.name.definition(); + if (!(node_def.id in in_use_ids)) { + in_use_ids[node_def.id] = true; + in_use.push(node_def); + } + } + initializations.add(node.name.name, node); + return true; // don't go in nested scopes + } + if (node instanceof AST_SymbolFunarg && scope === self) { + var_defs_by_id.add(node.definition().id, node); + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def){ + var node_def = def.name.definition(); + if (def.name instanceof AST_SymbolVar) { + var_defs_by_id.add(node_def.id, def); + } + if (!drop_vars) { if (!(node_def.id in in_use_ids)) { in_use_ids[node_def.id] = true; in_use.push(node_def); } } - initializations.add(node.name.name, node); - return true; // don't go in nested scopes - } - if (node instanceof AST_Definitions && scope === self) { - node.definitions.forEach(function(def){ - var node_def = def.name.definition(); - if (def.name instanceof AST_SymbolVar) { - var_defs_by_id.add(node_def.id, def); + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects(compressor)) { + def.value.walk(tw); } - if (!drop_vars) { - if (!(node_def.id in in_use_ids)) { - in_use_ids[node_def.id] = true; - in_use.push(node_def); - } - } - if (def.value) { - initializations.add(def.name.name, def.value); - if (def.value.has_side_effects(compressor)) { - def.value.walk(tw); - } - } - }); - return true; - } - var sym; - if (scope === self - && (sym = assign_as_unused(node)) instanceof AST_SymbolRef - && self.variables.get(sym.name) === sym.definition()) { - if (node instanceof AST_Assign) node.right.walk(tw); - return true; - } - if (node instanceof AST_SymbolRef) { - var node_def = node.definition(); - if (!(node_def.id in in_use_ids)) { - in_use_ids[node_def.id] = true; - in_use.push(node_def); } - return true; - } - if (node instanceof AST_Scope) { - var save_scope = scope; - scope = node; - descend(); - scope = save_scope; - return true; + }); + return true; + } + var sym; + if (scope === self + && (sym = assign_as_unused(node)) instanceof AST_SymbolRef + && self.variables.get(sym.name) === sym.definition()) { + if (node instanceof AST_Assign) node.right.walk(tw); + return true; + } + if (node instanceof AST_SymbolRef) { + var node_def = node.definition(); + if (!(node_def.id in in_use_ids)) { + in_use_ids[node_def.id] = true; + in_use.push(node_def); } + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; } }); self.walk(tw); diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js index e2c5f1be..b1e89a40 100644 --- a/test/compress/collapse_vars.js +++ b/test/compress/collapse_vars.js @@ -1388,6 +1388,7 @@ issue_1605_1: { options = { collapse_vars: true, toplevel: false, + unused: true, } input: { function foo(x) { @@ -1410,6 +1411,7 @@ issue_1605_2: { options = { collapse_vars: true, toplevel: "vars", + unused: true, } input: { function foo(x) { @@ -1537,6 +1539,7 @@ issue_1631_3: { var_side_effects_1: { options = { collapse_vars: true, + unused: true, } input: { var print = console.log.bind(console); @@ -1559,6 +1562,7 @@ var_side_effects_1: { var_side_effects_2: { options = { collapse_vars: true, + unused: true, } input: { var print = console.log.bind(console); @@ -1584,6 +1588,7 @@ var_side_effects_3: { collapse_vars: true, pure_getters: true, unsafe: true, + unused: true, } input: { var print = console.log.bind(console); @@ -1659,6 +1664,7 @@ iife_2: { }(foo); } expect: { + var foo; !function(x) { console.log(x); }(bar()); @@ -1945,6 +1951,7 @@ ref_scope: { chained_1: { options = { collapse_vars: true, + unused: true, } input: { var a = 2; @@ -1961,6 +1968,7 @@ chained_1: { chained_2: { options = { collapse_vars: true, + unused: true, } input: { var a; @@ -2061,6 +2069,7 @@ inner_lvalues: { double_def: { options = { collapse_vars: true, + unused: true, } input: { var a = x, a = a && y; @@ -2075,6 +2084,7 @@ double_def: { toplevel_single_reference: { options = { collapse_vars: true, + unused: true, } input: { var a; @@ -2084,9 +2094,10 @@ toplevel_single_reference: { } } expect: { - var a; - for (var b in x) + for (var b in x) { + var a; b(a = b); + } } } @@ -2889,6 +2900,7 @@ pure_getters_chain: { options = { collapse_vars: true, pure_getters: true, + unused: true, } input: { function o(t, r) { @@ -2909,6 +2921,7 @@ pure_getters_chain: { conditional_1: { options = { collapse_vars: true, + unused: true, } input: { function f(a, b) { @@ -2933,6 +2946,7 @@ conditional_1: { conditional_2: { options = { collapse_vars: true, + unused: true, } input: { function f(a, b) { diff --git a/test/compress/issue-973.js b/test/compress/issue-973.js index 30f886a8..fee05dfc 100644 --- a/test/compress/issue-973.js +++ b/test/compress/issue-973.js @@ -51,6 +51,7 @@ this_binding_collapse_vars: { options = { collapse_vars: true, toplevel: true, + unused: true, }; input: { var c = a; c(); diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 7714ad5d..1acd902b 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -2131,14 +2131,13 @@ redefine_farg_1: { } expect: { function f(a) { - var a; return typeof a; } function g() { - return"number"; + return "number"; } function h(a, b) { - var a = b; + a = b; return typeof a; } console.log(f([]), g([]), h([])); @@ -2173,10 +2172,9 @@ redefine_farg_2: { } expect: { console.log(function(a) { - var a; return typeof a; }([]), "number",function(a, b) { - var a = b; + a = b; return typeof a; }([])); } @@ -2185,11 +2183,13 @@ redefine_farg_2: { redefine_farg_3: { options = { + cascade: true, evaluate: true, inline: true, keep_fargs: false, - passes: 3, + passes: 2, reduce_vars: true, + sequences: true, side_effects: true, toplevel: true, unused: true,