From ae77ebe5a5f1be4b2634036f48d8b570b569cb21 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Sun, 19 May 2019 12:59:40 +0800 Subject: fix corner case in `arguments` (#3421) fixes #3420 --- lib/compress.js | 55 ++++++++++------ test/compress/arguments.js | 154 ++++++++++++++++++++++++++++++++++++++++++++ test/compress/keep_fargs.js | 66 +++++++++++++++++++ 3 files changed, 255 insertions(+), 20 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index b7e5b3d2..e1f0105c 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -105,10 +105,10 @@ function Compressor(options, false_by_default) { } if (this.options["inline"] === true) this.options["inline"] = 3; var keep_fargs = this.options["keep_fargs"]; - this.drop_fargs = keep_fargs == "strict" ? function(lambda) { + this.drop_fargs = keep_fargs == "strict" ? function(lambda, parent) { if (lambda.length_read) return false; var name = lambda.name; - if (!name) return true; + if (!name) return parent && parent.TYPE == "Call"; if (name.fixed_value() !== lambda) return false; var def = name.definition(); if (def.direct_access) return false; @@ -527,12 +527,9 @@ merge(Compressor.prototype, { function mark_assignment_to_arguments(node) { if (!(node instanceof AST_Sub)) return; var expr = node.expression; - var prop = node.property; - if (expr instanceof AST_SymbolRef - && is_arguments(expr.definition()) - && prop instanceof AST_Number) { - expr.definition().reassigned = true; - } + if (!(expr instanceof AST_SymbolRef)) return; + var def = expr.definition(); + if (is_arguments(def) && node.property instanceof AST_Number) def.reassigned = true; } var suppressor = new TreeWalker(function(node) { @@ -3641,7 +3638,7 @@ merge(Compressor.prototype, { node.name = null; } if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) { - var trim = compressor.drop_fargs(node); + var trim = compressor.drop_fargs(node, parent); for (var a = node.argnames, i = a.length; --i >= 0;) { var sym = a[i]; if (!(sym.definition().id in in_use_ids)) { @@ -3832,6 +3829,7 @@ merge(Compressor.prototype, { }; } }); + tt.push(compressor.parent()); self.transform(tt); function verify_safe_usage(def, read, modified) { @@ -6682,23 +6680,30 @@ merge(Compressor.prototype, { } } } - var fn; + var parent = compressor.parent(); + var def, fn, fn_parent; if (compressor.option("arguments") && expr instanceof AST_SymbolRef - && is_arguments(expr.definition()) + && is_arguments(def = expr.definition()) && prop instanceof AST_Number - && (fn = expr.scope) === compressor.find_parent(AST_Lambda)) { + && (fn = expr.scope) === find_lambda()) { var index = prop.getValue(); + if (parent instanceof AST_UnaryPrefix && parent.operator == "delete") { + if (!def.deleted) def.deleted = []; + def.deleted[index] = true; + } var argname = fn.argnames[index]; - if (argname && compressor.has_directive("use strict")) { - var def = argname.definition(); + if (def.deleted && def.deleted[index]) { + argname = null; + } else if (argname && compressor.has_directive("use strict")) { + var arg_def = argname.definition(); if (!compressor.option("reduce_vars") - || expr.definition().reassigned - || def.assignments - || def.orig.length > 1) { + || def.reassigned + || arg_def.assignments + || arg_def.orig.length > 1) { argname = null; } - } else if (!argname && compressor.drop_fargs(fn) && index < fn.argnames.length + 5) { + } else if (!argname && index < fn.argnames.length + 5 && compressor.drop_fargs(fn, fn_parent)) { while (index >= fn.argnames.length) { argname = make_node(AST_SymbolFunarg, fn, { name: fn.make_var_name("argument_" + fn.argnames.length), @@ -6711,14 +6716,14 @@ merge(Compressor.prototype, { if (argname && find_if(function(node) { return node.name === argname.name; }, fn.argnames) === argname) { - expr.definition().reassigned = false; + def.reassigned = false; var sym = make_node(AST_SymbolRef, self, argname); sym.reference({}); delete argname.__unused; return sym; } } - if (is_lhs(compressor.self(), compressor.parent())) return self; + if (is_lhs(compressor.self(), parent)) return self; if (key !== prop) { var sub = self.flatten_object(property, compressor); if (sub) { @@ -6767,6 +6772,16 @@ merge(Compressor.prototype, { return best_of(compressor, ev, self); } return self; + + function find_lambda() { + var i = 0, p; + while (p = compressor.parent(i++)) { + if (p instanceof AST_Lambda) { + fn_parent = compressor.parent(i); + return p; + } + } + } }); AST_Scope.DEFMETHOD("contains_this", function() { diff --git a/test/compress/arguments.js b/test/compress/arguments.js index eaff8119..119eaf2c 100644 --- a/test/compress/arguments.js +++ b/test/compress/arguments.js @@ -622,3 +622,157 @@ issue_3282_2_passes: { } expect_stdout: true } + +issue_3420_1: { + options = { + arguments: true, + keep_fargs: "strict", + } + input: { + console.log(function() { + return function() { + return arguments[0]; + }; + }().length); + } + expect: { + console.log(function() { + return function() { + return arguments[0]; + }; + }().length); + } + expect_stdout: "0" +} + +issue_3420_2: { + options = { + arguments: true, + keep_fargs: "strict", + } + input: { + var foo = function() { + delete arguments[0]; + }; + foo(); + } + expect: { + var foo = function() { + delete arguments[0]; + }; + foo(); + } + expect_stdout: true +} + +issue_3420_3: { + options = { + arguments: true, + keep_fargs: "strict", + } + input: { + "use strict"; + var foo = function() { + delete arguments[0]; + }; + foo(); + } + expect: { + "use strict"; + var foo = function() { + delete arguments[0]; + }; + foo(); + } + expect_stdout: true +} + +issue_3420_4: { + options = { + arguments: true, + keep_fargs: "strict", + } + input: { + !function() { + console.log(arguments[0]); + delete arguments[0]; + console.log(arguments[0]); + }(42); + } + expect: { + !function(argument_0) { + console.log(argument_0); + delete arguments[0]; + console.log(arguments[0]); + }(42); + } + expect_stdout: [ + "42", + "undefined", + ] +} + +issue_3420_5: { + options = { + arguments: true, + keep_fargs: "strict", + } + input: { + "use strict"; + !function() { + console.log(arguments[0]); + delete arguments[0]; + console.log(arguments[0]); + }(42); + } + expect: { + "use strict"; + !function(argument_0) { + console.log(argument_0); + delete arguments[0]; + console.log(arguments[0]); + }(42); + } + expect_stdout: [ + "42", + "undefined", + ] +} + +issue_3420_6: { + options = { + arguments: true, + keep_fargs: "strict", + } + input: { + console.log(function() { + return delete arguments[0]; + }()); + } + expect: { + console.log(function() { + return delete arguments[0]; + }()); + } + expect_stdout: "true" +} + +issue_3420_7: { + options = { + arguments: true, + keep_fargs: "strict", + } + input: { + "use strict"; + console.log(function() { + return delete arguments[0]; + }()); + } + expect: { + "use strict"; + console.log(function() { + return delete arguments[0]; + }()); + } + expect_stdout: "true" +} diff --git a/test/compress/keep_fargs.js b/test/compress/keep_fargs.js index b23e96f0..558b10bb 100644 --- a/test/compress/keep_fargs.js +++ b/test/compress/keep_fargs.js @@ -1051,3 +1051,69 @@ function_name_mangle_ie8: { expect_exact: "(function(){console.log(typeof function o(){})})();" expect_stdout: "function" } + +issue_3420_1: { + options = { + keep_fargs: "strict", + unused: true, + } + input: { + console.log(function() { + return function(a, b, c, d) { + return a + b; + }; + }().length); + } + expect: { + console.log(function() { + return function(a, b, c, d) { + return a + b; + }; + }().length); + } + expect_stdout: "4" +} + +issue_3420_2: { + options = { + inline: true, + keep_fargs: "strict", + unused: true, + } + input: { + console.log(function() { + return function(a, b, c, d) { + return a + b; + }; + }().length); + } + expect: { + console.log(function(a, b, c, d) { + return a + b; + }.length); + } + expect_stdout: "4" +} + +issue_3420_3: { + options = { + inline: true, + keep_fargs: "strict", + reduce_vars: true, + unused: true, + } + input: { + console.log(function() { + function f(a, b, c, d) { + return a + b; + } + return f; + }().length); + } + expect: { + console.log(function(a, b, c, d) { + return a + b; + }.length); + } + expect_stdout: "4" +} -- cgit v1.2.3