Better fix for equality of typeof ... against "undefined"
authorMihai Bazon <mihai@bazon.net>
Wed, 8 May 2013 13:22:39 +0000 (16:22 +0300)
committerMihai Bazon <mihai@bazon.net>
Wed, 8 May 2013 13:22:48 +0000 (16:22 +0300)
lib/compress.js
test/compress/issue-105.js

index c994a3a..c94af7d 100644 (file)
@@ -1726,8 +1726,8 @@ merge(Compressor.prototype, {
     var commutativeOperators = makePredicate("== === != !== * & | ^");
 
     OPT(AST_Binary, function(self, compressor){
-        function reverse(op) {
-            if (!(self.left.has_side_effects() || self.right.has_side_effects())) {
+        function reverse(op, force) {
+            if (force || !(self.left.has_side_effects() || self.right.has_side_effects())) {
                 if (op) self.operator = op;
                 var tmp = self.left;
                 self.left = self.right;
@@ -1737,7 +1737,10 @@ merge(Compressor.prototype, {
         if (commutativeOperators(self.operator)) {
             if (self.right instanceof AST_Constant
                 && !(self.left instanceof AST_Constant)) {
-                reverse();
+                // if right is a constant, whatever side effects the
+                // left side might have could not influence the
+                // result.  hence, force switch.
+                reverse(null, true);
             }
         }
         self = self.lift_sequences(compressor);
@@ -1751,15 +1754,15 @@ merge(Compressor.prototype, {
             // XXX: intentionally falling down to the next case
           case "==":
           case "!=":
-            if (compressor.option("unsafe")
-                && self.left instanceof AST_UnaryPrefix
-                && self.left.operator == "typeof"
-                && self.right instanceof AST_String
-                && self.right.value == "undefined") {
-                if (!(self.left.expression instanceof AST_SymbolRef)
-                    || !self.left.expression.undeclared()) {
-                    self.left = self.left.expression;
-                    self.right = make_node(AST_Undefined, self.left).optimize(compressor);
+            if (self.left instanceof AST_String
+                && self.left.value == "undefined"
+                && self.right instanceof AST_UnaryPrefix
+                && self.right.operator == "typeof"
+                && compressor.option("unsafe")) {
+                if (!(self.right.expression instanceof AST_SymbolRef)
+                    || !self.right.expression.undeclared()) {
+                    self.right = self.right.expression;
+                    self.left = make_node(AST_Undefined, self.left).optimize(compressor);
                     if (self.operator.length == 2) self.operator += "=";
                 }
             }
index 0c37eb8..ca17adb 100644 (file)
@@ -3,7 +3,7 @@ typeof_eq_undefined: {
         comparisons: true
     };
     input: { a = typeof b.c != "undefined" }
-    expect: { a = typeof b.c != "undefined" }
+    expect: { a = "undefined" != typeof b.c }
 }
 
 typeof_eq_undefined_unsafe: {
@@ -12,5 +12,14 @@ typeof_eq_undefined_unsafe: {
         unsafe: true
     };
     input: { a = typeof b.c != "undefined" }
-    expect: { a = b.c !== void 0 }
+    expect: { a = void 0 !== b.c }
+}
+
+typeof_eq_undefined_unsafe2: {
+    options = {
+        comparisons: true,
+        unsafe: true
+    };
+    input: { a = "undefined" != typeof b.c }
+    expect: { a = void 0 !== b.c }
 }