Skip to content

Commit

Permalink
convert function to arrow form
Browse files Browse the repository at this point in the history
closes #5904
  • Loading branch information
alexlamsl committed Aug 5, 2024
1 parent 8bbbc51 commit c78bd67
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 66 deletions.
50 changes: 23 additions & 27 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -6462,29 +6471,6 @@ 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;
}
return self;
}
OPT(AST_Arrow, opt_arrow);
OPT(AST_AsyncArrow, opt_arrow);

OPT(AST_Function, function(self, compressor) {
drop_rest_farg(self, compressor);
self.body = tighten_body(self.body, compressor);
Expand Down Expand Up @@ -11125,6 +11111,16 @@ Compressor.prototype.compress = function(node) {
return make_sequence(self, convert_args()).optimize(compressor);
}
}
if (compressor.option("arrows")
&& compressor.option("module")
&& (exp instanceof AST_AsyncFunction || exp instanceof AST_Function)
&& !exp.name
&& !exp.uses_arguments
&& !exp.pinned()
&& !exp.contains_this()) {
self.expression = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp, exp).transform(compressor);
return self;
}
if (compressor.option("drop_console")) {
if (exp instanceof AST_PropAccess) {
var name = exp.expression;
Expand Down
106 changes: 90 additions & 16 deletions test/compress/arrows.js
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,86 @@ instanceof_lambda_4: {
node_version: ">=4"
}

func_to_arrow: {
options = {
arrows: true,
module: true,
}
input: {
console.log(function(a, b, c) {
return b + a + c + c;
}("A", "P", "S"));
}
expect: {
console.log(((a, b, c) => b + a + c + c)("A", "P", "S"));
}
expect_stdout: "PASS"
node_version: ">=4"
}

func_to_arrow_var: {
options = {
arrows: true,
module: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f = function(a, b, c) {
return b + a + c + c;
};
console.log(f("A", "P", "S"));
}
expect: {
console.log(((a, b, c) => b + a + c + c)("A", "P", "S"));
}
expect_stdout: "PASS"
node_version: ">=4"
}

keep_new: {
options = {
arrows: true,
module: true,
}
input: {
new function(a, b, c) {
console.log(b + a + c + c);
}("A", "P", "S");
}
expect: {
new function(a, b, c) {
console.log(b + a + c + c);
}("A", "P", "S");
}
expect_stdout: "PASS"
node_version: ">=4"
}

keep_new_var: {
options = {
arrows: true,
module: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f = function(a, b, c) {
console.log(b + a + c + c);
};
new f("A", "P", "S");
}
expect: {
new function(a, b, c) {
console.log(b + a + c + c);
}("A", "P", "S");
}
expect_stdout: "PASS"
node_version: ">=4"
}

issue_4388: {
options = {
inline: true,
Expand Down Expand Up @@ -1175,13 +1255,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();
}
Expand Down Expand Up @@ -1210,12 +1288,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();
}
Expand Down Expand Up @@ -1311,9 +1387,7 @@ issue_5653: {
})());
}
expect: {
console.log((a => {
return +{};
})());
console.log((a => +{})());
}
expect_stdout: "NaN"
node_version: ">=4"
Expand Down
24 changes: 24 additions & 0 deletions test/compress/awaits.js
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,30 @@ instanceof_lambda_4: {
node_version: ">=8"
}

async_to_arrow: {
options = {
arrows: true,
module: true,
reduce_vars: true,
unused: true,
}
input: {
(async function() {
var f = async function(a, b, c) {
return b + a + c + c;
};
console.log(await f("A", "P", "S"));
})();
}
expect: {
(async () => {
console.log(await (async (a, b, c) => b + a + c + c)("A", "P", "S"));
})();
}
expect_stdout: "PASS"
node_version: ">=8"
}

issue_4335_1: {
options = {
inline: true,
Expand Down
55 changes: 55 additions & 0 deletions test/compress/yields.js
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,61 @@ instanceof_lambda: {
node_version: ">=4"
}

keep_yield: {
options = {
arrows: true,
module: true,
}
input: {
console.log(function*() {
yield "PASS";
}().next().value);
}
expect: {
console.log(function*() {
yield "PASS";
}().next().value);
}
expect_stdout: "PASS"
node_version: ">=4"
}

func_to_arrow_arg: {
options = {
arrows: true,
module: true,
}
input: {
console.log(function(yield) {
return yield;
}("PASS"));
}
expect: {
console.log((yield => yield)("PASS"));
}
expect_stdout: "PASS"
node_version: ">=4"
}

func_to_arrow_var: {
options = {
arrows: true,
module: true,
}
input: {
var yield = "PASS";
console.log(function() {
return yield;
}());
}
expect: {
var yield = "PASS";
console.log((() => yield)());
}
expect_stdout: "PASS"
node_version: ">=4"
}

issue_4454_1: {
rename = false
options = {
Expand Down
7 changes: 4 additions & 3 deletions test/mocha/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {",
Expand Down Expand Up @@ -1066,7 +1067,7 @@ describe("bin/uglifyjs", function() {
"return obj25.p + obj121.p + obj1024.p;",
"}());",
]).join("\n");
exec(uglifyjscmd + " -mc", function(err, stdout) {
exec(uglifyjscmd + " --no-module -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(run_code(stdout), run_code(code));
Expand Down
32 changes: 21 additions & 11 deletions test/mocha/minify.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ describe("minify", function() {
},
});
var code = result.code;
assert.strictEqual(code, "var a=function(){foo()}();");
assert.strictEqual(code, "var a=(()=>{foo()})();");
});
});

Expand Down Expand Up @@ -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");
}
});
});

Expand Down
Loading

0 comments on commit c78bd67

Please sign in to comment.