diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-04-07 03:42:17 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-07 03:42:17 +0800 |
commit | cc6aa3e5ac13c0da9f2481181f5b4f11275ca8c8 (patch) | |
tree | b0876f76806180f7d14a824312944cee61482718 /lib/compress.js | |
parent | e869779a988b519487da0d6e2bd8e4849cd6d9f1 (diff) | |
download | tracifyjs-cc6aa3e5ac13c0da9f2481181f5b4f11275ca8c8.tar.gz tracifyjs-cc6aa3e5ac13c0da9f2481181f5b4f11275ca8c8.zip |
fix incorrect context in variable substitution (#1791)
`AST_Node.optimize()` is context-aware, so don't cache its results to be used elsewhere.
Also fixed a few cases of AST corruption and beef up safety of `pure_getters`.
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/lib/compress.js b/lib/compress.js index 22c79b81..de3b4db2 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -283,10 +283,16 @@ merge(Compressor.prototype, { if (node instanceof AST_VarDef) { var d = node.name.definition(); if (d.fixed == null) { - d.fixed = node.value && function() { - return node.value; - }; + if (node.value) { + d.fixed = function() { + return node.value; + }; + descend(); + } else { + d.fixed = null; + } mark_as_safe(d); + return true; } else if (node.value) { d.fixed = false; } @@ -1160,13 +1166,42 @@ merge(Compressor.prototype, { && !node.expression.has_side_effects(compressor); } + // may_eq_null() + // returns true if this node may evaluate to null or undefined (function(def) { - def(AST_Node, return_false); + def(AST_Node, return_true); def(AST_Null, return_true); def(AST_Undefined, return_true); + def(AST_Constant, return_false); + def(AST_Array, return_false); + def(AST_Object, return_false); + def(AST_Function, return_false); + def(AST_UnaryPostfix, return_false); def(AST_UnaryPrefix, function() { return this.operator == "void"; }); + def(AST_Binary, function(compressor) { + switch (this.operator) { + case "&&": + return this.left.may_eq_null(compressor); + case "||": + return this.left.may_eq_null(compressor) + && this.right.may_eq_null(compressor); + default: + return false; + } + }) + def(AST_Assign, function(compressor) { + return this.operator == "=" + && this.right.may_eq_null(compressor); + }) + def(AST_Conditional, function(compressor) { + return this.consequent.may_eq_null(compressor) + || this.alternative.may_eq_null(compressor); + }) + def(AST_Seq, function(compressor) { + return this.cdr.may_eq_null(compressor); + }); def(AST_PropAccess, function(compressor) { return !compressor.option("unsafe"); }); @@ -3055,8 +3090,9 @@ merge(Compressor.prototype, { if (this.expression instanceof AST_Seq) { var seq = this.expression; var x = seq.to_array(); - this.expression = x.pop(); - x.push(this); + var e = this.clone(); + e.expression = x.pop(); + x.push(e); seq = AST_Seq.from_array(x).transform(compressor); return seq; } @@ -3110,9 +3146,14 @@ merge(Compressor.prototype, { if (e instanceof AST_Binary && (self.operator == "+" || self.operator == "-") && (e.operator == "*" || e.operator == "/" || e.operator == "%")) { - self.expression = e.left; - e.left = self; - return e; + return make_node(AST_Binary, self, { + operator: e.operator, + left: make_node(AST_UnaryPrefix, e.left, { + operator: self.operator, + expression: e.left + }), + right: e.right + }); } // avoids infinite recursion of numerals if (self.operator != "-" @@ -3131,23 +3172,25 @@ merge(Compressor.prototype, { if (this.left instanceof AST_Seq) { var seq = this.left; var x = seq.to_array(); - this.left = x.pop(); - x.push(this); + var e = this.clone(); + e.left = x.pop(); + x.push(e); return AST_Seq.from_array(x).optimize(compressor); } if (this.right instanceof AST_Seq && !this.left.has_side_effects(compressor)) { var assign = this.operator == "=" && this.left instanceof AST_SymbolRef; - var root = this.right; + var root = this.right.clone(); var cursor, seq = root; while (assign || !seq.car.has_side_effects(compressor)) { cursor = seq; if (seq.cdr instanceof AST_Seq) { - seq = seq.cdr; + seq = seq.cdr = seq.cdr.clone(); } else break; } if (cursor) { - this.right = cursor.cdr; - cursor.cdr = this; + var e = this.clone(); + e.right = cursor.cdr; + cursor.cdr = e; return root.optimize(compressor); } } @@ -3547,9 +3590,8 @@ merge(Compressor.prototype, { if (d.should_replace === undefined) { var init = fixed.evaluate(compressor); if (init !== fixed) { - init = make_node_from_constant(init, fixed).optimize(compressor); - init = best_of_expression(init, fixed); - var value = init.print_to_string().length; + init = make_node_from_constant(init, fixed); + var value = best_of_expression(init.optimize(compressor), fixed).print_to_string().length; var name = d.name.length; var freq = d.references.length; var overhead = d.global || !freq ? 0 : (name + 2 + value) / freq; @@ -3559,7 +3601,7 @@ merge(Compressor.prototype, { } } if (d.should_replace) { - return d.should_replace.clone(true); + return best_of_expression(d.should_replace.optimize(compressor), fixed).clone(true); } } } |