better fix for #512 & #2010 (#2019)
authorAlex Lam S.L <alexlamsl@gmail.com>
Mon, 29 May 2017 02:51:41 +0000 (10:51 +0800)
committerGitHub <noreply@github.com>
Mon, 29 May 2017 02:51:41 +0000 (10:51 +0800)
- remove duplicated functionalities
- fix similar issue with `else`

lib/compress.js
test/compress/if_return.js
test/compress/issue-1052.js

index 6359696..374d14d 100644 (file)
@@ -924,6 +924,45 @@ merge(Compressor.prototype, {
                     // step.  nevertheless, it's good to check.
                     continue loop;
                   case stat instanceof AST_If:
+                    var ab = aborts(stat.body);
+                    if (can_merge_flow(ab)) {
+                        if (ab.label) {
+                            remove(ab.label.thedef.references, ab);
+                        }
+                        CHANGED = true;
+                        var funs = extract_functions_from_statement_array(ret);
+                        var body = as_statement_array_with_return(stat.body, ab);
+                        stat = stat.clone();
+                        stat.condition = stat.condition.negate(compressor);
+                        stat.body = make_node(AST_BlockStatement, stat, {
+                            body: as_statement_array(stat.alternative).concat(ret)
+                        });
+                        stat.alternative = make_node(AST_BlockStatement, stat, {
+                            body: body
+                        });
+                        ret = [ stat.transform(compressor) ].concat(funs);
+                        continue loop;
+                    }
+
+                    var ab = aborts(stat.alternative);
+                    if (can_merge_flow(ab)) {
+                        if (ab.label) {
+                            remove(ab.label.thedef.references, ab);
+                        }
+                        CHANGED = true;
+                        var funs = extract_functions_from_statement_array(ret);
+                        stat = stat.clone();
+                        stat.body = make_node(AST_BlockStatement, stat.body, {
+                            body: as_statement_array(stat.body).concat(ret)
+                        });
+                        var body = as_statement_array_with_return(stat.alternative, ab);
+                        stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
+                            body: body
+                        });
+                        ret = [ stat.transform(compressor) ].concat(funs);
+                        continue loop;
+                    }
+
                     if (stat.body instanceof AST_Return) {
                         var value = stat.body.value;
                         //---
@@ -960,23 +999,6 @@ merge(Compressor.prototype, {
                             continue loop;
                         }
                         //---
-                        // if (foo()) return [ void bar() ]; [ else x...; ] y... ==> if (!foo()) { x...; y... } else bar();
-                        if (in_lambda && (!value || value instanceof AST_UnaryPrefix && value.operator == "void")) {
-                            CHANGED = true;
-                            stat = stat.clone();
-                            stat.condition = stat.condition.negate(compressor);
-                            var funs = extract_functions_from_statement_array(ret);
-                            var body = as_statement_array(stat.alternative).concat(ret);
-                            stat.body = make_node(AST_BlockStatement, stat, {
-                                body: body
-                            });
-                            stat.alternative = value ? make_node(AST_SimpleStatement, value, {
-                                body: value.expression
-                            }) : null;
-                            ret = [ stat.transform(compressor) ].concat(funs);
-                            continue loop;
-                        }
-                        //---
                         // if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
                         //
                         // if sequences is not enabled, this can lead to an endless loop (issue #866).
@@ -995,48 +1017,6 @@ merge(Compressor.prototype, {
                         }
                     }
 
-                    var ab = aborts(stat.body);
-                    var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
-                    if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
-                               || (ab instanceof AST_Continue && self === loop_body(lct))
-                               || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
-                        if (ab.label) {
-                            remove(ab.label.thedef.references, ab);
-                        }
-                        CHANGED = true;
-                        var body = as_statement_array(stat.body).slice(0, -1);
-                        stat = stat.clone();
-                        stat.condition = stat.condition.negate(compressor);
-                        stat.body = make_node(AST_BlockStatement, stat, {
-                            body: as_statement_array(stat.alternative).concat(ret)
-                        });
-                        stat.alternative = make_node(AST_BlockStatement, stat, {
-                            body: body
-                        });
-                        ret = [ stat.transform(compressor) ];
-                        continue loop;
-                    }
-
-                    var ab = aborts(stat.alternative);
-                    var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
-                    if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
-                               || (ab instanceof AST_Continue && self === loop_body(lct))
-                               || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
-                        if (ab.label) {
-                            remove(ab.label.thedef.references, ab);
-                        }
-                        CHANGED = true;
-                        stat = stat.clone();
-                        stat.body = make_node(AST_BlockStatement, stat.body, {
-                            body: as_statement_array(stat.body).concat(ret)
-                        });
-                        stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
-                            body: as_statement_array(stat.alternative).slice(0, -1)
-                        });
-                        ret = [ stat.transform(compressor) ];
-                        continue loop;
-                    }
-
                     ret.unshift(stat);
                     break;
                   default:
@@ -1056,6 +1036,28 @@ merge(Compressor.prototype, {
                 }
                 return false;
             }
+
+            function is_return_void(value) {
+                return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
+            }
+
+            function can_merge_flow(ab) {
+                if (!ab) return false;
+                var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
+                return ab instanceof AST_Return && in_lambda && is_return_void(ab.value)
+                    || ab instanceof AST_Continue && self === loop_body(lct)
+                    || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct;
+            }
+
+            function as_statement_array_with_return(node, ab) {
+                var body = as_statement_array(node).slice(0, -1);
+                if (ab.value) {
+                    body.push(make_node(AST_SimpleStatement, ab.value, {
+                        body: ab.value.expression
+                    }));
+                }
+                return body;
+            }
         };
 
         function eliminate_dead_code(statements, compressor) {
index c09d67b..72b69e7 100644 (file)
@@ -307,6 +307,8 @@ issue_512: {
     options = {
         conditionals: true,
         if_return: true,
+        sequences: true,
+        side_effects: true,
     }
     input: {
         function a() {
index e3dc732..30a563f 100644 (file)
@@ -136,7 +136,29 @@ defun_hoist_funs: {
             function f() {}
             function g() {}
             function h() {}
-            !window;
+            if (window);
+        }
+    }
+}
+
+defun_else_if_return: {
+    options = {
+        hoist_funs: false,
+        if_return: true,
+    }
+    input: {
+        function e() {
+            function f() {}
+            if (window) function g() {}
+            else return;
+            function h() {}
+        }
+    }
+    expect: {
+        function e() {
+            function f() {}
+            if (window) function g() {}
+            function h() {}
         }
     }
 }