aboutsummaryrefslogtreecommitdiff
path: root/bin/uglifyjs
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2020-06-07 06:48:51 +0100
committerGitHub <noreply@github.com>2020-06-07 13:48:51 +0800
commit28b7b15da19a2a081ab768f8315ce39db7c52b63 (patch)
treef114408c711f62fd2835235c171a136efde73c6c /bin/uglifyjs
parentaa37b196989edc13988ab225e4a7c954565e39eb (diff)
downloadtracifyjs-28b7b15da19a2a081ab768f8315ce39db7c52b63.tar.gz
tracifyjs-28b7b15da19a2a081ab768f8315ce39db7c52b63.zip
parse command line internally (#3961)
Diffstat (limited to 'bin/uglifyjs')
-rwxr-xr-xbin/uglifyjs481
1 files changed, 269 insertions, 212 deletions
diff --git a/bin/uglifyjs b/bin/uglifyjs
index 500fe6d8..c15acca6 100755
--- a/bin/uglifyjs
+++ b/bin/uglifyjs
@@ -8,185 +8,251 @@ require("../tools/exit");
var fs = require("fs");
var info = require("../package.json");
var path = require("path");
-var program = require("commander");
var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var files = {};
-var options = {
- compress: false,
- mangle: false
+var options = {};
+var short_forms = {
+ b: "beautify",
+ c: "compress",
+ d: "define",
+ e: "enclose",
+ h: "help",
+ m: "mangle",
+ o: "output",
+ O: "output-opts",
+ p: "parse",
+ v: "version",
+ V: "version",
};
-program.version(info.name + " " + info.version);
-program.parseArgv = program.parse;
-program.parse = undefined;
-if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
-else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
- var text = [];
- var toplevels = [];
- var padding = "";
- var options = UglifyJS.default_options();
- for (var name in options) {
- var option = options[name];
- if (option && typeof option == "object") {
- text.push("--" + ({
- output: "beautify",
- sourceMap: "source-map",
- }[name] || name) + " options:");
- text.push(format_object(option));
- text.push("");
- } else {
- if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
- toplevels.push([ {
- keep_fnames: "keep-fnames",
- nameCache: "name-cache",
- }[name] || name, option ]);
- }
- }
- toplevels.forEach(function(tokens) {
- text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
+var args = process.argv.slice(2);
+var paths = [];
+var output, nameCache;
+var specified = {};
+while (args.length) {
+ var arg = args.shift();
+ if (arg[0] != "-") {
+ paths.push(arg);
+ } else if (arg == "--") {
+ paths = paths.concat(args);
+ break;
+ } else if (arg[1] == "-") {
+ process_option(arg.slice(2));
+ } else [].forEach.call(arg.slice(1), function(letter, index, arg) {
+ process_option(short_forms[letter], index + 1 < arg.length);
});
- return text.join("\n");
-};
-program.option("-p, --parse <options>", "Specify parser options.", parse_js());
-program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
-program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
-program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
-program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
-program.option("-O, --output-opts [options]", "Output options (beautify disabled).", parse_js());
-program.option("-o, --output <file>", "Output file (default STDOUT).");
-program.option("--comments [filter]", "Preserve copyright comments in the output.");
-program.option("--config-file <file>", "Read minify() options from JSON file.");
-program.option("-d, --define <expr>[=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>", "File to hold mangled name mappings.");
-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("--toplevel", "Compress and/or mangle variables in toplevel scope.");
-program.option("--validate", "Perform validation during AST manipulations.");
-program.option("--verbose", "Print diagnostic messages.");
-program.option("--warn", "Print warning messages.");
-program.option("--wrap <name>", "Embed everything as a function with “exports” corresponding to “name” globally.");
-program.option("--reduce-test", "Reduce a standalone `console.log` based test case.");
-program.arguments("[files...]").parseArgv(process.argv);
-if (program.configFile) {
- options = JSON.parse(read_file(program.configFile));
- if (options.mangle && options.mangle.properties && options.mangle.properties.regex) {
- options.mangle.properties.regex = UglifyJS.parse(options.mangle.properties.regex, {
- expression: true
- }).value;
- }
-}
-if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
- fatal("cannot write source map to STDOUT");
-}
-[
- "compress",
- "enclose",
- "ie8",
- "mangle",
- "sourceMap",
- "toplevel",
- "validate",
- "wrap"
-].forEach(function(name) {
- if (name in program) {
- options[name] = program[name];
- }
-});
-if (program.verbose) {
- options.warnings = "verbose";
-} else if (program.warn) {
- options.warnings = true;
-}
-if (options.warnings) {
- UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
- delete options.warnings;
}
-if (program.beautify) {
- options.output = typeof program.beautify == "object" ? program.beautify : {};
- if (!("beautify" in options.output)) {
- options.output.beautify = true;
+
+function process_option(name, no_value) {
+ specified[name] = true;
+ switch (name) {
+ case "help":
+ switch (read_value()) {
+ case "ast":
+ print(UglifyJS.describe_ast());
+ break;
+ case "options":
+ var text = [];
+ var toplevels = [];
+ var padding = "";
+ var defaults = UglifyJS.default_options();
+ for (var name in defaults) {
+ var option = defaults[name];
+ if (option && typeof option == "object") {
+ text.push("--" + ({
+ output: "beautify",
+ sourceMap: "source-map",
+ }[name] || name) + " options:");
+ text.push(format_object(option));
+ text.push("");
+ } else {
+ if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
+ toplevels.push([ {
+ keep_fnames: "keep-fnames",
+ nameCache: "name-cache",
+ }[name] || name, option ]);
+ }
+ }
+ toplevels.forEach(function(tokens) {
+ text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
+ });
+ print(text.join("\n"));
+ break;
+ default:
+ print([
+ "Usage: uglifyjs [files...] [options]",
+ "",
+ "Options:",
+ " -h, --help Print usage information.",
+ " `--help options` for details on available options.",
+ " -v, -V, --version Print version number.",
+ " -p, --parse <options> Specify parser options.",
+ " -c, --compress [options] Enable compressor/specify compressor options.",
+ " -m, --mangle [options] Mangle names/specify mangler options.",
+ " --mangle-props [options] Mangle properties/specify mangler options.",
+ " -b, --beautify [options] Beautify output/specify output options.",
+ " -O, --output-opts <options> Output options (beautify disabled).",
+ " -o, --output <file> Output file (default STDOUT).",
+ " --comments [filter] Preserve copyright comments in the output.",
+ " --config-file <file> Read minify() options from JSON file.",
+ " -d, --define <expr>[=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.",
+ " --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
+ " --name-cache <file> File to hold mangled name mappings.",
+ " --rename Force symbol expansion.",
+ " --no-rename Disable symbol expansion.",
+ " --self Build UglifyJS as a library (implies --wrap UglifyJS)",
+ " --source-map [options] Enable source map/specify source map options.",
+ " --timings Display operations run time on STDERR.",
+ " --toplevel Compress and/or mangle variables in toplevel scope.",
+ " --validate Perform validation during AST manipulations.",
+ " --verbose Print diagnostic messages.",
+ " --warn Print warning messages.",
+ " --wrap <name> Embed everything as a function with “exports” corresponding to “name” globally.",
+ " --reduce-test Reduce a standalone test case.",
+ ].join("\n"));
+ }
+ process.exit();
+ case "version":
+ print(info.name + " " + info.version);
+ process.exit();
+ case "config-file":
+ var config = JSON.parse(read_file(read_value(true)));
+ if (config.mangle && config.mangle.properties && config.mangle.properties.regex) {
+ config.mangle.properties.regex = UglifyJS.parse(config.mangle.properties.regex, {
+ expression: true,
+ }).value;
+ }
+ for (var key in config) if (!(key in options)) options[key] = config[key];
+ break;
+ case "compress":
+ case "mangle":
+ options[name] = parse_js(read_value(), options[name]);
+ break;
+ case "source-map":
+ options.sourceMap = parse_js(read_value(), options.sourceMap);
+ break;
+ case "enclose":
+ options[name] = read_value();
+ break;
+ case "ie8":
+ case "timings":
+ case "toplevel":
+ case "validate":
+ options[name] = true;
+ break;
+ case "keep-fnames":
+ options.keep_fnames = true;
+ break;
+ case "wrap":
+ options[name] = read_value(true);
+ break;
+ case "verbose":
+ options.warnings = "verbose";
+ break;
+ case "warn":
+ if (!options.warnings) options.warnings = true;
+ break;
+ case "beautify":
+ options.output = parse_js(read_value(), options.output);
+ if (!("beautify" in options.output)) options.output.beautify = true;
+ break;
+ case "output-opts":
+ options.output = parse_js(read_value(true), options.output);
+ break;
+ case "comments":
+ if (typeof options.output != "object") options.output = {};
+ options.output.comments = read_value();
+ if (options.output.comments === true) options.output.comments = "some";
+ break;
+ case "define":
+ if (typeof options.compress != "object") options.compress = {};
+ options.compress.global_defs = parse_js(read_value(true), options.compress.global_defs, "define");
+ break;
+ case "mangle-props":
+ if (typeof options.mangle != "object") options.mangle = {};
+ options.mangle.properties = parse_js(read_value(), options.mangle.properties);
+ break;
+ case "name-cache":
+ nameCache = read_value(true);
+ options.nameCache = JSON.parse(read_file(nameCache, "{}"));
+ break;
+ case "output":
+ output = read_value(true);
+ break;
+ case "parse":
+ options.parse = parse_js(read_value(true), options.parse);
+ break;
+ case "rename":
+ options.rename = true;
+ break;
+ case "no-rename":
+ options.rename = false;
+ break;
+ case "reduce-test":
+ case "self":
+ break;
+ default:
+ fatal("invalid option --" + name);
}
-}
-if (program.outputOpts) {
- if (program.beautify) fatal("--beautify cannot be used with --output-opts");
- options.output = typeof program.outputOpts == "object" ? program.outputOpts : {};
-}
-if (program.comments) {
- if (typeof options.output != "object") options.output = {};
- options.output.comments = typeof program.comments == "string" ? program.comments : "some";
-}
-if (program.define) {
- if (typeof options.compress != "object") options.compress = {};
- if (typeof options.compress.global_defs != "object") options.compress.global_defs = {};
- for (var expr in program.define) {
- options.compress.global_defs[expr] = program.define[expr];
+
+ function read_value(required) {
+ if (no_value || !args.length || args[0][0] == "-") {
+ if (required) fatal("missing option argument for --" + name);
+ return true;
+ }
+ return args.shift();
}
}
-if (program.keepFnames) {
- options.keep_fnames = true;
-}
-if (program.mangleProps) {
- if (program.mangleProps.domprops) {
- delete program.mangleProps.domprops;
+if (!output && options.sourceMap && options.sourceMap.url != "inline") fatal("cannot write source map to STDOUT");
+if (specified["beautify"] && specified["output-opts"]) fatal("--beautify cannot be used with --output-opts");
+[ "compress", "mangle" ].forEach(function(name) {
+ if (!(name in options)) options[name] = false;
+});
+if (options.mangle && options.mangle.properties) {
+ if (options.mangle.properties.domprops) {
+ delete options.mangle.properties.domprops;
} else {
- if (typeof program.mangleProps != "object") program.mangleProps = {};
- if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
+ if (typeof options.mangle.properties != "object") options.mangle.properties = {};
+ if (!Array.isArray(options.mangle.properties.reserved)) options.mangle.properties.reserved = [];
require("../tools/domprops").forEach(function(name) {
- UglifyJS.push_uniq(program.mangleProps.reserved, name);
+ UglifyJS.push_uniq(options.mangle.properties.reserved, name);
});
}
- if (typeof options.mangle != "object") options.mangle = {};
- options.mangle.properties = program.mangleProps;
}
-if (program.nameCache) {
- options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
-}
-if (program.output == "ast") {
- options.output = {
- ast: true,
- code: false
- };
-}
-if (program.parse) {
- if (!program.parse.acorn && !program.parse.spidermonkey) {
- options.parse = program.parse;
- } else if (program.sourceMap && program.sourceMap.content == "inline") {
- fatal("inline source map only works with built-in parser");
- }
+if (output == "ast") options.output = {
+ ast: true,
+ code: false,
+};
+if (options.parse && (options.parse.acorn || options.parse.spidermonkey)
+ && options.sourceMap && options.sourceMap.content == "inline") {
+ fatal("inline source map only works with built-in parser");
}
-if (~program.rawArgs.indexOf("--rename")) {
- options.rename = true;
-} else if (!program.rename) {
- options.rename = false;
+if (options.warnings) {
+ UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
+ delete options.warnings;
}
var convert_path = function(name) {
return name;
};
-if (typeof program.sourceMap == "object" && "base" in program.sourceMap) {
+if (typeof options.sourceMap == "object" && "base" in options.sourceMap) {
convert_path = function() {
- var base = program.sourceMap.base;
+ var base = options.sourceMap.base;
delete options.sourceMap.base;
return function(name) {
return path.relative(base, name);
};
}();
}
-if (program.self) {
- if (program.args.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
+if (specified["self"]) {
+ if (paths.length) UglifyJS.AST_Node.warn("Ignoring input files since --self was passed");
if (!options.wrap) options.wrap = "UglifyJS";
- simple_glob(UglifyJS.FILES).forEach(function(name) {
- files[convert_path(name)] = read_file(name);
- });
- run();
-} else if (program.args.length) {
- simple_glob(program.args).forEach(function(name) {
+ paths = UglifyJS.FILES;
+}
+if (paths.length) {
+ simple_glob(paths).forEach(function(name) {
files[convert_path(name)] = read_file(name);
});
run();
@@ -207,15 +273,14 @@ function convert_ast(fn) {
}
function run() {
- var content = program.sourceMap && program.sourceMap.content;
+ var content = options.sourceMap && options.sourceMap.content;
if (content && content != "inline") {
UglifyJS.AST_Node.info("Using input source map: " + content);
options.sourceMap.content = read_file(content, content);
}
- if (program.timings) options.timings = true;
try {
- if (program.parse) {
- if (program.parse.acorn) {
+ if (options.parse) {
+ if (options.parse.acorn) {
files = convert_ast(function(toplevel, name) {
return require("acorn").parse(files[name], {
locations: true,
@@ -223,7 +288,7 @@ function run() {
sourceFile: name
});
});
- } else if (program.parse.spidermonkey) {
+ } else if (options.parse.spidermonkey) {
files = convert_ast(function(toplevel, name) {
var obj = JSON.parse(files[name]);
if (!toplevel) return obj;
@@ -235,17 +300,17 @@ function run() {
} catch (ex) {
fatal(ex);
}
- if (program.reduceTest) {
+ var result;
+ if (specified["reduce-test"]) {
// load on demand - assumes dev tree checked out
var reduce_test = require("../test/reduce");
- var testcase = files[0] || files[Object.keys(files)[0]];
- var result = reduce_test(testcase, options, {
+ if (Object.keys(files).length != 1) fatal("can only test on a single file");
+ result = reduce_test(files[Object.keys(files)[0]], options, {
log: print_error,
verbose: true,
});
- }
- else {
- var result = UglifyJS.minify(files, options);
+ } else {
+ result = UglifyJS.minify(files, options);
}
if (result.error) {
var ex = result.error;
@@ -275,10 +340,8 @@ function run() {
print_error(format_object(ex.defs));
}
fatal(ex);
- } else if (program.output == "ast") {
- if (!options.compress && !options.mangle) {
- result.ast.figure_out_scope({});
- }
+ } else if (output == "ast") {
+ if (!options.compress && !options.mangle) result.ast.figure_out_scope({});
print(JSON.stringify(result.ast, function(key, value) {
if (value) switch (key) {
case "thedef":
@@ -304,26 +367,22 @@ function run() {
}
return value;
}, 2));
- } else if (program.output == "spidermonkey") {
+ } else if (output == "spidermonkey") {
print(JSON.stringify(UglifyJS.minify(result.code, {
compress: false,
mangle: false,
output: {
ast: true,
code: false
- }
+ },
}).ast.to_mozilla_ast(), null, 2));
- } else if (program.output) {
- fs.writeFileSync(program.output, result.code);
- if (result.map) {
- fs.writeFileSync(program.output + ".map", result.map);
- }
+ } else if (output) {
+ fs.writeFileSync(output, result.code);
+ if (result.map) fs.writeFileSync(output + ".map", result.map);
} else {
print(result.code);
}
- if (program.nameCache) {
- fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
- }
+ if (nameCache) fs.writeFileSync(nameCache, JSON.stringify(options.nameCache));
if (result.timings) for (var phase in result.timings) {
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
}
@@ -379,47 +438,45 @@ function read_file(path, default_value) {
}
}
-function parse_js(flag) {
- return function(value, options) {
- options = options || {};
- try {
- UglifyJS.parse(value, {
- expression: true
- }).walk(new UglifyJS.TreeWalker(function(node) {
- if (node instanceof UglifyJS.AST_Assign) {
- var name = node.left.print_to_string();
- var value = node.right;
- if (flag) {
- options[name] = value;
- } else if (value instanceof UglifyJS.AST_Array) {
- options[name] = value.elements.map(to_string);
- } else {
- options[name] = to_string(value);
- }
- return true;
- }
- if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
- var name = node.print_to_string();
- options[name] = true;
- return true;
+function parse_js(value, options, flag) {
+ if (!options || typeof options != "object") options = {};
+ if (typeof value == "string") try {
+ UglifyJS.parse(value, {
+ expression: true
+ }).walk(new UglifyJS.TreeWalker(function(node) {
+ if (node instanceof UglifyJS.AST_Assign) {
+ var name = node.left.print_to_string();
+ var value = node.right;
+ if (flag) {
+ options[name] = value;
+ } else if (value instanceof UglifyJS.AST_Array) {
+ options[name] = value.elements.map(to_string);
+ } else {
+ options[name] = to_string(value);
}
- if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
+ return true;
+ }
+ if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
+ var name = node.print_to_string();
+ options[name] = true;
+ return true;
+ }
+ if (!(node instanceof UglifyJS.AST_Sequence)) throw node;
- function to_string(value) {
- return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({
- quote_keys: true
- });
- }
- }));
- } catch (ex) {
- if (flag) {
- fatal("cannot parse arguments for '" + flag + "': " + value);
- } else {
- options[value] = null;
+ function to_string(value) {
+ return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({
+ quote_keys: true
+ });
}
+ }));
+ } catch (ex) {
+ if (flag) {
+ fatal("cannot parse arguments for '" + flag + "': " + value);
+ } else {
+ options[value] = null;
}
- return options;
}
+ return options;
}
function skip_key(key) {