clean up webkit quirks (#3229)
authorAlex Lam S.L <alexlamsl@gmail.com>
Wed, 8 Aug 2018 08:15:45 +0000 (16:15 +0800)
committerGitHub <noreply@github.com>
Wed, 8 Aug 2018 08:15:45 +0000 (16:15 +0800)
lib/compress.js
lib/output.js
lib/scope.js
test/compress/functions.js
test/compress/webkit.js [new file with mode: 0644]
test/fetch.js
test/jetstream.js

index 4675b1c..08a22c5 100644 (file)
@@ -48,51 +48,51 @@ function Compressor(options, false_by_default) {
         return new Compressor(options, false_by_default);
     TreeTransformer.call(this, this.before, this.after);
     this.options = defaults(options, {
-        arguments     : !false_by_default,
-        booleans      : !false_by_default,
-        collapse_vars : !false_by_default,
-        comparisons   : !false_by_default,
-        conditionals  : !false_by_default,
-        dead_code     : !false_by_default,
-        directives    : !false_by_default,
-        drop_console  : false,
-        drop_debugger : !false_by_default,
-        evaluate      : !false_by_default,
-        expression    : false,
-        global_defs   : false,
-        hoist_funs    : false,
-        hoist_props   : !false_by_default,
-        hoist_vars    : false,
-        ie8           : false,
-        if_return     : !false_by_default,
-        inline        : !false_by_default,
-        join_vars     : !false_by_default,
-        keep_fargs    : true,
-        keep_fnames   : false,
-        keep_infinity : false,
-        loops         : !false_by_default,
-        negate_iife   : !false_by_default,
-        passes        : 1,
-        properties    : !false_by_default,
-        pure_getters  : !false_by_default && "strict",
-        pure_funcs    : null,
-        reduce_funcs  : !false_by_default,
-        reduce_vars   : !false_by_default,
-        sequences     : !false_by_default,
-        side_effects  : !false_by_default,
-        switches      : !false_by_default,
-        top_retain    : null,
-        toplevel      : !!(options && options["top_retain"]),
-        typeofs       : !false_by_default,
-        unsafe        : false,
-        unsafe_comps  : false,
-        unsafe_Function: false,
-        unsafe_math   : false,
-        unsafe_proto  : false,
-        unsafe_regexp : false,
+        arguments       : !false_by_default,
+        booleans        : !false_by_default,
+        collapse_vars   : !false_by_default,
+        comparisons     : !false_by_default,
+        conditionals    : !false_by_default,
+        dead_code       : !false_by_default,
+        directives      : !false_by_default,
+        drop_console    : false,
+        drop_debugger   : !false_by_default,
+        evaluate        : !false_by_default,
+        expression      : false,
+        global_defs     : false,
+        hoist_funs      : false,
+        hoist_props     : !false_by_default,
+        hoist_vars      : false,
+        ie8             : false,
+        if_return       : !false_by_default,
+        inline          : !false_by_default,
+        join_vars       : !false_by_default,
+        keep_fargs      : true,
+        keep_fnames     : false,
+        keep_infinity   : false,
+        loops           : !false_by_default,
+        negate_iife     : !false_by_default,
+        passes          : 1,
+        properties      : !false_by_default,
+        pure_getters    : !false_by_default && "strict",
+        pure_funcs      : null,
+        reduce_funcs    : !false_by_default,
+        reduce_vars     : !false_by_default,
+        sequences       : !false_by_default,
+        side_effects    : !false_by_default,
+        switches        : !false_by_default,
+        top_retain      : null,
+        toplevel        : !!(options && options["top_retain"]),
+        typeofs         : !false_by_default,
+        unsafe          : false,
+        unsafe_comps    : false,
+        unsafe_Function : false,
+        unsafe_math     : false,
+        unsafe_proto    : false,
+        unsafe_regexp   : false,
         unsafe_undefined: false,
-        unused        : !false_by_default,
-        warnings      : false,
+        unused          : !false_by_default,
+        warnings        : false,
     }, true);
     var global_defs = this.options["global_defs"];
     if (typeof global_defs == "object") for (var key in global_defs) {
index f3feabe..7f7e74d 100644 (file)
@@ -694,23 +694,15 @@ function OutputStream(options) {
     // a function expression needs parens around it when it's provably
     // the first token to appear in a statement.
     PARENS(AST_Function, function(output) {
-        if (!output.has_parens() && first_in_statement(output)) {
-            return true;
-        }
-
+        if (!output.has_parens() && first_in_statement(output)) return true;
         if (output.option('webkit')) {
             var p = output.parent();
-            if (p instanceof AST_PropAccess && p.expression === this) {
-                return true;
-            }
+            if (p instanceof AST_PropAccess && p.expression === this) return true;
         }
-
         if (output.option('wrap_iife')) {
             var p = output.parent();
-            return p instanceof AST_Call && p.expression === this;
+            if (p instanceof AST_Call && p.expression === this) return true;
         }
-
-        return false;
     });
 
     // same goes for an object literal, because otherwise it would be
@@ -784,17 +776,17 @@ function OutputStream(options) {
     });
 
     PARENS(AST_Call, function(output) {
-        var p = output.parent(), p1;
-        if (p instanceof AST_New && p.expression === this)
-            return true;
-
-        // workaround for Safari bug.
+        var p = output.parent();
+        if (p instanceof AST_New && p.expression === this) return true;
         // https://bugs.webkit.org/show_bug.cgi?id=123506
-        return this.expression instanceof AST_Function
-            && p instanceof AST_PropAccess
-            && p.expression === this
-            && (p1 = output.parent(1)) instanceof AST_Assign
-            && p1.left === p;
+        if (output.option('webkit')) {
+            var g = output.parent(1);
+            return this.expression instanceof AST_Function
+                && p instanceof AST_PropAccess
+                && p.expression === this
+                && g instanceof AST_Assign
+                && g.left === p;
+        }
     });
 
     PARENS(AST_New, function(output) {
index ac7df7d..c88ce8f 100644 (file)
@@ -320,14 +320,6 @@ function next_mangled_name(scope, options, def) {
     var in_use = names_in_use(scope, options);
     var holes = scope.cname_holes;
     var names = Object.create(null);
-    // #179, #326
-    // in Safari strict mode, something like (function x(x){...}) is a syntax error;
-    // a function expression's argument cannot shadow the function expression's name
-    if (scope instanceof AST_Function && scope.name && def.orig[0] instanceof AST_SymbolFunarg) {
-        var tricky_def = scope.name.definition();
-        // the function's mangled_name is null when keep_fnames is true
-        names[tricky_def.mangled_name || tricky_def.name] = true;
-    }
     var scopes = [ scope ];
     def.references.forEach(function(sym) {
         var scope = sym.scope;
index cff81e2..96689ea 100644 (file)
@@ -236,32 +236,6 @@ issue_203: {
     expect_stdout: "42"
 }
 
-no_webkit: {
-    beautify = {
-        webkit: false,
-    }
-    input: {
-        console.log(function() {
-            1 + 1;
-        }.a = 1);
-    }
-    expect_exact: "console.log(function(){1+1}.a=1);"
-    expect_stdout: "1"
-}
-
-webkit: {
-    beautify = {
-        webkit: true,
-    }
-    input: {
-        console.log(function() {
-            1 + 1;
-        }.a = 1);
-    }
-    expect_exact: "console.log((function(){1+1}).a=1);"
-    expect_stdout: "1"
-}
-
 issue_2084: {
     options = {
         collapse_vars: true,
diff --git a/test/compress/webkit.js b/test/compress/webkit.js
new file mode 100644 (file)
index 0000000..a554fdd
--- /dev/null
@@ -0,0 +1,60 @@
+lambda_call_dot_assign: {
+    beautify = {
+        webkit: false,
+    }
+    input: {
+        console.log(function() {
+            return {};
+        }().a = 1);
+    }
+    expect_exact: "console.log(function(){return{}}().a=1);"
+    expect_stdout: "1"
+}
+
+lambda_call_dot_assign_webkit: {
+    beautify = {
+        webkit: true,
+    }
+    input: {
+        console.log(function() {
+            return {};
+        }().a = 1);
+    }
+    expect_exact: "console.log((function(){return{}}()).a=1);"
+    expect_stdout: "1"
+}
+
+lambda_dot_assign: {
+    beautify = {
+        webkit: false,
+    }
+    input: {
+        console.log(function() {
+            1 + 1;
+        }.a = 1);
+    }
+    expect_exact: "console.log(function(){1+1}.a=1);"
+    expect_stdout: "1"
+}
+
+lambda_dot_assign_webkit: {
+    beautify = {
+        webkit: true,
+    }
+    input: {
+        console.log(function() {
+            1 + 1;
+        }.a = 1);
+    }
+    expect_exact: "console.log((function(){1+1}).a=1);"
+    expect_stdout: "1"
+}
+
+lambda_name_mangle: {
+    mangle = {}
+    input: {
+        console.log(typeof function foo(bar) {});
+    }
+    expect_exact: "console.log(typeof function o(n){});"
+    expect_stdout: "function"
+}
index eccdd71..cd78d2d 100644 (file)
@@ -23,10 +23,9 @@ module.exports = function(url, callback) {
         var options = parse(url);
         options.rejectUnauthorized = false;
         require(options.protocol.slice(0, -1)).get(options, function(res) {
-            if (res.statusCode !== 200) return callback(res);
-            res.pipe(fs.createWriteStream(local(url)).on("close", function() {
-                callback(null, read(url));
-            }));
+            if (res.statusCode !== 200) return callback(res.statusCode);
+            res.pipe(fs.createWriteStream(local(url)));
+            callback(null, res);
         });
     }).on("open", function() {
         callback(null, result);
index b646900..9545784 100644 (file)
@@ -25,30 +25,35 @@ if (typeof phantom == "undefined") {
         request.resume();
         var url = site + request.url;
         fetch(url, function(err, res) {
-            if (err) throw err;
-            response.writeHead(200, {
-                "Content-Type": {
-                    css: "text/css",
-                    js: "application/javascript",
-                    png: "image/png"
-                }[url.slice(url.lastIndexOf(".") + 1)] || "text/html; charset=utf-8"
-            });
-            if (/\.js$/.test(url)) {
-                var stderr = "";
-                var uglifyjs = child_process.fork("bin/uglifyjs", args, {
-                    silent: true
-                }).on("exit", function(code) {
-                    console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
-                    console.log(stderr);
-                    if (code) throw new Error("uglifyjs failed with code " + code);
-                });
-                uglifyjs.stderr.on("data", function(data) {
-                    stderr += data;
-                }).setEncoding("utf8");
-                uglifyjs.stdout.pipe(response);
-                res.pipe(uglifyjs.stdin);
+            if (err) {
+                if (typeof err != "number") throw err;
+                response.writeHead(err);
+                response.end();
             } else {
-                res.pipe(response);
+                response.writeHead(200, {
+                    "Content-Type": {
+                        css: "text/css",
+                        js: "application/javascript",
+                        png: "image/png"
+                    }[url.slice(url.lastIndexOf(".") + 1)] || "text/html; charset=utf-8"
+                });
+                if (/\.js$/.test(url)) {
+                    var stderr = "";
+                    var uglifyjs = child_process.fork("bin/uglifyjs", args, {
+                        silent: true
+                    }).on("exit", function(code) {
+                        console.log("uglifyjs", url.slice(site.length + 1), args.join(" "));
+                        console.log(stderr);
+                        if (code) throw new Error("uglifyjs failed with code " + code);
+                    });
+                    uglifyjs.stderr.on("data", function(data) {
+                        stderr += data;
+                    }).setEncoding("utf8");
+                    uglifyjs.stdout.pipe(response);
+                    res.pipe(uglifyjs.stdin);
+                } else {
+                    res.pipe(response);
+                }
             }
         });
     }).listen();