From ec4558be29d5381ed10f0b5aecfcf8273da00aaa Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 17 Jul 2022 09:03:12 +0100 Subject: [PATCH] fix corner cases with parameter scope (#5567) fixes #5566 --- lib/compress.js | 22 +++-- test/compress/default-values.js | 144 ++++++++++++++++++++++++++++++++ test/reduce.js | 62 ++++++++------ 3 files changed, 193 insertions(+), 35 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 4872c1f6..4e89eaf4 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2647,16 +2647,17 @@ Compressor.prototype.compress = function(node) { arg = null; return true; } - if (node instanceof AST_ObjectIdentity && (fn_strict || !arg_scope)) { - arg = null; + if (node instanceof AST_ObjectIdentity) { + if (fn_strict || !arg_scope) arg = null; 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; + if (node instanceof AST_SymbolRef) { + var def; + if (node.in_arg && !is_safe_lexical(node.definition()) + || (def = fn.variables.get(node.name)) && def !== node.definition()) { + arg = null; } - arg = null; + return true; } if (node instanceof AST_Scope && !is_arrow(node)) { var save_scope = arg_scope; @@ -5985,7 +5986,7 @@ Compressor.prototype.compress = function(node) { return true; } if (node instanceof AST_SymbolRef) { - if (self.inlined || node.redef) { + if (self.inlined || node.redef || node.in_arg) { result = false; return true; } @@ -7679,6 +7680,7 @@ Compressor.prototype.compress = function(node) { var def = node.left.definition(); if (def.scope.resolve() === self) assignments.add(def.id, node); } + if (node instanceof AST_SymbolRef && node.in_arg) var_defs[node.definition().id] = 0; if (node instanceof AST_Unary && node.expression instanceof AST_SymbolRef) { var def = node.expression.definition(); if (def.scope.resolve() === self) assignments.add(def.id, node); @@ -8172,7 +8174,9 @@ Compressor.prototype.compress = function(node) { // collect only vars which don't show up in self's arguments list var defns = []; if (self instanceof AST_Lambda) self.each_argname(function(argname) { - vars.del(argname.name); + if (all(argname.definition().references, function(ref) { + return !ref.in_arg; + })) vars.del(argname.name); }); vars.each(function(defn, name) { defn = defn.clone(); diff --git a/test/compress/default-values.js b/test/compress/default-values.js index d11a256e..f2fdde22 100644 --- a/test/compress/default-values.js +++ b/test/compress/default-values.js @@ -180,6 +180,26 @@ collapse_arg_sequence: { node_version: ">=6" } +collapse_in_arg: { + options = { + collapse_vars: true, + keep_fargs: false, + unused: true, + } + input: { + (function(a, b = a) { + b("PASS"); + })(console.log); + } + expect: { + (function(a) { + a("PASS"); + })(console.log); + } + expect_stdout: "PASS" + node_version: ">=6" +} + collapse_value_1: { options = { collapse_vars: true, @@ -2872,3 +2892,127 @@ issue_5536: { expect_stdout: "undefined" node_version: ">=6" } + +issue_5566_1: { + options = { + unused: true, + } + input: { + (function(a, f = function() { + return a; + }) { + var a = "foo"; + console.log(a, f()); + })("bar"); + } + expect: { + (function(a, f = function() { + return a; + }) { + var a = "foo"; + console.log(a, f()); + })("bar"); + } + expect_stdout: "foo bar" + node_version: ">=6" +} + +issue_5566_2: { + options = { + inline: true, + reduce_vars: true, + } + input: { + (function(a, f = function() { + return a; + }) { + function a() {} + console.log(typeof a, typeof f()); + })(42); + } + expect: { + (function(a, f = function() { + return a; + }) { + function a() {} + console.log(typeof a, typeof f()); + })(42); + } + expect_stdout: "function number" + node_version: ">=6" +} + +issue_5566_3: { + options = { + reduce_vars: true, + unused: true, + } + input: { + (function(a, f = function() { + return a; + }) { + function a() {} + console.log(typeof a, typeof f()); + })(42); + } + expect: { + (function(a, f = function() { + return a; + }) { + function a() {} + console.log(typeof a, typeof f()); + })(42); + } + expect_stdout: "function number" + node_version: ">=6" +} + +issue_5566_4: { + options = { + collapse_vars: true, + unused: true, + } + input: { + (function(a, b = function() { + return a; + }) { + var a = 0; + b()("PASS"); + })(console.log); + } + expect: { + (function(a, b = function() { + return a; + }) { + var a = 0; + b()("PASS"); + })(console.log); + } + expect_stdout: "PASS" + node_version: ">=6" +} + +issue_5566_5: { + options = { + hoist_vars: true, + } + input: { + (function(a, f = function() { + return a; + }) { + var a = "foo"; + var b; + console.log(a, f()); + })("bar"); + } + expect: { + (function(a, f = function() { + return a; + }) { + var b, a = "foo"; + console.log(a, f()); + })("bar"); + } + expect_stdout: "foo bar" + node_version: ">=6" +} diff --git a/test/reduce.js b/test/reduce.js index 71cdb2a6..4437e321 100644 --- a/test/reduce.js +++ b/test/reduce.js @@ -241,23 +241,6 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) CHANGED = true; return node.name; } - else if (node instanceof U.AST_DestructuredArray) { - var expr = node.elements[0]; - if (expr && !(expr instanceof U.AST_Hole)) { - node.start._permute++; - CHANGED = true; - return expr; - } - } - else if (node instanceof U.AST_DestructuredObject) { - // first property's value - var expr = node.properties[0]; - if (expr) { - node.start._permute++; - CHANGED = true; - return expr.value; - } - } else if (node instanceof U.AST_Defun) { switch (((node.start._permute += step) * steps | 0) % 2) { case 0: @@ -275,6 +258,23 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) } } } + else if (node instanceof U.AST_DestructuredArray) { + var expr = node.elements[0]; + if (expr && !(expr instanceof U.AST_Hole)) { + node.start._permute++; + CHANGED = true; + return expr; + } + } + else if (node instanceof U.AST_DestructuredObject) { + // first property's value + var expr = node.properties[0]; + if (expr) { + node.start._permute++; + CHANGED = true; + return expr.value; + } + } else if (node instanceof U.AST_DWLoop) { var expr = [ node.condition, @@ -296,6 +296,16 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) return to_statement(expr); } } + else if (node instanceof U.AST_ExportDeclaration) { + node.start._permute++; + CHANGED = true; + return node.body; + } + else if (node instanceof U.AST_ExportDefault) { + node.start._permute++; + CHANGED = true; + return to_statement(node.body); + } else if (node instanceof U.AST_Finally) { // drop finally block node.start._permute++; @@ -351,6 +361,15 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) return to_statement(expr); } } + else if (node instanceof U.AST_LabeledStatement) { + if (node.body instanceof U.AST_Statement + && !has_loopcontrol(node.body, node.body, node)) { + // replace labelled statement with its non-labelled body + node.start._permute = REPLACEMENTS.length; + CHANGED = true; + return node.body; + } + } else if (node instanceof U.AST_Object) { // first property's value var expr = node.properties[0]; @@ -441,15 +460,6 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options) return to_statement(node.definitions[0].value); } } - else if (node instanceof U.AST_LabeledStatement) { - if (node.body instanceof U.AST_Statement - && !has_loopcontrol(node.body, node.body, node)) { - // replace labelled statement with its non-labelled body - node.start._permute = REPLACEMENTS.length; - CHANGED = true; - return node.body; - } - } if (in_list) { // drop switch branches