From: Alex Lam S.L Date: Wed, 8 Aug 2018 08:15:45 +0000 (+0800) Subject: clean up webkit quirks (#3229) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=fc78423f1d9bfa10774a04563e37e130523bf46d;p=UglifyJS.git clean up webkit quirks (#3229) --- diff --git a/lib/compress.js b/lib/compress.js index 4675b1cc..08a22c54 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -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) { diff --git a/lib/output.js b/lib/output.js index f3feabec..7f7e74df 100644 --- a/lib/output.js +++ b/lib/output.js @@ -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) { diff --git a/lib/scope.js b/lib/scope.js index ac7df7df..c88ce8fc 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -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; diff --git a/test/compress/functions.js b/test/compress/functions.js index cff81e2d..96689eae 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -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 index 00000000..a554fddf --- /dev/null +++ b/test/compress/webkit.js @@ -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" +} diff --git a/test/fetch.js b/test/fetch.js index eccdd71f..cd78d2d0 100644 --- a/test/fetch.js +++ b/test/fetch.js @@ -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); diff --git a/test/jetstream.js b/test/jetstream.js index b6469008..9545784b 100644 --- a/test/jetstream.js +++ b/test/jetstream.js @@ -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();