var exprs = extract_exprs(body);
if (!exprs) return;
var trimmed = false;
- for (var i = exprs.length - 1; --i >= 0;) {
+ for (var i = exprs.length; --i >= 0;) {
var expr = exprs[i];
- if (!(expr instanceof AST_Assign)) continue;
- if (expr.operator != "=") continue;
- if (!(expr.left instanceof AST_SymbolRef)) continue;
- var tail = exprs.slice(i + 1);
+ if (!can_trim(expr)) continue;
+ var tail;
+ if (expr.left instanceof AST_SymbolRef) {
+ tail = exprs.slice(i + 1);
+ } else if (expr.left instanceof AST_PropAccess && can_trim(expr.left.expression)) {
+ tail = exprs.slice(i + 1);
+ var flattened = expr.clone();
+ expr = expr.left.expression;
+ flattened.left = flattened.left.clone();
+ flattened.left.expression = expr.left.clone();
+ tail.unshift(flattened);
+ } else {
+ continue;
+ }
+ if (tail.length == 0) continue;
if (!trim_assigns(expr.left, expr.right, tail)) continue;
trimmed = true;
- exprs = exprs.slice(0, i + 1).concat(tail);
+ exprs = exprs.slice(0, i).concat(expr, tail);
}
if (defn instanceof AST_Definitions) {
keep = keep || 0;
if (defn instanceof AST_Var && join_var_assign(defn.definitions, exprs, keep)) trimmed = true;
}
return trimmed && exprs;
+
+ function can_trim(node) {
+ return node instanceof AST_Assign && node.operator == "=";
+ }
}
function merge_assigns(prev, defn) {
}
function trim_assigns(name, value, exprs) {
+ var names = Object.create(null);
+ names[name.name] = true;
+ while (value instanceof AST_Assign && value.operator == "=") {
+ if (value.left instanceof AST_SymbolRef) names[value.left.name] = true;
+ value = value.right;
+ }
if (!(value instanceof AST_Object)) return;
var trimmed = false;
do {
- var node = exprs[0];
- if (!(node instanceof AST_Assign)) break;
- if (node.operator != "=") break;
- if (!(node.left instanceof AST_PropAccess)) break;
+ if (!try_join(exprs[0])) break;
+ exprs.shift();
+ trimmed = true;
+ } while (exprs.length);
+ return trimmed;
+
+ function try_join(node) {
+ if (!(node instanceof AST_Assign)) return;
+ if (node.operator != "=") return;
+ if (!(node.left instanceof AST_PropAccess)) return;
var sym = node.left.expression;
- if (!(sym instanceof AST_SymbolRef)) break;
- if (name.name != sym.name) break;
- if (!node.right.is_constant_expression(scope)) break;
+ if (!(sym instanceof AST_SymbolRef)) return;
+ if (!names[sym.name]) return;
+ if (!node.right.is_constant_expression(scope)) return;
var prop = node.left.property;
if (prop instanceof AST_Node) {
+ if (try_join(prop)) prop = node.left.property = prop.right;
prop = prop.evaluate(compressor);
}
- if (prop instanceof AST_Node) break;
+ if (prop instanceof AST_Node) return;
prop = "" + prop;
var diff = prop == "__proto__" || compressor.has_directive("use strict") ? function(node) {
var key = node.key;
}
return key !== "__proto__";
};
- if (!all(value.properties, diff)) break;
+ if (!all(value.properties, diff)) return;
value.properties.push(make_node(AST_ObjectKeyVal, node, {
key: prop,
value: node.right
}));
- exprs.shift();
- trimmed = true;
- } while (exprs.length);
- return trimmed;
+ return true;
+ }
}
function join_consecutive_vars(statements) {