@@ -518,14 +518,15 @@ merge(Compressor.prototype, {
|
|||||||
var sym = node.left;
|
var sym = node.left;
|
||||||
if (!(sym instanceof AST_SymbolRef)) return;
|
if (!(sym instanceof AST_SymbolRef)) return;
|
||||||
var d = sym.definition();
|
var d = sym.definition();
|
||||||
|
var safe = safe_to_assign(tw, d, sym.scope, node.right);
|
||||||
|
d.assignments++;
|
||||||
|
if (!safe) return;
|
||||||
var fixed = d.fixed;
|
var fixed = d.fixed;
|
||||||
if (!fixed && node.operator != "=") return;
|
if (!fixed && node.operator != "=") return;
|
||||||
if (!safe_to_assign(tw, d, sym.scope, node.right)) return;
|
|
||||||
var eq = node.operator == "=";
|
var eq = node.operator == "=";
|
||||||
var value = eq ? node.right : node;
|
var value = eq ? node.right : node;
|
||||||
if (is_modified(compressor, tw, node, value, 0)) return;
|
if (is_modified(compressor, tw, node, value, 0)) return;
|
||||||
d.references.push(sym);
|
d.references.push(sym);
|
||||||
d.assignments++;
|
|
||||||
if (!eq) d.chained = true;
|
if (!eq) d.chained = true;
|
||||||
d.fixed = eq ? function() {
|
d.fixed = eq ? function() {
|
||||||
return node.right;
|
return node.right;
|
||||||
@@ -657,7 +658,7 @@ merge(Compressor.prototype, {
|
|||||||
// So existing transformation rules can work on them.
|
// So existing transformation rules can work on them.
|
||||||
node.argnames.forEach(function(arg, i) {
|
node.argnames.forEach(function(arg, i) {
|
||||||
var d = arg.definition();
|
var d = arg.definition();
|
||||||
if (!node.uses_arguments && d.fixed === undefined) {
|
if (d.fixed === undefined && (!node.uses_arguments || tw.has_directive("use strict"))) {
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
return iife.args[i] || make_node(AST_Undefined, iife);
|
return iife.args[i] || make_node(AST_Undefined, iife);
|
||||||
};
|
};
|
||||||
@@ -760,11 +761,12 @@ merge(Compressor.prototype, {
|
|||||||
var exp = node.expression;
|
var exp = node.expression;
|
||||||
if (!(exp instanceof AST_SymbolRef)) return;
|
if (!(exp instanceof AST_SymbolRef)) return;
|
||||||
var d = exp.definition();
|
var d = exp.definition();
|
||||||
|
var safe = safe_to_assign(tw, d, exp.scope, true);
|
||||||
|
d.assignments++;
|
||||||
|
if (!safe) return;
|
||||||
var fixed = d.fixed;
|
var fixed = d.fixed;
|
||||||
if (!fixed) return;
|
if (!fixed) return;
|
||||||
if (!safe_to_assign(tw, d, exp.scope, true)) return;
|
|
||||||
d.references.push(exp);
|
d.references.push(exp);
|
||||||
d.assignments++;
|
|
||||||
d.chained = true;
|
d.chained = true;
|
||||||
d.fixed = function() {
|
d.fixed = function() {
|
||||||
return make_node(AST_Binary, node, {
|
return make_node(AST_Binary, node, {
|
||||||
@@ -3289,6 +3291,15 @@ merge(Compressor.prototype, {
|
|||||||
// this scope (not in nested scopes).
|
// this scope (not in nested scopes).
|
||||||
var scope = this;
|
var scope = this;
|
||||||
var tw = new TreeWalker(function(node, descend) {
|
var tw = new TreeWalker(function(node, descend) {
|
||||||
|
if (node instanceof AST_Lambda && node.uses_arguments && !tw.has_directive("use strict")) {
|
||||||
|
node.argnames.forEach(function(argname) {
|
||||||
|
var def = argname.definition();
|
||||||
|
if (!(def.id in in_use_ids)) {
|
||||||
|
in_use_ids[def.id] = true;
|
||||||
|
in_use.push(def);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
if (node === self) return;
|
if (node === self) return;
|
||||||
if (node instanceof AST_Defun) {
|
if (node instanceof AST_Defun) {
|
||||||
var node_def = node.name.definition();
|
var node_def = node.name.definition();
|
||||||
@@ -3376,8 +3387,7 @@ merge(Compressor.prototype, {
|
|||||||
// any declarations with same name will overshadow
|
// any declarations with same name will overshadow
|
||||||
// name of this anonymous function and can therefore
|
// name of this anonymous function and can therefore
|
||||||
// never be used anywhere
|
// never be used anywhere
|
||||||
if (!(def.id in in_use_ids) || def.orig.length > 1)
|
if (!(def.id in in_use_ids) || def.orig.length > 1) node.name = null;
|
||||||
node.name = null;
|
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
|
||||||
var trim = !compressor.option("keep_fargs");
|
var trim = !compressor.option("keep_fargs");
|
||||||
@@ -3389,8 +3399,7 @@ merge(Compressor.prototype, {
|
|||||||
a.pop();
|
a.pop();
|
||||||
compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
|
compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
trim = false;
|
trim = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6208,6 +6217,39 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var fn;
|
||||||
|
if (compressor.option("arguments")
|
||||||
|
&& expr instanceof AST_SymbolRef
|
||||||
|
&& expr.name == "arguments"
|
||||||
|
&& expr.definition().orig.length == 1
|
||||||
|
&& (fn = expr.scope) instanceof AST_Lambda
|
||||||
|
&& prop instanceof AST_Number) {
|
||||||
|
var index = prop.getValue();
|
||||||
|
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) {
|
||||||
|
argname = null;
|
||||||
|
}
|
||||||
|
} else if (!argname && !compressor.option("keep_fargs") && index < fn.argnames.length + 5) {
|
||||||
|
while (index >= fn.argnames.length) {
|
||||||
|
argname = make_node(AST_SymbolFunarg, fn, {
|
||||||
|
name: fn.make_var_name("argument_" + fn.argnames.length),
|
||||||
|
scope: fn
|
||||||
|
});
|
||||||
|
fn.argnames.push(argname);
|
||||||
|
fn.enclosed.push(fn.def_variable(argname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argname && find_if(function(node) {
|
||||||
|
return node.name === argname.name;
|
||||||
|
}, fn.argnames) === argname) {
|
||||||
|
var sym = make_node(AST_SymbolRef, self, argname);
|
||||||
|
sym.reference({});
|
||||||
|
delete argname.__unused;
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (is_lhs(self, compressor.parent())) return self;
|
if (is_lhs(self, compressor.parent())) return self;
|
||||||
if (key !== prop) {
|
if (key !== prop) {
|
||||||
var sub = self.flatten_object(property, compressor);
|
var sub = self.flatten_object(property, compressor);
|
||||||
@@ -6251,31 +6293,6 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var fn;
|
|
||||||
if (compressor.option("arguments")
|
|
||||||
&& expr instanceof AST_SymbolRef
|
|
||||||
&& expr.name == "arguments"
|
|
||||||
&& expr.definition().orig.length == 1
|
|
||||||
&& (fn = expr.scope) instanceof AST_Lambda
|
|
||||||
&& prop instanceof AST_Number) {
|
|
||||||
var index = prop.getValue();
|
|
||||||
var argname = fn.argnames[index];
|
|
||||||
if (!argname && !compressor.option("keep_fargs")) {
|
|
||||||
while (index >= fn.argnames.length) {
|
|
||||||
argname = make_node(AST_SymbolFunarg, fn, {
|
|
||||||
name: fn.make_var_name("argument_" + fn.argnames.length),
|
|
||||||
scope: fn
|
|
||||||
});
|
|
||||||
fn.argnames.push(argname);
|
|
||||||
fn.enclosed.push(fn.def_variable(argname));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (argname) {
|
|
||||||
var sym = make_node(AST_SymbolRef, self, argname);
|
|
||||||
sym.reference({});
|
|
||||||
return sym;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var ev = self.evaluate(compressor);
|
var ev = self.evaluate(compressor);
|
||||||
if (ev !== self) {
|
if (ev !== self) {
|
||||||
ev = make_node_from_constant(ev, self).optimize(compressor);
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ function member(name, array) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function find_if(func, array) {
|
function find_if(func, array) {
|
||||||
for (var i = 0, n = array.length; i < n; ++i) {
|
for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
|
||||||
if (func(array[i])) return array[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function repeat_string(str, i) {
|
function repeat_string(str, i) {
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ replace_index: {
|
|||||||
properties: true,
|
properties: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(arguments && arguments[0]);
|
var arguments = [];
|
||||||
|
console.log(arguments[0]);
|
||||||
(function() {
|
(function() {
|
||||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
@@ -21,7 +22,8 @@ replace_index: {
|
|||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(arguments && arguments[0]);
|
var arguments = [];
|
||||||
|
console.log(arguments[0]);
|
||||||
(function() {
|
(function() {
|
||||||
console.log(arguments[1], arguments[1], arguments.foo);
|
console.log(arguments[1], arguments[1], arguments.foo);
|
||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
@@ -45,6 +47,37 @@ replace_index: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
replace_index_strict: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
evaluate: true,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function() {
|
||||||
|
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||||
|
})("bar", 42);
|
||||||
|
(function(a, b) {
|
||||||
|
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||||
|
})("bar", 42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
(function() {
|
||||||
|
console.log(arguments[1], arguments[1], arguments.foo);
|
||||||
|
})("bar", 42);
|
||||||
|
(function(a, b) {
|
||||||
|
console.log(b, b, arguments.foo);
|
||||||
|
})("bar", 42);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"42 42 undefined",
|
||||||
|
"42 42 undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
replace_index_keep_fargs: {
|
replace_index_keep_fargs: {
|
||||||
options = {
|
options = {
|
||||||
arguments: true,
|
arguments: true,
|
||||||
@@ -53,7 +86,8 @@ replace_index_keep_fargs: {
|
|||||||
properties: true,
|
properties: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
console.log(arguments && arguments[0]);
|
var arguments = [];
|
||||||
|
console.log(arguments[0]);
|
||||||
(function() {
|
(function() {
|
||||||
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
@@ -69,7 +103,8 @@ replace_index_keep_fargs: {
|
|||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
console.log(arguments && arguments[0]);
|
var arguments = [];
|
||||||
|
console.log(arguments[0]);
|
||||||
(function(argument_0, argument_1) {
|
(function(argument_0, argument_1) {
|
||||||
console.log(argument_1, argument_1, arguments.foo);
|
console.log(argument_1, argument_1, arguments.foo);
|
||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
@@ -93,6 +128,38 @@ replace_index_keep_fargs: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
replace_index_keep_fargs_strict: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
evaluate: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
properties: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function() {
|
||||||
|
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||||
|
})("bar", 42);
|
||||||
|
(function(a, b) {
|
||||||
|
console.log(arguments[1], arguments["1"], arguments["foo"]);
|
||||||
|
})("bar", 42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
(function(argument_0, argument_1) {
|
||||||
|
console.log(argument_1, argument_1, arguments.foo);
|
||||||
|
})("bar", 42);
|
||||||
|
(function(a, b) {
|
||||||
|
console.log(b, b, arguments.foo);
|
||||||
|
})("bar", 42);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"42 42 undefined",
|
||||||
|
"42 42 undefined",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
modified: {
|
modified: {
|
||||||
options = {
|
options = {
|
||||||
arguments: true,
|
arguments: true,
|
||||||
@@ -101,8 +168,10 @@ modified: {
|
|||||||
(function(a, b) {
|
(function(a, b) {
|
||||||
var c = arguments[0];
|
var c = arguments[0];
|
||||||
var d = arguments[1];
|
var d = arguments[1];
|
||||||
a = "foo";
|
var a = "foo";
|
||||||
b++;
|
b++;
|
||||||
|
arguments[0] = "moo";
|
||||||
|
arguments[1] *= 2;
|
||||||
console.log(a, b, c, d, arguments[0], arguments[1]);
|
console.log(a, b, c, d, arguments[0], arguments[1]);
|
||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
}
|
}
|
||||||
@@ -110,10 +179,61 @@ modified: {
|
|||||||
(function(a, b) {
|
(function(a, b) {
|
||||||
var c = a;
|
var c = a;
|
||||||
var d = b;
|
var d = b;
|
||||||
a = "foo";
|
var a = "foo";
|
||||||
b++;
|
b++;
|
||||||
|
a = "moo";
|
||||||
|
b *= 2;
|
||||||
console.log(a, b, c, d, a, b);
|
console.log(a, b, c, d, a, b);
|
||||||
})("bar", 42);
|
})("bar", 42);
|
||||||
}
|
}
|
||||||
expect_stdout: "foo 43 bar 42 foo 43"
|
expect_stdout: "moo 86 bar 42 moo 86"
|
||||||
|
}
|
||||||
|
|
||||||
|
modified_strict: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function(a, b) {
|
||||||
|
var c = arguments[0];
|
||||||
|
var d = arguments[1];
|
||||||
|
var a = "foo";
|
||||||
|
b++;
|
||||||
|
arguments[0] = "moo";
|
||||||
|
arguments[1] *= 2;
|
||||||
|
console.log(a, b, c, d, arguments[0], arguments[1]);
|
||||||
|
})("bar", 42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
(function(a, b) {
|
||||||
|
var c = arguments[0];
|
||||||
|
var d = arguments[1];
|
||||||
|
var a = "foo";
|
||||||
|
b++;
|
||||||
|
arguments[0] = "moo";
|
||||||
|
arguments[1] *= 2;
|
||||||
|
console.log(a, b, c, d, arguments[0], arguments[1]);
|
||||||
|
})("bar", 42);
|
||||||
|
}
|
||||||
|
expect_stdout: "foo 43 bar 42 moo 84"
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_argname: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a, b, a) {
|
||||||
|
console.log(a, b, arguments[0], arguments[1], arguments[2]);
|
||||||
|
})("foo", 42, "bar");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a, b, a) {
|
||||||
|
console.log(a, b, arguments[0], b, a);
|
||||||
|
})("foo", 42, "bar");
|
||||||
|
}
|
||||||
|
expect_stdout: "bar 42 foo 42 bar"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1926,3 +1926,31 @@ issue_3146_4: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_3192: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
console.log(a = "foo", arguments[0]);
|
||||||
|
})("bar");
|
||||||
|
(function(a) {
|
||||||
|
"use strict";
|
||||||
|
console.log(a = "foo", arguments[0]);
|
||||||
|
})("bar");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
console.log(a = "foo", arguments[0]);
|
||||||
|
})("bar");
|
||||||
|
(function(a) {
|
||||||
|
"use strict";
|
||||||
|
console.log("foo", arguments[0]);
|
||||||
|
})("bar");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo foo",
|
||||||
|
"foo bar",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user