fold cascade functionality into collapse_vars (#2586)

This commit is contained in:
Alex Lam S.L
2017-12-14 01:20:36 +08:00
committed by GitHub
parent 7f418978c9
commit ef618332ea
23 changed files with 269 additions and 207 deletions

View File

@@ -49,7 +49,6 @@ function Compressor(options, false_by_default) {
TreeTransformer.call(this, this.before, this.after);
this.options = defaults(options, {
booleans : !false_by_default,
cascade : !false_by_default,
collapse_vars : !false_by_default,
comparisons : !false_by_default,
conditionals : !false_by_default,
@@ -884,6 +883,8 @@ merge(Compressor.prototype, {
if (!hit) {
if (node === candidate) {
hit = true;
stop_after = find_stop(node, 0);
if (stop_after === node) abort = true;
return node;
}
return;
@@ -963,12 +964,13 @@ merge(Compressor.prototype, {
&& (parent instanceof AST_Binary && lazy_op(parent.operator)
|| parent instanceof AST_Conditional
|| parent instanceof AST_If)) {
if (!(node instanceof AST_Scope)) descend(node, scanner);
abort = true;
return node;
stop_after = node;
if (node instanceof AST_Scope) abort = true;
}
// Skip (non-executed) functions
if (node instanceof AST_Scope) return node;
}, function(node) {
if (!abort && stop_after === node) abort = true;
});
var multi_replacer = new TreeTransformer(function(node) {
if (abort) return node;
@@ -1003,6 +1005,7 @@ merge(Compressor.prototype, {
while (candidates.length > 0) {
var candidate = candidates.pop();
var value_def = null;
var stop_after = 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
@@ -1094,19 +1097,43 @@ merge(Compressor.prototype, {
if (expr instanceof AST_Assign && !expr.left.has_side_effects(compressor)
|| expr instanceof AST_Unary && (expr.operator == "++" || expr.operator == "--")) {
candidates.push(expr);
} else if (expr instanceof AST_Sequence) {
expr.expressions.forEach(extract_candidates);
} else if (expr instanceof AST_Case) {
extract_candidates(expr.expression);
} else if (expr instanceof AST_Conditional) {
extract_candidates(expr.condition);
extract_candidates(expr.consequent);
extract_candidates(expr.alternative);
} else if (expr instanceof AST_Definitions) {
expr.definitions.forEach(function(var_def) {
if (var_def.value) candidates.push(var_def);
});
} else if (expr instanceof AST_Exit) {
if (expr.value) extract_candidates(expr.value);
} else if (expr instanceof AST_For) {
if (expr.init) extract_candidates(expr.init);
} else if (expr instanceof AST_If) {
extract_candidates(expr.condition);
} else if (expr instanceof AST_Sequence) {
expr.expressions.forEach(extract_candidates);
} else if (expr instanceof AST_SimpleStatement) {
extract_candidates(expr.body);
} else if (expr instanceof AST_For && expr.init) {
extract_candidates(expr.init);
} else if (expr instanceof AST_Switch) {
extract_candidates(expr.expression);
expr.body.forEach(extract_candidates);
}
}
function find_stop(node, level) {
var parent = scanner.parent(level);
if (parent instanceof AST_Case) return node;
if (parent instanceof AST_Conditional) return node;
if (parent instanceof AST_Exit) return node;
if (parent instanceof AST_If) return node;
if (parent instanceof AST_Sequence) return find_stop(parent, level + 1);
if (parent instanceof AST_Switch) return node;
return null;
}
function mangleable_var(var_def) {
var value = var_def.value;
if (!(value instanceof AST_SymbolRef)) return;
@@ -3898,7 +3925,6 @@ merge(Compressor.prototype, {
filter_for_side_effects();
var end = expressions.length - 1;
trim_right_for_undefined();
if (end > 0 && compressor.option("cascade")) trim_left_for_assignment();
if (end == 0) {
self = maintain_this_binding(compressor.parent(), compressor.self(), expressions[0]);
if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);
@@ -3929,71 +3955,6 @@ merge(Compressor.prototype, {
expressions.length = end + 1;
}
}
function trim_left_for_assignment() {
for (var i = 0, j = 1; j <= end; j++) {
var left = expressions[i];
var cdr = expressions[j];
if (left instanceof AST_Assign
&& !left.left.has_side_effects(compressor)) {
left = left.left;
} else if (left instanceof AST_Unary
&& (left.operator == "++" || left.operator == "--")) {
left = left.expression;
} else left = null;
if (!left || is_lhs_read_only(left) || left.has_side_effects(compressor)) {
expressions[++i] = cdr;
continue;
}
var parent = null, field;
expressions[j] = cdr = cdr.clone();
while (true) {
if (cdr.equivalent_to(left)) {
var car = expressions[i];
if (car instanceof AST_UnaryPostfix) {
car = make_node(AST_UnaryPrefix, car, {
operator: car.operator,
expression: left
});
} else {
car.write_only = false;
}
if (parent) {
parent[field] = car;
expressions[i] = expressions[j];
} else {
expressions[i] = car;
}
break;
}
if (cdr instanceof AST_Binary && !(cdr instanceof AST_Assign)) {
if (cdr.left.is_constant()) {
if (lazy_op(cdr.operator)) {
expressions[++i] = expressions[j];
break;
}
field = "right";
} else {
field = "left";
}
} else if (cdr instanceof AST_Call
&& !(left instanceof AST_PropAccess && cdr.expression.equivalent_to(left))
|| cdr instanceof AST_PropAccess
|| cdr instanceof AST_Unary && !unary_side_effects(cdr.operator)) {
field = "expression";
} else if (cdr instanceof AST_Conditional) {
field = "condition";
} else {
expressions[++i] = expressions[j];
break;
}
parent = cdr;
cdr = cdr[field] = cdr[field].clone();
}
}
end = i;
expressions.length = end + 1;
}
});
AST_Unary.DEFMETHOD("lift_sequences", function(compressor){