fix corner case in arguments (#3330)
Track modifications to `arguments[i]` under Strict Mode. fixes #3273
This commit is contained in:
@@ -497,6 +497,15 @@ merge(Compressor.prototype, {
|
|||||||
d.direct_access = true;
|
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) {
|
var suppressor = new TreeWalker(function(node) {
|
||||||
if (!(node instanceof AST_Symbol)) return;
|
if (!(node instanceof AST_Symbol)) return;
|
||||||
var d = node.definition();
|
var d = node.definition();
|
||||||
@@ -515,7 +524,10 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Assign, function(tw, descend, compressor) {
|
def(AST_Assign, function(tw, descend, compressor) {
|
||||||
var node = this;
|
var node = this;
|
||||||
var sym = node.left;
|
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 d = sym.definition();
|
||||||
var safe = safe_to_assign(tw, d, sym.scope, node.right);
|
var safe = safe_to_assign(tw, d, sym.scope, node.right);
|
||||||
d.assignments++;
|
d.assignments++;
|
||||||
@@ -758,7 +770,10 @@ merge(Compressor.prototype, {
|
|||||||
var node = this;
|
var node = this;
|
||||||
if (node.operator != "++" && node.operator != "--") return;
|
if (node.operator != "++" && node.operator != "--") return;
|
||||||
var exp = node.expression;
|
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 d = exp.definition();
|
||||||
var safe = safe_to_assign(tw, d, exp.scope, true);
|
var safe = safe_to_assign(tw, d, exp.scope, true);
|
||||||
d.assignments++;
|
d.assignments++;
|
||||||
@@ -6325,7 +6340,10 @@ merge(Compressor.prototype, {
|
|||||||
var argname = fn.argnames[index];
|
var argname = fn.argnames[index];
|
||||||
if (argname && compressor.has_directive("use strict")) {
|
if (argname && compressor.has_directive("use strict")) {
|
||||||
var def = argname.definition();
|
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;
|
argname = null;
|
||||||
}
|
}
|
||||||
} else if (!argname && !compressor.option("keep_fargs") && index < fn.argnames.length + 5) {
|
} else if (!argname && !compressor.option("keep_fargs") && index < fn.argnames.length + 5) {
|
||||||
|
|||||||
@@ -237,3 +237,170 @@ duplicate_argname: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "bar 42 foo 42 bar"
|
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",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user