Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea999b0e92 | ||
|
|
ce7e220de4 | ||
|
|
2bdaca10ae | ||
|
|
aa0029204e | ||
|
|
f352bcec3a | ||
|
|
08514030f4 | ||
|
|
694ca5d045 | ||
|
|
57fb58b263 | ||
|
|
18c1c9b38a |
241
lib/compress.js
241
lib/compress.js
@@ -450,8 +450,7 @@ merge(Compressor.prototype, {
|
||||
return value instanceof AST_Node && def.fixed.parent_scope === scope;
|
||||
}
|
||||
return all(def.orig, function(sym) {
|
||||
return !(sym instanceof AST_SymbolDefun
|
||||
|| sym instanceof AST_SymbolLambda);
|
||||
return !(sym instanceof AST_SymbolDefun || sym instanceof AST_SymbolLambda);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1482,14 +1481,26 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
function get_rhs(expr) {
|
||||
if (!(candidate instanceof AST_Assign && candidate.operator == "=")) return;
|
||||
return candidate.right;
|
||||
return candidate instanceof AST_Assign && candidate.operator == "=" && candidate.right;
|
||||
}
|
||||
|
||||
function get_rvalue(expr) {
|
||||
return expr[expr instanceof AST_Assign ? "right" : "value"];
|
||||
}
|
||||
|
||||
function invariant(expr) {
|
||||
if (expr instanceof AST_Array) return false;
|
||||
if (expr instanceof AST_Binary && lazy_op[expr.operator]) {
|
||||
return invariant(expr.left) && invariant(expr.right);
|
||||
}
|
||||
if (expr instanceof AST_Call) return false;
|
||||
if (expr instanceof AST_Conditional) {
|
||||
return invariant(expr.consequent) && invariant(expr.alternative);
|
||||
}
|
||||
if (expr instanceof AST_Object) return false;
|
||||
return !expr.has_side_effects(compressor);
|
||||
}
|
||||
|
||||
function foldable(expr) {
|
||||
if (expr instanceof AST_SymbolRef) {
|
||||
var value = expr.evaluate(compressor);
|
||||
@@ -1502,7 +1513,7 @@ merge(Compressor.prototype, {
|
||||
return rhs_fuzzy_match(expr.evaluate(compressor), rhs_exact_match);
|
||||
}
|
||||
if (!(lhs instanceof AST_SymbolRef)) return false;
|
||||
if (expr.has_side_effects(compressor)) return false;
|
||||
if (!invariant(expr)) return false;
|
||||
var circular;
|
||||
var def = lhs.definition();
|
||||
expr.walk(new TreeWalker(function(node) {
|
||||
@@ -1699,6 +1710,19 @@ merge(Compressor.prototype, {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ab && !stat.alternative && stat.body instanceof AST_BlockStatement && next instanceof AST_Jump) {
|
||||
var negated = stat.condition.negate(compressor);
|
||||
if (negated.print_to_string().length <= stat.condition.print_to_string().length) {
|
||||
CHANGED = true;
|
||||
stat = stat.clone();
|
||||
stat.condition = negated;
|
||||
statements[j] = stat.body;
|
||||
stat.body = next;
|
||||
statements[i] = stat.transform(compressor);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var ab = aborts(stat.alternative);
|
||||
if (can_merge_flow(ab)) {
|
||||
if (ab.label) {
|
||||
@@ -2968,19 +2992,21 @@ merge(Compressor.prototype, {
|
||||
|
||||
// determine if expression has side effects
|
||||
(function(def) {
|
||||
def(AST_Node, return_true);
|
||||
|
||||
def(AST_EmptyStatement, return_false);
|
||||
def(AST_Constant, return_false);
|
||||
def(AST_This, return_false);
|
||||
|
||||
function any(list, compressor) {
|
||||
for (var i = list.length; --i >= 0;)
|
||||
if (list[i].has_side_effects(compressor))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
def(AST_Node, return_true);
|
||||
def(AST_Array, function(compressor) {
|
||||
return any(this.elements, compressor);
|
||||
});
|
||||
def(AST_Assign, return_true);
|
||||
def(AST_Binary, function(compressor) {
|
||||
return this.left.has_side_effects(compressor)
|
||||
|| this.right.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Block, function(compressor) {
|
||||
return any(this.body, compressor);
|
||||
});
|
||||
@@ -2992,19 +3018,24 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return any(this.args, compressor);
|
||||
});
|
||||
def(AST_Switch, function(compressor) {
|
||||
return this.expression.has_side_effects(compressor)
|
||||
|| any(this.body, compressor);
|
||||
});
|
||||
def(AST_Case, function(compressor) {
|
||||
return this.expression.has_side_effects(compressor)
|
||||
|| any(this.body, compressor);
|
||||
});
|
||||
def(AST_Try, function(compressor) {
|
||||
return any(this.body, compressor)
|
||||
|| this.bcatch && this.bcatch.has_side_effects(compressor)
|
||||
|| this.bfinally && this.bfinally.has_side_effects(compressor);
|
||||
def(AST_Conditional, function(compressor) {
|
||||
return this.condition.has_side_effects(compressor)
|
||||
|| this.consequent.has_side_effects(compressor)
|
||||
|| this.alternative.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Constant, return_false);
|
||||
def(AST_Definitions, function(compressor) {
|
||||
return any(this.definitions, compressor);
|
||||
});
|
||||
def(AST_Dot, function(compressor) {
|
||||
return this.expression.may_throw_on_access(compressor)
|
||||
|| this.expression.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_EmptyStatement, return_false);
|
||||
def(AST_If, function(compressor) {
|
||||
return this.condition.has_side_effects(compressor)
|
||||
|| this.body && this.body.has_side_effects(compressor)
|
||||
@@ -3013,41 +3044,13 @@ merge(Compressor.prototype, {
|
||||
def(AST_LabeledStatement, function(compressor) {
|
||||
return this.body.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_SimpleStatement, function(compressor) {
|
||||
return this.body.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Lambda, return_false);
|
||||
def(AST_Binary, function(compressor) {
|
||||
return this.left.has_side_effects(compressor)
|
||||
|| this.right.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Assign, return_true);
|
||||
def(AST_Conditional, function(compressor) {
|
||||
return this.condition.has_side_effects(compressor)
|
||||
|| this.consequent.has_side_effects(compressor)
|
||||
|| this.alternative.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Unary, function(compressor) {
|
||||
return unary_side_effects[this.operator]
|
||||
|| this.expression.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_SymbolRef, function(compressor) {
|
||||
return !this.is_declared(compressor);
|
||||
});
|
||||
def(AST_SymbolDeclaration, return_false);
|
||||
def(AST_Object, function(compressor) {
|
||||
return any(this.properties, compressor);
|
||||
});
|
||||
def(AST_ObjectProperty, function(compressor) {
|
||||
return this.value.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Array, function(compressor) {
|
||||
return any(this.elements, compressor);
|
||||
});
|
||||
def(AST_Dot, function(compressor) {
|
||||
return this.expression.may_throw_on_access(compressor)
|
||||
|| this.expression.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Sub, function(compressor) {
|
||||
return this.expression.may_throw_on_access(compressor)
|
||||
|| this.expression.has_side_effects(compressor)
|
||||
@@ -3056,8 +3059,26 @@ merge(Compressor.prototype, {
|
||||
def(AST_Sequence, function(compressor) {
|
||||
return any(this.expressions, compressor);
|
||||
});
|
||||
def(AST_Definitions, function(compressor) {
|
||||
return any(this.definitions, compressor);
|
||||
def(AST_SimpleStatement, function(compressor) {
|
||||
return this.body.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Switch, function(compressor) {
|
||||
return this.expression.has_side_effects(compressor)
|
||||
|| any(this.body, compressor);
|
||||
});
|
||||
def(AST_SymbolDeclaration, return_false);
|
||||
def(AST_SymbolRef, function(compressor) {
|
||||
return !this.is_declared(compressor);
|
||||
});
|
||||
def(AST_This, return_false);
|
||||
def(AST_Try, function(compressor) {
|
||||
return any(this.body, compressor)
|
||||
|| this.bcatch && this.bcatch.has_side_effects(compressor)
|
||||
|| this.bfinally && this.bfinally.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_Unary, function(compressor) {
|
||||
return unary_side_effects[this.operator]
|
||||
|| this.expression.has_side_effects(compressor);
|
||||
});
|
||||
def(AST_VarDef, function(compressor) {
|
||||
return this.value;
|
||||
@@ -3316,13 +3337,14 @@ merge(Compressor.prototype, {
|
||||
} else if (node instanceof AST_Unary && node.write_only) {
|
||||
sym = node.expression;
|
||||
}
|
||||
if (/strict/.test(compressor.option("pure_getters"))) {
|
||||
if (!/strict/.test(compressor.option("pure_getters"))) return sym instanceof AST_SymbolRef && sym;
|
||||
while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) {
|
||||
if (sym instanceof AST_Sub) props.unshift(sym.property);
|
||||
sym = sym.expression;
|
||||
}
|
||||
}
|
||||
return sym;
|
||||
return sym instanceof AST_SymbolRef && all(sym.definition().orig, function(sym) {
|
||||
return !(sym instanceof AST_SymbolLambda);
|
||||
}) && sym;
|
||||
};
|
||||
var in_use = [];
|
||||
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
||||
@@ -3417,7 +3439,7 @@ merge(Compressor.prototype, {
|
||||
var parent = tt.parent();
|
||||
if (drop_vars) {
|
||||
var props = [], sym = assign_as_unused(node, props);
|
||||
if (sym instanceof AST_SymbolRef) {
|
||||
if (sym) {
|
||||
var def = sym.definition();
|
||||
var in_use = def.id in in_use_ids;
|
||||
var value = null;
|
||||
@@ -3616,8 +3638,7 @@ merge(Compressor.prototype, {
|
||||
|
||||
function scan_ref_scoped(node, descend) {
|
||||
var node_def, props = [], sym = assign_as_unused(node, props);
|
||||
if (sym instanceof AST_SymbolRef
|
||||
&& self.variables.get(sym.name) === (node_def = sym.definition())) {
|
||||
if (sym && self.variables.get(sym.name) === (node_def = sym.definition())) {
|
||||
props.forEach(function(prop) {
|
||||
prop.walk(tw);
|
||||
});
|
||||
@@ -5730,38 +5751,34 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
var parent = compressor.parent();
|
||||
if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
|
||||
var d = self.definition();
|
||||
var def = self.definition();
|
||||
var fixed = self.fixed_value();
|
||||
var single_use = d.single_use
|
||||
&& !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
|
||||
var single_use = def.single_use && !(parent instanceof AST_Call && parent.is_expr_pure(compressor));
|
||||
if (single_use && fixed instanceof AST_Lambda) {
|
||||
if (d.scope !== self.scope
|
||||
&& (!compressor.option("reduce_funcs")
|
||||
|| d.escaped == 1
|
||||
|| fixed.inlined)) {
|
||||
if (def.scope !== self.scope
|
||||
&& (!compressor.option("reduce_funcs") || def.escaped == 1 || fixed.inlined)) {
|
||||
single_use = false;
|
||||
} else if (recursive_ref(compressor, d)) {
|
||||
} else if (recursive_ref(compressor, def)) {
|
||||
single_use = false;
|
||||
} else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) {
|
||||
} else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
|
||||
single_use = fixed.is_constant_expression(self.scope);
|
||||
if (single_use == "f") {
|
||||
var scope = self.scope;
|
||||
do {
|
||||
if (scope instanceof AST_Defun || scope instanceof AST_Function) {
|
||||
do if (scope instanceof AST_Defun || scope instanceof AST_Function) {
|
||||
scope.inlined = true;
|
||||
}
|
||||
} while (scope = scope.parent_scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (single_use && fixed) {
|
||||
def.single_use = false;
|
||||
if (fixed instanceof AST_Defun) {
|
||||
fixed._squeezed = true;
|
||||
fixed = make_node(AST_Function, fixed, fixed);
|
||||
fixed.name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
|
||||
}
|
||||
var value;
|
||||
if (d.recursive_refs > 0) {
|
||||
if (def.recursive_refs > 0) {
|
||||
value = fixed.clone(true);
|
||||
var defun_def = value.name.definition();
|
||||
var lambda_def = value.variables.get(value.name.name);
|
||||
@@ -5773,9 +5790,13 @@ merge(Compressor.prototype, {
|
||||
lambda_def = value.def_function(name);
|
||||
}
|
||||
value.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
|
||||
if (!(node instanceof AST_SymbolRef)) return;
|
||||
var def = node.definition();
|
||||
if (def === defun_def) {
|
||||
node.thedef = lambda_def;
|
||||
lambda_def.references.push(node);
|
||||
} else {
|
||||
def.single_use = false;
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
@@ -5784,12 +5805,11 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if (fixed && d.should_replace === undefined) {
|
||||
if (fixed && def.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;
|
||||
if (!(def.orig[0] instanceof AST_SymbolFunarg) && all(def.references, function(ref) {
|
||||
return def.scope === ref.scope;
|
||||
})) {
|
||||
init = fixed;
|
||||
}
|
||||
@@ -5814,18 +5834,18 @@ merge(Compressor.prototype, {
|
||||
return result === init || result === fixed ? result.clone(true) : result;
|
||||
};
|
||||
}
|
||||
var name_length = d.name.length;
|
||||
var name_length = def.name.length;
|
||||
var overhead = 0;
|
||||
if (compressor.option("unused") && !compressor.exposed(d)) {
|
||||
overhead = (name_length + 2 + value_length) / (d.references.length - d.assignments);
|
||||
if (compressor.option("unused") && !compressor.exposed(def)) {
|
||||
overhead = (name_length + 2 + value_length) / (def.references.length - def.assignments);
|
||||
}
|
||||
d.should_replace = value_length <= name_length + overhead ? fn : false;
|
||||
def.should_replace = value_length <= name_length + overhead ? fn : false;
|
||||
} else {
|
||||
d.should_replace = false;
|
||||
def.should_replace = false;
|
||||
}
|
||||
}
|
||||
if (d.should_replace) {
|
||||
return d.should_replace();
|
||||
if (def.should_replace) {
|
||||
return def.should_replace();
|
||||
}
|
||||
}
|
||||
return self;
|
||||
@@ -6027,23 +6047,27 @@ merge(Compressor.prototype, {
|
||||
// |
|
||||
// v
|
||||
// exp = foo ? something : something_else;
|
||||
if (consequent instanceof AST_Assign
|
||||
&& alternative instanceof AST_Assign
|
||||
&& consequent.operator == alternative.operator
|
||||
&& consequent.left.equivalent_to(alternative.left)
|
||||
&& (!self.condition.has_side_effects(compressor)
|
||||
|| consequent.operator == "="
|
||||
&& !consequent.left.has_side_effects(compressor))) {
|
||||
var seq_tail = consequent.tail_node();
|
||||
if (seq_tail instanceof AST_Assign) {
|
||||
var is_eq = seq_tail.operator == "=";
|
||||
var alt_tail = is_eq ? alternative.tail_node() : alternative;
|
||||
if ((is_eq || consequent instanceof AST_Assign)
|
||||
&& alt_tail instanceof AST_Assign
|
||||
&& seq_tail.operator == alt_tail.operator
|
||||
&& seq_tail.left.equivalent_to(alt_tail.left)
|
||||
&& (!condition.has_side_effects(compressor)
|
||||
|| is_eq && !seq_tail.left.has_side_effects(compressor))) {
|
||||
return make_node(AST_Assign, self, {
|
||||
operator: consequent.operator,
|
||||
left: consequent.left,
|
||||
operator: seq_tail.operator,
|
||||
left: seq_tail.left,
|
||||
right: make_node(AST_Conditional, self, {
|
||||
condition: self.condition,
|
||||
consequent: consequent.right,
|
||||
alternative: alternative.right
|
||||
condition: condition,
|
||||
consequent: pop_lhs(consequent),
|
||||
alternative: pop_lhs(alternative)
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
// x ? y(a) : y(b) --> y(x ? a : b)
|
||||
var arg_index;
|
||||
if (consequent instanceof AST_Call
|
||||
@@ -6051,12 +6075,12 @@ merge(Compressor.prototype, {
|
||||
&& consequent.args.length > 0
|
||||
&& consequent.args.length == alternative.args.length
|
||||
&& consequent.expression.equivalent_to(alternative.expression)
|
||||
&& !self.condition.has_side_effects(compressor)
|
||||
&& !condition.has_side_effects(compressor)
|
||||
&& !consequent.expression.has_side_effects(compressor)
|
||||
&& typeof (arg_index = single_arg_diff()) == "number") {
|
||||
var node = consequent.clone();
|
||||
node.args[arg_index] = make_node(AST_Conditional, self, {
|
||||
condition: self.condition,
|
||||
condition: condition,
|
||||
consequent: consequent.args[arg_index],
|
||||
alternative: alternative.args[arg_index]
|
||||
});
|
||||
@@ -6067,7 +6091,7 @@ merge(Compressor.prototype, {
|
||||
&& consequent.alternative.equivalent_to(alternative)) {
|
||||
return make_node(AST_Conditional, self, {
|
||||
condition: make_node(AST_Binary, self, {
|
||||
left: self.condition,
|
||||
left: condition,
|
||||
operator: "&&",
|
||||
right: consequent.condition
|
||||
}),
|
||||
@@ -6078,7 +6102,7 @@ merge(Compressor.prototype, {
|
||||
// x ? y : y --> x, y
|
||||
if (consequent.equivalent_to(alternative)) {
|
||||
return make_sequence(self, [
|
||||
self.condition,
|
||||
condition,
|
||||
consequent
|
||||
]).optimize(compressor);
|
||||
}
|
||||
@@ -6087,7 +6111,7 @@ merge(Compressor.prototype, {
|
||||
&& consequent.tail_node().equivalent_to(alternative.tail_node())) {
|
||||
return make_sequence(self, [
|
||||
make_node(AST_Conditional, self, {
|
||||
condition: self.condition,
|
||||
condition: condition,
|
||||
consequent: pop_seq(consequent),
|
||||
alternative: pop_seq(alternative)
|
||||
}),
|
||||
@@ -6102,7 +6126,7 @@ merge(Compressor.prototype, {
|
||||
operator: "||",
|
||||
left: make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: self.condition,
|
||||
left: condition,
|
||||
right: consequent.left
|
||||
}),
|
||||
right: alternative
|
||||
@@ -6112,24 +6136,24 @@ merge(Compressor.prototype, {
|
||||
if (is_true(self.consequent)) {
|
||||
if (is_false(self.alternative)) {
|
||||
// c ? true : false ---> !!c
|
||||
return booleanize(self.condition);
|
||||
return booleanize(condition);
|
||||
}
|
||||
// c ? true : x ---> !!c || x
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: booleanize(self.condition),
|
||||
left: booleanize(condition),
|
||||
right: self.alternative
|
||||
});
|
||||
}
|
||||
if (is_false(self.consequent)) {
|
||||
if (is_true(self.alternative)) {
|
||||
// c ? false : true ---> !c
|
||||
return booleanize(self.condition.negate(compressor));
|
||||
return booleanize(condition.negate(compressor));
|
||||
}
|
||||
// c ? false : x ---> !c && x
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: booleanize(self.condition.negate(compressor)),
|
||||
left: booleanize(condition.negate(compressor)),
|
||||
right: self.alternative
|
||||
});
|
||||
}
|
||||
@@ -6137,7 +6161,7 @@ merge(Compressor.prototype, {
|
||||
// c ? x : true ---> !c || x
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: booleanize(self.condition.negate(compressor)),
|
||||
left: booleanize(condition.negate(compressor)),
|
||||
right: self.consequent
|
||||
});
|
||||
}
|
||||
@@ -6145,7 +6169,7 @@ merge(Compressor.prototype, {
|
||||
// c ? x : false ---> !!c && x
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: booleanize(self.condition),
|
||||
left: booleanize(condition),
|
||||
right: self.consequent
|
||||
});
|
||||
}
|
||||
@@ -6197,6 +6221,13 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
function pop_lhs(node) {
|
||||
if (!(node instanceof AST_Sequence)) return node.right;
|
||||
var exprs = node.expressions.slice();
|
||||
exprs.push(exprs.pop().right);
|
||||
return make_sequence(node, exprs);
|
||||
}
|
||||
|
||||
function pop_seq(node) {
|
||||
if (!(node instanceof AST_Sequence)) return make_node(AST_Number, node, {
|
||||
value: 0
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.4.7",
|
||||
"version": "3.4.9",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
@@ -23,7 +23,7 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.16.0",
|
||||
"commander": "~2.17.1",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -5827,3 +5827,183 @@ issue_3215_4: {
|
||||
}
|
||||
expect_stdout: "number"
|
||||
}
|
||||
|
||||
issue_3238_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = Object.create(null);
|
||||
c = Object.create(null);
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = Object.create(null);
|
||||
c = Object.create(null);
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect_stdout: "true false"
|
||||
}
|
||||
|
||||
issue_3238_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = Error();
|
||||
c = Error();
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = Error();
|
||||
c = Error();
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect_stdout: "true false"
|
||||
}
|
||||
|
||||
issue_3238_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = new Date();
|
||||
c = new Date();
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = new Date();
|
||||
c = new Date();
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect_stdout: "true false"
|
||||
}
|
||||
|
||||
issue_3238_4: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = a && {};
|
||||
c = a && {};
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = a && {};
|
||||
c = a && {};
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect_stdout: "true false"
|
||||
}
|
||||
|
||||
issue_3238_5: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = a ? [] : 42;
|
||||
c = a ? [] : 42;
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = a ? [] : 42;
|
||||
c = a ? [] : 42;
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect_stdout: "true false"
|
||||
}
|
||||
|
||||
issue_3238_6: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = a && 0 || [];
|
||||
c = a && 0 || [];
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var b, c;
|
||||
if (a) {
|
||||
b = a && 0 || [];
|
||||
c = a && 0 || [];
|
||||
}
|
||||
return b === c;
|
||||
}
|
||||
console.log(f(0), f(1));
|
||||
}
|
||||
expect_stdout: "true false"
|
||||
}
|
||||
|
||||
@@ -1292,3 +1292,95 @@ to_and_or: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
cond_seq_assign_1: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var t;
|
||||
if (a) {
|
||||
t = "foo";
|
||||
t = "bar";
|
||||
} else {
|
||||
console.log(t);
|
||||
t = 42;
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
f(f);
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var t;
|
||||
t = a ? (t = "foo", "bar") : (console.log(t), 42),
|
||||
console.log(t);
|
||||
}
|
||||
f(f),
|
||||
f();
|
||||
}
|
||||
expect_stdout: [
|
||||
"bar",
|
||||
"undefined",
|
||||
"42",
|
||||
]
|
||||
}
|
||||
|
||||
cond_seq_assign_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var t;
|
||||
if (a) {
|
||||
t = "foo";
|
||||
a = "bar";
|
||||
} else {
|
||||
console.log(t);
|
||||
t = 42;
|
||||
}
|
||||
console.log(t);
|
||||
}
|
||||
f(f);
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
var t;
|
||||
a ? (t = "foo", a = "bar") : (console.log(t), t = 42),
|
||||
console.log(t);
|
||||
}
|
||||
f(f),
|
||||
f();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"undefined",
|
||||
"42",
|
||||
]
|
||||
}
|
||||
|
||||
cond_seq_assign_3: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var c = 0;
|
||||
if (this)
|
||||
c = 1 + c, c = c + 1;
|
||||
else
|
||||
c = 1 + c, c = c + 1;
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = 0;
|
||||
this, c = 1 + c, c += 1;
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
@@ -1982,3 +1982,26 @@ issue_3192: {
|
||||
"foo bar",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3233: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = function b() {
|
||||
b.c = "PASS";
|
||||
};
|
||||
a();
|
||||
console.log(a.c);
|
||||
}
|
||||
expect: {
|
||||
var a = function b() {
|
||||
b.c = "PASS";
|
||||
};
|
||||
a();
|
||||
console.log(a.c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -396,3 +396,151 @@ if_if_return_return: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if_body_return_1: {
|
||||
options = {
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
var c = "PASS";
|
||||
function f(a, b) {
|
||||
if (a) {
|
||||
if (b) throw new Error(c);
|
||||
return 42;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
console.log(f(0, 0));
|
||||
console.log(f(0, 1));
|
||||
console.log(f(1, 0));
|
||||
try {
|
||||
f(1, 1);
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var c = "PASS";
|
||||
function f(a, b) {
|
||||
if (a) {
|
||||
if (b) throw new Error(c);
|
||||
return 42;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
console.log(f(0, 0));
|
||||
console.log(f(0, 1));
|
||||
console.log(f(1, 0));
|
||||
try {
|
||||
f(1, 1);
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"true",
|
||||
"true",
|
||||
"42",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
if_body_return_2: {
|
||||
options = {
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
var c = "PASS";
|
||||
function f(a, b) {
|
||||
if (0 + a) {
|
||||
if (b) throw new Error(c);
|
||||
return 42;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
console.log(f(0, 0));
|
||||
console.log(f(0, 1));
|
||||
console.log(f(1, 0));
|
||||
try {
|
||||
f(1, 1);
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var c = "PASS";
|
||||
function f(a, b) {
|
||||
if (0 + a) {
|
||||
if (b) throw new Error(c);
|
||||
return 42;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
console.log(f(0, 0));
|
||||
console.log(f(0, 1));
|
||||
console.log(f(1, 0));
|
||||
try {
|
||||
f(1, 1);
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"true",
|
||||
"true",
|
||||
"42",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
if_body_return_3: {
|
||||
options = {
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
var c = "PASS";
|
||||
function f(a, b) {
|
||||
if (1 == a) {
|
||||
if (b) throw new Error(c);
|
||||
return 42;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
console.log(f(0, 0));
|
||||
console.log(f(0, 1));
|
||||
console.log(f(1, 0));
|
||||
try {
|
||||
f(1, 1);
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var c = "PASS";
|
||||
function f(a, b) {
|
||||
if (1 != a) return true;
|
||||
if (b) throw new Error(c);
|
||||
return 42;
|
||||
}
|
||||
console.log(f(0, 0));
|
||||
console.log(f(0, 1));
|
||||
console.log(f(1, 0));
|
||||
try {
|
||||
f(1, 1);
|
||||
console.log("FAIL");
|
||||
} catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
}
|
||||
expect_stdout: [
|
||||
"true",
|
||||
"true",
|
||||
"42",
|
||||
"PASS",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5354,6 +5354,7 @@ issue_2774: {
|
||||
|
||||
issue_2799_1: {
|
||||
options = {
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
@@ -6429,3 +6430,159 @@ issue_3140_5: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_3240_1: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
f(1);
|
||||
function f(a) {
|
||||
console.log(a);
|
||||
var g = function() {
|
||||
f(a - 1);
|
||||
};
|
||||
if (a) g();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function f(a) {
|
||||
console.log(a);
|
||||
var g = function() {
|
||||
f(a - 1);
|
||||
};
|
||||
if (a) g();
|
||||
})(1);
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3240_2: {
|
||||
options = {
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
f(1);
|
||||
function f(a) {
|
||||
console.log(a);
|
||||
var g = function() {
|
||||
f(a - 1);
|
||||
};
|
||||
if (a) g();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function f(a) {
|
||||
console.log(a);
|
||||
if (a) (function() {
|
||||
f(a - 1);
|
||||
})();
|
||||
})(1);
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"0",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3240_3: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
f();
|
||||
function f(b) {
|
||||
if (!f.a) f.a = 0;
|
||||
console.log(f.a.toString());
|
||||
var g = function() {
|
||||
(b ? function() {} : function() {
|
||||
f.a++;
|
||||
f(1);
|
||||
})();
|
||||
};
|
||||
g();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function f(b) {
|
||||
if (!f.a) f.a = 0;
|
||||
console.log(f.a.toString());
|
||||
var g = function() {
|
||||
(b ? function() {} : function() {
|
||||
f.a++;
|
||||
f(1);
|
||||
})();
|
||||
};
|
||||
g();
|
||||
})();
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"1",
|
||||
]
|
||||
}
|
||||
|
||||
issue_3240_4: {
|
||||
options = {
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
f();
|
||||
function f(b) {
|
||||
if (!f.a) f.a = 0;
|
||||
console.log(f.a.toString());
|
||||
var g = function() {
|
||||
(b ? function() {} : function() {
|
||||
f.a++;
|
||||
f(1);
|
||||
})();
|
||||
};
|
||||
g();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function f(b) {
|
||||
if (!f.a) f.a = 0;
|
||||
console.log(f.a.toString());
|
||||
(function() {
|
||||
(b ? function() {} : function() {
|
||||
f.a++;
|
||||
f(1);
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"1",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -651,7 +651,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should work with explicit --no-rename", function(done) {
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -mc --no-rename";
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, "function f(n){return function(n){return n}(n)}\n");
|
||||
@@ -659,7 +659,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should work with implicit --rename", function(done) {
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -mc";
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, "function f(n){return n}\n");
|
||||
@@ -667,7 +667,7 @@ describe("bin/uglifyjs", function() {
|
||||
});
|
||||
});
|
||||
it("Should work with implicit --no-rename", function(done) {
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -c";
|
||||
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
|
||||
exec(command, function(err, stdout, stderr) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(stdout, "function f(x){return function(x){return x}(x)}\n");
|
||||
|
||||
Reference in New Issue
Block a user