From: Alex Lam S.L Date: Tue, 12 Mar 2019 22:59:53 +0000 (+0800) Subject: fix corner case in `arguments` (#3330) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=e250396d7e9f494bc772bbee03c63a3912998b15;p=UglifyJS.git fix corner case in `arguments` (#3330) Track modifications to `arguments[i]` under Strict Mode. fixes #3273 --- diff --git a/lib/compress.js b/lib/compress.js index 61c3a268..9109a696 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -497,6 +497,15 @@ merge(Compressor.prototype, { d.direct_access = true; } + 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 && expr.name == "arguments" && prop instanceof AST_Number) { + expr.definition().reassigned = true; + } + } + var suppressor = new TreeWalker(function(node) { if (!(node instanceof AST_Symbol)) return; var d = node.definition(); @@ -515,7 +524,10 @@ merge(Compressor.prototype, { def(AST_Assign, function(tw, descend, compressor) { var node = this; var sym = node.left; - if (!(sym instanceof AST_SymbolRef)) return; + if (!(sym instanceof AST_SymbolRef)) { + mark_assignment_to_arguments(sym); + return; + } var d = sym.definition(); var safe = safe_to_assign(tw, d, sym.scope, node.right); d.assignments++; @@ -758,7 +770,10 @@ merge(Compressor.prototype, { var node = this; if (node.operator != "++" && node.operator != "--") return; var exp = node.expression; - if (!(exp instanceof AST_SymbolRef)) return; + if (!(exp instanceof AST_SymbolRef)) { + mark_assignment_to_arguments(exp); + return; + } var d = exp.definition(); var safe = safe_to_assign(tw, d, exp.scope, true); d.assignments++; @@ -6325,7 +6340,10 @@ merge(Compressor.prototype, { var argname = fn.argnames[index]; if (argname && compressor.has_directive("use strict")) { var def = argname.definition(); - if (!compressor.option("reduce_vars") || def.assignments || def.orig.length > 1) { + if (!compressor.option("reduce_vars") + || expr.definition().reassigned + || def.assignments + || def.orig.length > 1) { argname = null; } } else if (!argname && !compressor.option("keep_fargs") && index < fn.argnames.length + 5) { diff --git a/test/compress/arguments.js b/test/compress/arguments.js index 04857441..8a19c8a6 100644 --- a/test/compress/arguments.js +++ b/test/compress/arguments.js @@ -237,3 +237,170 @@ duplicate_argname: { } expect_stdout: "bar 42 foo 42 bar" } + +issue_3273: { + options = { + arguments: true, + } + input: { + function f(a) { + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect: { + function f(a) { + console.log(a, a); + a++; + console.log(a, a); + } + f(0); + } + expect_stdout: [ + "0 0", + "1 1", + ] +} + +issue_3273_reduce_vars: { + options = { + arguments: true, + reduce_vars: true, + } + input: { + function f(a) { + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect: { + function f(a) { + console.log(a, a); + a++; + console.log(a, a); + } + f(0); + } + expect_stdout: [ + "0 0", + "1 1", + ] +} + +issue_3273_local_strict: { + options = { + arguments: true, + } + input: { + function f(a) { + "use strict"; + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect: { + function f(a) { + "use strict"; + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect_stdout: [ + "0 0", + "1 0", + ] +} + +issue_3273_local_strict_reduce_vars: { + options = { + arguments: true, + reduce_vars: true, + } + input: { + function f(a) { + "use strict"; + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect: { + function f(a) { + "use strict"; + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect_stdout: [ + "0 0", + "1 0", + ] +} + +issue_3273_global_strict: { + options = { + arguments: true, + } + input: { + "use strict"; + function f(a) { + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect: { + "use strict"; + function f(a) { + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect_stdout: [ + "0 0", + "1 0", + ] +} + +issue_3273_global_strict_reduce_vars: { + options = { + arguments: true, + reduce_vars: true, + } + input: { + "use strict"; + function f(a) { + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect: { + "use strict"; + function f(a) { + console.log(arguments[0], a); + arguments[0]++; + console.log(arguments[0], a); + } + f(0); + } + expect_stdout: [ + "0 0", + "1 0", + ] +}