adding an imaginary "return undefined" can sometimes help
authorMihai Bazon <mihai@bazon.net>
Fri, 14 Sep 2012 13:26:30 +0000 (16:26 +0300)
committerMihai Bazon <mihai@bazon.net>
Fri, 14 Sep 2012 13:26:30 +0000 (16:26 +0300)
function f() {
  if (foo) return x();
  if (!bar) return y();
}

==>

function f() {
  return foo ? x() : bar ? void 0 : y();
}

lib/compress.js
lib/output.js

index 52dc011..3fd6940 100644 (file)
@@ -190,33 +190,42 @@ function Compressor(options, false_by_default) {
             return MAP(statements, function(stat, i){
                 if (stat instanceof AST_If
                     && stat.body instanceof AST_Return
-                    && !stat.body.value
                     && !stat.alternative
                     && in_lambda) {
-                    CHANGED = true;
-                    if (i < last) {
-                        var rest = statements.slice(i + 1);
-                        var cond = stat.condition;
-                        while (rest[0] instanceof AST_If
-                               && rest[0].body instanceof AST_Return
-                               && !rest[0].alternative) {
-                            cond = make_node(AST_Binary, rest[0], {
-                                operator: "||",
-                                left: cond,
-                                right: rest[0].condition
-                            });
-                            rest.shift();
+                    if (!stat.body.value) {
+                        CHANGED = true;
+                        if (i < last) {
+                            var rest = statements.slice(i + 1);
+                            var cond = stat.condition;
+                            while (rest[0] instanceof AST_If
+                                   && rest[0].body instanceof AST_Return
+                                   && !rest[0].alternative) {
+                                cond = make_node(AST_Binary, rest[0], {
+                                    operator: "||",
+                                    left: cond,
+                                    right: rest[0].condition
+                                });
+                                rest.shift();
+                            }
+                            return MAP.last(make_node(AST_If, stat, {
+                                condition: cond.negate(compressor),
+                                body: make_node(AST_BlockStatement, stat, {
+                                    body: rest
+                                }).optimize(compressor)
+                            }).optimize(compressor));
+                        } else {
+                            return make_node(AST_SimpleStatement, stat, {
+                                body: stat.condition
+                            }).optimize(compressor);
                         }
-                        return MAP.last(make_node(AST_If, stat, {
-                            condition: cond.negate(compressor),
-                            body: make_node(AST_BlockStatement, stat, {
-                                body: rest
-                            }).optimize(compressor)
-                        }).optimize(compressor));
-                    } else {
-                        return make_node(AST_SimpleStatement, stat, {
-                            body: stat.condition
-                        }).optimize(compressor);
+                    } else if (i == last && last > 0
+                               && statements[last - 1] instanceof AST_If
+                               && statements[last - 1].body instanceof AST_Return
+                               && !statements[last - 1].alternative) {
+                        CHANGED = true;
+                        return MAP.splice([ stat, make_node(AST_Return, stat, {
+                            value: make_node(AST_Undefined, stat)
+                        })]);
                     }
                 }
                 if (stat instanceof AST_If
@@ -697,7 +706,7 @@ function Compressor(options, false_by_default) {
                 }
             });
             self.walk(tw);
-            if (vars_found > 0 && vardecl.length > 0) {
+            if (vars_found > 0 && vardecl.length > 1) {
                 vardecl.forEach(function(v){ v.hoisted = true });
                 var node = make_node(AST_Var, self, {
                     definitions: Object.keys(vars).map(function(name){
@@ -1338,6 +1347,17 @@ function Compressor(options, false_by_default) {
         return self.optimize(compressor);
     });
 
+    SQUEEZE(AST_SymbolRef, function(self, compressor){
+        return self.optimize(compressor);
+    });
+
+    AST_SymbolRef.DEFMETHOD("optimize", function(compressor){
+        if (this.name == "undefined" && this.undeclared()) {
+            return make_node(AST_Undefined, this);
+        }
+        return this;
+    });
+
     var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
     AST_Assign.DEFMETHOD("optimize", function(compressor){
         if (this.operator == "="
index a93f738..602fa60 100644 (file)
@@ -889,6 +889,10 @@ function OutputStream(options) {
         var def = self.definition();
         output.print_name(def ? def.mangled_name || def.name : self.name);
     });
+    DEFPRINT(AST_Undefined, function(self, output){
+        // XXX: should add more options for this
+        output.print("void 0");
+    });
     DEFPRINT(AST_This, function(self, output){
         output.print("this");
     });