From: Jiavan Date: Fri, 1 Jun 2018 08:47:11 +0000 (+0800) Subject: re-introduce `enclose` (#3163) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=b39043f3ab0061f2db91514dbb69e85a49a99997;p=UglifyJS.git re-introduce `enclose` (#3163) fixes #2443 --- diff --git a/README.md b/README.md index 6d1cdf8f..663ce7b4 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,8 @@ a double dash to prevent input files being used as option arguments: sequences. --config-file Read `minify()` options from JSON file. -d, --define [=value] Global definitions. + -e, --enclose [arg[:value]] Embed everything in a big function, with configurable + argument(s) & value(s). --ie8 Support non-standard Internet Explorer 8. Equivalent to setting `ie8: true` in `minify()` for `compress`, `mangle` and `output` options. diff --git a/bin/uglifyjs b/bin/uglifyjs index 7617d781..fb6ae2fb 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -40,6 +40,7 @@ program.option("-o, --output ", "Output file (default STDOUT)."); program.option("--comments [filter]", "Preserve copyright comments in the output."); program.option("--config-file ", "Read minify() options from JSON file."); program.option("-d, --define [=value]", "Global definitions.", parse_js("define")); +program.option("-e, --enclose [arg[,...][:value[,...]]]", "Embed everything in a big function, with configurable argument(s) & value(s)."); program.option("--ie8", "Support non-standard Internet Explorer 8."); program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name."); program.option("--name-cache ", "File to hold mangled name mappings."); @@ -47,7 +48,7 @@ program.option("--rename", "Force symbol expansion."); program.option("--no-rename", "Disable symbol expansion."); program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)"); program.option("--source-map [options]", "Enable source map/specify source map options.", parse_js()); -program.option("--timings", "Display operations run time on STDERR.") +program.option("--timings", "Display operations run time on STDERR."); program.option("--toplevel", "Compress and/or mangle variables in toplevel scope."); program.option("--verbose", "Print diagnostic messages."); program.option("--warn", "Print warning messages."); @@ -61,6 +62,7 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") { } [ "compress", + "enclose", "ie8", "mangle", "sourceMap", diff --git a/lib/ast.js b/lib/ast.js index 331d340b..1a77a59d 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -335,6 +335,23 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", { } })); return wrapped_tl; + }, + wrap_enclose: function(args_values) { + if (typeof args_values != "string") args_values = ""; + var index = args_values.indexOf(":"); + if (index < 0) index = args_values.length; + var body = this.body; + return parse([ + "(function(", + args_values.slice(0, index), + '){"$ORIG"})(', + args_values.slice(index + 1), + ")" + ].join("")).transform(new TreeTransformer(function(node) { + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(body); + } + })); } }, AST_Scope); diff --git a/lib/minify.js b/lib/minify.js index 399b8615..d84f6825 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -55,6 +55,7 @@ function minify(files, options) { try { options = defaults(options, { compress: {}, + enclose: false, ie8: false, keep_fnames: false, mangle: {}, @@ -157,6 +158,9 @@ function minify(files, options) { if (options.wrap) { toplevel = toplevel.wrap_commonjs(options.wrap); } + if (options.enclose) { + toplevel = toplevel.wrap_enclose(options.enclose); + } if (timings) timings.rename = Date.now(); if (options.rename) { toplevel.figure_out_scope(options.mangle); diff --git a/test/input/enclose/input.js b/test/input/enclose/input.js new file mode 100644 index 00000000..5f53997b --- /dev/null +++ b/test/input/enclose/input.js @@ -0,0 +1,4 @@ +function enclose() { + console.log("test enclose"); +} +enclose(); diff --git a/test/mocha/cli.js b/test/mocha/cli.js index 3b3dcab1..2e1c3b64 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -6,7 +6,7 @@ function read(path) { return fs.readFileSync(path, "utf8"); } -describe("bin/uglifyjs", function () { +describe("bin/uglifyjs", function() { var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs'; it("should produce a functional build when using --self", function (done) { this.timeout(30000); @@ -744,4 +744,36 @@ describe("bin/uglifyjs", function () { done(); }); }); + it("Should work with --enclose", function(done) { + var command = uglifyjscmd + " test/input/enclose/input.js --enclose"; + exec(command, function(err, stdout, stderr) { + if (err) throw err; + assert.strictEqual(stdout, '(function(){function enclose(){console.log("test enclose")}enclose()})();\n'); + done(); + }); + }); + it("Should work with --enclose arg", function(done) { + var command = uglifyjscmd + " test/input/enclose/input.js --enclose undefined"; + exec(command, function(err, stdout, stderr) { + if (err) throw err; + assert.strictEqual(stdout, '(function(undefined){function enclose(){console.log("test enclose")}enclose()})();\n'); + done(); + }); + }); + it("Should work with --enclose arg:value", function(done) { + var command = uglifyjscmd + " test/input/enclose/input.js --enclose window,undefined:window"; + exec(command, function(err, stdout, stderr) { + if (err) throw err; + assert.strictEqual(stdout, '(function(window,undefined){function enclose(){console.log("test enclose")}enclose()})(window);\n'); + done(); + }); + }); + it("Should work with --enclose & --wrap", function(done) { + var command = uglifyjscmd + " test/input/enclose/input.js --enclose window,undefined:window --wrap exports"; + exec(command, function(err, stdout, stderr) { + if (err) throw err; + assert.strictEqual(stdout, '(function(window,undefined){(function(exports){function enclose(){console.log("test enclose")}enclose()})(typeof exports=="undefined"?exports={}:exports)})(window);\n'); + done(); + }); + }); }); diff --git a/test/mocha/minify.js b/test/mocha/minify.js index c8c17778..f394cc62 100644 --- a/test/mocha/minify.js +++ b/test/mocha/minify.js @@ -303,4 +303,45 @@ describe("minify", function() { } }); }); + + describe("enclose", function() { + var code = read("test/input/enclose/input.js"); + it("Should work with true", function() { + var result = Uglify.minify(code, { + compress: false, + enclose: true, + mangle: false, + }); + if (result.error) throw result.error; + assert.strictEqual(result.code, '(function(){function enclose(){console.log("test enclose")}enclose()})();'); + }); + it("Should work with arg", function() { + var result = Uglify.minify(code, { + compress: false, + enclose: 'undefined', + mangle: false, + }); + if (result.error) throw result.error; + assert.strictEqual(result.code, '(function(undefined){function enclose(){console.log("test enclose")}enclose()})();'); + }); + it("Should work with arg:value", function() { + var result = Uglify.minify(code, { + compress: false, + enclose: 'window,undefined:window', + mangle: false, + }); + if (result.error) throw result.error; + assert.strictEqual(result.code, '(function(window,undefined){function enclose(){console.log("test enclose")}enclose()})(window);'); + }); + it("Should work alongside wrap", function() { + var result = Uglify.minify(code, { + compress: false, + enclose: 'window,undefined:window', + mangle: false, + wrap: 'exports', + }); + if (result.error) throw result.error; + assert.strictEqual(result.code, '(function(window,undefined){(function(exports){function enclose(){console.log("test enclose")}enclose()})(typeof exports=="undefined"?exports={}:exports)})(window);'); + }); + }); });