enhance `if_return` (#3560)
authorAlex Lam S.L <alexlamsl@gmail.com>
Thu, 31 Oct 2019 18:08:31 +0000 (02:08 +0800)
committerGitHub <noreply@github.com>
Thu, 31 Oct 2019 18:08:31 +0000 (02:08 +0800)
lib/compress.js
test/compress/typeof.js

index 65768c0..0321a53 100644 (file)
@@ -1749,9 +1749,7 @@ merge(Compressor.prototype, {
                 if (stat instanceof AST_If) {
                     var ab = aborts(stat.body);
                     if (can_merge_flow(ab)) {
-                        if (ab.label) {
-                            remove(ab.label.thedef.references, ab);
-                        }
+                        if (ab.label) remove(ab.label.thedef.references, ab);
                         CHANGED = true;
                         stat = stat.clone();
                         stat.condition = stat.condition.negate(compressor);
@@ -1779,23 +1777,34 @@ merge(Compressor.prototype, {
                         }
                     }
 
-                    var ab = aborts(stat.alternative);
-                    if (can_merge_flow(ab)) {
-                        if (ab.label) {
-                            remove(ab.label.thedef.references, ab);
-                        }
+                    var alt = aborts(stat.alternative);
+                    if (can_merge_flow(alt)) {
+                        if (alt.label) remove(alt.label.thedef.references, alt);
                         CHANGED = true;
                         stat = stat.clone();
                         stat.body = make_node(AST_BlockStatement, stat.body, {
                             body: as_statement_array(stat.body).concat(extract_functions())
                         });
-                        var body = as_statement_array_with_return(stat.alternative, ab);
+                        var body = as_statement_array_with_return(stat.alternative, alt);
                         stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
                             body: body
                         });
                         statements[i] = stat.transform(compressor);
                         continue;
                     }
+
+                    if (compressor.option("typeofs")) {
+                        if (ab && !alt) {
+                            mark_locally_defined(stat.condition, null, make_node(AST_BlockStatement, self, {
+                                body: statements.slice(i + 1)
+                            }));
+                        }
+                        if (!ab && alt) {
+                            mark_locally_defined(stat.condition, make_node(AST_BlockStatement, self, {
+                                body: statements.slice(i + 1)
+                            }));
+                        }
+                    }
                 }
 
                 if (stat instanceof AST_If && stat.body instanceof AST_Return) {
@@ -1940,9 +1949,7 @@ merge(Compressor.prototype, {
                             && loop_body(lct) === self
                         || stat instanceof AST_Continue
                             && loop_body(lct) === self) {
-                        if (stat.label) {
-                            remove(stat.label.thedef.references, stat);
-                        }
+                        if (stat.label) remove(stat.label.thedef.references, stat);
                     } else {
                         statements[n++] = stat;
                     }
index c3c2e9e..3b99521 100644 (file)
@@ -409,3 +409,31 @@ typeof_defined_4: {
         "object" != typeof A || "object" == typeof B || B;
     }
 }
+
+emberjs_global: {
+    options = {
+        comparisons: true,
+        conditionals: true,
+        if_return: true,
+        passes: 2,
+        side_effects: true,
+        toplevel: true,
+        typeofs: true,
+        unused: true,
+    }
+    input: {
+        var a;
+        if (typeof A === "object") {
+            a = A;
+        } else if (typeof B === "object") {
+            a = B;
+        } else {
+            throw new Error("PASS");
+        }
+    }
+    expect: {
+        if ("object" != typeof A && "object" != typeof B)
+            throw new Error("PASS");
+    }
+    expect_stdout: Error("PASS")
+}