improve usability (#5758)

This commit is contained in:
Alex Lam S.L
2022-12-04 03:10:32 +02:00
committed by GitHub
parent 0cbd5ea64a
commit 17c3ae6cba
18 changed files with 38 additions and 76 deletions

View File

@@ -9,9 +9,9 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
options: options:
- '-mb braces'
- '--ie -c' - '--ie -c'
- '-mc' - '-mb braces'
- '--toplevel -mc'
- '-p acorn -mco spidermonkey' - '-p acorn -mco spidermonkey'
- '-mc passes=3,pure_getters,unsafe' - '-mc passes=3,pure_getters,unsafe'
script: script:

View File

@@ -533,8 +533,8 @@ if (result.error) throw result.error;
Pass an object to specify custom [mangle property options](#mangle-properties-options). Pass an object to specify custom [mangle property options](#mangle-properties-options).
- `module` (default: `true`) — process input as ES module, i.e. implicit - `module` (default: `true`) — process input as ES module, i.e. implicit
`"use strict";` and support for top-level `await`, alongside with `toplevel` `"use strict";` and support for top-level `await`. When explicitly specified,
enabled. also enables `toplevel`.
- `nameCache` (default: `null`) — pass an empty object `{}` or a previously - `nameCache` (default: `null`) — pass an empty object `{}` or a previously
used `nameCache` object if you wish to cache mangled variable and used `nameCache` object if you wish to cache mangled variable and
@@ -752,7 +752,7 @@ to be `false` and all symbol names will be omitted.
- `merge_vars` (default: `true`) — combine and reuse variables. - `merge_vars` (default: `true`) — combine and reuse variables.
- `module` (default: `false`) — set to `true` if you wish to process input as - `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` alongside with `toplevel` enabled. ES module, i.e. implicit `"use strict";`.
- `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions" - `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions"
where the return value is discarded, to avoid the parentheses that the where the return value is discarded, to avoid the parentheses that the
@@ -927,9 +927,8 @@ can pass additional arguments that control the code output:
regexps (affects directives with non-ascii characters becoming invalid) regexps (affects directives with non-ascii characters becoming invalid)
- `beautify` (default: `true`) — whether to actually beautify the output. - `beautify` (default: `true`) — whether to actually beautify the output.
Passing `-b` will set this to true, but you might need to pass `-b` even Passing `-b` will set this to true. Use `-O` if you want to generate minified
when you want to generate minified code, in order to specify additional code and specify additional arguments.
arguments, so you can use `-b beautify=false` to override it.
- `braces` (default: `false`) — always insert braces in `if`, `for`, - `braces` (default: `false`) — always insert braces in `if`, `for`,
`do`, `while` or `with` statements, even if their body is a single `do`, `while` or `with` statements, even if their body is a single

View File

@@ -272,7 +272,6 @@ if (typeof options.sourceMap == "object" && "base" in options.sourceMap) {
if (specified["self"]) { if (specified["self"]) {
if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed"); if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
if (!options.wrap) options.wrap = "UglifyJS"; if (!options.wrap) options.wrap = "UglifyJS";
if (!("toplevel" in options)) options.toplevel = false;
paths = UglifyJS.FILES; paths = UglifyJS.FILES;
} else if (paths.length) { } else if (paths.length) {
paths = simple_glob(paths); paths = simple_glob(paths);

View File

@@ -98,7 +98,7 @@ function Compressor(options, false_by_default) {
switches : !false_by_default, switches : !false_by_default,
templates : !false_by_default, templates : !false_by_default,
top_retain : null, top_retain : null,
toplevel : !!(options && !options["expression"] && (options["module"] || options["top_retain"])), toplevel : !!(options && !options["expression"] && options["top_retain"]),
typeofs : !false_by_default, typeofs : !false_by_default,
unsafe : false, unsafe : false,
unsafe_comps : false, unsafe_comps : false,

View File

@@ -89,7 +89,7 @@ function minify(files, options) {
rename: undefined, rename: undefined,
sourceMap: false, sourceMap: false,
timings: false, timings: false,
toplevel: undefined, toplevel: options && !options["expression"] && options["module"] ? true : undefined,
v8: false, v8: false,
validate: false, validate: false,
warnings: false, warnings: false,
@@ -106,7 +106,6 @@ function minify(files, options) {
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]); if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]);
if (options.module === undefined && !options.ie) options.module = true; if (options.module === undefined && !options.ie) options.module = true;
if (options.module) set_shorthand("module", options, [ "compress", "parse" ]); if (options.module) set_shorthand("module", options, [ "compress", "parse" ]);
if (options.toplevel === undefined && !options.expression && options.module) options.toplevel = true;
if (options.toplevel !== undefined) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]); if (options.toplevel !== undefined) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]);
if (options.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]); if (options.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]);
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]); if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]);

View File

@@ -8663,6 +8663,7 @@ module_inline: {
inline: true, inline: true,
module: true, module: true,
reduce_vars: true, reduce_vars: true,
toplevel: true,
} }
input: { input: {
var a = f; var a = f;

View File

@@ -14,7 +14,7 @@ if (typeof phantom == "undefined") {
args.splice(debug, 1); args.splice(debug, 1);
debug = true; debug = true;
} }
if (!args.length) args.push("-mcb", "beautify=false,webkit"); if (!args.length) args.push("-mcO", "webkit");
args.unshift("bin/uglifyjs"); args.unshift("bin/uglifyjs");
args.push("--validate", "--timings"); args.push("--validate", "--timings");
var child_process = require("child_process"); var child_process = require("child_process");

View File

@@ -1068,7 +1068,7 @@ describe("bin/uglifyjs", function() {
]).join("\n"); ]).join("\n");
exec(uglifyjscmd + " -mc", function(err, stdout) { exec(uglifyjscmd + " -mc", function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "console.log({p:25}.p+{p:121}.p+{p:1024}.p);\n"); 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)); assert.strictEqual(run_code(stdout), run_code(code));
done(); done();
}).stdin.end(code); }).stdin.end(code);

View File

@@ -117,7 +117,6 @@ describe("comments", function() {
beautify: true, beautify: true,
comments: "all", comments: "all",
}, },
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, [ assert.strictEqual(result.code, [
@@ -377,7 +376,6 @@ describe("comments", function() {
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
compress: { collapse_vars: false, reduce_vars: false }, compress: { collapse_vars: false, reduce_vars: false },
output: { comments: true }, output: { comments: true },
toplevel: false,
}); });
assert.strictEqual(result.code, 'function f(){/*c1*/var/*c2*/n=/*c3*/!1;return n}'); assert.strictEqual(result.code, 'function f(){/*c1*/var/*c2*/n=/*c3*/!1;return n}');
}); });
@@ -386,7 +384,6 @@ describe("comments", function() {
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
compress: { collapse_vars: false, reduce_vars: false }, compress: { collapse_vars: false, reduce_vars: false },
output: { comments: false }, output: { comments: false },
toplevel: false,
}); });
assert.strictEqual(result.code, 'function f(){var n=!1;return n}'); assert.strictEqual(result.code, 'function f(){var n=!1;return n}');
}); });
@@ -461,7 +458,6 @@ describe("comments", function() {
it("Should handle shebang and preamble correctly", function() { it("Should handle shebang and preamble correctly", function() {
var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", { var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", {
output: { preamble: "/* Build */" }, output: { preamble: "/* Build */" },
toplevel: false,
}).code; }).code;
assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;"); assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;");
}); });
@@ -469,7 +465,6 @@ describe("comments", function() {
it("Should handle preamble without shebang correctly", function() { it("Should handle preamble without shebang correctly", function() {
var code = UglifyJS.minify("var x = 10;", { var code = UglifyJS.minify("var x = 10;", {
output: { preamble: "/* Build */" }, output: { preamble: "/* Build */" },
toplevel: false,
}).code; }).code;
assert.strictEqual(code, "/* Build */\nvar x=10;"); assert.strictEqual(code, "/* Build */\nvar x=10;");
}); });
@@ -483,7 +478,6 @@ describe("comments", function() {
js += "x; }"; js += "x; }";
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
mangle: false, mangle: false,
toplevel: false,
}); });
assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}"); assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
}); });

View File

@@ -8,7 +8,6 @@ describe("Input file as map", function() {
}; };
var result = UglifyJS.minify(jsMap, { var result = UglifyJS.minify(jsMap, {
sourceMap: true, sourceMap: true,
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
@@ -31,7 +30,6 @@ describe("Input file as map", function() {
]; ];
var result = UglifyJS.minify(jsSeq, { var result = UglifyJS.minify(jsSeq, {
sourceMap: true, sourceMap: true,
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
@@ -47,7 +45,6 @@ describe("Input file as map", function() {
sourceMap: { sourceMap: {
includeSources: true, includeSources: true,
}, },
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);

View File

@@ -11,9 +11,7 @@ function read(path) {
describe("minify", function() { describe("minify", function() {
it("Should test basic sanity of minify with default options", function() { it("Should test basic sanity of minify with default options", function() {
var js = "function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }"; var js = "function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }";
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js);
module: false,
});
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, "function foo(n){return n?3:7}"); assert.strictEqual(result.code, "function foo(n){return n?3:7}");
}); });
@@ -48,9 +46,6 @@ describe("minify", function() {
].forEach(function(file) { ].forEach(function(file) {
var code = read("test/input/issue-1242/" + file); var code = read("test/input/issue-1242/" + file);
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
compress: {
toplevel: false,
},
mangle: { mangle: {
cache: cache, cache: cache,
toplevel: true, toplevel: true,
@@ -83,9 +78,6 @@ describe("minify", function() {
].forEach(function(file) { ].forEach(function(file) {
var code = read("test/input/issue-1242/" + file); var code = read("test/input/issue-1242/" + file);
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
compress: {
toplevel: false,
},
mangle: { mangle: {
toplevel: true, toplevel: true,
}, },
@@ -172,7 +164,6 @@ describe("minify", function() {
output: { output: {
keep_quoted_props: true, keep_quoted_props: true,
}, },
toplevel: false,
}); });
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};'); assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
}); });
@@ -183,7 +174,6 @@ describe("minify", function() {
keep_quoted_props: true, keep_quoted_props: true,
quote_style: 3, quote_style: 3,
}, },
toplevel: false,
}); });
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};'); assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
}); });
@@ -194,7 +184,6 @@ describe("minify", function() {
keep_quoted_props: false, keep_quoted_props: false,
quote_style: 3, quote_style: 3,
}, },
toplevel: false,
}); });
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
}); });
@@ -248,7 +237,6 @@ describe("minify", function() {
comments: "all", comments: "all",
beautify: false, beautify: false,
}, },
toplevel: false,
}); });
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=function(){foo()}();"); assert.strictEqual(code, "var a=function(){foo()}();");
@@ -328,7 +316,6 @@ describe("minify", function() {
UglifyJS.minify(ast, { UglifyJS.minify(ast, {
compress: { compress: {
sequences: false, sequences: false,
toplevel: false,
}, },
mangle: false, mangle: false,
}); });

View File

@@ -333,6 +333,7 @@ describe("test/reduce.js", function() {
unsafe_math: true, unsafe_math: true,
}, },
mangle: false, mangle: false,
module: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, [ assert.strictEqual(result.code, [
@@ -346,7 +347,8 @@ describe("test/reduce.js", function() {
'// "compress": {', '// "compress": {',
'// "unsafe_math": true', '// "unsafe_math": true',
'// },', '// },',
'// "mangle": false', '// "mangle": false,',
'// "module": false',
"// }", "// }",
].join("\n")); ].join("\n"));
}); });

View File

@@ -109,7 +109,6 @@ describe("sourcemaps", function() {
"}", "}",
].join("\n"), { ].join("\n"), {
sourceMap: true, sourceMap: true,
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, "class A{static P=42;set#q(s){}}"); assert.strictEqual(result.code, "class A{static P=42;set#q(s){}}");
@@ -188,7 +187,6 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
content: "inline", content: "inline",
}, },
toplevel: false,
warnings: true, warnings: true,
}); });
assert.strictEqual(result.code, "var bar=function(bar){return bar};"); assert.strictEqual(result.code, "var bar=function(bar){return bar};");
@@ -203,7 +201,6 @@ describe("sourcemaps", function() {
content: "inline", content: "inline",
url: "inline", url: "inline",
}, },
toplevel: false,
warnings: true, warnings: true,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
@@ -301,7 +298,6 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
url: "inline", url: "inline",
}, },
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var code = result.code; var code = result.code;
@@ -309,9 +305,7 @@ describe("sourcemaps", function() {
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BLENBQUsifQ=="); "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BLENBQUsifQ==");
}); });
it("Should not append source map to output js when sourceMapInline is not enabled", function() { 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; };", { var result = UglifyJS.minify("var a = function(foo) { return foo; };");
module: false,
});
if (result.error) throw result.error; if (result.error) throw result.error;
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=function(n){return n};"); assert.strictEqual(code, "var a=function(n){return n};");
@@ -327,7 +321,6 @@ describe("sourcemaps", function() {
sourceMap: { sourceMap: {
url: "inline", url: "inline",
}, },
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, read("test/input/issue-505/output.js")); assert.strictEqual(result.code, read("test/input/issue-505/output.js"));
@@ -342,7 +335,6 @@ describe("sourcemaps", function() {
includeSources: true, includeSources: true,
url: "inline", url: "inline",
}, },
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
@@ -357,7 +349,6 @@ describe("sourcemaps", function() {
content: "inline", content: "inline",
includeSources: true, includeSources: true,
}, },
toplevel: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
map = JSON.parse(result.map); map = JSON.parse(result.map);

View File

@@ -20,6 +20,9 @@ Error.stackTraceLimit = Infinity;
module.exports = function reduce_test(testcase, minify_options, reduce_options) { module.exports = function reduce_test(testcase, minify_options, reduce_options) {
minify_options = minify_options || {}; minify_options = minify_options || {};
reduce_options = reduce_options || {}; reduce_options = reduce_options || {};
var parse_options = {
module: minify_options.module || minify_options.module === undefined,
}
var print_options = {}; var print_options = {};
[ [
"ie", "ie",
@@ -539,9 +542,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var before_iterations, diff_error_message, passes = 3, testcase_ast; var before_iterations, diff_error_message, passes = 3, testcase_ast;
for (var pass = 1; pass <= passes; pass++) { for (var pass = 1; pass <= passes; pass++) {
if (before_iterations !== testcase) { if (before_iterations !== testcase) {
testcase_ast = U.parse(testcase, { testcase_ast = U.parse(testcase, parse_options);
module: minify_options.module,
});
if (diff_error_message === testcase) { if (diff_error_message === testcase) {
// only difference detected is in error message, so expose that and try again // only difference detected is in error message, so expose that and try again
testcase_ast.transform(new U.TreeTransformer(function(node, descend) { testcase_ast.transform(new U.TreeTransformer(function(node, descend) {
@@ -563,9 +564,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
testcase = code; testcase = code;
differs = diff; differs = diff;
} else { } else {
testcase_ast = U.parse(testcase, { testcase_ast = U.parse(testcase, parse_options);
module: minify_options.module,
});
} }
} }
diff_error_message = null; diff_error_message = null;
@@ -778,7 +777,7 @@ function run_code(code, toplevel, result_cache, timeout) {
if (!value) { if (!value) {
var start = Date.now(); var start = Date.now();
result_cache[key] = value = { result_cache[key] = value = {
result: sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout), result: sandbox.run_code(code, toplevel, timeout),
elapsed: Date.now() - start, elapsed: Date.now() - start,
}; };
} }
@@ -806,13 +805,7 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) {
}; };
function run(code, timeout) { function run(code, timeout) {
if (minify_options.module) code = [ return run_code(sandbox.patch_module_statements(code, minify_options.module), toplevel, result_cache, timeout);
'"use strict";',
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
].join("\n");
return run_code(code, toplevel, result_cache, timeout);
} }
} }

View File

@@ -1,11 +1,8 @@
require("./run")([ require("./run")([
"-b", "-mb braces",
"-b braces", "--toplevel -c",
"-m",
"-mc passes=3",
"--no-module -mc", "--no-module -mc",
"-mc passes=3,unsafe", "-mc passes=3,unsafe",
"-mc keep_fargs=false,passes=3",
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto", "-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
].map(function(options) { ].map(function(options) {
var args = options.split(/ /); var args = options.split(/ /);

View File

@@ -4,7 +4,7 @@ require("./run")([
].map(function(options) { ].map(function(options) {
var args = options.split(/ /); var args = options.split(/ /);
args.unshift("test/jetstream.js"); args.unshift("test/jetstream.js");
args.push("-b", "beautify=false,webkit"); args.push("-O", "webkit");
args.push("--no-module"); args.push("--no-module");
return args; return args;
})); }));

View File

@@ -48,7 +48,16 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
} : function(expected, actual) { } : function(expected, actual) {
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual); return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
}; };
exports.patch_module_statements = function(code) { exports.patch_module_statements = function(code, module) {
if (module || module === undefined && /\bawait\b/.test(code)) {
code = [
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
];
if (module) code.unshift('"use strict";');
code = code.join("\n");
}
var count = 0, has_default = "", imports = [], strict_mode = ""; var count = 0, has_default = "", imports = [], strict_mode = "";
code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) { code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) {
strict_mode = match; strict_mode = match;

View File

@@ -2113,13 +2113,7 @@ if (require.main !== module) {
} }
function run_code(code, toplevel, timeout) { function run_code(code, toplevel, timeout) {
if (async && has_await) code = [ return sandbox.run_code(sandbox.patch_module_statements(code, async && has_await), toplevel, timeout);
'"use strict";',
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
].join("\n");
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
} }
function writeln(stream, msg) { function writeln(stream, msg) {