diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 59f7073b973..5f92e7e4c67 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,9 +9,9 @@ jobs: fail-fast: false matrix: options: - - '-mb braces' - '--ie -c' - - '-mc' + - '-mb braces' + - '--toplevel -mc' - '-p acorn -mco spidermonkey' - '-mc passes=3,pure_getters,unsafe' script: diff --git a/README.md b/README.md index c008c96afce..e86f33d0589 100644 --- a/README.md +++ b/README.md @@ -533,8 +533,8 @@ if (result.error) throw result.error; Pass an object to specify custom [mangle property options](#mangle-properties-options). - `module` (default: `true`) — process input as ES module, i.e. implicit - `"use strict";` and support for top-level `await`, alongside with `toplevel` - enabled. + `"use strict";` and support for top-level `await`. When explicitly specified, + also enables `toplevel`. - `nameCache` (default: `null`) — pass an empty object `{}` or a previously 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. - `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" 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) - `beautify` (default: `true`) — whether to actually beautify the output. - Passing `-b` will set this to true, but you might need to pass `-b` even - when you want to generate minified code, in order to specify additional - arguments, so you can use `-b beautify=false` to override it. + Passing `-b` will set this to true. Use `-O` if you want to generate minified + code and specify additional arguments. - `braces` (default: `false`) — always insert braces in `if`, `for`, `do`, `while` or `with` statements, even if their body is a single diff --git a/bin/uglifyjs b/bin/uglifyjs index 345765a41ee..a2a0257520f 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -272,7 +272,6 @@ if (typeof options.sourceMap == "object" && "base" in options.sourceMap) { if (specified["self"]) { if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed"); if (!options.wrap) options.wrap = "UglifyJS"; - if (!("toplevel" in options)) options.toplevel = false; paths = UglifyJS.FILES; } else if (paths.length) { paths = simple_glob(paths); diff --git a/lib/compress.js b/lib/compress.js index 2c725997642..245c3737b2f 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -98,7 +98,7 @@ function Compressor(options, false_by_default) { switches : !false_by_default, templates : !false_by_default, top_retain : null, - toplevel : !!(options && !options["expression"] && (options["module"] || options["top_retain"])), + toplevel : !!(options && !options["expression"] && options["top_retain"]), typeofs : !false_by_default, unsafe : false, unsafe_comps : false, diff --git a/lib/minify.js b/lib/minify.js index eaec6527f64..1771338c1ff 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -89,7 +89,7 @@ function minify(files, options) { rename: undefined, sourceMap: false, timings: false, - toplevel: undefined, + toplevel: options && !options["expression"] && options["module"] ? true : undefined, v8: false, validate: 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.module === undefined && !options.ie) options.module = true; 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.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]); if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]); diff --git a/test/compress/functions.js b/test/compress/functions.js index f97e750ee48..8a46879cbb6 100644 --- a/test/compress/functions.js +++ b/test/compress/functions.js @@ -8663,6 +8663,7 @@ module_inline: { inline: true, module: true, reduce_vars: true, + toplevel: true, } input: { var a = f; diff --git a/test/jetstream.js b/test/jetstream.js index 114c8988f0c..f5d91a13758 100644 --- a/test/jetstream.js +++ b/test/jetstream.js @@ -14,7 +14,7 @@ if (typeof phantom == "undefined") { args.splice(debug, 1); debug = true; } - if (!args.length) args.push("-mcb", "beautify=false,webkit"); + if (!args.length) args.push("-mcO", "webkit"); args.unshift("bin/uglifyjs"); args.push("--validate", "--timings"); var child_process = require("child_process"); diff --git a/test/mocha/cli.js b/test/mocha/cli.js index 00e346351fd..2e7f8fe517f 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -1068,7 +1068,7 @@ describe("bin/uglifyjs", function() { ]).join("\n"); exec(uglifyjscmd + " -mc", function(err, stdout) { 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)); done(); }).stdin.end(code); diff --git a/test/mocha/comments.js b/test/mocha/comments.js index 38beaf5bb80..86a6a004362 100644 --- a/test/mocha/comments.js +++ b/test/mocha/comments.js @@ -117,7 +117,6 @@ describe("comments", function() { beautify: true, comments: "all", }, - toplevel: false, }); if (result.error) throw result.error; assert.strictEqual(result.code, [ @@ -377,7 +376,6 @@ describe("comments", function() { var result = UglifyJS.minify(js, { compress: { collapse_vars: false, reduce_vars: false }, output: { comments: true }, - toplevel: false, }); 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, { compress: { collapse_vars: false, reduce_vars: false }, output: { comments: false }, - toplevel: false, }); 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() { var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", { output: { preamble: "/* Build */" }, - toplevel: false, }).code; 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() { var code = UglifyJS.minify("var x = 10;", { output: { preamble: "/* Build */" }, - toplevel: false, }).code; assert.strictEqual(code, "/* Build */\nvar x=10;"); }); @@ -483,7 +478,6 @@ describe("comments", function() { js += "x; }"; var result = UglifyJS.minify(js, { mangle: false, - toplevel: false, }); assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}"); }); diff --git a/test/mocha/minify-file-map.js b/test/mocha/minify-file-map.js index 68d8ec1f1c3..29005845f02 100644 --- a/test/mocha/minify-file-map.js +++ b/test/mocha/minify-file-map.js @@ -8,7 +8,6 @@ describe("Input file as map", function() { }; var result = UglifyJS.minify(jsMap, { sourceMap: true, - toplevel: false, }); if (result.error) throw result.error; var map = JSON.parse(result.map); @@ -31,7 +30,6 @@ describe("Input file as map", function() { ]; var result = UglifyJS.minify(jsSeq, { sourceMap: true, - toplevel: false, }); if (result.error) throw result.error; var map = JSON.parse(result.map); @@ -47,7 +45,6 @@ describe("Input file as map", function() { sourceMap: { includeSources: true, }, - toplevel: false, }); if (result.error) throw result.error; var map = JSON.parse(result.map); diff --git a/test/mocha/minify.js b/test/mocha/minify.js index 8c229069a2c..e63acd82d26 100644 --- a/test/mocha/minify.js +++ b/test/mocha/minify.js @@ -11,9 +11,7 @@ function read(path) { describe("minify", 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 result = UglifyJS.minify(js, { - module: false, - }); + var result = UglifyJS.minify(js); if (result.error) throw result.error; assert.strictEqual(result.code, "function foo(n){return n?3:7}"); }); @@ -48,9 +46,6 @@ describe("minify", function() { ].forEach(function(file) { var code = read("test/input/issue-1242/" + file); var result = UglifyJS.minify(code, { - compress: { - toplevel: false, - }, mangle: { cache: cache, toplevel: true, @@ -83,9 +78,6 @@ describe("minify", function() { ].forEach(function(file) { var code = read("test/input/issue-1242/" + file); var result = UglifyJS.minify(code, { - compress: { - toplevel: false, - }, mangle: { toplevel: true, }, @@ -172,7 +164,6 @@ describe("minify", function() { output: { keep_quoted_props: true, }, - toplevel: false, }); assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};'); }); @@ -183,7 +174,6 @@ describe("minify", function() { keep_quoted_props: true, quote_style: 3, }, - toplevel: false, }); assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};'); }); @@ -194,7 +184,6 @@ describe("minify", function() { keep_quoted_props: false, quote_style: 3, }, - toplevel: false, }); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); }); @@ -248,7 +237,6 @@ describe("minify", function() { comments: "all", beautify: false, }, - toplevel: false, }); var code = result.code; assert.strictEqual(code, "var a=function(){foo()}();"); @@ -328,7 +316,6 @@ describe("minify", function() { UglifyJS.minify(ast, { compress: { sequences: false, - toplevel: false, }, mangle: false, }); diff --git a/test/mocha/reduce.js b/test/mocha/reduce.js index e022d3a7b8f..6aecbb88a42 100644 --- a/test/mocha/reduce.js +++ b/test/mocha/reduce.js @@ -333,6 +333,7 @@ describe("test/reduce.js", function() { unsafe_math: true, }, mangle: false, + module: false, }); if (result.error) throw result.error; assert.strictEqual(result.code, [ @@ -346,7 +347,8 @@ describe("test/reduce.js", function() { '// "compress": {', '// "unsafe_math": true', '// },', - '// "mangle": false', + '// "mangle": false,', + '// "module": false', "// }", ].join("\n")); }); diff --git a/test/mocha/sourcemaps.js b/test/mocha/sourcemaps.js index 00560aaec75..4efd42d13ce 100644 --- a/test/mocha/sourcemaps.js +++ b/test/mocha/sourcemaps.js @@ -109,7 +109,6 @@ describe("sourcemaps", function() { "}", ].join("\n"), { sourceMap: true, - toplevel: false, }); if (result.error) throw result.error; assert.strictEqual(result.code, "class A{static P=42;set#q(s){}}"); @@ -188,7 +187,6 @@ describe("sourcemaps", function() { sourceMap: { content: "inline", }, - toplevel: false, warnings: true, }); assert.strictEqual(result.code, "var bar=function(bar){return bar};"); @@ -203,7 +201,6 @@ describe("sourcemaps", function() { content: "inline", url: "inline", }, - toplevel: false, warnings: true, }); if (result.error) throw result.error; @@ -301,7 +298,6 @@ describe("sourcemaps", function() { sourceMap: { url: "inline", }, - toplevel: false, }); if (result.error) throw result.error; var code = result.code; @@ -309,9 +305,7 @@ describe("sourcemaps", function() { "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BLENBQUsifQ=="); }); 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; };", { - module: false, - }); + 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};"); @@ -327,7 +321,6 @@ describe("sourcemaps", function() { sourceMap: { url: "inline", }, - toplevel: false, }); if (result.error) throw result.error; assert.strictEqual(result.code, read("test/input/issue-505/output.js")); @@ -342,7 +335,6 @@ describe("sourcemaps", function() { includeSources: true, url: "inline", }, - toplevel: false, }); if (result.error) throw result.error; var map = JSON.parse(result.map); @@ -357,7 +349,6 @@ describe("sourcemaps", function() { content: "inline", includeSources: true, }, - toplevel: false, }); if (result.error) throw result.error; map = JSON.parse(result.map); diff --git a/test/reduce.js b/test/reduce.js index beb05f5930f..bb80538ec6b 100644 --- a/test/reduce.js +++ b/test/reduce.js @@ -20,6 +20,9 @@ Error.stackTraceLimit = Infinity; module.exports = function reduce_test(testcase, minify_options, reduce_options) { minify_options = minify_options || {}; reduce_options = reduce_options || {}; + var parse_options = { + module: minify_options.module || minify_options.module === undefined, + } var print_options = {}; [ "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; for (var pass = 1; pass <= passes; pass++) { if (before_iterations !== testcase) { - testcase_ast = U.parse(testcase, { - module: minify_options.module, - }); + testcase_ast = U.parse(testcase, parse_options); if (diff_error_message === testcase) { // only difference detected is in error message, so expose that and try again 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; differs = diff; } else { - testcase_ast = U.parse(testcase, { - module: minify_options.module, - }); + testcase_ast = U.parse(testcase, parse_options); } } diff_error_message = null; @@ -778,7 +777,7 @@ function run_code(code, toplevel, result_cache, timeout) { if (!value) { var start = Date.now(); 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, }; } @@ -806,13 +805,7 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) { }; function run(code, timeout) { - if (minify_options.module) code = [ - '"use strict";', - "(async()=>{", - code, - '})().catch(e=>process.on("exit",()=>{throw e}));', - ].join("\n"); - return run_code(code, toplevel, result_cache, timeout); + return run_code(sandbox.patch_module_statements(code, minify_options.module), toplevel, result_cache, timeout); } } diff --git a/test/release/benchmark.js b/test/release/benchmark.js index a27c8c8291a..78405e31a69 100644 --- a/test/release/benchmark.js +++ b/test/release/benchmark.js @@ -1,11 +1,8 @@ require("./run")([ - "-b", - "-b braces", - "-m", - "-mc passes=3", + "-mb braces", + "--toplevel -c", "--no-module -mc", "-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", ].map(function(options) { var args = options.split(/ /); diff --git a/test/release/jetstream.js b/test/release/jetstream.js index 2194899756f..679728fcefe 100644 --- a/test/release/jetstream.js +++ b/test/release/jetstream.js @@ -4,7 +4,7 @@ require("./run")([ ].map(function(options) { var args = options.split(/ /); args.unshift("test/jetstream.js"); - args.push("-b", "beautify=false,webkit"); + args.push("-O", "webkit"); args.push("--no-module"); return args; })); diff --git a/test/sandbox.js b/test/sandbox.js index 4cb9f2ef5a6..0fd9fc2daea 100644 --- a/test/sandbox.js +++ b/test/sandbox.js @@ -48,7 +48,16 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec } : function(expected, 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 = ""; code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) { strict_mode = match; diff --git a/test/ufuzz/index.js b/test/ufuzz/index.js index cc9d20668b2..eb38de375cd 100644 --- a/test/ufuzz/index.js +++ b/test/ufuzz/index.js @@ -2113,13 +2113,7 @@ if (require.main !== module) { } function run_code(code, toplevel, timeout) { - if (async && has_await) code = [ - '"use strict";', - "(async()=>{", - code, - '})().catch(e=>process.on("exit",()=>{throw e}));', - ].join("\n"); - return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout); + return sandbox.run_code(sandbox.patch_module_statements(code, async && has_await), toplevel, timeout); } function writeln(stream, msg) {