Merge branch 'master' into harmony-v3.2.2

This commit is contained in:
alexlamsl
2017-12-10 14:12:24 +08:00
7 changed files with 572 additions and 127 deletions

View File

@@ -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){