Skip to content

Commit

Permalink
fix corner case in arguments (#3330)
Browse files Browse the repository at this point in the history
Track modifications to `arguments[i]` under Strict Mode.

fixes #3273
  • Loading branch information
alexlamsl committed Mar 12, 2019
1 parent c6fa39b commit e250396
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 3 deletions.
24 changes: 21 additions & 3 deletions lib/compress.js
Expand Up @@ -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();
Expand All @@ -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++;
Expand Down Expand Up @@ -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++;
Expand Down Expand Up @@ -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) {
Expand Down
167 changes: 167 additions & 0 deletions test/compress/arguments.js
Expand Up @@ -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",
]
}

0 comments on commit e250396

Please sign in to comment.