point cli to built version
This commit is contained in:
parent
e09d92dc52
commit
84464b7750
266
bin/uglifyjs
266
bin/uglifyjs
|
|
@ -8,10 +8,27 @@ require("../tools/tty");
|
|||
var fs = require("fs");
|
||||
var info = require("../package.json");
|
||||
var path = require("path");
|
||||
var UglifyJS = require("../tools/node");
|
||||
var UglifyJS = require("..");
|
||||
|
||||
var skip_keys = [ "cname", "fixed", "in_arg", "inlined", "length_read", "parent_scope", "redef", "scope", "unused" ];
|
||||
var truthy_keys = [ "optional", "pure", "terminal", "uses_arguments", "uses_eval", "uses_with" ];
|
||||
var skip_keys = [
|
||||
"cname",
|
||||
"fixed",
|
||||
"in_arg",
|
||||
"inlined",
|
||||
"length_read",
|
||||
"parent_scope",
|
||||
"redef",
|
||||
"scope",
|
||||
"unused",
|
||||
];
|
||||
var truthy_keys = [
|
||||
"optional",
|
||||
"pure",
|
||||
"terminal",
|
||||
"uses_arguments",
|
||||
"uses_eval",
|
||||
"uses_with",
|
||||
];
|
||||
|
||||
var files = {};
|
||||
var options = {};
|
||||
|
|
@ -41,7 +58,8 @@ while (args.length) {
|
|||
break;
|
||||
} else if (arg[1] == "-") {
|
||||
process_option(arg.slice(2));
|
||||
} else [].forEach.call(arg.slice(1), function(letter, index, arg) {
|
||||
} else
|
||||
[].forEach.call(arg.slice(1), function (letter, index, arg) {
|
||||
if (!(letter in short_forms)) fatal("invalid option -" + letter);
|
||||
process_option(short_forms[letter], index + 1 < arg.length);
|
||||
});
|
||||
|
|
@ -63,28 +81,39 @@ function process_option(name, no_value) {
|
|||
for (var name in defaults) {
|
||||
var option = defaults[name];
|
||||
if (option && typeof option == "object") {
|
||||
text.push("--" + ({
|
||||
text.push(
|
||||
"--" +
|
||||
({
|
||||
output: "beautify",
|
||||
sourceMap: "source-map",
|
||||
}[name] || name) + " options:");
|
||||
}[name] || name) +
|
||||
" options:"
|
||||
);
|
||||
text.push(format_object(option));
|
||||
text.push("");
|
||||
} else {
|
||||
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||
toplevels.push([ {
|
||||
if (padding.length < name.length)
|
||||
padding = Array(name.length + 1).join(" ");
|
||||
toplevels.push([
|
||||
{
|
||||
keep_fargs: "keep-fargs",
|
||||
keep_fnames: "keep-fnames",
|
||||
nameCache: "name-cache",
|
||||
}[name] || name, option ]);
|
||||
}[name] || name,
|
||||
option,
|
||||
]);
|
||||
}
|
||||
}
|
||||
toplevels.forEach(function(tokens) {
|
||||
text.push("--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||
toplevels.forEach(function (tokens) {
|
||||
text.push(
|
||||
"--" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]
|
||||
);
|
||||
});
|
||||
print(text.join("\n"));
|
||||
break;
|
||||
default:
|
||||
print([
|
||||
print(
|
||||
[
|
||||
"Usage: uglifyjs [files...] [options]",
|
||||
"",
|
||||
"Options:",
|
||||
|
|
@ -127,7 +156,8 @@ function process_option(name, no_value) {
|
|||
"(internal debug use only)",
|
||||
" --in-situ Warning: replaces original source files with minified output.",
|
||||
" --reduce-test Reduce a standalone test case (assumes cloned repository).",
|
||||
].join("\n"));
|
||||
].join("\n")
|
||||
);
|
||||
}
|
||||
process.exit();
|
||||
case "version":
|
||||
|
|
@ -135,10 +165,17 @@ function process_option(name, no_value) {
|
|||
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, {
|
||||
if (
|
||||
config.mangle &&
|
||||
config.mangle.properties &&
|
||||
config.mangle.properties.regex
|
||||
) {
|
||||
config.mangle.properties.regex = UglifyJS.parse(
|
||||
config.mangle.properties.regex,
|
||||
{
|
||||
expression: true,
|
||||
}).value;
|
||||
}
|
||||
).value;
|
||||
}
|
||||
for (var key in config) if (!(key in options)) options[key] = config[key];
|
||||
break;
|
||||
|
|
@ -195,11 +232,18 @@ function process_option(name, no_value) {
|
|||
break;
|
||||
case "define":
|
||||
if (typeof options.compress != "object") options.compress = {};
|
||||
options.compress.global_defs = parse_js(read_value(true), options.compress.global_defs, "define");
|
||||
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);
|
||||
options.mangle.properties = parse_js(
|
||||
read_value(),
|
||||
options.mangle.properties
|
||||
);
|
||||
break;
|
||||
case "module":
|
||||
options.module = true;
|
||||
|
|
@ -239,9 +283,11 @@ function process_option(name, no_value) {
|
|||
return args.shift();
|
||||
}
|
||||
}
|
||||
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 (!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 (/^ast|spidermonkey$/.test(output)) {
|
||||
|
|
@ -249,38 +295,47 @@ if (/^ast|spidermonkey$/.test(output)) {
|
|||
options.output.ast = true;
|
||||
options.output.code = false;
|
||||
}
|
||||
if (options.parse && (options.parse.acorn || options.parse.spidermonkey)
|
||||
&& options.sourceMap && options.sourceMap.content == "inline") {
|
||||
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 (options.warnings) {
|
||||
UglifyJS.AST_Node.log_function(print_error, options.warnings == "verbose");
|
||||
delete options.warnings;
|
||||
}
|
||||
var convert_path = function(name) {
|
||||
var convert_path = function (name) {
|
||||
return name;
|
||||
};
|
||||
if (typeof options.sourceMap == "object" && "base" in options.sourceMap) {
|
||||
convert_path = function() {
|
||||
convert_path = (function () {
|
||||
var base = options.sourceMap.base;
|
||||
delete options.sourceMap.base;
|
||||
return function(name) {
|
||||
return function (name) {
|
||||
return path.relative(base, name);
|
||||
};
|
||||
}();
|
||||
})();
|
||||
}
|
||||
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";
|
||||
paths = UglifyJS.FILES;
|
||||
} else if (paths.length) {
|
||||
paths = simple_glob(paths);
|
||||
}
|
||||
if (specified["in-situ"]) {
|
||||
if (output && output != "spidermonkey" || specified["reduce-test"] || specified["self"]) {
|
||||
if (
|
||||
(output && output != "spidermonkey") ||
|
||||
specified["reduce-test"] ||
|
||||
specified["self"]
|
||||
) {
|
||||
fatal("incompatible options specified");
|
||||
}
|
||||
paths.forEach(function(name) {
|
||||
paths.forEach(function (name) {
|
||||
print(name);
|
||||
if (/^ast|spidermonkey$/.test(name)) fatal("invalid file name specified");
|
||||
files = {};
|
||||
|
|
@ -289,19 +344,29 @@ if (specified["in-situ"]) {
|
|||
run();
|
||||
});
|
||||
} else if (paths.length) {
|
||||
paths.forEach(function(name) {
|
||||
paths.forEach(function (name) {
|
||||
files[convert_path(name)] = read_file(name);
|
||||
});
|
||||
run();
|
||||
} else {
|
||||
var timerId = process.stdin.isTTY && process.argv.length < 3 && setTimeout(function() {
|
||||
print_error("Waiting for input... (use `--help` to print usage information)");
|
||||
var timerId =
|
||||
process.stdin.isTTY &&
|
||||
process.argv.length < 3 &&
|
||||
setTimeout(function () {
|
||||
print_error(
|
||||
"Waiting for input... (use `--help` to print usage information)"
|
||||
);
|
||||
}, 1500);
|
||||
var chunks = [];
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.once("data", function() {
|
||||
process.stdin
|
||||
.once("data", function () {
|
||||
clearTimeout(timerId);
|
||||
}).on("data", process.stdin.isTTY ? function(chunk) {
|
||||
})
|
||||
.on(
|
||||
"data",
|
||||
process.stdin.isTTY
|
||||
? function (chunk) {
|
||||
// emulate console input termination via Ctrl+D / Ctrl+Z
|
||||
var match = /[\x04\x1a]\r?\n?$/.exec(chunk);
|
||||
if (match) {
|
||||
|
|
@ -311,9 +376,12 @@ if (specified["in-situ"]) {
|
|||
} else {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
} : function(chunk) {
|
||||
}
|
||||
: function (chunk) {
|
||||
chunks.push(chunk);
|
||||
}).once("end", function() {
|
||||
}
|
||||
)
|
||||
.once("end", function () {
|
||||
files = { STDIN: chunks.join("") };
|
||||
run();
|
||||
});
|
||||
|
|
@ -321,14 +389,16 @@ if (specified["in-situ"]) {
|
|||
}
|
||||
|
||||
function convert_ast(fn) {
|
||||
return UglifyJS.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null));
|
||||
return UglifyJS.AST_Node.from_mozilla_ast(
|
||||
Object.keys(files).reduce(fn, null)
|
||||
);
|
||||
}
|
||||
|
||||
function run() {
|
||||
var content = options.sourceMap && options.sourceMap.content;
|
||||
if (content && content != "inline") {
|
||||
UglifyJS.AST_Node.info("Using input source map: {content}", {
|
||||
content : content,
|
||||
content: content,
|
||||
});
|
||||
options.sourceMap.content = read_file(content, content);
|
||||
}
|
||||
|
|
@ -336,19 +406,19 @@ function run() {
|
|||
if (options.parse) {
|
||||
if (options.parse.acorn) {
|
||||
var annotations = Object.create(null);
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
files = convert_ast(function (toplevel, name) {
|
||||
var content = files[name];
|
||||
var list = annotations[name] = [];
|
||||
var list = (annotations[name] = []);
|
||||
var prev = -1;
|
||||
return require("acorn").parse(content, {
|
||||
allowHashBang: true,
|
||||
ecmaVersion: "latest",
|
||||
locations: true,
|
||||
onComment: function(block, text, start, end) {
|
||||
onComment: function (block, text, start, end) {
|
||||
var match = /[@#]__PURE__/.exec(text);
|
||||
if (!match) {
|
||||
if (start != prev) return;
|
||||
match = [ list[prev] ];
|
||||
match = [list[prev]];
|
||||
}
|
||||
while (/\s/.test(content[end])) end++;
|
||||
list[end] = match[0];
|
||||
|
|
@ -360,20 +430,23 @@ function run() {
|
|||
sourceType: "module",
|
||||
});
|
||||
});
|
||||
files.walk(new UglifyJS.TreeWalker(function(node) {
|
||||
files.walk(
|
||||
new UglifyJS.TreeWalker(function (node) {
|
||||
if (!(node instanceof UglifyJS.AST_Call)) return;
|
||||
var list = annotations[node.start.file];
|
||||
var pure = list[node.start.pos];
|
||||
if (!pure) {
|
||||
var tokens = node.start.parens;
|
||||
if (tokens) for (var i = 0; !pure && i < tokens.length; i++) {
|
||||
if (tokens)
|
||||
for (var i = 0; !pure && i < tokens.length; i++) {
|
||||
pure = list[tokens[i].pos];
|
||||
}
|
||||
}
|
||||
if (pure) node.pure = pure;
|
||||
}));
|
||||
})
|
||||
);
|
||||
} else if (options.parse.spidermonkey) {
|
||||
files = convert_ast(function(toplevel, name) {
|
||||
files = convert_ast(function (toplevel, name) {
|
||||
var obj = JSON.parse(files[name]);
|
||||
if (!toplevel) return obj;
|
||||
toplevel.body = toplevel.body.concat(obj.body);
|
||||
|
|
@ -399,7 +472,9 @@ function run() {
|
|||
if (result.error) {
|
||||
var ex = result.error;
|
||||
if (ex.name == "SyntaxError") {
|
||||
print_error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
|
||||
print_error(
|
||||
"Parse error at " + ex.filename + ":" + ex.line + "," + ex.col
|
||||
);
|
||||
var file = files[ex.filename];
|
||||
if (file) {
|
||||
var col = ex.col;
|
||||
|
|
@ -428,17 +503,22 @@ function run() {
|
|||
if (!options.compress && !options.mangle) {
|
||||
var toplevel = result.ast;
|
||||
if (!(toplevel instanceof UglifyJS.AST_Toplevel)) {
|
||||
if (!(toplevel instanceof UglifyJS.AST_Statement)) toplevel = new UglifyJS.AST_SimpleStatement({
|
||||
if (!(toplevel instanceof UglifyJS.AST_Statement))
|
||||
toplevel = new UglifyJS.AST_SimpleStatement({
|
||||
body: toplevel,
|
||||
});
|
||||
toplevel = new UglifyJS.AST_Toplevel({
|
||||
body: [ toplevel ],
|
||||
body: [toplevel],
|
||||
});
|
||||
}
|
||||
toplevel.figure_out_scope({});
|
||||
}
|
||||
print(JSON.stringify(result.ast, function(key, value) {
|
||||
if (value) switch (key) {
|
||||
print(
|
||||
JSON.stringify(
|
||||
result.ast,
|
||||
function (key, value) {
|
||||
if (value)
|
||||
switch (key) {
|
||||
case "enclosed":
|
||||
return value.length ? value.map(symdef) : undefined;
|
||||
case "functions":
|
||||
|
|
@ -453,15 +533,18 @@ function run() {
|
|||
if (value instanceof UglifyJS.Dictionary) return;
|
||||
if (value instanceof UglifyJS.AST_Node) {
|
||||
var result = {
|
||||
_class: "AST_" + value.TYPE
|
||||
_class: "AST_" + value.TYPE,
|
||||
};
|
||||
value.CTOR.PROPS.forEach(function(prop) {
|
||||
value.CTOR.PROPS.forEach(function (prop) {
|
||||
result[prop] = value[prop];
|
||||
});
|
||||
return result;
|
||||
}
|
||||
return value;
|
||||
}, 2));
|
||||
},
|
||||
2
|
||||
)
|
||||
);
|
||||
} else if (output == "spidermonkey") {
|
||||
print(JSON.stringify(result.ast.to_mozilla_ast(), null, 2));
|
||||
} else if (output) {
|
||||
|
|
@ -471,7 +554,9 @@ function run() {
|
|||
for (var name in options.output) {
|
||||
if (!/^ast|code$/.test(name)) opts[name] = options.output[name];
|
||||
}
|
||||
code = UglifyJS.AST_Node.from_mozilla_ast(result.ast.to_mozilla_ast()).print_to_string(opts);
|
||||
code = UglifyJS.AST_Node.from_mozilla_ast(
|
||||
result.ast.to_mozilla_ast()
|
||||
).print_to_string(opts);
|
||||
} else {
|
||||
code = result.code;
|
||||
}
|
||||
|
|
@ -481,14 +566,15 @@ function run() {
|
|||
print(result.code);
|
||||
}
|
||||
if (nameCache) fs.writeFileSync(nameCache, JSON.stringify(options.nameCache));
|
||||
if (result.timings) for (var phase in result.timings) {
|
||||
if (result.timings)
|
||||
for (var phase in result.timings) {
|
||||
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||
}
|
||||
}
|
||||
|
||||
function fatal(message) {
|
||||
if (message instanceof Error) {
|
||||
message = message.stack.replace(/^\S*?Error:/, "ERROR:")
|
||||
message = message.stack.replace(/^\S*?Error:/, "ERROR:");
|
||||
} else {
|
||||
message = "ERROR: " + message;
|
||||
}
|
||||
|
|
@ -501,11 +587,11 @@ function fatal(message) {
|
|||
// Argument `paths` must be an array of strings.
|
||||
// Returns an array of strings. Garbage in, garbage out.
|
||||
function simple_glob(paths) {
|
||||
return paths.reduce(function(paths, glob) {
|
||||
return paths.reduce(function (paths, glob) {
|
||||
if (/\*|\?/.test(glob)) {
|
||||
var dir = path.dirname(glob);
|
||||
try {
|
||||
var entries = fs.readdirSync(dir).filter(function(name) {
|
||||
var entries = fs.readdirSync(dir).filter(function (name) {
|
||||
try {
|
||||
return fs.statSync(path.join(dir, name)).isFile();
|
||||
} catch (ex) {
|
||||
|
|
@ -514,15 +600,22 @@ function simple_glob(paths) {
|
|||
});
|
||||
} catch (ex) {}
|
||||
if (entries) {
|
||||
var pattern = "^" + path.basename(glob)
|
||||
var pattern =
|
||||
"^" +
|
||||
path
|
||||
.basename(glob)
|
||||
.replace(/[.+^$[\]\\(){}]/g, "\\$&")
|
||||
.replace(/\*/g, "[^/\\\\]*")
|
||||
.replace(/\?/g, "[^/\\\\]") + "$";
|
||||
.replace(/\?/g, "[^/\\\\]") +
|
||||
"$";
|
||||
var mod = process.platform === "win32" ? "i" : "";
|
||||
var rx = new RegExp(pattern, mod);
|
||||
var results = entries.filter(function(name) {
|
||||
var results = entries
|
||||
.filter(function (name) {
|
||||
return rx.test(name);
|
||||
}).sort().map(function(name) {
|
||||
})
|
||||
.sort()
|
||||
.map(function (name) {
|
||||
return path.join(dir, name);
|
||||
});
|
||||
if (results.length) {
|
||||
|
|
@ -547,10 +640,12 @@ function read_file(path, default_value) {
|
|||
|
||||
function parse_js(value, options, flag) {
|
||||
if (!options || typeof options != "object") options = Object.create(null);
|
||||
if (typeof value == "string") try {
|
||||
if (typeof value == "string")
|
||||
try {
|
||||
UglifyJS.parse(value, {
|
||||
expression: true
|
||||
}).walk(new UglifyJS.TreeWalker(function(node) {
|
||||
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;
|
||||
|
|
@ -563,7 +658,10 @@ function parse_js(value, options, flag) {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {
|
||||
if (
|
||||
node instanceof UglifyJS.AST_Symbol ||
|
||||
node instanceof UglifyJS.AST_PropAccess
|
||||
) {
|
||||
var name = node.print_to_string();
|
||||
options[name] = true;
|
||||
return true;
|
||||
|
|
@ -571,11 +669,14 @@ function parse_js(value, options, flag) {
|
|||
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
|
||||
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);
|
||||
|
|
@ -587,13 +688,15 @@ function parse_js(value, options, flag) {
|
|||
}
|
||||
|
||||
function skip_property(key, value) {
|
||||
return skip_keys.indexOf(key) >= 0
|
||||
return (
|
||||
skip_keys.indexOf(key) >= 0 ||
|
||||
// only skip truthy_keys if their value is falsy
|
||||
|| truthy_keys.indexOf(key) >= 0 && !value;
|
||||
(truthy_keys.indexOf(key) >= 0 && !value)
|
||||
);
|
||||
}
|
||||
|
||||
function symdef(def) {
|
||||
var ret = (1e6 + def.id) + " " + def.name;
|
||||
var ret = 1e6 + def.id + " " + def.name;
|
||||
if (def.mangled_name) ret += " " + def.mangled_name;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -601,11 +704,16 @@ function symdef(def) {
|
|||
function format_object(obj) {
|
||||
var lines = [];
|
||||
var padding = "";
|
||||
Object.keys(obj).map(function(name) {
|
||||
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||
return [ name, JSON.stringify(obj[name]) ];
|
||||
}).forEach(function(tokens) {
|
||||
lines.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||
Object.keys(obj)
|
||||
.map(function (name) {
|
||||
if (padding.length < name.length)
|
||||
padding = Array(name.length + 1).join(" ");
|
||||
return [name, JSON.stringify(obj[name])];
|
||||
})
|
||||
.forEach(function (tokens) {
|
||||
lines.push(
|
||||
" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]
|
||||
);
|
||||
});
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user