Merge branch 'master' into harmony-v3.2.0

This commit is contained in:
alexlamsl
2017-11-26 04:23:57 +08:00
12 changed files with 967 additions and 103 deletions

View File

@@ -63,7 +63,7 @@ function Compressor(options, false_by_default) {
expression : false,
global_defs : {},
hoist_funs : !false_by_default,
hoist_props : false,
hoist_props : !false_by_default,
hoist_vars : false,
ie8 : false,
if_return : !false_by_default,
@@ -341,7 +341,7 @@ merge(Compressor.prototype, {
}
}
}
mark_escaped(d, node, value, 0);
mark_escaped(d, node.scope, node, value, 0);
}
if (node instanceof AST_SymbolCatch) {
node.definition().fixed = false;
@@ -627,7 +627,8 @@ merge(Compressor.prototype, {
|| !immutable
&& parent instanceof AST_Call
&& parent.expression === node
&& (!(value instanceof AST_Function) || value.contains_this(parent))) {
&& (!(value instanceof AST_Function)
|| !(parent instanceof AST_New) && value.contains_this())) {
return true;
} else if (parent instanceof AST_Array) {
return is_modified(parent, parent, level + 1);
@@ -639,10 +640,13 @@ merge(Compressor.prototype, {
}
}
function mark_escaped(d, node, value, level) {
function mark_escaped(d, scope, node, value, level) {
var parent = tw.parent(level);
if (value instanceof AST_Constant || value instanceof AST_ClassExpression) return;
if (level > 0 && value instanceof AST_Function) return;
if (value) {
if (value.is_constant()) return;
if (value instanceof AST_ClassExpression) return;
if (level > 0 && value.is_constant_expression(scope)) 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
@@ -650,13 +654,13 @@ merge(Compressor.prototype, {
d.escaped = true;
return;
} else if (parent instanceof AST_Array) {
mark_escaped(d, parent, parent, level + 1);
mark_escaped(d, scope, 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);
mark_escaped(d, scope, 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);
mark_escaped(d, scope, parent, value, level + 1);
if (value) return;
}
if (level == 0) d.direct_access = true;
@@ -845,6 +849,12 @@ merge(Compressor.prototype, {
}
}
function is_identifier_atom(node) {
return node instanceof AST_Infinity
|| node instanceof AST_NaN
|| node instanceof AST_Undefined;
}
function tighten_body(statements, compressor) {
var CHANGED, max_iter = 10;
do {
@@ -911,7 +921,7 @@ merge(Compressor.prototype, {
&& !(node instanceof AST_SymbolDeclaration)
&& lhs.equivalent_to(node)) {
if (is_lhs(node, parent)) {
if (candidate.multiple) replaced++;
if (value_def) replaced++;
return node;
}
CHANGED = abort = true;
@@ -926,19 +936,24 @@ merge(Compressor.prototype, {
return make_node(AST_UnaryPrefix, candidate, candidate);
}
if (candidate instanceof AST_VarDef) {
if (candidate.multiple) {
if (value_def) {
abort = false;
return node;
}
var def = candidate.name.definition();
var value = candidate.value;
if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {
def.replaced++;
return maintain_this_binding(parent, node, candidate.value);
if (funarg && is_identifier_atom(value)) {
return value.transform(compressor);
} else {
return maintain_this_binding(parent, node, value);
}
}
return make_node(AST_Assign, candidate, {
operator: "=",
left: make_node(AST_SymbolRef, candidate.name, candidate.name),
right: candidate.value
right: value
});
}
candidate.write_only = false;
@@ -1000,18 +1015,20 @@ merge(Compressor.prototype, {
extract_candidates(statements[stat_index]);
while (candidates.length > 0) {
var candidate = candidates.pop();
var value_def = null;
var lhs = get_lhs(candidate);
if (!lhs || is_lhs_read_only(lhs) || lhs.has_side_effects(compressor)) continue;
// Locate symbols which may execute code outside of scanning range
var lvalues = get_lvalues(candidate);
if (lhs instanceof AST_SymbolRef) lvalues[lhs.name] = false;
var replace_all = candidate.multiple;
var replace_all = value_def;
if (!replace_all && lhs instanceof AST_SymbolRef) {
var def = lhs.definition();
replace_all = def.references.length - def.replaced == 1;
}
var side_effects = value_has_side_effects(candidate);
var hit = candidate.name instanceof AST_SymbolFunarg;
var funarg = candidate.name instanceof AST_SymbolFunarg;
var hit = funarg;
var abort = false, replaced = 0, can_replace = !args || !hit;
if (!can_replace) {
for (var j = compressor.self().argnames.lastIndexOf(candidate.name) + 1; !abort && j < args.length; j++) {
@@ -1022,13 +1039,12 @@ merge(Compressor.prototype, {
for (var i = stat_index; !abort && i < statements.length; i++) {
statements[i].transform(scanner);
}
if (candidate.multiple) {
if (value_def) {
var def = candidate.name.definition();
if (abort && def.references.length - def.replaced > replaced) replaced = false;
else {
abort = false;
hit = candidate.name instanceof AST_SymbolFunarg;
var value_def = candidate.value.definition();
hit = funarg;
for (var i = stat_index; !abort && i < statements.length; i++) {
statements[i].transform(multi_replacer);
}
@@ -1131,13 +1147,13 @@ merge(Compressor.prototype, {
}
}
function mangleable_var(expr) {
var value = expr.value;
if (!(value instanceof AST_SymbolRef)) return false;
if (value.name == "arguments") return false;
if (value.definition().undeclared) return false;
expr.multiple = true;
return true;
function mangleable_var(var_def) {
var value = var_def.value;
if (!(value instanceof AST_SymbolRef)) return;
if (value.name == "arguments") return;
var def = value.definition();
if (def.undeclared) return;
return value_def = def;
}
function get_lhs(expr) {
@@ -4062,9 +4078,7 @@ merge(Compressor.prototype, {
if (self.operator == "delete"
&& !(e instanceof AST_SymbolRef
|| e instanceof AST_PropAccess
|| e instanceof AST_NaN
|| e instanceof AST_Infinity
|| e instanceof AST_Undefined)) {
|| is_identifier_atom(e))) {
if (e instanceof AST_Sequence) {
e = e.expressions.slice();
e.push(make_node(AST_True, self));
@@ -4972,6 +4986,17 @@ merge(Compressor.prototype, {
if (compressor.option("properties")) {
var key = prop.evaluate(compressor);
if (key !== prop) {
if (typeof key == "string") {
if (key == "undefined") {
key = undefined;
} else {
var value = parseFloat(key);
if (value.toString() == key) {
key = value;
}
}
}
prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));
var property = "" + key;
if (is_identifier_string(property)
&& property.length <= prop.print_to_string().length + 1) {
@@ -4980,14 +5005,6 @@ merge(Compressor.prototype, {
property: property
}).optimize(compressor);
}
if (!(prop instanceof AST_Number)) {
var value = parseFloat(property);
if (value.toString() == property) {
prop = self.property = make_node(AST_Number, prop, {
value: value
});
}
}
}
}
if (is_lhs(self, compressor.parent())) return self;
@@ -5044,8 +5061,7 @@ merge(Compressor.prototype, {
return self;
});
AST_Lambda.DEFMETHOD("contains_this", function(grandparent) {
if (grandparent instanceof AST_New) return false;
AST_Lambda.DEFMETHOD("contains_this", function() {
var result;
var self = this;
self.walk(new TreeWalker(function(node) {
@@ -5071,7 +5087,8 @@ merge(Compressor.prototype, {
})) break;
var value = prop.value;
if ((value instanceof AST_Accessor || value instanceof AST_Function)
&& value.contains_this(compressor.parent())) break;
&& !(compressor.parent() instanceof AST_New)
&& value.contains_this()) break;
return make_node(AST_Sub, this, {
expression: make_node(AST_Array, expr, {
elements: props.map(function(prop) {