Account for side effects in `string + expr` optimization
authorkzc <zaxxon2011@gmail.com>
Thu, 1 Sep 2016 13:24:56 +0000 (09:24 -0400)
committerkzc <zaxxon2011@gmail.com>
Thu, 1 Sep 2016 13:24:56 +0000 (09:24 -0400)
lib/compress.js
test/compress/issue-1275.js [new file with mode: 0644]

index 8f786d7..8a08572 100644 (file)
@@ -2499,8 +2499,8 @@ merge(Compressor.prototype, {
           case "+":
             var ll = self.left.evaluate(compressor);
             var rr = self.right.evaluate(compressor);
-            if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) ||
-                (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) {
+            if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1] && !self.right.has_side_effects(compressor)) ||
+                (rr.length > 1 && rr[0] instanceof AST_String && rr[1] && !self.left.has_side_effects(compressor))) {
                 compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
                 return make_node(AST_True, self);
             }
diff --git a/test/compress/issue-1275.js b/test/compress/issue-1275.js
new file mode 100644 (file)
index 0000000..e88e284
--- /dev/null
@@ -0,0 +1,49 @@
+string_plus_optimization: {
+    options = {
+        side_effects  : true,
+        evaluate      : true,
+        conditionals  : true,
+        comparisons   : true,
+        dead_code     : true,
+        booleans      : true,
+        unused        : true,
+        if_return     : true,
+        join_vars     : true,
+        cascade       : true,
+        hoist_funs    : true,
+    };
+    input: {
+        function foo(anything) {
+            function throwing_function() {
+                throw "nope";
+            }
+            try {
+                console.log('0' + throwing_function() ? "yes" : "no");
+            } catch (ex) {
+                console.log(ex);
+            }
+            console.log('0' + anything ? "yes" : "no");
+            console.log(anything + '0' ? "Yes" : "No");
+            console.log('' + anything);
+            console.log(anything + '');
+        }
+        foo();
+    }
+    expect: {
+        function foo(anything) {
+            function throwing_function() {
+                throw "nope";
+            }
+            try {
+                console.log('0' + throwing_function() ? "yes" : "no");
+            } catch (ex) {
+                console.log(ex);
+            }
+            console.log("yes");
+            console.log("Yes");
+            console.log('' + anything);
+            console.log(anything + '');
+        }
+        foo();
+    }
+}