aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compress.js109
1 files changed, 35 insertions, 74 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 004858ac..6e984ffa 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -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){