some fixes (need testing) in AST_If codegen
authorMihai Bazon <mihai@bazon.net>
Sat, 18 Aug 2012 09:29:57 +0000 (12:29 +0300)
committerMihai Bazon <mihai@bazon.net>
Sat, 18 Aug 2012 09:29:57 +0000 (12:29 +0300)
lib/output.js
tmp/test-node.js [moved from lib/node.js with 68% similarity]

index 05a0447..893ab05 100644 (file)
@@ -363,12 +363,15 @@ function OutputStream(options) {
     /* -----[ statements ]----- */
 
     function display_body(body, is_toplevel, output) {
-        body.forEach(function(stmt){
+        var last = body.length - 1;
+        body.forEach(function(stmt, i){
             if (!(stmt instanceof AST_EmptyStatement)) {
                 output.indent();
                 stmt.print(output);
-                output.newline();
-                if (is_toplevel) output.newline();
+                if (!(i == last && is_toplevel)) {
+                    output.newline();
+                    if (is_toplevel) output.newline();
+                }
             }
         });
     };
@@ -391,8 +394,10 @@ function OutputStream(options) {
         output.semicolon();
     });
     DEFPRINT(AST_BlockStatement, function(self, output){
-        if (self.body.length > 0) output.with_block(function(){
-            display_body(self.body, false, output);
+        var body = self.body;
+        //if (!(body instanceof Array)) body = [ body ];
+        if (body.length > 0) output.with_block(function(){
+            display_body(body, false, output);
         });
         else output.print("{}");
     });
@@ -526,6 +531,43 @@ function OutputStream(options) {
     });
 
     /* -----[ if ]----- */
+    function make_then(self, output) {
+        // The squeezer replaces "block"-s that contain only a single
+        // statement with the statement itself; technically, the AST
+        // is correct, but this can create problems when we output an
+        // IF having an ELSE clause where the THEN clause ends in an
+        // IF *without* an ELSE block (then the outer ELSE would refer
+        // to the inner IF).  This function checks for this case and
+        // adds the block brackets if needed.
+        if (!self.consequent)
+            return output.semicolon();
+        if (self.consequent instanceof AST_Do) {
+            // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE
+            // croaks with "syntax error" on code like this: if (foo)
+            // do ... while(cond); else ...  we need block brackets
+            // around do/while
+            make_block(self.consequent, output);
+            return;
+        }
+        var b = self.consequent;
+        while (true) {
+            if (b instanceof AST_If) {
+                if (!b.alternative) {
+                    make_block(self.consequent, output);
+                    return;
+                }
+                b = b.alternative;
+            }
+            else if (b instanceof AST_While ||
+                     b instanceof AST_Do ||
+                     b instanceof AST_For ||
+                     b instanceof AST_ForIn) {
+                b = b.body;
+            }
+            else break;
+        }
+        self.consequent.print(output);
+    };
     DEFPRINT(AST_If, function(self, output){
         output.print("if");
         output.space();
@@ -533,12 +575,14 @@ function OutputStream(options) {
             self.condition.print(output);
         });
         output.space();
-        self.consequent.print(output);
         if (self.alternative) {
+            make_then(self, output);
             output.space();
             output.print("else");
             output.space();
             self.alternative.print(output);
+        } else {
+            self.consequent.print(output);
         }
     });
 
@@ -849,4 +893,16 @@ function OutputStream(options) {
         return best_of(a);
     };
 
+    function make_block(stmt, output) {
+        if (stmt instanceof AST_BlockStatement) {
+            stmt.print(output);
+            return;
+        }
+        output.with_block(function(){
+            output.indent();
+            stmt.print(output);
+            output.newline();
+        });
+    };
+
 })();
similarity index 68%
rename from lib/node.js
rename to tmp/test-node.js
index ae2ec84..10b520e 100755 (executable)
@@ -7,14 +7,19 @@
     var sys = require("util");
 
     function load_global(file) {
-        var code = fs.readFileSync(file, "utf8");
-        return vm.runInThisContext(code, file);
+        try {
+            var code = fs.readFileSync(file, "utf8");
+            return vm.runInThisContext(code, file);
+        } catch(ex) {
+            sys.debug("ERROR in file: " + file + " / " + ex);
+            process.exit(1);
+        }
     };
 
-    load_global("./utils.js");
-    load_global("./ast.js");
-    load_global("./parse.js");
-    load_global("./output.js");
+    load_global("../lib/utils.js");
+    load_global("../lib/ast.js");
+    load_global("../lib/parse.js");
+    load_global("../lib/output.js");
 
     ///