diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/compress.js | 106 |
1 files changed, 54 insertions, 52 deletions
diff --git a/lib/compress.js b/lib/compress.js index f3fc5e0e..17b3ecf7 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -384,10 +384,10 @@ merge(Compressor.prototype, { reset_def(tw, compressor, def); if (def.fixed === null) { def.safe_ids = tw.safe_ids; - mark(tw, def, true); + mark(tw, def); } else if (def.fixed) { tw.loop_ids[def.id] = tw.in_loop; - mark(tw, def, true); + mark(tw, def); } }); scope.may_call_this = function() { @@ -446,8 +446,8 @@ merge(Compressor.prototype, { tw.safe_ids = Object.getPrototypeOf(tw.safe_ids); } - function mark(tw, def, safe) { - tw.safe_ids[def.id] = safe && {}; + function mark(tw, def) { + tw.safe_ids[def.id] = {}; } function push_ref(def, ref) { @@ -459,10 +459,11 @@ merge(Compressor.prototype, { if (def.single_use == "m") return false; var safe = tw.safe_ids[def.id]; if (safe) { - if (!HOP(tw.safe_ids, def.id)) safe.read = safe.read ? true : tw.safe_ids; + if (!HOP(tw.safe_ids, def.id)) safe.read = safe.read && safe.read !== tw.safe_ids ? true : tw.safe_ids; if (def.fixed == null) { if (is_arguments(def)) return false; if (def.global && def.name == "arguments") return false; + tw.loop_ids[def.id] = null; def.fixed = make_node(AST_Undefined, def.orig[0]); return true; } @@ -478,20 +479,23 @@ merge(Compressor.prototype, { delete def.safe_ids; return true; } + if (def.fixed === false) return false; var safe = tw.safe_ids[def.id]; if (!HOP(tw.safe_ids, def.id)) { if (!safe) return false; - safe.assign = safe.assign ? true : tw.safe_ids; + if (safe.read && def.scope !== tw.find_parent(AST_Scope)) return false; + safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids; } - if (!safe_to_read(tw, def)) return false; - if (def.fixed === false) return false; - if (def.fixed != null && safe.read && safe.read !== tw.safe_ids) return false; - return all(def.orig, function(sym) { + if (def.fixed != null && safe.read) { + if (safe.read !== tw.safe_ids) return false; + if (tw.loop_ids[def.id] !== tw.in_loop) return false; + } + return safe_to_read(tw, def) && all(def.orig, function(sym) { return !(sym instanceof AST_SymbolLambda); }); } - function ref_once(tw, compressor, def) { + function ref_once(compressor, def) { return compressor.option("unused") && !def.scope.pinned() && def.references.length - def.recursive_refs == 1; @@ -568,22 +572,17 @@ merge(Compressor.prototype, { } var d = sym.definition(); d.assignments++; + var fixed = d.fixed; var eq = node.operator == "="; var value = eq ? node.right : node; if (is_modified(compressor, tw, node, value, 0)) return; - var safe = (eq || safe_to_read(tw, d)) && safe_to_assign(tw, d); - var fixed = d.fixed; - if (safe) { + node.right.walk(tw); + if ((eq || safe_to_read(tw, d)) && safe_to_assign(tw, d)) { push_ref(d, sym); - mark(tw, d, false); - node.right.walk(tw); - mark(tw, d, true); - if (eq) mark_escaped(tw, d, sym.scope, node, value, 0, 1); - } else { - descend(); - } - if (fixed !== false && d.fixed !== false) { + mark(tw, d); if (eq) { + tw.loop_ids[d.id] = tw.in_loop; + mark_escaped(tw, d, sym.scope, node, value, 0, 1); sym.fixed = d.fixed = function() { return node.right; }; @@ -600,6 +599,9 @@ merge(Compressor.prototype, { } sym.fixed.assigns = eq || !fixed.assigns ? [] : fixed.assigns.slice(); sym.fixed.assigns.push(node); + } else { + sym.walk(tw); + d.fixed = false; } return true; }); @@ -739,7 +741,7 @@ merge(Compressor.prototype, { var d = arg.definition(); if (d.fixed === undefined && (!fn.uses_arguments || tw.has_directive("use strict"))) { tw.loop_ids[d.id] = tw.in_loop; - mark(tw, d, true); + mark(tw, d); var value = iife.args[i]; d.fixed = function() { var j = fn.argnames.indexOf(arg); @@ -800,7 +802,7 @@ merge(Compressor.prototype, { var recursive = recursive_ref(tw, d); if (recursive) { d.recursive_refs++; - } else if (value && ref_once(tw, compressor, d)) { + } else if (value && ref_once(compressor, d)) { d.in_loop = tw.loop_ids[d.id] !== tw.in_loop; d.single_use = value instanceof AST_Lambda && !value.pinned() @@ -864,15 +866,10 @@ merge(Compressor.prototype, { } var d = exp.definition(); d.assignments++; - var safe = safe_to_read(tw, d) && safe_to_assign(tw, d); var fixed = d.fixed; - if (safe) { + if (safe_to_read(tw, d) && safe_to_assign(tw, d)) { push_ref(d, exp); - mark(tw, d, true); - } else { - descend(); - } - if (fixed !== false && d.fixed !== false) { + mark(tw, d); if (fixed == null) fixed = make_node(AST_Undefined, d.orig[0]); d.fixed = function() { var value = fixed instanceof AST_Node ? fixed : fixed(); @@ -901,29 +898,28 @@ merge(Compressor.prototype, { }; exp.fixed.assigns = fixed.assigns; } + } else { + exp.walk(tw); + d.fixed = false; } return true; }); def(AST_VarDef, function(tw, descend) { var node = this; + if (!node.value) return; + descend(); var d = node.name.definition(); - if (node.value) { - if (safe_to_assign(tw, d)) { - tw.loop_ids[d.id] = tw.in_loop; - mark(tw, d, false); - descend(); - mark(tw, d, true); - if (d.fixed !== false) { - d.fixed = function() { - return node.value; - }; - d.fixed.assigns = [ node ]; - } - return true; - } else { - d.fixed = false; - } + if (safe_to_assign(tw, d)) { + mark(tw, d); + tw.loop_ids[d.id] = tw.in_loop; + d.fixed = function() { + return node.value; + }; + d.fixed.assigns = [ node ]; + } else { + d.fixed = false; } + return true; }); def(AST_While, function(tw, descend) { var saved_loop = tw.in_loop; @@ -4710,7 +4706,7 @@ merge(Compressor.prototype, { } } } - track_assigns(node_def, sym); + if (track_assigns(node_def, sym) && is_lhs(sym, node) !== sym) add_assigns(node_def, sym); return true; } if (node instanceof AST_SymbolRef) { @@ -7885,16 +7881,22 @@ merge(Compressor.prototype, { && self.right.left.name == self.left.name && ASSIGN_OPS[self.right.operator]) { // x = x - 2 => x -= 2 - self.operator = self.right.operator + "="; - self.right = self.right.right; + return make_node(AST_Assign, self, { + operator: self.right.operator + "=", + left: self.left, + right: self.right.right, + }).optimize(compressor); } else if (self.right.right instanceof AST_SymbolRef && self.right.right.name == self.left.name && ASSIGN_OPS_COMMUTATIVE[self.right.operator] && !self.right.left.has_side_effects(compressor)) { // x = 2 & x => x &= 2 - self.operator = self.right.operator + "="; - self.right = self.right.left; + return make_node(AST_Assign, self, { + operator: self.right.operator + "=", + left: self.left, + right: self.right.left, + }).optimize(compressor); } } if ((self.operator == "-=" || self.operator == "+=" |