diff --git a/lib/compress.js b/lib/compress.js index b515c4259ce..4d9be943984 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -210,10 +210,19 @@ Compressor.prototype = new TreeTransformer(function(node, descend) { // output and performance. descend(node, this); var opt = node.optimize(this); - if (is_scope && opt === node && !this.has_directive("use asm") && !opt.pinned()) { - opt.drop_unused(this); - if (opt.merge_variables(this)) opt.drop_unused(this); - descend(opt, this); + if (is_scope) { + if (opt === node && !this.has_directive("use asm") && !opt.pinned()) { + opt.drop_unused(this); + if (opt.merge_variables(this)) opt.drop_unused(this); + descend(opt, this); + } + if (this.option("arrows") && is_arrow(opt) && opt.body.length == 1) { + var stat = opt.body[0]; + if (stat instanceof AST_Return) { + opt.body.length = 0; + opt.value = stat.value; + } + } } if (opt === node) opt._squeezed = true; return opt; @@ -6462,28 +6471,25 @@ Compressor.prototype.compress = function(node) { return self; }); - function opt_arrow(self, compressor) { - if (!compressor.option("arrows")) return self; - drop_rest_farg(self, compressor); - if (self.value) self.body = [ self.first_statement() ]; - var body = tighten_body(self.body, compressor); - switch (body.length) { - case 1: - var stat = body[0]; - if (stat instanceof AST_Return) { - self.body.length = 0; - self.value = stat.value; - break; - } - default: - self.body = body; - self.value = null; - break; + function try_arrow(type, self, parent, compressor) { + if (!compressor.option("arrows")) return; + if (!compressor.option("module")) return; + if (self.name) return; + if (self.uses_arguments || self.pinned()) return; + var parent = compressor.parent(); + if (parent instanceof AST_ClassMethod || parent instanceof AST_ObjectMethod) { + if (parent.value === self) return; } - return self; + if (self.contains_this()) return; + return make_node(type, self, self).optimize(compressor); } - OPT(AST_Arrow, opt_arrow); - OPT(AST_AsyncArrow, opt_arrow); + + OPT(AST_AsyncFunction, function(self, compressor) { + drop_rest_farg(self, compressor); + self.body = tighten_body(self.body, compressor); + var arrow = try_arrow(AST_AsyncArrow, self, compressor.parent(), compressor); + return arrow ? arrow : self; + }); OPT(AST_Function, function(self, compressor) { drop_rest_farg(self, compressor); @@ -6547,7 +6553,8 @@ Compressor.prototype.compress = function(node) { } break; } - return self; + var arrow = try_arrow(AST_Arrow, self, parent, compressor); + return arrow ? arrow : self; }); var NO_MERGE = makePredicate("arguments await yield"); diff --git a/test/compress/arrows.js b/test/compress/arrows.js index b20316f8807..91aaba85e99 100644 --- a/test/compress/arrows.js +++ b/test/compress/arrows.js @@ -749,6 +749,42 @@ instanceof_lambda_4: { node_version: ">=4" } +func_to_arrow: { + options = { + arrows: true, + module: true, + } + input: { + var f = function(a, b, c) { + return b + a + c + c; + }; + console.log(f(...[].sort.call("SPA".split("")))); + } + expect: { + var f = (a, b, c) => b + a + c + c; + console.log(f(...[].sort.call("SPA".split("")))); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +iife_to_arrow: { + options = { + arrows: true, + module: true, + } + input: { + console.log(function(a, b, c) { + return b + a + c + c; + }(...[].sort.call("SPA".split("")))); + } + expect: { + console.log(((a, b, c) => b + a + c + c)(...[].sort.call("SPA".split("")))); + } + expect_stdout: "PASS" + node_version: ">=4" +} + issue_4388: { options = { inline: true, @@ -1175,13 +1211,11 @@ issue_5416_1: { } expect: { var f = () => { - { - console; - arguments = void 0, - console.log(arguments); - var arguments; - return; - } + console; + arguments = void 0, + console.log(arguments); + var arguments; + return; }; f(); } @@ -1210,12 +1244,10 @@ issue_5416_2: { } expect: { var f = () => { - { - console; - var arguments = void 0; - for (; console.log(arguments);); - return; - } + console; + var arguments = void 0; + for (; console.log(arguments);); + return; }; f(); } @@ -1311,9 +1343,7 @@ issue_5653: { })()); } expect: { - console.log((a => { - return +{}; - })()); + console.log((a => +{})()); } expect_stdout: "NaN" node_version: ">=4" diff --git a/test/compress/awaits.js b/test/compress/awaits.js index 45d5dd3eca1..6e837ad33a6 100644 --- a/test/compress/awaits.js +++ b/test/compress/awaits.js @@ -1407,6 +1407,29 @@ instanceof_lambda_4: { node_version: ">=8" } +async_to_arrow: { + options = { + arrows: true, + module: true, + } + input: { + (async function() { + var f = async function(a, b, c) { + return b + a + c + c; + }; + console.log(await f(...[].sort.call("SPA".split("")))); + })(); + } + expect: { + (async () => { + var f = async (a, b, c) => b + a + c + c; + console.log(await f(...[].sort.call("SPA".split("")))); + })(); + } + expect_stdout: "PASS" + node_version: ">=8" +} + issue_4335_1: { options = { inline: true, diff --git a/test/mocha/cli.js b/test/mocha/cli.js index 2e7f8fe517f..010d28c9948 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -16,8 +16,9 @@ describe("bin/uglifyjs", function() { var command = [ uglifyjscmd, "--self", - semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc", "--wrap WrappedUglifyJS", + semver.satisfies(process.version, "<4") ? "--no-module" : "--module", + semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc", ].join(" "); exec(command, { maxBuffer: 1048576 }, function(err, stdout) { if (err) throw err; @@ -61,7 +62,7 @@ describe("bin/uglifyjs", function() { "--mangle", ].join(" "), function(err, stdout) { if (err) throw err; - assert.strictEqual(stdout, "function(n){for(;n(););return 42}(A)\n"); + assert.strictEqual(stdout, "(r=>{for(;r(););return 42})(A)\n"); done(); }).stdin.end([ "function(x) {", @@ -1068,7 +1069,7 @@ describe("bin/uglifyjs", function() { ]).join("\n"); exec(uglifyjscmd + " -mc", function(err, stdout) { if (err) throw err; - assert.strictEqual(stdout, "console.log(function(){var p={p:25},n={p:121},o={p:1024};return p.p+n.p+o.p}());\n"); + assert.strictEqual(stdout, "console.log((()=>{var p={p:25},o={p:121},r={p:1024};return p.p+o.p+r.p})());\n"); assert.strictEqual(run_code(stdout), run_code(code)); done(); }).stdin.end(code); diff --git a/test/mocha/minify.js b/test/mocha/minify.js index e63acd82d26..a9ef993980e 100644 --- a/test/mocha/minify.js +++ b/test/mocha/minify.js @@ -239,7 +239,7 @@ describe("minify", function() { }, }); var code = result.code; - assert.strictEqual(code, "var a=function(){foo()}();"); + assert.strictEqual(code, "var a=(()=>{foo()})();"); }); }); @@ -325,20 +325,30 @@ describe("minify", function() { }); describe("module", function() { - it("Should not inline `await` variables", function() { - if (semver.satisfies(process.version, "<8")) return; - var code = [ - "console.log(function() {", - " return typeof await;", - "}());", - ].join("\n"); - assert.strictEqual(run_code("(async function(){" + code + "})();"), "undefined\n"); + var code = [ + "console.log(function() {", + " return typeof await;", + "}());", + ].join("\n"); + it("Should inline `await` variables", function() { + var result = UglifyJS.minify(code, { + module: false, + }); + if (result.error) throw result.error; + assert.strictEqual(result.code, "console.log(typeof await);"); + assert.strictEqual(run_code(code), "undefined\n"); + assert.strictEqual(run_code(result.code), "undefined\n"); + }); + it("Should not inline `await` variables in ES modules", function() { var result = UglifyJS.minify(code, { module: true, }); if (result.error) throw result.error; - assert.strictEqual(result.code, "console.log(function(){return typeof await}());"); - assert.strictEqual(run_code("(async function(){" + result.code + "})();"), "undefined\n"); + assert.strictEqual(result.code, "console.log((()=>typeof await)());"); + if (semver.satisfies(process.version, ">=8")) { + assert.strictEqual(run_code("(async function(){" + code + "})();"), "undefined\n"); + assert.strictEqual(run_code("(async function(){" + result.code + "})();"), "undefined\n"); + } }); }); diff --git a/test/mocha/sourcemaps.js b/test/mocha/sourcemaps.js index 4efd42d13ce..4a74fdeda1c 100644 --- a/test/mocha/sourcemaps.js +++ b/test/mocha/sourcemaps.js @@ -301,14 +301,14 @@ describe("sourcemaps", function() { }); if (result.error) throw result.error; var code = result.code; - assert.strictEqual(code, "var a=function(n){return n};\n" + - "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BLENBQUsifQ=="); + assert.strictEqual(code, "var a=a=>a;\n" + + "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBYUMsR0FBY0EifQ=="); }); it("Should not append source map to output js when sourceMapInline is not enabled", function() { var result = UglifyJS.minify("var a = function(foo) { return foo; };"); if (result.error) throw result.error; var code = result.code; - assert.strictEqual(code, "var a=function(n){return n};"); + assert.strictEqual(code, "var a=a=>a;"); }); it("Should work with max_line_len", function() { var result = UglifyJS.minify(read("test/input/issue-505/input.js"), { diff --git a/test/mocha/spidermonkey.js b/test/mocha/spidermonkey.js index 79b0f29fd76..9babfc710f7 100644 --- a/test/mocha/spidermonkey.js +++ b/test/mocha/spidermonkey.js @@ -7,20 +7,21 @@ describe("spidermonkey export/import sanity test", function() { it("Should produce a functional build when using --self with spidermonkey", function(done) { this.timeout(120000); var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs'; - var options = semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc"; + var options = [ + semver.satisfies(process.version, "<4") ? "--no-module" : "--module", + semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc", + ]; var command = [ [ uglifyjs, "--self", - options, "--wrap SpiderUglify", "-o spidermonkey", - ].join(" "), + ].concat(options).join(" "), [ uglifyjs, "-p spidermonkey", - options, - ].join(" "), + ].concat(options).join(" "), ].join(" | "); exec(command, { maxBuffer: 1048576 }, function(err, stdout) { if (err) throw err;