Merge branch 'master' into harmony-v3.2.2
This commit is contained in:
137
lib/compress.js
137
lib/compress.js
@@ -680,11 +680,13 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
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_Exit && node === parent.value && node.scope !== d.scope
|
||||
|| parent instanceof AST_VarDef && node === parent.value) {
|
||||
d.escaped = true;
|
||||
return;
|
||||
} else if (parent instanceof AST_Array) {
|
||||
} else if (parent instanceof AST_Array
|
||||
|| parent instanceof AST_Conditional && node !== parent.condition
|
||||
|| parent instanceof AST_Sequence && node === parent.tail_node()) {
|
||||
mark_escaped(d, scope, parent, parent, level + 1);
|
||||
} else if (parent instanceof AST_ObjectKeyVal && node === parent.value) {
|
||||
var obj = tw.parent(level + 1);
|
||||
@@ -1298,10 +1300,19 @@ merge(Compressor.prototype, {
|
||||
var stat = statements[i];
|
||||
var next = statements[i + 1];
|
||||
|
||||
if (in_lambda && stat instanceof AST_Return && !stat.value && !next) {
|
||||
CHANGED = true;
|
||||
statements.length--;
|
||||
continue;
|
||||
if (in_lambda && !next && stat instanceof AST_Return) {
|
||||
if (!stat.value) {
|
||||
CHANGED = true;
|
||||
statements.length--;
|
||||
continue;
|
||||
}
|
||||
if (stat.value instanceof AST_UnaryPrefix && stat.value.operator == "void") {
|
||||
CHANGED = true;
|
||||
statements[i] = make_node(AST_SimpleStatement, stat, {
|
||||
body: stat.value.expression
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (stat instanceof AST_If) {
|
||||
@@ -1388,9 +1399,16 @@ merge(Compressor.prototype, {
|
||||
&& prev instanceof AST_If && prev.body instanceof AST_Return
|
||||
&& i + 2 == statements.length && next instanceof AST_SimpleStatement) {
|
||||
CHANGED = true;
|
||||
statements.push(make_node(AST_Return, next, {
|
||||
value: null
|
||||
}).transform(compressor));
|
||||
stat = stat.clone();
|
||||
stat.alternative = make_node(AST_BlockStatement, next, {
|
||||
body: [
|
||||
next,
|
||||
make_node(AST_Return, next, {
|
||||
value: null
|
||||
})
|
||||
]
|
||||
});
|
||||
statements.splice(i, 2, stat.transform(compressor));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2627,6 +2645,21 @@ merge(Compressor.prototype, {
|
||||
// pass 3: we should drop declarations not in_use
|
||||
var tt = new TreeTransformer(
|
||||
function before(node, descend, in_list) {
|
||||
var parent = tt.parent();
|
||||
if (drop_vars) {
|
||||
var sym = assign_as_unused(node);
|
||||
if (sym instanceof AST_SymbolRef
|
||||
&& !((sym = sym.definition()).id in in_use_ids)
|
||||
&& (drop_vars || !sym.global)) {
|
||||
if (node instanceof AST_Assign) {
|
||||
return maintain_this_binding(parent, node, node.right.transform(tt));
|
||||
}
|
||||
return make_node(AST_Number, node, {
|
||||
value: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
if (scope !== self) return;
|
||||
if (node.name
|
||||
&& (!compressor.option("keep_classnames") && node instanceof AST_ClassExpression
|
||||
|| !compressor.option("keep_fnames") && node instanceof AST_Function)) {
|
||||
@@ -2672,9 +2705,7 @@ merge(Compressor.prototype, {
|
||||
def.eliminated++;
|
||||
return make_node(AST_EmptyStatement, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
var parent = tt.parent();
|
||||
if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) {
|
||||
var drop_block = !(parent instanceof AST_Toplevel) && !(node instanceof AST_Var);
|
||||
// place uninitialized names at the start
|
||||
@@ -2757,19 +2788,6 @@ 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)
|
||||
&& (drop_vars || !def.global)) {
|
||||
if (node instanceof AST_Assign) {
|
||||
return maintain_this_binding(parent, node, node.right.transform(tt));
|
||||
}
|
||||
return make_node(AST_Number, node, {
|
||||
value: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
// certain combination of unused name + side effect leads to:
|
||||
// https://github.com/mishoo/UglifyJS2/issues/44
|
||||
// https://github.com/mishoo/UglifyJS2/issues/1830
|
||||
@@ -2807,8 +2825,13 @@ merge(Compressor.prototype, {
|
||||
return MAP.splice(node.body);
|
||||
}
|
||||
}
|
||||
if (node instanceof AST_Scope && node !== self)
|
||||
if (node instanceof AST_Scope) {
|
||||
var save_scope = scope;
|
||||
scope = node;
|
||||
descend(node, this);
|
||||
scope = save_scope;
|
||||
return node;
|
||||
}
|
||||
|
||||
function template(sym) {
|
||||
return {
|
||||
@@ -2824,8 +2847,7 @@ merge(Compressor.prototype, {
|
||||
|
||||
function scan_ref_scoped(node, descend) {
|
||||
var sym;
|
||||
if (scope === self
|
||||
&& (sym = assign_as_unused(node)) instanceof AST_SymbolRef
|
||||
if ((sym = assign_as_unused(node)) instanceof AST_SymbolRef
|
||||
&& !is_ref_of(node.left, AST_SymbolBlockDeclaration)
|
||||
&& self.variables.get(sym.name) === sym.definition()) {
|
||||
if (node instanceof AST_Assign) node.right.walk(tw);
|
||||
@@ -3674,12 +3696,12 @@ merge(Compressor.prototype, {
|
||||
var simple_args = all(self.args, function(arg) {
|
||||
return !(arg instanceof AST_Expansion);
|
||||
});
|
||||
if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) {
|
||||
fn = fn.fixed_value();
|
||||
}
|
||||
if (compressor.option("unused")
|
||||
&& simple_args
|
||||
&& (is_func_expr(fn)
|
||||
|| compressor.option("reduce_vars")
|
||||
&& fn instanceof AST_SymbolRef
|
||||
&& is_func_expr(fn = fn.fixed_value()))
|
||||
&& is_func_expr(fn)
|
||||
&& !fn.uses_arguments
|
||||
&& !fn.uses_eval) {
|
||||
var pos = 0, last = 0;
|
||||
@@ -3930,15 +3952,16 @@ merge(Compressor.prototype, {
|
||||
return make_sequence(self, args).optimize(compressor);
|
||||
}
|
||||
}
|
||||
if (is_func_expr(exp) && !exp.is_generator && !exp.async) {
|
||||
if (is_func_expr(fn) && !fn.is_generator && !fn.async) {
|
||||
if (compressor.option("inline")
|
||||
&& exp === fn
|
||||
&& simple_args
|
||||
&& !exp.name
|
||||
&& !exp.uses_arguments
|
||||
&& !exp.uses_eval
|
||||
&& (exp.body instanceof AST_Node || exp.body.length == 1)
|
||||
&& !exp.contains_this()
|
||||
&& all(exp.argnames, function(arg) {
|
||||
&& !fn.name
|
||||
&& !fn.uses_arguments
|
||||
&& !fn.uses_eval
|
||||
&& (fn.body instanceof AST_Node || fn.body.length == 1)
|
||||
&& !fn.contains_this()
|
||||
&& all(fn.argnames, function(arg) {
|
||||
if (arg instanceof AST_Expansion) return arg.expression.__unused;
|
||||
return arg.__unused;
|
||||
})
|
||||
@@ -3957,7 +3980,7 @@ merge(Compressor.prototype, {
|
||||
return make_sequence(self, args).optimize(compressor);
|
||||
}
|
||||
}
|
||||
if (compressor.option("side_effects") && !(exp.body instanceof AST_Node) && all(exp.body, is_empty)) {
|
||||
if (compressor.option("side_effects") && !(fn.body instanceof AST_Node) && all(fn.body, is_empty)) {
|
||||
var args = self.args.concat(make_node(AST_Undefined, self));
|
||||
return make_sequence(self, args).optimize(compressor);
|
||||
}
|
||||
@@ -4930,20 +4953,22 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
}
|
||||
// x ? y(a) : y(b) --> y(x ? a : b)
|
||||
var arg_index;
|
||||
if (consequent instanceof AST_Call
|
||||
&& alternative.TYPE === consequent.TYPE
|
||||
&& consequent.args.length == 1
|
||||
&& alternative.args.length == 1
|
||||
&& !(consequent.args[0] instanceof AST_Expansion)
|
||||
&& !(alternative.args[0] instanceof AST_Expansion)
|
||||
&& consequent.args.length > 0
|
||||
&& consequent.args.length == alternative.args.length
|
||||
&& consequent.expression.equivalent_to(alternative.expression)
|
||||
&& !consequent.expression.has_side_effects(compressor)) {
|
||||
consequent.args[0] = make_node(AST_Conditional, self, {
|
||||
&& !self.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,
|
||||
consequent: consequent.args[0],
|
||||
alternative: alternative.args[0]
|
||||
consequent: consequent.args[arg_index],
|
||||
alternative: alternative.args[arg_index]
|
||||
});
|
||||
return consequent;
|
||||
return node;
|
||||
}
|
||||
// x?y?z:a:a --> x&&y?z:a
|
||||
if (consequent instanceof AST_Conditional
|
||||
@@ -5040,6 +5065,22 @@ merge(Compressor.prototype, {
|
||||
&& node.expression instanceof AST_Constant
|
||||
&& node.expression.getValue());
|
||||
}
|
||||
|
||||
function single_arg_diff() {
|
||||
var a = consequent.args;
|
||||
var b = alternative.args;
|
||||
for (var i = 0, len = a.length; i < len; i++) {
|
||||
if (a[i] instanceof AST_Expansion) return;
|
||||
if (!a[i].equivalent_to(b[i])) {
|
||||
if (b[i] instanceof AST_Expansion) return;
|
||||
for (var j = i + 1; j < len; j++) {
|
||||
if (a[j] instanceof AST_Expansion) return;
|
||||
if (!a[j].equivalent_to(b[j])) return;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
OPT(AST_Boolean, function(self, compressor){
|
||||
|
||||
Reference in New Issue
Block a user