enhance `if_return` (#3232)
authorAlex Lam S.L <alexlamsl@gmail.com>
Tue, 21 Aug 2018 10:34:16 +0000 (18:34 +0800)
committerGitHub <noreply@github.com>
Tue, 21 Aug 2018 10:34:16 +0000 (18:34 +0800)
lib/compress.js
test/compress/if_return.js

index 9b6e336..eded00c 100644 (file)
@@ -1699,6 +1699,19 @@ merge(Compressor.prototype, {
                         continue;
                     }
 
+                    if (ab && !stat.alternative && stat.body instanceof AST_BlockStatement && next instanceof AST_Jump) {
+                        var negated = stat.condition.negate(compressor);
+                        if (negated.print_to_string().length <= stat.condition.print_to_string().length) {
+                            CHANGED = true;
+                            stat = stat.clone();
+                            stat.condition = negated;
+                            statements[j] = stat.body;
+                            stat.body = next;
+                            statements[i] = stat.transform(compressor);
+                            continue;
+                        }
+                    }
+
                     var ab = aborts(stat.alternative);
                     if (can_merge_flow(ab)) {
                         if (ab.label) {
index c56fa04..857406d 100644 (file)
@@ -396,3 +396,151 @@ if_if_return_return: {
         }
     }
 }
+
+if_body_return_1: {
+    options = {
+        if_return: true,
+    }
+    input: {
+        var c = "PASS";
+        function f(a, b) {
+            if (a) {
+                if (b) throw new Error(c);
+                return 42;
+            }
+            return true;
+        }
+        console.log(f(0, 0));
+        console.log(f(0, 1));
+        console.log(f(1, 0));
+        try {
+            f(1, 1);
+            console.log("FAIL");
+        } catch (e) {
+            console.log(e.message);
+        }
+    }
+    expect: {
+        var c = "PASS";
+        function f(a, b) {
+            if (a) {
+                if (b) throw new Error(c);
+                return 42;
+            }
+            return true;
+        }
+        console.log(f(0, 0));
+        console.log(f(0, 1));
+        console.log(f(1, 0));
+        try {
+            f(1, 1);
+            console.log("FAIL");
+        } catch (e) {
+            console.log(e.message);
+        }
+    }
+    expect_stdout: [
+        "true",
+        "true",
+        "42",
+        "PASS",
+    ]
+}
+
+if_body_return_2: {
+    options = {
+        if_return: true,
+    }
+    input: {
+        var c = "PASS";
+        function f(a, b) {
+            if (0 + a) {
+                if (b) throw new Error(c);
+                return 42;
+            }
+            return true;
+        }
+        console.log(f(0, 0));
+        console.log(f(0, 1));
+        console.log(f(1, 0));
+        try {
+            f(1, 1);
+            console.log("FAIL");
+        } catch (e) {
+            console.log(e.message);
+        }
+    }
+    expect: {
+        var c = "PASS";
+        function f(a, b) {
+            if (0 + a) {
+                if (b) throw new Error(c);
+                return 42;
+            }
+            return true;
+        }
+        console.log(f(0, 0));
+        console.log(f(0, 1));
+        console.log(f(1, 0));
+        try {
+            f(1, 1);
+            console.log("FAIL");
+        } catch (e) {
+            console.log(e.message);
+        }
+    }
+    expect_stdout: [
+        "true",
+        "true",
+        "42",
+        "PASS",
+    ]
+}
+
+if_body_return_3: {
+    options = {
+        if_return: true,
+    }
+    input: {
+        var c = "PASS";
+        function f(a, b) {
+            if (1 == a) {
+                if (b) throw new Error(c);
+                return 42;
+            }
+            return true;
+        }
+        console.log(f(0, 0));
+        console.log(f(0, 1));
+        console.log(f(1, 0));
+        try {
+            f(1, 1);
+            console.log("FAIL");
+        } catch (e) {
+            console.log(e.message);
+        }
+    }
+    expect: {
+        var c = "PASS";
+        function f(a, b) {
+            if (1 != a) return true;
+            if (b) throw new Error(c);
+            return 42;
+        }
+        console.log(f(0, 0));
+        console.log(f(0, 1));
+        console.log(f(1, 0));
+        try {
+            f(1, 1);
+            console.log("FAIL");
+        } catch (e) {
+            console.log(e.message);
+        }
+    }
+    expect_stdout: [
+        "true",
+        "true",
+        "42",
+        "PASS",
+    ]
+}