Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
346fa12e0e | ||
|
|
cda27b0970 | ||
|
|
3c74047368 | ||
|
|
94525d859f | ||
|
|
1127a2caf3 | ||
|
|
246d9d4e83 | ||
|
|
4c0b0177b6 | ||
|
|
38bfb73f06 | ||
|
|
bbedbf4ea0 | ||
|
|
2cfb5aa7da | ||
|
|
6c45101870 | ||
|
|
2c2fd89e34 | ||
|
|
f46281e2b7 | ||
|
|
25a18883f5 | ||
|
|
5b4b07e9a7 | ||
|
|
a8aa28a7a6 | ||
|
|
fe5a68f9d5 | ||
|
|
71e61153b1 | ||
|
|
c8b6f4733d | ||
|
|
a48f87abf2 |
@@ -689,6 +689,11 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
||||
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
||||
|
||||
- `reduce_funcs` (default: `true`) -- Allows single-use functions
|
||||
to be inlined as function expressions when permissible.
|
||||
Enabled by default. Option depends on `reduce_vars` being enabled.
|
||||
For speed critical code this option should be disabled.
|
||||
|
||||
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
|
||||
used as constant values.
|
||||
|
||||
|
||||
378
lib/compress.js
378
lib/compress.js
@@ -75,6 +75,7 @@ function Compressor(options, false_by_default) {
|
||||
properties : !false_by_default,
|
||||
pure_getters : !false_by_default && "strict",
|
||||
pure_funcs : null,
|
||||
reduce_funcs : !false_by_default,
|
||||
reduce_vars : !false_by_default,
|
||||
sequences : !false_by_default,
|
||||
side_effects : !false_by_default,
|
||||
@@ -150,7 +151,9 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
var passes = +this.options.passes || 1;
|
||||
var last_count = 1 / 0;
|
||||
var mangle = { ie8: this.option("ie8") };
|
||||
for (var pass = 0; pass < passes; pass++) {
|
||||
node.figure_out_scope(mangle);
|
||||
if (pass > 0 || this.option("reduce_vars"))
|
||||
node.reset_opt_flags(this);
|
||||
node = node.transform(this);
|
||||
@@ -285,7 +288,7 @@ merge(Compressor.prototype, {
|
||||
self.transform(tt);
|
||||
});
|
||||
|
||||
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor) {
|
||||
AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) {
|
||||
var reduce_vars = compressor.option("reduce_vars");
|
||||
var unused = compressor.option("unused");
|
||||
// Stack of look-up tables to keep track of whether a `SymbolDef` has been
|
||||
@@ -311,16 +314,16 @@ merge(Compressor.prototype, {
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var d = node.definition();
|
||||
d.references.push(node);
|
||||
var value;
|
||||
if (d.fixed === undefined || !safe_to_read(d) || d.single_use == "m") {
|
||||
d.fixed = false;
|
||||
} else if (d.fixed) {
|
||||
var value = node.fixed_value();
|
||||
if (unused) {
|
||||
d.single_use = value
|
||||
&& d.references.length == 1
|
||||
&& loop_ids[d.id] === in_loop
|
||||
&& d.scope === node.scope
|
||||
&& value.is_constant_expression();
|
||||
value = node.fixed_value();
|
||||
if (value && ref_once(d)) {
|
||||
d.single_use = value instanceof AST_Lambda
|
||||
|| d.scope === node.scope && value.is_constant_expression();
|
||||
} else {
|
||||
d.single_use = false;
|
||||
}
|
||||
if (is_modified(node, value, 0, is_immutable(value))) {
|
||||
if (d.single_use) {
|
||||
@@ -328,10 +331,9 @@ merge(Compressor.prototype, {
|
||||
} else {
|
||||
d.fixed = false;
|
||||
}
|
||||
} else {
|
||||
mark_escaped(d, node, value, 0);
|
||||
}
|
||||
}
|
||||
mark_escaped(d, node, value, 0);
|
||||
}
|
||||
if (node instanceof AST_SymbolCatch) {
|
||||
node.definition().fixed = false;
|
||||
@@ -376,7 +378,9 @@ merge(Compressor.prototype, {
|
||||
d.fixed = false;
|
||||
} else {
|
||||
d.fixed = node;
|
||||
loop_ids[d.id] = in_loop;
|
||||
mark(d, true);
|
||||
d.single_use = ref_once(d);
|
||||
}
|
||||
var save_ids = safe_ids;
|
||||
safe_ids = Object.create(null);
|
||||
@@ -527,6 +531,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return def.fixed instanceof AST_Defun;
|
||||
}
|
||||
|
||||
function safe_to_assign(def, value) {
|
||||
@@ -551,7 +556,7 @@ merge(Compressor.prototype, {
|
||||
function reset_def(def) {
|
||||
def.direct_access = false;
|
||||
def.escaped = false;
|
||||
if (def.scope.uses_eval) {
|
||||
if (def.scope.uses_eval || def.scope.uses_with) {
|
||||
def.fixed = false;
|
||||
} else if (!compressor.exposed(def)) {
|
||||
def.fixed = undefined;
|
||||
@@ -563,8 +568,19 @@ merge(Compressor.prototype, {
|
||||
def.single_use = undefined;
|
||||
}
|
||||
|
||||
function ref_once(def) {
|
||||
return unused
|
||||
&& !def.scope.uses_eval
|
||||
&& !def.scope.uses_with
|
||||
&& def.references.length == 1
|
||||
&& loop_ids[def.id] === in_loop;
|
||||
}
|
||||
|
||||
function is_immutable(value) {
|
||||
return value && (value.is_constant() || value instanceof AST_Lambda);
|
||||
if (!value) return false;
|
||||
return value.is_constant()
|
||||
|| value instanceof AST_Lambda
|
||||
|| value instanceof AST_This;
|
||||
}
|
||||
|
||||
function read_property(obj, key) {
|
||||
@@ -592,10 +608,13 @@ merge(Compressor.prototype, {
|
||||
|| !immutable
|
||||
&& parent instanceof AST_Call
|
||||
&& parent.expression === node
|
||||
&& (!(value instanceof AST_Function) || value.contains_this())) {
|
||||
&& (!(value instanceof AST_Function) || value.contains_this(parent))) {
|
||||
return true;
|
||||
} else if (parent instanceof AST_Array || parent instanceof AST_Object) {
|
||||
} else if (parent instanceof AST_Array) {
|
||||
return is_modified(parent, parent, level + 1);
|
||||
} else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
|
||||
var obj = tw.parent(level + 1);
|
||||
return is_modified(obj, obj, level + 2);
|
||||
} else if (parent instanceof AST_PropAccess && parent.expression === node) {
|
||||
return !immutable && is_modified(parent, read_property(value, parent.property), level + 1);
|
||||
}
|
||||
@@ -603,15 +622,19 @@ merge(Compressor.prototype, {
|
||||
|
||||
function mark_escaped(d, node, value, level) {
|
||||
var parent = tw.parent(level);
|
||||
if (value instanceof AST_Constant || value instanceof AST_Function) return;
|
||||
if (value instanceof AST_Constant) return;
|
||||
if (level > 0 && value instanceof AST_Function) return;
|
||||
if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
|
||||
|| parent instanceof AST_Call && node !== parent.expression
|
||||
|| parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
|
||||
|| parent instanceof AST_VarDef && node === parent.value) {
|
||||
d.escaped = true;
|
||||
return;
|
||||
} else if (parent instanceof AST_Array || parent instanceof AST_Object) {
|
||||
} else if (parent instanceof AST_Array) {
|
||||
mark_escaped(d, parent, parent, level + 1);
|
||||
} else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
|
||||
var obj = tw.parent(level + 1);
|
||||
mark_escaped(d, obj, obj, level + 2);
|
||||
} else if (parent instanceof AST_PropAccess && node === parent.expression) {
|
||||
value = read_property(value, parent.property);
|
||||
mark_escaped(d, parent, value, level + 1);
|
||||
@@ -772,6 +795,14 @@ merge(Compressor.prototype, {
|
||||
|| compressor.option("unsafe") && global_names(this.name);
|
||||
});
|
||||
|
||||
function drop_decl(def) {
|
||||
def._eliminiated = (def._eliminiated || 0) + 1;
|
||||
if (def.orig.length == def._eliminiated) {
|
||||
def.scope.functions.del(def.name);
|
||||
def.scope.variables.del(def.name);
|
||||
}
|
||||
}
|
||||
|
||||
function tighten_body(statements, compressor) {
|
||||
var CHANGED, max_iter = 10;
|
||||
do {
|
||||
@@ -805,6 +836,7 @@ merge(Compressor.prototype, {
|
||||
function collapse(statements, compressor) {
|
||||
var scope = compressor.find_parent(AST_Scope);
|
||||
if (scope.uses_eval || scope.uses_with) return statements;
|
||||
var args;
|
||||
var candidates = [];
|
||||
var stat_index = statements.length;
|
||||
while (--stat_index >= 0) {
|
||||
@@ -825,7 +857,7 @@ merge(Compressor.prototype, {
|
||||
var one_off = lhs instanceof AST_Symbol && lhs.definition().references.length == 1;
|
||||
var side_effects = value_has_side_effects(candidate);
|
||||
var hit = candidate.name instanceof AST_SymbolFunarg;
|
||||
var abort = false, replaced = false;
|
||||
var abort = false, replaced = false, can_replace = !args || !hit;
|
||||
var tt = new TreeTransformer(function(node, descend) {
|
||||
if (abort) return node;
|
||||
// Skip nodes before `candidate` as quickly as possible
|
||||
@@ -850,7 +882,8 @@ merge(Compressor.prototype, {
|
||||
return node;
|
||||
}
|
||||
// Replace variable with assignment when found
|
||||
if (!(node instanceof AST_SymbolDeclaration)
|
||||
if (can_replace
|
||||
&& !(node instanceof AST_SymbolDeclaration)
|
||||
&& !is_lhs(node, parent)
|
||||
&& lhs.equivalent_to(node)) {
|
||||
CHANGED = replaced = abort = true;
|
||||
@@ -901,6 +934,12 @@ merge(Compressor.prototype, {
|
||||
// Skip (non-executed) functions and (leading) default case in switch statements
|
||||
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
||||
});
|
||||
if (!can_replace) {
|
||||
for (var j = compressor.self().argnames.lastIndexOf(candidate.name) + 1; j < args.length; j++) {
|
||||
args[j].transform(tt);
|
||||
}
|
||||
can_replace = true;
|
||||
}
|
||||
for (var i = stat_index; !abort && i < statements.length; i++) {
|
||||
statements[i].transform(tt);
|
||||
}
|
||||
@@ -918,12 +957,18 @@ merge(Compressor.prototype, {
|
||||
&& iife.expression === fn) {
|
||||
var fn_strict = compressor.has_directive("use strict");
|
||||
if (fn_strict && fn.body.indexOf(fn_strict) < 0) fn_strict = false;
|
||||
var len = fn.argnames.length;
|
||||
args = iife.args.slice(len);
|
||||
var names = Object.create(null);
|
||||
for (var i = fn.argnames.length; --i >= 0;) {
|
||||
for (var i = len; --i >= 0;) {
|
||||
var sym = fn.argnames[i];
|
||||
var arg = iife.args[i];
|
||||
args.unshift(make_node(AST_VarDef, sym, {
|
||||
name: sym,
|
||||
value: arg
|
||||
}));
|
||||
if (sym.name in names) continue;
|
||||
names[sym.name] = true;
|
||||
var arg = iife.args[i];
|
||||
if (!arg) arg = make_node(AST_Undefined, sym).transform(compressor);
|
||||
else {
|
||||
var tw = new TreeWalker(function(node) {
|
||||
@@ -970,7 +1015,8 @@ merge(Compressor.prototype, {
|
||||
function get_lhs(expr) {
|
||||
if (expr instanceof AST_VarDef) {
|
||||
var def = expr.name.definition();
|
||||
if (def.orig.length > 1 && !(expr.name instanceof AST_SymbolFunarg)
|
||||
if (def.orig.length - (def._eliminiated || 0) > 1
|
||||
&& !(expr.name instanceof AST_SymbolFunarg)
|
||||
|| def.references.length == 1 && !compressor.exposed(def)) {
|
||||
return make_node(AST_SymbolRef, expr.name, expr.name);
|
||||
}
|
||||
@@ -979,6 +1025,10 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
function get_rvalue(expr) {
|
||||
return expr[expr instanceof AST_Assign ? "right" : "value"];
|
||||
}
|
||||
|
||||
function get_lvalues(expr) {
|
||||
var lvalues = Object.create(null);
|
||||
if (expr instanceof AST_Unary) return lvalues;
|
||||
@@ -989,7 +1039,7 @@ merge(Compressor.prototype, {
|
||||
lvalues[sym.name] = lvalues[sym.name] || is_lhs(node, tw.parent());
|
||||
}
|
||||
});
|
||||
expr[expr instanceof AST_Assign ? "right" : "value"].walk(tw);
|
||||
get_rvalue(expr).walk(tw);
|
||||
return lvalues;
|
||||
}
|
||||
|
||||
@@ -1010,10 +1060,12 @@ merge(Compressor.prototype, {
|
||||
var found = false;
|
||||
return statements[stat_index].transform(new TreeTransformer(function(node, descend, in_list) {
|
||||
if (found) return node;
|
||||
if (node === expr) {
|
||||
if (node === expr || node.body === expr) {
|
||||
found = true;
|
||||
if (node instanceof AST_VarDef) {
|
||||
remove(node.name.definition().orig, node.name);
|
||||
drop_decl(node.name.definition());
|
||||
node.value = null;
|
||||
return node;
|
||||
}
|
||||
return in_list ? MAP.skip : null;
|
||||
}
|
||||
@@ -1022,16 +1074,12 @@ merge(Compressor.prototype, {
|
||||
case 0: return null;
|
||||
case 1: return node.expressions[0];
|
||||
}
|
||||
if (node instanceof AST_Definitions && node.definitions.length == 0
|
||||
|| node instanceof AST_SimpleStatement && !node.body) {
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
function value_has_side_effects(expr) {
|
||||
if (expr instanceof AST_Unary) return false;
|
||||
return expr[expr instanceof AST_Assign ? "right" : "value"].has_side_effects(compressor);
|
||||
return get_rvalue(expr).has_side_effects(compressor);
|
||||
}
|
||||
|
||||
function references_in_scope(def) {
|
||||
@@ -2148,18 +2196,25 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
def(AST_Node, return_false);
|
||||
def(AST_Constant, return_true);
|
||||
def(AST_Function, function(){
|
||||
def(AST_Lambda, function(scope){
|
||||
var self = this;
|
||||
var result = true;
|
||||
self.walk(new TreeWalker(function(node) {
|
||||
if (!result) return true;
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var def = node.definition();
|
||||
if (self.enclosed.indexOf(def) >= 0
|
||||
&& self.variables.get(def.name) !== def) {
|
||||
if (member(def, self.enclosed)
|
||||
&& !self.variables.has(def.name)) {
|
||||
if (scope) {
|
||||
var scope_def = scope.find_variable(node);
|
||||
if (def.undeclared ? !scope_def : scope_def === def) {
|
||||
result = "f";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
return result;
|
||||
@@ -2269,58 +2324,63 @@ merge(Compressor.prototype, {
|
||||
// this scope (not in nested scopes).
|
||||
var scope = this;
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node !== self) {
|
||||
if (node instanceof AST_Defun) {
|
||||
if (!drop_funcs && scope === self) {
|
||||
var node_def = node.name.definition();
|
||||
if (node === self) return;
|
||||
if (node instanceof AST_Defun) {
|
||||
if (!drop_funcs && scope === self) {
|
||||
var node_def = node.name.definition();
|
||||
if (!(node_def.id in in_use_ids)) {
|
||||
in_use_ids[node_def.id] = true;
|
||||
in_use.push(node_def);
|
||||
}
|
||||
}
|
||||
initializations.add(node.name.name, node);
|
||||
return true; // don't go in nested scopes
|
||||
}
|
||||
if (node instanceof AST_SymbolFunarg && scope === self) {
|
||||
var_defs_by_id.add(node.definition().id, node);
|
||||
}
|
||||
if (node instanceof AST_Definitions && scope === self) {
|
||||
node.definitions.forEach(function(def){
|
||||
var node_def = def.name.definition();
|
||||
if (def.name instanceof AST_SymbolVar) {
|
||||
var_defs_by_id.add(node_def.id, def);
|
||||
}
|
||||
if (!drop_vars) {
|
||||
if (!(node_def.id in in_use_ids)) {
|
||||
in_use_ids[node_def.id] = true;
|
||||
in_use.push(node_def);
|
||||
}
|
||||
}
|
||||
initializations.add(node.name.name, node);
|
||||
return true; // don't go in nested scopes
|
||||
}
|
||||
if (node instanceof AST_Definitions && scope === self) {
|
||||
node.definitions.forEach(function(def){
|
||||
var node_def = def.name.definition();
|
||||
if (def.name instanceof AST_SymbolVar) {
|
||||
var_defs_by_id.add(node_def.id, def);
|
||||
if (def.value) {
|
||||
initializations.add(def.name.name, def.value);
|
||||
if (def.value.has_side_effects(compressor)) {
|
||||
def.value.walk(tw);
|
||||
}
|
||||
if (!drop_vars) {
|
||||
if (!(node_def.id in in_use_ids)) {
|
||||
in_use_ids[node_def.id] = true;
|
||||
in_use.push(node_def);
|
||||
}
|
||||
}
|
||||
if (def.value) {
|
||||
initializations.add(def.name.name, def.value);
|
||||
if (def.value.has_side_effects(compressor)) {
|
||||
def.value.walk(tw);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (assign_as_unused(node) instanceof AST_SymbolRef && scope === self) {
|
||||
if (node instanceof AST_Assign) node.right.walk(tw);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var node_def = node.definition();
|
||||
if (!(node_def.id in in_use_ids)) {
|
||||
in_use_ids[node_def.id] = true;
|
||||
in_use.push(node_def);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
var save_scope = scope;
|
||||
scope = node;
|
||||
descend();
|
||||
scope = save_scope;
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
var sym;
|
||||
if (scope === self
|
||||
&& (sym = assign_as_unused(node)) instanceof AST_SymbolRef
|
||||
&& self.variables.get(sym.name) === sym.definition()) {
|
||||
if (node instanceof AST_Assign) node.right.walk(tw);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var node_def = node.definition();
|
||||
if (!(node_def.id in in_use_ids)) {
|
||||
in_use_ids[node_def.id] = true;
|
||||
in_use.push(node_def);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Scope) {
|
||||
var save_scope = scope;
|
||||
scope = node;
|
||||
descend();
|
||||
scope = save_scope;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
self.walk(tw);
|
||||
@@ -2375,8 +2435,10 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
if (drop_funcs && node instanceof AST_Defun && node !== self) {
|
||||
if (!(node.name.definition().id in in_use_ids)) {
|
||||
var def = node.name.definition();
|
||||
if (!(def.id in in_use_ids)) {
|
||||
compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name));
|
||||
drop_decl(def);
|
||||
return make_node(AST_EmptyStatement, node);
|
||||
}
|
||||
return node;
|
||||
@@ -2398,7 +2460,7 @@ merge(Compressor.prototype, {
|
||||
if (var_defs.length > 1 && !def.value) {
|
||||
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
||||
remove(var_defs, def);
|
||||
remove(sym.orig, def.name);
|
||||
drop_decl(sym);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2431,7 +2493,7 @@ merge(Compressor.prototype, {
|
||||
} else {
|
||||
compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", template(def.name));
|
||||
}
|
||||
remove(sym.orig, def.name);
|
||||
drop_decl(sym);
|
||||
}
|
||||
});
|
||||
if (head.length == 0 && tail.length == 1 && tail[0].name instanceof AST_SymbolVar) {
|
||||
@@ -2440,7 +2502,7 @@ merge(Compressor.prototype, {
|
||||
var def = tail.pop();
|
||||
compressor.warn("Converting duplicated definition of variable {name} to assignment [{file}:{line},{col}]", template(def.name));
|
||||
remove(var_defs, def);
|
||||
remove(def.name.definition().orig, def.name);
|
||||
drop_decl(def.name.definition());
|
||||
side_effects.unshift(make_node(AST_Assign, def, {
|
||||
operator: "=",
|
||||
left: make_node(AST_SymbolRef, def.name, def.name),
|
||||
@@ -2469,10 +2531,9 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
if (drop_vars) {
|
||||
var def = assign_as_unused(node);
|
||||
if (def instanceof AST_SymbolRef
|
||||
&& !((def = def.definition()).id in in_use_ids)
|
||||
&& self.variables.get(def.name) === def) {
|
||||
var sym = assign_as_unused(node);
|
||||
if (sym instanceof AST_SymbolRef
|
||||
&& !(sym.definition().id in in_use_ids)) {
|
||||
if (node instanceof AST_Assign) {
|
||||
return maintain_this_binding(parent, node, node.right.transform(tt));
|
||||
}
|
||||
@@ -3242,7 +3303,7 @@ merge(Compressor.prototype, {
|
||||
}));
|
||||
if (reduce_vars) name.definition().fixed = false;
|
||||
}
|
||||
remove(def.name.definition().orig, def.name);
|
||||
drop_decl(def.name.definition());
|
||||
return a;
|
||||
}, []);
|
||||
if (assignments.length == 0) return null;
|
||||
@@ -3484,6 +3545,7 @@ merge(Compressor.prototype, {
|
||||
&& !exp.uses_arguments
|
||||
&& !exp.uses_eval
|
||||
&& exp.body.length == 1
|
||||
&& !exp.contains_this()
|
||||
&& all(exp.argnames, function(arg) {
|
||||
return arg.__unused;
|
||||
})
|
||||
@@ -3497,23 +3559,6 @@ merge(Compressor.prototype, {
|
||||
expression: stat.body
|
||||
});
|
||||
}
|
||||
if (value) {
|
||||
var tw = new TreeWalker(function(node) {
|
||||
if (!value) return true;
|
||||
if (node instanceof AST_SymbolRef) {
|
||||
var ref = node.scope.find_variable(node);
|
||||
if (ref && ref.scope.parent_scope === fn.parent_scope) {
|
||||
value = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_This && !tw.find_parent(AST_Scope)) {
|
||||
value = null;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
value.walk(tw);
|
||||
}
|
||||
if (value) {
|
||||
var args = self.args.concat(value);
|
||||
return make_sequence(self, args).optimize(compressor);
|
||||
@@ -4176,6 +4221,17 @@ merge(Compressor.prototype, {
|
||||
return self;
|
||||
});
|
||||
|
||||
function recursive_ref(compressor, def) {
|
||||
var node;
|
||||
for (var i = 0; node = compressor.parent(i); i++) {
|
||||
if (node instanceof AST_Lambda) {
|
||||
var name = node.name;
|
||||
if (name && name.definition() === def) break;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
OPT(AST_SymbolRef, function(self, compressor){
|
||||
var def = self.resolve_defines(compressor);
|
||||
if (def) {
|
||||
@@ -4201,49 +4257,68 @@ merge(Compressor.prototype, {
|
||||
if (fixed instanceof AST_Defun) {
|
||||
d.fixed = fixed = make_node(AST_Function, fixed, fixed);
|
||||
}
|
||||
if (compressor.option("unused")
|
||||
&& fixed
|
||||
&& d.references.length == 1
|
||||
&& (d.single_use || fixed instanceof AST_Function
|
||||
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
|
||||
&& !d.scope.uses_eval
|
||||
&& compressor.find_parent(AST_Scope) === fixed.parent_scope)) {
|
||||
if (d.single_use && fixed instanceof AST_Function) {
|
||||
if (!compressor.option("reduce_funcs") && d.scope !== self.scope) {
|
||||
d.single_use = false;
|
||||
} else if (d.escaped && d.scope !== self.scope || recursive_ref(compressor, d)) {
|
||||
d.single_use = false;
|
||||
} else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) {
|
||||
d.single_use = fixed.is_constant_expression(self.scope);
|
||||
if (d.single_use == "f") {
|
||||
var scope = self.scope;
|
||||
do {
|
||||
if (scope.name) scope.name.definition().single_use = false;
|
||||
} while (scope = scope.parent_scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (d.single_use && fixed) {
|
||||
var value = fixed.optimize(compressor);
|
||||
return value === fixed ? fixed.clone(true) : value;
|
||||
}
|
||||
if (compressor.option("evaluate") && fixed) {
|
||||
if (d.should_replace === undefined) {
|
||||
var init = fixed.evaluate(compressor);
|
||||
if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
|
||||
init = make_node_from_constant(init, fixed);
|
||||
var value_length = init.optimize(compressor).print_to_string().length;
|
||||
var fn;
|
||||
if (has_symbol_ref(fixed)) {
|
||||
fn = function() {
|
||||
var result = init.optimize(compressor);
|
||||
return result === init ? result.clone(true) : result;
|
||||
};
|
||||
} else {
|
||||
value_length = Math.min(value_length, fixed.print_to_string().length);
|
||||
fn = function() {
|
||||
var result = best_of_expression(init.optimize(compressor), fixed);
|
||||
return result === init || result === fixed ? result.clone(true) : result;
|
||||
};
|
||||
}
|
||||
var name_length = d.name.length;
|
||||
var overhead = 0;
|
||||
if (compressor.option("unused") && !compressor.exposed(d)) {
|
||||
overhead = (name_length + 2 + value_length) / d.references.length;
|
||||
}
|
||||
d.should_replace = value_length <= name_length + overhead ? fn : false;
|
||||
} else {
|
||||
d.should_replace = false;
|
||||
if (fixed && d.should_replace === undefined) {
|
||||
var init;
|
||||
if (fixed instanceof AST_This) {
|
||||
if (!(d.orig[0] instanceof AST_SymbolFunarg)
|
||||
&& all(d.references, function(ref) {
|
||||
return d.scope === ref.scope;
|
||||
})) {
|
||||
init = fixed;
|
||||
}
|
||||
} else {
|
||||
var ev = fixed.evaluate(compressor);
|
||||
if (ev !== fixed && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))) {
|
||||
init = make_node_from_constant(ev, fixed);
|
||||
}
|
||||
}
|
||||
if (d.should_replace) {
|
||||
return d.should_replace();
|
||||
if (init) {
|
||||
var value_length = init.optimize(compressor).print_to_string().length;
|
||||
var fn;
|
||||
if (has_symbol_ref(fixed)) {
|
||||
fn = function() {
|
||||
var result = init.optimize(compressor);
|
||||
return result === init ? result.clone(true) : result;
|
||||
};
|
||||
} else {
|
||||
value_length = Math.min(value_length, fixed.print_to_string().length);
|
||||
fn = function() {
|
||||
var result = best_of_expression(init.optimize(compressor), fixed);
|
||||
return result === init || result === fixed ? result.clone(true) : result;
|
||||
};
|
||||
}
|
||||
var name_length = d.name.length;
|
||||
var overhead = 0;
|
||||
if (compressor.option("unused") && !compressor.exposed(d)) {
|
||||
overhead = (name_length + 2 + value_length) / d.references.length;
|
||||
}
|
||||
d.should_replace = value_length <= name_length + overhead ? fn : false;
|
||||
} else {
|
||||
d.should_replace = false;
|
||||
}
|
||||
}
|
||||
if (d.should_replace) {
|
||||
return d.should_replace();
|
||||
}
|
||||
}
|
||||
return self;
|
||||
|
||||
@@ -4561,11 +4636,11 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
if (is_lhs(self, compressor.parent())) return self;
|
||||
if (compressor.option("properties") && key !== prop) {
|
||||
var node = self.flatten_object(property);
|
||||
if (node) {
|
||||
expr = self.expression = node.expression;
|
||||
prop = self.property = node.property;
|
||||
if (key !== prop) {
|
||||
var sub = self.flatten_object(property, compressor);
|
||||
if (sub) {
|
||||
expr = self.expression = sub.expression;
|
||||
prop = self.property = sub.property;
|
||||
}
|
||||
}
|
||||
if (compressor.option("properties") && compressor.option("side_effects")
|
||||
@@ -4611,7 +4686,8 @@ merge(Compressor.prototype, {
|
||||
return self;
|
||||
});
|
||||
|
||||
AST_Lambda.DEFMETHOD("contains_this", function() {
|
||||
AST_Lambda.DEFMETHOD("contains_this", function(grandparent) {
|
||||
if (grandparent instanceof AST_New) return false;
|
||||
var result;
|
||||
var self = this;
|
||||
self.walk(new TreeWalker(function(node) {
|
||||
@@ -4622,7 +4698,8 @@ merge(Compressor.prototype, {
|
||||
return result;
|
||||
});
|
||||
|
||||
AST_PropAccess.DEFMETHOD("flatten_object", function(key) {
|
||||
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
||||
if (!compressor.option("properties")) return;
|
||||
var expr = this.expression;
|
||||
if (expr instanceof AST_Object) {
|
||||
var props = expr.properties;
|
||||
@@ -4633,7 +4710,8 @@ merge(Compressor.prototype, {
|
||||
return prop instanceof AST_ObjectKeyVal;
|
||||
})) break;
|
||||
var value = prop.value;
|
||||
if (value instanceof AST_Function && value.contains_this()) break;
|
||||
if (value instanceof AST_Function
|
||||
&& value.contains_this(compressor.parent())) break;
|
||||
return make_node(AST_Sub, this, {
|
||||
expression: make_node(AST_Array, expr, {
|
||||
elements: props.map(function(prop) {
|
||||
@@ -4677,10 +4755,8 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
if (is_lhs(self, compressor.parent())) return self;
|
||||
if (compressor.option("properties")) {
|
||||
var node = self.flatten_object(self.property);
|
||||
if (node) return node.optimize(compressor);
|
||||
}
|
||||
var sub = self.flatten_object(self.property, compressor);
|
||||
if (sub) return sub.optimize(compressor);
|
||||
var ev = self.evaluate(compressor);
|
||||
if (ev !== self) {
|
||||
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||
|
||||
@@ -137,11 +137,9 @@ function minify(files, options) {
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
if (timings) timings.scope1 = Date.now();
|
||||
if (options.compress) toplevel.figure_out_scope(options.mangle);
|
||||
if (timings) timings.compress = Date.now();
|
||||
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
if (timings) timings.scope2 = Date.now();
|
||||
if (timings) timings.scope = Date.now();
|
||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||
if (timings) timings.mangle = Date.now();
|
||||
if (options.mangle) {
|
||||
@@ -199,9 +197,9 @@ function minify(files, options) {
|
||||
if (timings) {
|
||||
timings.end = Date.now();
|
||||
result.timings = {
|
||||
parse: 1e-3 * (timings.scope1 - timings.parse),
|
||||
scope: 1e-3 * (timings.compress - timings.scope1 + timings.mangle - timings.scope2),
|
||||
compress: 1e-3 * (timings.scope2 - timings.compress),
|
||||
parse: 1e-3 * (timings.compress - timings.parse),
|
||||
compress: 1e-3 * (timings.scope - timings.compress),
|
||||
scope: 1e-3 * (timings.mangle - timings.scope),
|
||||
mangle: 1e-3 * (timings.properties - timings.mangle),
|
||||
properties: 1e-3 * (timings.output - timings.properties),
|
||||
output: 1e-3 * (timings.end - timings.output),
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": "http://lisperator.net/uglifyjs",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.1.6",
|
||||
"version": "3.1.9",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -129,6 +129,7 @@ constant_join_3: {
|
||||
for_loop: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
@@ -185,6 +186,7 @@ for_loop: {
|
||||
index: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -203,6 +205,7 @@ index: {
|
||||
length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -221,6 +224,7 @@ length: {
|
||||
index_length: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
|
||||
@@ -2,7 +2,8 @@ collapse_vars_side_effects_1: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -150,7 +151,8 @@ collapse_vars_issue_721: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
define(["require", "exports", 'handlebars'], function (require, exports, hb) {
|
||||
@@ -216,7 +218,8 @@ collapse_vars_properties: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1(obj) {
|
||||
@@ -243,7 +246,8 @@ collapse_vars_if: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -293,7 +297,8 @@ collapse_vars_while: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:false, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1(y) {
|
||||
@@ -712,7 +717,8 @@ collapse_vars_misc1: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f0(o, a, h) {
|
||||
@@ -789,7 +795,8 @@ collapse_vars_repeated: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -831,7 +838,8 @@ collapse_vars_closures: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function constant_vars_can_be_replaced_in_any_scope() {
|
||||
@@ -921,7 +929,8 @@ collapse_vars_try: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1() {
|
||||
@@ -1118,7 +1127,8 @@ collapse_vars_constants: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true, reduce_vars:true
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
function f1(x) {
|
||||
@@ -1156,7 +1166,7 @@ collapse_vars_arguments: {
|
||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||
toplevel:true, reduce_vars:true
|
||||
toplevel:true, reduce_funcs: true, reduce_vars:true
|
||||
}
|
||||
input: {
|
||||
var outer = function() {
|
||||
@@ -1280,6 +1290,7 @@ collapse_vars_regexp: {
|
||||
hoist_funs: true,
|
||||
keep_fargs: true,
|
||||
loops: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -1355,6 +1366,7 @@ issue_1562: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -1388,6 +1400,7 @@ issue_1605_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: false,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
@@ -1410,6 +1423,7 @@ issue_1605_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: "vars",
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
@@ -1537,6 +1551,7 @@ issue_1631_3: {
|
||||
var_side_effects_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
@@ -1559,6 +1574,7 @@ var_side_effects_1: {
|
||||
var_side_effects_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
@@ -1584,6 +1600,7 @@ var_side_effects_3: {
|
||||
collapse_vars: true,
|
||||
pure_getters: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
@@ -1606,6 +1623,7 @@ var_side_effects_3: {
|
||||
reduce_vars_assign: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
@@ -1628,6 +1646,7 @@ reduce_vars_assign: {
|
||||
iife_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -1648,6 +1667,7 @@ iife_1: {
|
||||
iife_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_funcs: false,
|
||||
reduce_vars: false,
|
||||
toplevel: true,
|
||||
unused: false,
|
||||
@@ -1659,6 +1679,7 @@ iife_2: {
|
||||
}(foo);
|
||||
}
|
||||
expect: {
|
||||
var foo;
|
||||
!function(x) {
|
||||
console.log(x);
|
||||
}(bar());
|
||||
@@ -1945,6 +1966,7 @@ ref_scope: {
|
||||
chained_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 2;
|
||||
@@ -1961,6 +1983,7 @@ chained_1: {
|
||||
chained_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
@@ -2061,6 +2084,7 @@ inner_lvalues: {
|
||||
double_def: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = x, a = a && y;
|
||||
@@ -2075,6 +2099,7 @@ double_def: {
|
||||
toplevel_single_reference: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
@@ -2084,9 +2109,10 @@ toplevel_single_reference: {
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
for (var b in x)
|
||||
for (var b in x) {
|
||||
var a;
|
||||
b(a = b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2094,6 +2120,7 @@ unused_orig: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2132,6 +2159,7 @@ issue_315: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
@@ -2358,6 +2386,7 @@ duplicate_argname: {
|
||||
issue_2298: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2723,6 +2752,7 @@ issue_2364_5: {
|
||||
evaluate: true,
|
||||
pure_getters: true,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -2889,6 +2919,7 @@ pure_getters_chain: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function o(t, r) {
|
||||
@@ -2909,6 +2940,7 @@ pure_getters_chain: {
|
||||
conditional_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
@@ -2933,6 +2965,7 @@ conditional_1: {
|
||||
conditional_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
@@ -2949,3 +2982,119 @@ conditional_2: {
|
||||
}
|
||||
expect_stdout: "5 5"
|
||||
}
|
||||
|
||||
issue_2425_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 8;
|
||||
(function(b) {
|
||||
b.toString();
|
||||
})(--a, a |= 10);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 8;
|
||||
(function(b) {
|
||||
b.toString();
|
||||
})(--a, a |= 10);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "15"
|
||||
}
|
||||
|
||||
issue_2425_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 8;
|
||||
(function(b, c) {
|
||||
b.toString();
|
||||
})(--a, a |= 10);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 8;
|
||||
(function(b, c) {
|
||||
b.toString();
|
||||
})(--a, a |= 10);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "15"
|
||||
}
|
||||
|
||||
issue_2425_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 8;
|
||||
(function(b, b) {
|
||||
b.toString();
|
||||
})(--a, a |= 10);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = 8;
|
||||
(function(b, b) {
|
||||
(a |= 10).toString();
|
||||
})(--a);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "15"
|
||||
}
|
||||
|
||||
issue_2437: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
inline: true,
|
||||
join_vars: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
sequences: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
bar();
|
||||
}
|
||||
function bar() {
|
||||
if (xhrDesc) {
|
||||
var req = new XMLHttpRequest();
|
||||
var result = !!req.onreadystatechange;
|
||||
Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
var req = new XMLHttpRequest();
|
||||
var detectFunc = function () { };
|
||||
req.onreadystatechange = detectFunc;
|
||||
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
||||
req.onreadystatechange = null;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
foo();
|
||||
}
|
||||
expect: {
|
||||
!function() {
|
||||
if (xhrDesc)
|
||||
return result = !!(req = new XMLHttpRequest()).onreadystatechange,
|
||||
Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
|
||||
result;
|
||||
var req = new XMLHttpRequest(), detectFunc = function() {};
|
||||
req.onreadystatechange = detectFunc;
|
||||
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
|
||||
req.onreadystatechange = null;
|
||||
}();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ self_comparison_1: {
|
||||
self_comparison_2: {
|
||||
options = {
|
||||
comparisons: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
|
||||
@@ -292,6 +292,7 @@ global_timeout_and_interval_symbols: {
|
||||
issue_2233_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
@@ -323,6 +324,7 @@ issue_2233_2: {
|
||||
issue_2233_3: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
|
||||
@@ -673,6 +673,7 @@ issue_1539: {
|
||||
vardef_value: {
|
||||
options = {
|
||||
keep_fnames: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -734,6 +735,7 @@ assign_chain: {
|
||||
issue_1583: {
|
||||
options = {
|
||||
keep_fargs: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -1080,6 +1082,7 @@ var_catch_toplevel: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -1109,11 +1112,12 @@ var_catch_toplevel: {
|
||||
}
|
||||
}
|
||||
|
||||
issue_2105: {
|
||||
issue_2105_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -1139,17 +1143,51 @@ issue_2105: {
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var quux = function() {
|
||||
({
|
||||
prop: function() {
|
||||
console.log;
|
||||
console.log("PASS");
|
||||
};
|
||||
return {
|
||||
prop: function() {
|
||||
console.log;
|
||||
quux();
|
||||
}
|
||||
}).prop();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2105_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
properties: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
!function(factory) {
|
||||
factory();
|
||||
}( function() {
|
||||
return function(fn) {
|
||||
fn()().prop();
|
||||
}( function() {
|
||||
function bar() {
|
||||
var quux = function() {
|
||||
console.log("PASS");
|
||||
}, foo = function() {
|
||||
console.log;
|
||||
quux();
|
||||
};
|
||||
return { prop: foo };
|
||||
}
|
||||
};
|
||||
})().prop();
|
||||
return bar;
|
||||
} );
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -251,6 +251,7 @@ unsafe_constant: {
|
||||
unsafe_object: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -279,6 +280,7 @@ unsafe_object: {
|
||||
unsafe_object_nested: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -307,6 +309,7 @@ unsafe_object_nested: {
|
||||
unsafe_object_complex: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -335,6 +338,7 @@ unsafe_object_complex: {
|
||||
unsafe_object_repeated: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -363,6 +367,7 @@ unsafe_object_repeated: {
|
||||
unsafe_object_accessor: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
@@ -663,6 +668,7 @@ call_args: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
@@ -686,6 +692,7 @@ call_args_drop_param: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
keep_fargs: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -1016,6 +1023,7 @@ Infinity_NaN_undefined_LHS: {
|
||||
issue_1964_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe_regexp: false,
|
||||
unused: true,
|
||||
@@ -1045,6 +1053,7 @@ issue_1964_1: {
|
||||
issue_1964_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unsafe_regexp: true,
|
||||
unused: true,
|
||||
@@ -1201,6 +1210,7 @@ issue_2231_2: {
|
||||
self_comparison_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
@@ -1221,6 +1231,7 @@ self_comparison_2: {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
|
||||
@@ -19,6 +19,7 @@ iifes_returning_constants_keep_fargs_true: {
|
||||
booleans : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
reduce_funcs : true,
|
||||
reduce_vars : true,
|
||||
cascade : true,
|
||||
inline : true,
|
||||
@@ -55,6 +56,7 @@ iifes_returning_constants_keep_fargs_false: {
|
||||
booleans : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
reduce_funcs : true,
|
||||
reduce_vars : true,
|
||||
cascade : true,
|
||||
inline : true,
|
||||
@@ -101,6 +103,7 @@ issue_1841_1: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -127,6 +130,7 @@ issue_1841_2: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
pure_getters: false,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -154,6 +158,7 @@ function_returning_constant_literal: {
|
||||
inline: true,
|
||||
passes: 2,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -305,6 +310,7 @@ issue_2084: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -340,6 +346,7 @@ issue_2084: {
|
||||
issue_2097: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -508,3 +515,42 @@ issue_2114_2: {
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
issue_2428: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
inline: true,
|
||||
passes: 3,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function bar(k) {
|
||||
console.log(k);
|
||||
}
|
||||
function foo(x) {
|
||||
return bar(x);
|
||||
}
|
||||
function baz(a) {
|
||||
foo(a);
|
||||
}
|
||||
baz(42);
|
||||
baz("PASS");
|
||||
}
|
||||
expect: {
|
||||
function baz(a) {
|
||||
console.log(a);
|
||||
}
|
||||
baz(42);
|
||||
baz("PASS");
|
||||
}
|
||||
expect_stdout: [
|
||||
"42",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ issue_2377_1: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -35,6 +36,7 @@ issue_2377_2: {
|
||||
inline: true,
|
||||
hoist_props: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -66,6 +68,7 @@ issue_2377_3: {
|
||||
inline: true,
|
||||
hoist_props: true,
|
||||
passes: 3,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -92,6 +95,7 @@ issue_2377_3: {
|
||||
direct_access_1: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -120,6 +124,7 @@ direct_access_1: {
|
||||
direct_access_2: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -143,6 +148,7 @@ direct_access_2: {
|
||||
direct_access_3: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -163,6 +169,7 @@ direct_access_3: {
|
||||
single_use: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -187,6 +194,7 @@ single_use: {
|
||||
name_collision_1: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
@@ -224,6 +232,7 @@ name_collision_1: {
|
||||
name_collision_2: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
@@ -257,6 +266,7 @@ name_collision_2: {
|
||||
name_collision_3: {
|
||||
options = {
|
||||
hoist_props: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
}
|
||||
@@ -293,6 +303,7 @@ contains_this_1: {
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -318,6 +329,7 @@ contains_this_2: {
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -345,6 +357,7 @@ contains_this_3: {
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -369,3 +382,32 @@ contains_this_3: {
|
||||
}
|
||||
expect_stdout: "1 1 true"
|
||||
}
|
||||
|
||||
new_this: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
f: function(a) {
|
||||
this.b = a;
|
||||
}
|
||||
};
|
||||
console.log(new o.f(o.a).b, o.b);
|
||||
}
|
||||
expect: {
|
||||
console.log(new function(a) {
|
||||
this.b = a;
|
||||
}(1).b, 2);
|
||||
}
|
||||
expect_stdout: "1 2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
@@ -16,6 +17,7 @@ const_pragma: {
|
||||
not_const: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ chained_evaluation_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -28,6 +29,7 @@ chained_evaluation_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ f7: {
|
||||
negate_iife: true,
|
||||
passes: 3,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
side_effects_catch: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -34,6 +35,7 @@ side_effects_catch: {
|
||||
|
||||
side_effects_else: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -62,6 +64,7 @@ side_effects_else: {
|
||||
|
||||
side_effects_finally: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -98,6 +101,7 @@ side_effects_finally: {
|
||||
|
||||
side_effects_label: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -130,6 +134,7 @@ side_effects_label: {
|
||||
|
||||
side_effects_switch: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
|
||||
@@ -2,6 +2,7 @@ unary_prefix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
iife_for: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -26,6 +27,7 @@ iife_for: {
|
||||
iife_for_in: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -51,6 +53,7 @@ iife_for_in: {
|
||||
iife_do: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -80,6 +83,7 @@ iife_do: {
|
||||
iife_while: {
|
||||
options = {
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
|
||||
@@ -3,6 +3,7 @@ collapse_vars_constants: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -240,6 +241,7 @@ negate_iife_issue_1073: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
@@ -267,6 +269,7 @@ issue_1288_side_effects: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
negate_iife: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -299,6 +302,7 @@ inner_var_for_in_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
@@ -330,6 +334,7 @@ issue_1595_3: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ this_binding_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
};
|
||||
input: {
|
||||
var c = a; c();
|
||||
|
||||
@@ -833,6 +833,7 @@ lhs_prop_2: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
@@ -879,6 +880,7 @@ prop_side_effects_1: {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -915,6 +917,7 @@ prop_side_effects_2: {
|
||||
inline: true,
|
||||
passes: 2,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -1006,3 +1009,22 @@ array_hole: {
|
||||
}
|
||||
expect_stdout: "2 undefined 3"
|
||||
}
|
||||
|
||||
new_this: {
|
||||
options = {
|
||||
properties: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
new {
|
||||
f: function(a) {
|
||||
this.a = a;
|
||||
}
|
||||
}.f(42);
|
||||
}
|
||||
expect: {
|
||||
new function(a) {
|
||||
this.a = a;
|
||||
}(42);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
strict: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: false,
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -30,6 +31,7 @@ strict: {
|
||||
strict_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -58,6 +60,7 @@ strict_reduce_vars: {
|
||||
unsafe: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_funcs: false,
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -84,6 +87,7 @@ unsafe: {
|
||||
unsafe_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
@@ -185,6 +189,7 @@ issue_2110_1: {
|
||||
pure_getters: "strict",
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -215,6 +220,7 @@ issue_2110_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -247,6 +253,7 @@ set_immutable_1: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -270,6 +277,7 @@ set_immutable_2: {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -293,6 +301,7 @@ set_immutable_3: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
@@ -318,6 +327,7 @@ set_immutable_4: {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
@@ -343,6 +353,7 @@ set_mutable_1: {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
@@ -367,6 +378,7 @@ set_mutable_2: {
|
||||
cascade: true,
|
||||
conditionals: true,
|
||||
pure_getters: "strict",
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -187,6 +187,7 @@ dont_screw_try_catch_undefined: {
|
||||
reduce_vars: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
ie8: true,
|
||||
unused: true,
|
||||
|
||||
@@ -714,6 +714,7 @@ issue_1705_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
evaluate: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
|
||||
@@ -297,4 +297,36 @@ describe("minify", function() {
|
||||
assert.strictEqual(result.code, "alert({bar:42});");
|
||||
});
|
||||
});
|
||||
|
||||
describe("collapse_vars", function() {
|
||||
it("Should not produce invalid AST", function() {
|
||||
var code = [
|
||||
"function f(a) {",
|
||||
" a = x();",
|
||||
" return a;",
|
||||
"}",
|
||||
"f();",
|
||||
].join("\n");
|
||||
var ast = Uglify.minify(code, {
|
||||
compress: false,
|
||||
mangle: false,
|
||||
output: {
|
||||
ast: true
|
||||
},
|
||||
}).ast;
|
||||
assert.strictEqual(ast.TYPE, "Toplevel");
|
||||
assert.strictEqual(ast.body.length, 2);
|
||||
assert.strictEqual(ast.body[0].TYPE, "Defun");
|
||||
assert.strictEqual(ast.body[0].body.length, 2);
|
||||
assert.strictEqual(ast.body[0].body[0].TYPE, "SimpleStatement");
|
||||
var stat = ast.body[0].body[0];
|
||||
Uglify.minify(ast, {
|
||||
compress: {
|
||||
sequences: false
|
||||
}
|
||||
});
|
||||
assert.ok(stat.body);
|
||||
assert.strictEqual(stat.print_to_string(), "a=x()");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -162,6 +162,7 @@ var VALUES = [
|
||||
'"object"',
|
||||
'"number"',
|
||||
'"function"',
|
||||
'this',
|
||||
];
|
||||
|
||||
var BINARY_OPS_NO_COMMA = [
|
||||
@@ -349,10 +350,10 @@ function createParams() {
|
||||
return params.join(', ');
|
||||
}
|
||||
|
||||
function createArgs() {
|
||||
function createArgs(recurmax, stmtDepth, canThrow) {
|
||||
var args = [];
|
||||
for (var n = rng(4); --n >= 0;) {
|
||||
args.push(createValue());
|
||||
args.push(rng(2) ? createValue() : createExpression(recurmax - 1, COMMA_OK, stmtDepth, canThrow));
|
||||
}
|
||||
return args.join(', ');
|
||||
}
|
||||
@@ -390,9 +391,10 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||
|
||||
VAR_NAMES.length = namesLenBefore;
|
||||
|
||||
if (noDecl) s = 'var ' + createVarName(MANDATORY) + ' = ' + s + '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ');';
|
||||
if (noDecl) s = 'var ' + createVarName(MANDATORY) + ' = ' + s;
|
||||
// avoid "function statements" (decl inside statements)
|
||||
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name + '(' + createArgs() + ');';
|
||||
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name;
|
||||
s += '(' + createArgs(recurmax, stmtDepth, canThrow) + ');';
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -626,6 +628,9 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
case p++:
|
||||
case p++:
|
||||
return createValue();
|
||||
case p++:
|
||||
case p++:
|
||||
return getVarName();
|
||||
case p++:
|
||||
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||
case p++:
|
||||
|
||||
Reference in New Issue
Block a user