diff --git a/lib/compress.js b/lib/compress.js index 56b9e8ce..9e1d8232 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -848,6 +848,21 @@ merge(Compressor.prototype, { } } + function has_overlapping_symbol(fn, arg) { + var found = false; + arg.walk(new TreeWalker(function(node) { + if (found) return true; + if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) { + var s = node.definition().scope; + if (s !== scope) while (s = s.parent_scope) { + if (s === scope) return true; + } + found = true; + } + })); + return found; + } + function extract_args() { var iife, fn = compressor.self(); if (is_func_expr(fn) @@ -860,23 +875,27 @@ merge(Compressor.prototype, { return !(arg instanceof AST_Expansion); })) { fn.argnames.forEach(function(sym, i) { - if (!(sym instanceof AST_SymbolFunarg)) return; - var arg = iife.args[i]; - if (!arg) arg = make_node(AST_Undefined, sym); - else arg.walk(new TreeWalker(function(node) { - if (!arg) return true; - if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) { - var s = node.definition().scope; - if (s !== scope) while (s = s.parent_scope) { - if (s === scope) return true; - } - arg = null; + if (sym instanceof AST_Expansion) { + var elements = iife.args.slice(i); + if (all(elements, function(arg) { + return !has_overlapping_symbol(fn, arg); + })) { + candidates.push(make_node(AST_VarDef, sym, { + name: sym.expression, + value: make_node(AST_Array, iife, { + elements: elements + }) + })); } - })); - if (arg) candidates.push(make_node(AST_VarDef, sym, { - name: sym, - value: arg - })); + } else { + var arg = iife.args[i]; + if (!arg) arg = make_node(AST_Undefined, sym); + else if (has_overlapping_symbol(fn, arg)) arg = null; + if (arg) candidates.push(make_node(AST_VarDef, sym, { + name: sym, + value: arg + })); + } }); } } @@ -945,11 +964,16 @@ merge(Compressor.prototype, { function remove_candidate(expr) { if (expr.name instanceof AST_SymbolFunarg) { - var index = compressor.self().argnames.indexOf(expr.name); - var args = compressor.parent().args; - if (args[index]) args[index] = make_node(AST_Number, args[index], { - value: 0 - }); + var iife = compressor.parent(), argnames = compressor.self().argnames; + var index = argnames.indexOf(expr.name); + if (index < 0) { + iife.args.length = Math.min(iife.args.length, argnames.length - 1); + } else { + var args = iife.args; + if (args[index]) args[index] = make_node(AST_Number, args[index], { + value: 0 + }); + } return true; } var found = false; @@ -3154,7 +3178,7 @@ merge(Compressor.prototype, { var pos = 0, last = 0; for (var i = 0, len = self.args.length; i < len; i++) { if (fn.argnames[i] instanceof AST_Expansion) { - if (fn.argnames[i].__unused) while (i < len) { + if (fn.argnames[i].expression.__unused) while (i < len) { var node = self.args[i++].drop_side_effect_free(compressor); if (node) { self.args[pos++] = node; @@ -3403,6 +3427,7 @@ merge(Compressor.prototype, { && !exp.uses_eval && (exp.body instanceof AST_Node || exp.body.length == 1) && all(exp.argnames, function(arg) { + if (arg instanceof AST_Expansion) return arg.expression.__unused; return arg.__unused; }) && !self.has_pure_annotation(compressor)) { diff --git a/test/compress/arrow.js b/test/compress/arrow.js index 2d9eb73b..fc19eeb5 100644 --- a/test/compress/arrow.js +++ b/test/compress/arrow.js @@ -374,7 +374,7 @@ issue_2105_2: { expect_stdout: "PASS" node_version: ">=6" } -/* + issue_2136_2: { options = { arrows: true, @@ -430,7 +430,7 @@ issue_2136_3: { expect_stdout: "2" node_version: ">=6" } -*/ + call_args: { options = { arrows: true, diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js index 18170dec..c08d5784 100644 --- a/test/compress/drop-unused.js +++ b/test/compress/drop-unused.js @@ -1358,7 +1358,7 @@ issue_2136_1: { expect_stdout: "[]" node_version: ">=6" } -/* + issue_2136_2: { options = { collapse_vars: true, @@ -1410,7 +1410,7 @@ issue_2136_3: { expect_stdout: "2" node_version: ">=6" } -*/ + issue_2163: { options = { pure_funcs: [ "pure" ],