Compare commits
6 Commits
harmony-v3
...
v3.0.13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e0a22e5c8 | ||
|
|
1aa38051fb | ||
|
|
e62b879b48 | ||
|
|
c6c9f4f5a8 | ||
|
|
fec14379f6 | ||
|
|
79131cd647 |
@@ -45,6 +45,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
|
|
||||||
```
|
```
|
||||||
-h, --help Print usage information.
|
-h, --help Print usage information.
|
||||||
|
`--help options` for details on available options.
|
||||||
-V, --version Print version number.
|
-V, --version Print version number.
|
||||||
-p, --parse <options> Specify parser options:
|
-p, --parse <options> Specify parser options:
|
||||||
`acorn` Use Acorn for parsing.
|
`acorn` Use Acorn for parsing.
|
||||||
@@ -713,14 +714,14 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
|||||||
|
|
||||||
### Mangle properties options
|
### Mangle properties options
|
||||||
|
|
||||||
- `reserved` (default: `[]`) -- Do not mangle property names listed in the
|
- `reserved` (default: `[]`) -- Do not mangle property names listed in the
|
||||||
`reserved` array.
|
`reserved` array.
|
||||||
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
|
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
|
||||||
names matching the regular expression.
|
names matching the regular expression.
|
||||||
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
|
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
|
||||||
- `debug` (default: `false`) -— Mangle names with the original name still present.
|
- `debug` (default: `false`) -— Mangle names with the original name still present.
|
||||||
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
|
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
|
||||||
- `builtins` (default: `false`) -- Use `true` to allow the mangling of builtin
|
- `builtins` (default: `false`) -- Use `true` to allow the mangling of builtin
|
||||||
DOM properties. Not recommended to override this setting.
|
DOM properties. Not recommended to override this setting.
|
||||||
|
|
||||||
## Output options
|
## Output options
|
||||||
|
|||||||
21
bin/uglifyjs
21
bin/uglifyjs
@@ -21,10 +21,27 @@ var options = {
|
|||||||
compress: false,
|
compress: false,
|
||||||
mangle: false
|
mangle: false
|
||||||
};
|
};
|
||||||
program.version(info.name + ' ' + info.version);
|
program.version(info.name + " " + info.version);
|
||||||
program.parseArgv = program.parse;
|
program.parseArgv = program.parse;
|
||||||
program.parse = undefined;
|
program.parse = undefined;
|
||||||
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
||||||
|
else if (process.argv.indexOf("options") >= 0) program.helpInformation = function() {
|
||||||
|
var text = [];
|
||||||
|
var options = UglifyJS.default_options();
|
||||||
|
for (var option in options) {
|
||||||
|
text.push("--" + (option == "output" ? "beautify" : option == "sourceMap" ? "source-map" : option) + " options:");
|
||||||
|
var defs = options[option];
|
||||||
|
var padding = "";
|
||||||
|
Object.keys(defs).map(function(name) {
|
||||||
|
if (padding.length < name.length) padding = Array(name.length + 1).join(" ");
|
||||||
|
return [ name, JSON.stringify(defs[name]) ];
|
||||||
|
}).forEach(function(tokens) {
|
||||||
|
text.push(" " + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);
|
||||||
|
});
|
||||||
|
text.push("");
|
||||||
|
}
|
||||||
|
return text.join("\n");
|
||||||
|
};
|
||||||
program.option("-p, --parse <options>", "Specify parser options.", parse_js("parse", true));
|
program.option("-p, --parse <options>", "Specify parser options.", parse_js("parse", true));
|
||||||
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js("compress", true));
|
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js("compress", true));
|
||||||
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js("mangle", true));
|
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js("mangle", true));
|
||||||
@@ -351,7 +368,7 @@ function parse_js(flag, constants) {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
fatal("Error parsing arguments for '" + flag + "': " + value);
|
options[value] = null;
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|||||||
120
lib/compress.js
120
lib/compress.js
@@ -924,6 +924,45 @@ merge(Compressor.prototype, {
|
|||||||
// step. nevertheless, it's good to check.
|
// step. nevertheless, it's good to check.
|
||||||
continue loop;
|
continue loop;
|
||||||
case stat instanceof AST_If:
|
case stat instanceof AST_If:
|
||||||
|
var ab = aborts(stat.body);
|
||||||
|
if (can_merge_flow(ab)) {
|
||||||
|
if (ab.label) {
|
||||||
|
remove(ab.label.thedef.references, ab);
|
||||||
|
}
|
||||||
|
CHANGED = true;
|
||||||
|
var funs = extract_functions_from_statement_array(ret);
|
||||||
|
var body = as_statement_array_with_return(stat.body, ab);
|
||||||
|
stat = stat.clone();
|
||||||
|
stat.condition = stat.condition.negate(compressor);
|
||||||
|
stat.body = make_node(AST_BlockStatement, stat, {
|
||||||
|
body: as_statement_array(stat.alternative).concat(ret)
|
||||||
|
});
|
||||||
|
stat.alternative = make_node(AST_BlockStatement, stat, {
|
||||||
|
body: body
|
||||||
|
});
|
||||||
|
ret = [ stat.transform(compressor) ].concat(funs);
|
||||||
|
continue loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ab = aborts(stat.alternative);
|
||||||
|
if (can_merge_flow(ab)) {
|
||||||
|
if (ab.label) {
|
||||||
|
remove(ab.label.thedef.references, ab);
|
||||||
|
}
|
||||||
|
CHANGED = true;
|
||||||
|
var funs = extract_functions_from_statement_array(ret);
|
||||||
|
stat = stat.clone();
|
||||||
|
stat.body = make_node(AST_BlockStatement, stat.body, {
|
||||||
|
body: as_statement_array(stat.body).concat(ret)
|
||||||
|
});
|
||||||
|
var body = as_statement_array_with_return(stat.alternative, ab);
|
||||||
|
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
||||||
|
body: body
|
||||||
|
});
|
||||||
|
ret = [ stat.transform(compressor) ].concat(funs);
|
||||||
|
continue loop;
|
||||||
|
}
|
||||||
|
|
||||||
if (stat.body instanceof AST_Return) {
|
if (stat.body instanceof AST_Return) {
|
||||||
var value = stat.body.value;
|
var value = stat.body.value;
|
||||||
//---
|
//---
|
||||||
@@ -960,23 +999,6 @@ merge(Compressor.prototype, {
|
|||||||
continue loop;
|
continue loop;
|
||||||
}
|
}
|
||||||
//---
|
//---
|
||||||
// if (foo()) return [ void bar() ]; [ else x...; ] y... ==> if (!foo()) { x...; y... } else bar();
|
|
||||||
if (in_lambda && (!value || value instanceof AST_UnaryPrefix && value.operator == "void")) {
|
|
||||||
CHANGED = true;
|
|
||||||
stat = stat.clone();
|
|
||||||
stat.condition = stat.condition.negate(compressor);
|
|
||||||
var funs = extract_functions_from_statement_array(ret);
|
|
||||||
var body = as_statement_array(stat.alternative).concat(ret);
|
|
||||||
stat.body = make_node(AST_BlockStatement, stat, {
|
|
||||||
body: body
|
|
||||||
});
|
|
||||||
stat.alternative = value ? make_node(AST_SimpleStatement, value, {
|
|
||||||
body: value.expression
|
|
||||||
}) : null;
|
|
||||||
ret = [ stat.transform(compressor) ].concat(funs);
|
|
||||||
continue loop;
|
|
||||||
}
|
|
||||||
//---
|
|
||||||
// if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
|
// if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
|
||||||
//
|
//
|
||||||
// if sequences is not enabled, this can lead to an endless loop (issue #866).
|
// if sequences is not enabled, this can lead to an endless loop (issue #866).
|
||||||
@@ -995,48 +1017,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ab = aborts(stat.body);
|
|
||||||
var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
|
|
||||||
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|
|
||||||
|| (ab instanceof AST_Continue && self === loop_body(lct))
|
|
||||||
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
|
|
||||||
if (ab.label) {
|
|
||||||
remove(ab.label.thedef.references, ab);
|
|
||||||
}
|
|
||||||
CHANGED = true;
|
|
||||||
var body = as_statement_array(stat.body).slice(0, -1);
|
|
||||||
stat = stat.clone();
|
|
||||||
stat.condition = stat.condition.negate(compressor);
|
|
||||||
stat.body = make_node(AST_BlockStatement, stat, {
|
|
||||||
body: as_statement_array(stat.alternative).concat(ret)
|
|
||||||
});
|
|
||||||
stat.alternative = make_node(AST_BlockStatement, stat, {
|
|
||||||
body: body
|
|
||||||
});
|
|
||||||
ret = [ stat.transform(compressor) ];
|
|
||||||
continue loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ab = aborts(stat.alternative);
|
|
||||||
var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
|
|
||||||
if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
|
|
||||||
|| (ab instanceof AST_Continue && self === loop_body(lct))
|
|
||||||
|| (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
|
|
||||||
if (ab.label) {
|
|
||||||
remove(ab.label.thedef.references, ab);
|
|
||||||
}
|
|
||||||
CHANGED = true;
|
|
||||||
stat = stat.clone();
|
|
||||||
stat.body = make_node(AST_BlockStatement, stat.body, {
|
|
||||||
body: as_statement_array(stat.body).concat(ret)
|
|
||||||
});
|
|
||||||
stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
|
|
||||||
body: as_statement_array(stat.alternative).slice(0, -1)
|
|
||||||
});
|
|
||||||
ret = [ stat.transform(compressor) ];
|
|
||||||
continue loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.unshift(stat);
|
ret.unshift(stat);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1056,6 +1036,28 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function is_return_void(value) {
|
||||||
|
return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
|
||||||
|
}
|
||||||
|
|
||||||
|
function can_merge_flow(ab) {
|
||||||
|
if (!ab) return false;
|
||||||
|
var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
|
||||||
|
return ab instanceof AST_Return && in_lambda && is_return_void(ab.value)
|
||||||
|
|| ab instanceof AST_Continue && self === loop_body(lct)
|
||||||
|
|| ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct;
|
||||||
|
}
|
||||||
|
|
||||||
|
function as_statement_array_with_return(node, ab) {
|
||||||
|
var body = as_statement_array(node).slice(0, -1);
|
||||||
|
if (ab.value) {
|
||||||
|
body.push(make_node(AST_SimpleStatement, ab.value, {
|
||||||
|
body: ab.value.expression
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function eliminate_dead_code(statements, compressor) {
|
function eliminate_dead_code(statements, compressor) {
|
||||||
|
|||||||
@@ -700,7 +700,7 @@ function parse($TEXT, options) {
|
|||||||
shebang : true,
|
shebang : true,
|
||||||
strict : false,
|
strict : false,
|
||||||
toplevel : null,
|
toplevel : null,
|
||||||
});
|
}, true);
|
||||||
|
|
||||||
var S = {
|
var S = {
|
||||||
input : (typeof $TEXT == "string"
|
input : (typeof $TEXT == "string"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.0.12",
|
"version": "3.0.13",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ dead_code_2_should_warn_strict: {
|
|||||||
f();
|
f();
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
node_version: "=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_constant_boolean_should_warn_more: {
|
dead_code_constant_boolean_should_warn_more: {
|
||||||
|
|||||||
@@ -243,5 +243,5 @@ hoist_funs_strict: {
|
|||||||
"5 'function' 'function'",
|
"5 'function' 'function'",
|
||||||
"6 'undefined' 'function'",
|
"6 'undefined' 'function'",
|
||||||
]
|
]
|
||||||
node_version: "=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -307,6 +307,8 @@ issue_512: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function a() {
|
function a() {
|
||||||
|
|||||||
@@ -136,7 +136,29 @@ defun_hoist_funs: {
|
|||||||
function f() {}
|
function f() {}
|
||||||
function g() {}
|
function g() {}
|
||||||
function h() {}
|
function h() {}
|
||||||
!window;
|
if (window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defun_else_if_return: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: false,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function e() {
|
||||||
|
function f() {}
|
||||||
|
if (window) function g() {}
|
||||||
|
else return;
|
||||||
|
function h() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function e() {
|
||||||
|
function f() {}
|
||||||
|
if (window) function g() {}
|
||||||
|
function h() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -537,4 +537,13 @@ describe("bin/uglifyjs", function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should print supported options on invalid option syntax", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/input/comments/filter.js -b ascii-only";
|
||||||
|
exec(command, function (err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.strictEqual(stdout, "");
|
||||||
|
assert.ok(/^Supported options:\n\{[^}]+}\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
stream._handle.setBlocking(true);
|
stream._handle.setBlocking(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
var UglifyJS = require("./node");
|
var UglifyJS = require("..");
|
||||||
var randomBytes = require("crypto").randomBytes;
|
var randomBytes = require("crypto").randomBytes;
|
||||||
var sandbox = require("./sandbox");
|
var sandbox = require("./sandbox");
|
||||||
|
|
||||||
@@ -962,32 +962,15 @@ function try_beautify(code, result) {
|
|||||||
console.log(code);
|
console.log(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
function infer_options(ctor) {
|
var default_options = UglifyJS.default_options();
|
||||||
try {
|
|
||||||
ctor({ 0: 0 });
|
|
||||||
} catch (e) {
|
|
||||||
return e.defs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var default_options = {
|
|
||||||
compress: infer_options(UglifyJS.Compressor),
|
|
||||||
mangle: {
|
|
||||||
"cache": null,
|
|
||||||
"eval": false,
|
|
||||||
"ie8": false,
|
|
||||||
"keep_fnames": false,
|
|
||||||
"toplevel": false,
|
|
||||||
},
|
|
||||||
output: infer_options(UglifyJS.OutputStream),
|
|
||||||
};
|
|
||||||
|
|
||||||
function log_suspects(minify_options, component) {
|
function log_suspects(minify_options, component) {
|
||||||
var options = component in minify_options ? minify_options[component] : true;
|
var options = component in minify_options ? minify_options[component] : true;
|
||||||
if (!options) return;
|
if (!options) return;
|
||||||
options = UglifyJS.defaults(options, default_options[component]);
|
if (typeof options != "object") options = {};
|
||||||
var suspects = Object.keys(default_options[component]).filter(function(name) {
|
var defs = default_options[component];
|
||||||
if (options[name]) {
|
var suspects = Object.keys(defs).filter(function(name) {
|
||||||
|
if ((name in options ? options : defs)[name]) {
|
||||||
var m = JSON.parse(JSON.stringify(minify_options));
|
var m = JSON.parse(JSON.stringify(minify_options));
|
||||||
var o = JSON.parse(JSON.stringify(options));
|
var o = JSON.parse(JSON.stringify(options));
|
||||||
o[name] = false;
|
o[name] = false;
|
||||||
|
|||||||
@@ -63,3 +63,20 @@ function describe_ast() {
|
|||||||
doitem(AST_Node);
|
doitem(AST_Node);
|
||||||
return out + "\n";
|
return out + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function infer_options(options) {
|
||||||
|
var result = UglifyJS.minify("", options);
|
||||||
|
return result.error && result.error.defs;
|
||||||
|
}
|
||||||
|
|
||||||
|
UglifyJS.default_options = function() {
|
||||||
|
var defs = {};
|
||||||
|
Object.keys(infer_options({ 0: 0 })).forEach(function(component) {
|
||||||
|
var options = {};
|
||||||
|
options[component] = { 0: 0 };
|
||||||
|
if (options = infer_options(options)) {
|
||||||
|
defs[component] = options;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return defs;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user