Skip to content

Commit 2255074

Browse files
authoredAug 6, 2024··
convert function to arrow form (#5907)
closes #5904
1 parent e9cf8de commit 2255074

File tree

8 files changed

+243
-71
lines changed

8 files changed

+243
-71
lines changed
 

‎lib/compress.js

+31-32
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,19 @@ Compressor.prototype = new TreeTransformer(function(node, descend) {
210210
// output and performance.
211211
descend(node, this);
212212
var opt = node.optimize(this);
213-
if (is_scope && opt === node && !this.has_directive("use asm") && !opt.pinned()) {
214-
opt.drop_unused(this);
215-
if (opt.merge_variables(this)) opt.drop_unused(this);
216-
descend(opt, this);
213+
if (is_scope) {
214+
if (opt === node && !this.has_directive("use asm") && !opt.pinned()) {
215+
opt.drop_unused(this);
216+
if (opt.merge_variables(this)) opt.drop_unused(this);
217+
descend(opt, this);
218+
}
219+
if (this.option("arrows") && is_arrow(opt) && opt.body.length == 1) {
220+
var stat = opt.body[0];
221+
if (stat instanceof AST_Return) {
222+
opt.body.length = 0;
223+
opt.value = stat.value;
224+
}
225+
}
217226
}
218227
if (opt === node) opt._squeezed = true;
219228
return opt;
@@ -6474,29 +6483,6 @@ Compressor.prototype.compress = function(node) {
64746483
return self;
64756484
});
64766485

6477-
function opt_arrow(self, compressor) {
6478-
if (!compressor.option("arrows")) return self;
6479-
drop_rest_farg(self, compressor);
6480-
if (self.value) self.body = [ self.first_statement() ];
6481-
var body = tighten_body(self.body, compressor);
6482-
switch (body.length) {
6483-
case 1:
6484-
var stat = body[0];
6485-
if (stat instanceof AST_Return) {
6486-
self.body.length = 0;
6487-
self.value = stat.value;
6488-
break;
6489-
}
6490-
default:
6491-
self.body = body;
6492-
self.value = null;
6493-
break;
6494-
}
6495-
return self;
6496-
}
6497-
OPT(AST_Arrow, opt_arrow);
6498-
OPT(AST_AsyncArrow, opt_arrow);
6499-
65006486
OPT(AST_Function, function(self, compressor) {
65016487
drop_rest_farg(self, compressor);
65026488
self.body = tighten_body(self.body, compressor);
@@ -11138,6 +11124,19 @@ Compressor.prototype.compress = function(node) {
1113811124
return make_sequence(self, convert_args()).optimize(compressor);
1113911125
}
1114011126
}
11127+
if (compressor.option("arrows")
11128+
&& compressor.option("module")
11129+
&& (exp instanceof AST_AsyncFunction || exp instanceof AST_Function)
11130+
&& !exp.name
11131+
&& !exp.uses_arguments
11132+
&& !exp.pinned()
11133+
&& !exp.contains_this()) {
11134+
var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp, exp);
11135+
arrow.init_vars(exp.parent_scope, exp);
11136+
arrow.variables.del("arguments");
11137+
self.expression = arrow.transform(compressor);
11138+
return self;
11139+
}
1114111140
if (compressor.option("drop_console")) {
1114211141
if (exp instanceof AST_PropAccess) {
1114311142
var name = exp.expression;
@@ -14233,8 +14232,8 @@ Compressor.prototype.compress = function(node) {
1423314232
if (fn.pinned()) return;
1423414233
if (is_generator(fn)) return;
1423514234
var arrow = is_arrow(fn);
14236-
if (arrow && fn.value) return;
14237-
if (fn.body[0] instanceof AST_Directive) return;
14235+
var fn_body = arrow && fn.value ? [ fn.first_statement() ] : fn.body;
14236+
if (fn_body[0] instanceof AST_Directive) return;
1423814237
if (fn.contains_this()) return;
1423914238
if (!scope) scope = find_scope(compressor);
1424014239
var defined = new Dictionary();
@@ -14333,7 +14332,7 @@ Compressor.prototype.compress = function(node) {
1433314332
return !abort;
1433414333
};
1433514334
}
14336-
if (verify_body && !all(fn.body, verify_body)) return;
14335+
if (verify_body && !all(fn_body, verify_body)) return;
1433714336
if (!safe_from_await_yield(fn, avoid_await_yield(compressor, scope))) return;
1433814337
fn.functions.each(function(def, name) {
1433914338
scope.functions.set(name, def);
@@ -14404,7 +14403,7 @@ Compressor.prototype.compress = function(node) {
1440414403
[].unshift.apply(def.orig, orig);
1440514404
def.eliminated += orig.length;
1440614405
});
14407-
[].push.apply(body, in_loop ? fn.body.filter(function(stat) {
14406+
[].push.apply(body, in_loop ? fn_body.filter(function(stat) {
1440814407
if (!(stat instanceof AST_LambdaDefinition)) return true;
1440914408
var name = make_node(AST_SymbolVar, flatten_var(stat.name));
1441014409
var def = name.definition();
@@ -14418,7 +14417,7 @@ Compressor.prototype.compress = function(node) {
1441814417
}) ],
1441914418
}));
1442014419
return false;
14421-
}) : fn.body);
14420+
}) : fn_body);
1442214421
var inlined = make_node(AST_BlockStatement, call, { body: body });
1442314422
if (!no_return) {
1442414423
if (async) scan_local_returns(inlined, function(node) {

‎test/compress/arrows.js

+90-16
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,86 @@ instanceof_lambda_4: {
749749
node_version: ">=4"
750750
}
751751

752+
func_to_arrow: {
753+
options = {
754+
arrows: true,
755+
module: true,
756+
}
757+
input: {
758+
console.log(function(a, b, c) {
759+
return b + a + c + c;
760+
}("A", "P", "S"));
761+
}
762+
expect: {
763+
console.log(((a, b, c) => b + a + c + c)("A", "P", "S"));
764+
}
765+
expect_stdout: "PASS"
766+
node_version: ">=4"
767+
}
768+
769+
func_to_arrow_var: {
770+
options = {
771+
arrows: true,
772+
module: true,
773+
reduce_vars: true,
774+
toplevel: true,
775+
unused: true,
776+
}
777+
input: {
778+
var f = function(a, b, c) {
779+
return b + a + c + c;
780+
};
781+
console.log(f("A", "P", "S"));
782+
}
783+
expect: {
784+
console.log(((a, b, c) => b + a + c + c)("A", "P", "S"));
785+
}
786+
expect_stdout: "PASS"
787+
node_version: ">=4"
788+
}
789+
790+
keep_new: {
791+
options = {
792+
arrows: true,
793+
module: true,
794+
}
795+
input: {
796+
new function(a, b, c) {
797+
console.log(b + a + c + c);
798+
}("A", "P", "S");
799+
}
800+
expect: {
801+
new function(a, b, c) {
802+
console.log(b + a + c + c);
803+
}("A", "P", "S");
804+
}
805+
expect_stdout: "PASS"
806+
node_version: ">=4"
807+
}
808+
809+
keep_new_var: {
810+
options = {
811+
arrows: true,
812+
module: true,
813+
reduce_vars: true,
814+
toplevel: true,
815+
unused: true,
816+
}
817+
input: {
818+
var f = function(a, b, c) {
819+
console.log(b + a + c + c);
820+
};
821+
new f("A", "P", "S");
822+
}
823+
expect: {
824+
new function(a, b, c) {
825+
console.log(b + a + c + c);
826+
}("A", "P", "S");
827+
}
828+
expect_stdout: "PASS"
829+
node_version: ">=4"
830+
}
831+
752832
issue_4388: {
753833
options = {
754834
inline: true,
@@ -1175,13 +1255,11 @@ issue_5416_1: {
11751255
}
11761256
expect: {
11771257
var f = () => {
1178-
{
1179-
console;
1180-
arguments = void 0,
1181-
console.log(arguments);
1182-
var arguments;
1183-
return;
1184-
}
1258+
console;
1259+
arguments = void 0,
1260+
console.log(arguments);
1261+
var arguments;
1262+
return;
11851263
};
11861264
f();
11871265
}
@@ -1210,12 +1288,10 @@ issue_5416_2: {
12101288
}
12111289
expect: {
12121290
var f = () => {
1213-
{
1214-
console;
1215-
var arguments = void 0;
1216-
for (; console.log(arguments););
1217-
return;
1218-
}
1291+
console;
1292+
var arguments = void 0;
1293+
for (; console.log(arguments););
1294+
return;
12191295
};
12201296
f();
12211297
}
@@ -1311,9 +1387,7 @@ issue_5653: {
13111387
})());
13121388
}
13131389
expect: {
1314-
console.log((a => {
1315-
return +{};
1316-
})());
1390+
console.log((a => +{})());
13171391
}
13181392
expect_stdout: "NaN"
13191393
node_version: ">=4"

‎test/compress/awaits.js

+24
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,30 @@ instanceof_lambda_4: {
14071407
node_version: ">=8"
14081408
}
14091409

1410+
async_to_arrow: {
1411+
options = {
1412+
arrows: true,
1413+
module: true,
1414+
reduce_vars: true,
1415+
unused: true,
1416+
}
1417+
input: {
1418+
(async function() {
1419+
var f = async function(a, b, c) {
1420+
return b + a + c + c;
1421+
};
1422+
console.log(await f("A", "P", "S"));
1423+
})();
1424+
}
1425+
expect: {
1426+
(async () => {
1427+
console.log(await (async (a, b, c) => b + a + c + c)("A", "P", "S"));
1428+
})();
1429+
}
1430+
expect_stdout: "PASS"
1431+
node_version: ">=8"
1432+
}
1433+
14101434
issue_4335_1: {
14111435
options = {
14121436
inline: true,

‎test/compress/yields.js

+55
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,61 @@ instanceof_lambda: {
970970
node_version: ">=4"
971971
}
972972

973+
keep_yield: {
974+
options = {
975+
arrows: true,
976+
module: true,
977+
}
978+
input: {
979+
console.log(function*() {
980+
yield "PASS";
981+
}().next().value);
982+
}
983+
expect: {
984+
console.log(function*() {
985+
yield "PASS";
986+
}().next().value);
987+
}
988+
expect_stdout: "PASS"
989+
node_version: ">=4"
990+
}
991+
992+
func_to_arrow_arg: {
993+
options = {
994+
arrows: true,
995+
module: true,
996+
}
997+
input: {
998+
console.log(function(yield) {
999+
return yield;
1000+
}("PASS"));
1001+
}
1002+
expect: {
1003+
console.log((yield => yield)("PASS"));
1004+
}
1005+
expect_stdout: "PASS"
1006+
node_version: ">=4"
1007+
}
1008+
1009+
func_to_arrow_var: {
1010+
options = {
1011+
arrows: true,
1012+
module: true,
1013+
}
1014+
input: {
1015+
var yield = "PASS";
1016+
console.log(function() {
1017+
return yield;
1018+
}());
1019+
}
1020+
expect: {
1021+
var yield = "PASS";
1022+
console.log((() => yield)());
1023+
}
1024+
expect_stdout: "PASS"
1025+
node_version: ">=4"
1026+
}
1027+
9731028
issue_4454_1: {
9741029
rename = false
9751030
options = {

‎test/mocha/cli.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ describe("bin/uglifyjs", function() {
1616
var command = [
1717
uglifyjscmd,
1818
"--self",
19-
semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc",
2019
"--wrap WrappedUglifyJS",
20+
semver.satisfies(process.version, "<4") ? "--no-module" : "--module",
21+
semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc",
2122
].join(" ");
2223
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
2324
if (err) throw err;
@@ -61,7 +62,7 @@ describe("bin/uglifyjs", function() {
6162
"--mangle",
6263
].join(" "), function(err, stdout) {
6364
if (err) throw err;
64-
assert.strictEqual(stdout, "function(n){for(;n(););return 42}(A)\n");
65+
assert.strictEqual(stdout, "(r=>{for(;r(););return 42})(A)\n");
6566
done();
6667
}).stdin.end([
6768
"function(x) {",
@@ -1066,7 +1067,7 @@ describe("bin/uglifyjs", function() {
10661067
"return obj25.p + obj121.p + obj1024.p;",
10671068
"}());",
10681069
]).join("\n");
1069-
exec(uglifyjscmd + " -mc", function(err, stdout) {
1070+
exec(uglifyjscmd + " --no-module -mc", function(err, stdout) {
10701071
if (err) throw err;
10711072
assert.strictEqual(stdout, "console.log(function(){var p={p:25},n={p:121},o={p:1024};return p.p+n.p+o.p}());\n");
10721073
assert.strictEqual(run_code(stdout), run_code(code));

‎test/mocha/minify.js

+21-11
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ describe("minify", function() {
239239
},
240240
});
241241
var code = result.code;
242-
assert.strictEqual(code, "var a=function(){foo()}();");
242+
assert.strictEqual(code, "var a=(()=>{foo()})();");
243243
});
244244
});
245245

@@ -325,20 +325,30 @@ describe("minify", function() {
325325
});
326326

327327
describe("module", function() {
328-
it("Should not inline `await` variables", function() {
329-
if (semver.satisfies(process.version, "<8")) return;
330-
var code = [
331-
"console.log(function() {",
332-
" return typeof await;",
333-
"}());",
334-
].join("\n");
335-
assert.strictEqual(run_code("(async function(){" + code + "})();"), "undefined\n");
328+
var code = [
329+
"console.log(function() {",
330+
" return typeof await;",
331+
"}());",
332+
].join("\n");
333+
it("Should inline `await` variables", function() {
334+
var result = UglifyJS.minify(code, {
335+
module: false,
336+
});
337+
if (result.error) throw result.error;
338+
assert.strictEqual(result.code, "console.log(typeof await);");
339+
assert.strictEqual(run_code(code), "undefined\n");
340+
assert.strictEqual(run_code(result.code), "undefined\n");
341+
});
342+
it("Should not inline `await` variables in ES modules", function() {
336343
var result = UglifyJS.minify(code, {
337344
module: true,
338345
});
339346
if (result.error) throw result.error;
340-
assert.strictEqual(result.code, "console.log(function(){return typeof await}());");
341-
assert.strictEqual(run_code("(async function(){" + result.code + "})();"), "undefined\n");
347+
assert.strictEqual(result.code, "console.log((()=>typeof await)());");
348+
if (semver.satisfies(process.version, ">=8")) {
349+
assert.strictEqual(run_code("(async function(){" + code + "})();"), "undefined\n");
350+
assert.strictEqual(run_code("(async function(){" + result.code + "})();"), "undefined\n");
351+
}
342352
});
343353
});
344354

‎test/mocha/reduce.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,20 @@ describe("test/reduce.js", function() {
224224
].join("\n"));
225225
});
226226
it("Should ignore difference in Error.message", function() {
227-
var result = reduce_test("null[function() {\n}];");
227+
var result = reduce_test("null[function() {\n}];", {
228+
module: false,
229+
});
228230
if (result.error) throw result.error;
229231
assert.strictEqual(result.code, (semver.satisfies(process.version, "<=0.10") ? [
230232
"// Can't reproduce test failure",
231-
"// minify options: {}",
233+
"// minify options: {",
234+
'// "module": false',
235+
"// }",
232236
] : [
233237
"// No differences except in error message",
234-
"// minify options: {}",
238+
"// minify options: {",
239+
'// "module": false',
240+
"// }",
235241
]).join("\n"));
236242
});
237243
it("Should report trailing whitespace difference in stringified format", function() {
@@ -245,6 +251,7 @@ describe("test/reduce.js", function() {
245251
unsafe_math: true,
246252
},
247253
mangle: false,
254+
module: false,
248255
});
249256
if (result.error) throw result.error;
250257
assert.strictEqual(result.code, [
@@ -257,7 +264,8 @@ describe("test/reduce.js", function() {
257264
'// "compress": {',
258265
'// "unsafe_math": true',
259266
'// },',
260-
'// "mangle": false',
267+
'// "mangle": false,',
268+
'// "module": false',
261269
"// }",
262270
].join("\n"));
263271
});

‎test/mocha/spidermonkey.js

+6-5
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@ describe("spidermonkey export/import sanity test", function() {
77
it("Should produce a functional build when using --self with spidermonkey", function(done) {
88
this.timeout(120000);
99
var uglifyjs = '"' + process.argv[0] + '" bin/uglifyjs';
10-
var options = semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc";
10+
var options = [
11+
semver.satisfies(process.version, "<4") ? "--no-module" : "--module",
12+
semver.satisfies(process.version, "<=0.12") ? "-mc hoist_funs" : "-mc",
13+
];
1114
var command = [
1215
[
1316
uglifyjs,
1417
"--self",
15-
options,
1618
"--wrap SpiderUglify",
1719
"-o spidermonkey",
18-
].join(" "),
20+
].concat(options).join(" "),
1921
[
2022
uglifyjs,
2123
"-p spidermonkey",
22-
options,
23-
].join(" "),
24+
].concat(options).join(" "),
2425
].join(" | ");
2526
exec(command, { maxBuffer: 1048576 }, function(err, stdout) {
2627
if (err) throw err;

0 commit comments

Comments
 (0)
Please sign in to comment.