enhance arguments (#3193)

fixes #3192
This commit is contained in:
Alex Lam S.L
2018-06-21 14:10:37 +08:00
committed by alexlamsl
parent 915c7e234d
commit 766a4147d4
4 changed files with 207 additions and 44 deletions

View File

@@ -518,14 +518,15 @@ merge(Compressor.prototype, {
var sym = node.left;
if (!(sym instanceof AST_SymbolRef)) return;
var d = sym.definition();
var safe = safe_to_assign(tw, d, sym.scope, node.right);
d.assignments++;
if (!safe) return;
var fixed = d.fixed;
if (!fixed && node.operator != "=") return;
if (!safe_to_assign(tw, d, sym.scope, node.right)) return;
var eq = node.operator == "=";
var value = eq ? node.right : node;
if (is_modified(compressor, tw, node, value, 0)) return;
d.references.push(sym);
d.assignments++;
if (!eq) d.chained = true;
d.fixed = eq ? function() {
return node.right;
@@ -657,7 +658,7 @@ merge(Compressor.prototype, {
// So existing transformation rules can work on them.
node.argnames.forEach(function(arg, i) {
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() {
return iife.args[i] || make_node(AST_Undefined, iife);
};
@@ -760,11 +761,12 @@ merge(Compressor.prototype, {
var exp = node.expression;
if (!(exp instanceof AST_SymbolRef)) return;
var d = exp.definition();
var safe = safe_to_assign(tw, d, exp.scope, true);
d.assignments++;
if (!safe) return;
var fixed = d.fixed;
if (!fixed) return;
if (!safe_to_assign(tw, d, exp.scope, true)) return;
d.references.push(exp);
d.assignments++;
d.chained = true;
d.fixed = function() {
return make_node(AST_Binary, node, {
@@ -3289,6 +3291,15 @@ merge(Compressor.prototype, {
// this scope (not in nested scopes).
var scope = this;
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 instanceof AST_Defun) {
var node_def = node.name.definition();
@@ -3376,8 +3387,7 @@ merge(Compressor.prototype, {
// any declarations with same name will overshadow
// name of this anonymous function and can therefore
// never be used anywhere
if (!(def.id in in_use_ids) || def.orig.length > 1)
node.name = null;
if (!(def.id in in_use_ids) || def.orig.length > 1) node.name = null;
}
if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
var trim = !compressor.option("keep_fargs");
@@ -3389,8 +3399,7 @@ merge(Compressor.prototype, {
a.pop();
compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", template(sym));
}
}
else {
} else {
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 (key !== prop) {
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);
if (ev !== self) {
ev = make_node_from_constant(ev, self).optimize(compressor);