Merge branch 'master' into harmony-v3.1.4

This commit is contained in:
alexlamsl
2017-10-16 12:32:50 +08:00
7 changed files with 600 additions and 189 deletions

View File

@@ -303,6 +303,8 @@ merge(Compressor.prototype, {
if (node instanceof AST_SymbolRef) d.references.push(node);
d.fixed = false;
});
var in_loop = null;
var loop_ids = Object.create(null);
var tw = new TreeWalker(function(node, descend) {
node._squeezed = false;
node._optimized = false;
@@ -314,7 +316,7 @@ merge(Compressor.prototype, {
var d = node.definition();
d.references.push(node);
if (d.fixed === undefined || !safe_to_read(d)
|| is_modified(node, 0, is_immutable(node.fixed_value()))) {
|| is_modified(node, 0, is_immutable(node))) {
d.fixed = false;
} else {
var parent = tw.parent();
@@ -339,6 +341,7 @@ merge(Compressor.prototype, {
d.fixed = function() {
return node.value;
};
loop_ids[d.id] = in_loop;
mark(d, false);
descend();
} else {
@@ -398,6 +401,7 @@ merge(Compressor.prototype, {
d.fixed = function() {
return iife.args[i] || make_node(AST_Undefined, iife);
};
loop_ids[d.id] = in_loop;
mark(d, true);
} else {
d.fixed = false;
@@ -446,10 +450,13 @@ merge(Compressor.prototype, {
return true;
}
if (node instanceof AST_DWLoop) {
var saved_loop = in_loop;
in_loop = node;
push();
node.condition.walk(tw);
node.body.walk(tw);
pop();
in_loop = saved_loop;
return true;
}
if (node instanceof AST_LabeledStatement) {
@@ -460,6 +467,8 @@ merge(Compressor.prototype, {
}
if (node instanceof AST_For) {
if (node.init) node.init.walk(tw);
var saved_loop = in_loop;
in_loop = node;
if (node.condition) {
push();
node.condition.walk(tw);
@@ -473,14 +482,18 @@ merge(Compressor.prototype, {
node.step.walk(tw);
pop();
}
in_loop = saved_loop;
return true;
}
if (node instanceof AST_ForIn) {
node.init.walk(suppressor);
node.object.walk(tw);
var saved_loop = in_loop;
in_loop = node;
push();
node.body.walk(tw);
pop();
in_loop = saved_loop;
return true;
}
if (node instanceof AST_Try) {
@@ -551,10 +564,23 @@ merge(Compressor.prototype, {
}
def.references = [];
def.should_replace = undefined;
def.single_use = undefined;
}
function is_immutable(value) {
return value && value.is_constant() || value instanceof AST_Lambda;
function is_immutable(node) {
var value = node.fixed_value();
if (!value) return false;
if (value.is_constant()) return true;
if (compressor.option("unused")) {
var d = node.definition();
if (d.single_use === undefined) {
d.single_use = loop_ids[d.id] === in_loop
&& d.scope === node.scope
&& value.is_constant_expression();
}
if (d.references.length == 1 && d.single_use) return true;
}
return value instanceof AST_Lambda;
}
function is_modified(node, level, immutable) {
@@ -854,7 +880,7 @@ merge(Compressor.prototype, {
var sym;
if (node instanceof AST_Call
|| node instanceof AST_Exit
|| node instanceof AST_PropAccess
|| node instanceof AST_PropAccess && node.has_side_effects(compressor)
|| node instanceof AST_SymbolRef
&& (lvalues[node.name]
|| side_effects && !references_in_scope(node.definition()))
@@ -2226,6 +2252,22 @@ merge(Compressor.prototype, {
}
def(AST_Node, return_false);
def(AST_Constant, return_true);
def(AST_Function, function(){
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) {
result = false;
return true;
}
}
}));
return result;
});
def(AST_Unary, function(){
return this.expression.is_constant_expression();
});
@@ -4306,12 +4348,13 @@ merge(Compressor.prototype, {
d.fixed = fixed = make_node(AST_Function, fixed, fixed);
}
if (compressor.option("unused")
&& is_func_expr(fixed)
&& d.references.length == 1
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
&& !d.scope.uses_eval
&& compressor.find_parent(AST_Scope) === fixed.parent_scope) {
return fixed.clone(true);
&& (d.single_use || is_func_expr(fixed)
&& !(d.scope.uses_arguments && d.orig[0] instanceof AST_SymbolFunarg)
&& !d.scope.uses_eval
&& compressor.find_parent(AST_Scope) === fixed.parent_scope)) {
var value = fixed.optimize(compressor);
return value === fixed ? fixed.clone(true) : value;
}
if (compressor.option("evaluate") && fixed) {
if (d.should_replace === undefined) {