diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-04-06 11:18:59 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-06 11:18:59 +0800 |
commit | 06cdb74279d01ed9b4b625200882611482333825 (patch) | |
tree | 7d6c5fb4cdedf4bf07ebe88897a887429e76c061 /lib/compress.js | |
parent | ff289b90a92739641dcb7fc7f6c8ecf8ee74d15f (diff) | |
download | tracifyjs-06cdb74279d01ed9b4b625200882611482333825.tar.gz tracifyjs-06cdb74279d01ed9b4b625200882611482333825.zip |
improve `pure_getters` (#1786)
- property access to `null` & `undefined` always has side effects
- utilise `reduce_vars` to determine safe property access
- may-be cases treated as side effects unless `unsafe`
Diffstat (limited to 'lib/compress.js')
-rw-r--r-- | lib/compress.js | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/lib/compress.js b/lib/compress.js index ef7f0441..22c79b81 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1160,6 +1160,26 @@ merge(Compressor.prototype, { && !node.expression.has_side_effects(compressor); } + (function(def) { + def(AST_Node, return_false); + def(AST_Null, return_true); + def(AST_Undefined, return_true); + def(AST_UnaryPrefix, function() { + return this.operator == "void"; + }); + def(AST_PropAccess, function(compressor) { + return !compressor.option("unsafe"); + }); + def(AST_SymbolRef, function(compressor) { + if (this.is_undefined) return true; + if (compressor.option("unsafe")) return false; + var fixed = this.fixed_value(); + return !fixed || fixed.may_eq_null(compressor); + }); + })(function(node, func) { + node.DEFMETHOD("may_eq_null", func); + }); + /* -----[ boolean/negation helpers ]----- */ // methods to determine whether an expression has a boolean result type @@ -1688,7 +1708,7 @@ merge(Compressor.prototype, { || this.expression.has_side_effects(compressor); }); def(AST_SymbolRef, function(compressor){ - return this.global() && this.undeclared(); + return this.undeclared(); }); def(AST_Object, function(compressor){ return any(this.properties, compressor); @@ -1701,16 +1721,15 @@ merge(Compressor.prototype, { }); def(AST_Dot, function(compressor){ if (!compressor.option("pure_getters")) return true; - return this.expression.has_side_effects(compressor); + return this.expression.may_eq_null(compressor) + || this.expression.has_side_effects(compressor); }); def(AST_Sub, function(compressor){ if (!compressor.option("pure_getters")) return true; - return this.expression.has_side_effects(compressor) + return this.expression.may_eq_null(compressor) + || this.expression.has_side_effects(compressor) || this.property.has_side_effects(compressor); }); - def(AST_PropAccess, function(compressor){ - return !compressor.option("pure_getters"); - }); def(AST_Seq, function(compressor){ return this.car.has_side_effects(compressor) || this.cdr.has_side_effects(compressor); @@ -2275,10 +2294,12 @@ merge(Compressor.prototype, { }); def(AST_Dot, function(compressor, first_in_statement){ if (!compressor.option("pure_getters")) return this; + if (this.expression.may_eq_null(compressor)) return this; return this.expression.drop_side_effect_free(compressor, first_in_statement); }); def(AST_Sub, function(compressor, first_in_statement){ if (!compressor.option("pure_getters")) return this; + if (this.expression.may_eq_null(compressor)) return this; var expression = this.expression.drop_side_effect_free(compressor, first_in_statement); if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement); var property = this.property.drop_side_effect_free(compressor); @@ -3509,7 +3530,6 @@ merge(Compressor.prototype, { // testing against !self.scope.uses_with first is an optimization if (compressor.option("screw_ie8") && self.undeclared() - && !isLHS(self, compressor.parent()) && (!self.scope.uses_with || !compressor.find_parent(AST_With))) { switch (self.name) { case "undefined": |