Merge branch 'master' into harmony-v3.0.12
This commit is contained in:
93
README.md
93
README.md
@@ -123,7 +123,7 @@ a double dash to prevent input files being used as option arguments:
|
||||
the source map.
|
||||
`url` If specified, path to the source map to append in
|
||||
`//# sourceMappingURL`.
|
||||
--stats Display operations run time on STDERR.
|
||||
--timings Display operations run time on STDERR.
|
||||
--toplevel Compress and/or mangle variables in top level scope.
|
||||
--verbose Print diagnostic messages.
|
||||
--warn Print warning messages.
|
||||
@@ -215,24 +215,54 @@ to prevent the `require`, `exports` and `$` names from being changed.
|
||||
|
||||
### CLI mangling property names (`--mangle-props`)
|
||||
|
||||
**Note:** this will probably break your code. Mangling property names is a
|
||||
separate step, different from variable name mangling. Pass
|
||||
`--mangle-props`. It will mangle all properties that are seen in some
|
||||
object literal, or that are assigned to. For example:
|
||||
**Note:** THIS WILL PROBABLY BREAK YOUR CODE. Mangling property names
|
||||
is a separate step, different from variable name mangling. Pass
|
||||
`--mangle-props` to enable it. It will mangle all properties in the
|
||||
input code with the exception of built in DOM properties and properties
|
||||
in core javascript classes. For example:
|
||||
|
||||
```javascript
|
||||
// example.js
|
||||
var x = {
|
||||
foo: 1
|
||||
baz_: 0,
|
||||
foo_: 1,
|
||||
calc: function() {
|
||||
return this.foo_ + this.baz_;
|
||||
}
|
||||
};
|
||||
|
||||
x.bar = 2;
|
||||
x["baz"] = 3;
|
||||
x[condition ? "moo" : "boo"] = 4;
|
||||
console.log(x.something());
|
||||
x.bar_ = 2;
|
||||
x["baz_"] = 3;
|
||||
console.log(x.calc());
|
||||
```
|
||||
Mangle all properties (except for javascript `builtins`):
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());
|
||||
```
|
||||
Mangle all properties except for `reserved` properties:
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());
|
||||
```
|
||||
Mangle all properties matching a `regex`:
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props regex=/_$/
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());
|
||||
```
|
||||
|
||||
In the above code, `foo`, `bar`, `baz`, `moo` and `boo` will be replaced
|
||||
with single characters, while `something()` will be left as is.
|
||||
Combining mangle properties options:
|
||||
```bash
|
||||
$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
|
||||
```
|
||||
```javascript
|
||||
var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());
|
||||
```
|
||||
|
||||
In order for this to be of any use, we avoid mangling standard JS names by
|
||||
default (`--mangle-props builtins` to override).
|
||||
@@ -241,7 +271,7 @@ A default exclusion file is provided in `tools/domprops.json` which should
|
||||
cover most standard JS and DOM properties defined in various browsers. Pass
|
||||
`--mangle-props domprops` to disable this feature.
|
||||
|
||||
You can also use a regular expression to define which property names should be
|
||||
A regular expression can be used to define which property names should be
|
||||
mangled. For example, `--mangle-props regex=/^_/` will only mangle property
|
||||
names that start with an underscore.
|
||||
|
||||
@@ -269,9 +299,20 @@ Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
|
||||
so that it is not mangled throughout the entire script even when used in an
|
||||
unquoted style (`o.foo`). Example:
|
||||
|
||||
```javascript
|
||||
// stuff.js
|
||||
var o = {
|
||||
"foo": 1,
|
||||
bar: 3
|
||||
};
|
||||
o.foo += o.bar;
|
||||
console.log(o.foo);
|
||||
```
|
||||
```bash
|
||||
$ echo 'var o={"foo":1, bar:3}; o.foo += o.bar; console.log(o.foo);' | uglifyjs --mangle-props keep_quoted -mc
|
||||
var o={foo:1,a:3};o.foo+=o.a,console.log(o.foo);
|
||||
$ uglifyjs stuff.js --mangle-props keep_quoted -c -m
|
||||
```
|
||||
```javascript
|
||||
var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
|
||||
```
|
||||
|
||||
### Debugging property name mangling
|
||||
@@ -282,6 +323,13 @@ would mangle to `o._$foo$_` with this option. This allows property mangling
|
||||
of a large codebase while still being able to debug the code and identify
|
||||
where mangling is breaking things.
|
||||
|
||||
```bash
|
||||
$ uglifyjs stuff.js --mangle-props debug -c -m
|
||||
```
|
||||
```javascript
|
||||
var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
|
||||
```
|
||||
|
||||
You can also pass a custom suffix using `--mangle-props debug=XYZ`. This would then
|
||||
mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
|
||||
script to identify how a property got mangled. One technique is to pass a
|
||||
@@ -662,10 +710,15 @@ UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
|
||||
|
||||
### Mangle properties options
|
||||
|
||||
- `regex` — Pass a RegExp to only mangle certain names
|
||||
- `keep_quoted` — Only mangle unquoted property names
|
||||
- `debug` — Mangle names with the original name still present. Defaults to `false`.
|
||||
Pass an empty string to enable, or a non-empty string to set the suffix.
|
||||
- `reserved` (default: `[]`) -- Do not mangle property names listed in the
|
||||
`reserved` array.
|
||||
- `regex` (default: `null`) -— Pass a RegExp literal to only mangle property
|
||||
names matching the regular expression.
|
||||
- `keep_quoted` (default: `false`) -— Only mangle unquoted property names.
|
||||
- `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.
|
||||
- `builtins` (default: `false`) -- Use `true` to allow the mangling of builtin
|
||||
DOM properties. Not recommended to override this setting.
|
||||
|
||||
## Output options
|
||||
|
||||
|
||||
15
bin/uglifyjs
15
bin/uglifyjs
@@ -24,6 +24,7 @@ var options = {
|
||||
program.version(info.name + ' ' + info.version);
|
||||
program.parseArgv = program.parse;
|
||||
program.parse = undefined;
|
||||
if (process.argv.indexOf("ast") >= 0) program.helpInformation = UglifyJS.describe_ast;
|
||||
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("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js("mangle", true));
|
||||
@@ -38,7 +39,7 @@ program.option("--keep-fnames", "Do not mangle/drop function names. Useful for c
|
||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||
program.option("--source-map [options]", "Enable source map/specify source map options.", parse_source_map());
|
||||
program.option("--stats", "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.");
|
||||
@@ -114,10 +115,10 @@ if (program.output == "ast") {
|
||||
};
|
||||
}
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn || program.parse.spidermonkey) {
|
||||
if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser");
|
||||
} else {
|
||||
if (!program.parse.acorn && !program.parse.spidermonkey) {
|
||||
options.parse = program.parse;
|
||||
} else if (program.sourceMap && program.sourceMap.content == "inline") {
|
||||
fatal("ERROR: inline source map only works with built-in parser");
|
||||
}
|
||||
}
|
||||
var convert_path = function(name) {
|
||||
@@ -171,7 +172,7 @@ function run() {
|
||||
UglifyJS.AST_Node.warn_function = function(msg) {
|
||||
console.error("WARN:", msg);
|
||||
};
|
||||
if (program.stats) program.stats = Date.now();
|
||||
if (program.timings) options.timings = true;
|
||||
try {
|
||||
if (program.parse) {
|
||||
if (program.parse.acorn) {
|
||||
@@ -258,7 +259,9 @@ function run() {
|
||||
return value instanceof UglifyJS.Dictionary ? value.toObject() : value;
|
||||
}));
|
||||
}
|
||||
if (program.stats) console.error("Elapsed:", Date.now() - program.stats);
|
||||
if (result.timings) for (var phase in result.timings) {
|
||||
console.error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
|
||||
}
|
||||
}
|
||||
|
||||
function fatal(message) {
|
||||
|
||||
@@ -991,15 +991,15 @@ merge(Compressor.prototype, {
|
||||
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);
|
||||
var funs = extract_functions_from_statement_array(body);
|
||||
stat.body = make_node(AST_BlockStatement, stat, {
|
||||
body: body
|
||||
});
|
||||
stat.alternative = value ? make_node(AST_SimpleStatement, value, {
|
||||
body: value.expression
|
||||
}) : null;
|
||||
ret = funs.concat([ stat.transform(compressor) ]);
|
||||
ret = [ stat.transform(compressor) ].concat(funs);
|
||||
continue loop;
|
||||
}
|
||||
//---
|
||||
@@ -1248,7 +1248,7 @@ merge(Compressor.prototype, {
|
||||
target.push(node);
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_Defun) {
|
||||
if (node instanceof AST_Defun && (node === stat || !compressor.has_directive("use strict"))) {
|
||||
target.push(node);
|
||||
return true;
|
||||
}
|
||||
@@ -2386,11 +2386,13 @@ merge(Compressor.prototype, {
|
||||
dirs.push(node);
|
||||
return make_node(AST_EmptyStatement, node);
|
||||
}
|
||||
if (hoist_funs && node instanceof AST_Defun && !(tt.parent() instanceof AST_Export)) {
|
||||
if (hoist_funs && node instanceof AST_Defun
|
||||
&& !(tt.parent() instanceof AST_Export)
|
||||
&& (tt.parent() === self || !compressor.has_directive("use strict"))) {
|
||||
hoisted.push(node);
|
||||
return make_node(AST_EmptyStatement, node);
|
||||
}
|
||||
if (node instanceof AST_Var && hoist_vars) {
|
||||
if (hoist_vars && node instanceof AST_Var) {
|
||||
node.definitions.forEach(function(def){
|
||||
if (def.name instanceof AST_Destructuring) return;
|
||||
vars.set(def.name.name, def);
|
||||
|
||||
@@ -30,9 +30,6 @@ function set_shorthand(name, options, keys) {
|
||||
function minify(files, options) {
|
||||
var warn_function = AST_Node.warn_function;
|
||||
try {
|
||||
if (typeof files == "string") {
|
||||
files = [ files ];
|
||||
}
|
||||
options = defaults(options, {
|
||||
compress: {},
|
||||
ie8: false,
|
||||
@@ -41,10 +38,14 @@ function minify(files, options) {
|
||||
output: {},
|
||||
parse: {},
|
||||
sourceMap: false,
|
||||
timings: false,
|
||||
toplevel: false,
|
||||
warnings: false,
|
||||
wrap: false,
|
||||
}, true);
|
||||
var timings = options.timings && {
|
||||
start: Date.now()
|
||||
};
|
||||
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
|
||||
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||
@@ -77,10 +78,14 @@ function minify(files, options) {
|
||||
warnings.push(warning);
|
||||
};
|
||||
}
|
||||
if (timings) timings.parse = Date.now();
|
||||
var toplevel;
|
||||
if (files instanceof AST_Toplevel) {
|
||||
toplevel = files;
|
||||
} else {
|
||||
if (typeof files == "string") {
|
||||
files = [ files ];
|
||||
}
|
||||
options.parse = options.parse || {};
|
||||
options.parse.toplevel = null;
|
||||
for (var name in files) {
|
||||
@@ -97,19 +102,23 @@ function minify(files, options) {
|
||||
if (options.wrap) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
if (options.compress) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
}
|
||||
if (timings) timings.scope1 = Date.now();
|
||||
if (options.compress) toplevel.figure_out_scope(options.mangle);
|
||||
if (timings) timings.compress = Date.now();
|
||||
if (options.compress) toplevel = new Compressor(options.compress).compress(toplevel);
|
||||
if (timings) timings.scope2 = Date.now();
|
||||
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
||||
if (timings) timings.mangle = Date.now();
|
||||
if (options.mangle) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
base54.reset();
|
||||
toplevel.compute_char_frequency(options.mangle);
|
||||
toplevel.mangle_names(options.mangle);
|
||||
if (options.mangle.properties) {
|
||||
}
|
||||
if (timings) timings.properties = Date.now();
|
||||
if (options.mangle && options.mangle.properties) {
|
||||
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
||||
}
|
||||
}
|
||||
if (timings) timings.output = Date.now();
|
||||
var result = {};
|
||||
if (options.output.ast) {
|
||||
result.ast = toplevel;
|
||||
@@ -125,7 +134,9 @@ function minify(files, options) {
|
||||
root: options.sourceMap.root
|
||||
});
|
||||
if (options.sourceMap.includeSources) {
|
||||
for (var name in files) {
|
||||
if (files instanceof AST_Toplevel) {
|
||||
throw new Error("original source content unavailable");
|
||||
} else for (var name in files) {
|
||||
options.output.source_map.get().setSourceContent(name, files[name]);
|
||||
}
|
||||
}
|
||||
@@ -144,6 +155,18 @@ function minify(files, options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (timings) {
|
||||
timings.end = Date.now();
|
||||
result.timings = {
|
||||
parse: 1e-3 * (timings.scope1 - timings.parse),
|
||||
scope: 1e-3 * (timings.compress - timings.scope1 + timings.mangle - timings.scope2),
|
||||
compress: 1e-3 * (timings.scope2 - timings.compress),
|
||||
mangle: 1e-3 * (timings.properties - timings.mangle),
|
||||
properties: 1e-3 * (timings.output - timings.properties),
|
||||
output: 1e-3 * (timings.end - timings.output),
|
||||
total: 1e-3 * (timings.end - timings.start)
|
||||
}
|
||||
}
|
||||
if (warnings.length) {
|
||||
result.warnings = warnings;
|
||||
}
|
||||
|
||||
22
lib/scope.js
22
lib/scope.js
@@ -237,16 +237,8 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
self.walk(tw);
|
||||
|
||||
// pass 2: find back references and eval
|
||||
var func = null;
|
||||
var globals = self.globals = new Dictionary();
|
||||
self.globals = new Dictionary();
|
||||
var tw = new TreeWalker(function(node, descend){
|
||||
if (node instanceof AST_Lambda) {
|
||||
var prev_func = func;
|
||||
func = node;
|
||||
descend();
|
||||
func = prev_func;
|
||||
return true;
|
||||
}
|
||||
if (node instanceof AST_LoopControl && node.label) {
|
||||
node.label.thedef.references.push(node);
|
||||
return true;
|
||||
@@ -440,9 +432,7 @@ AST_Symbol.DEFMETHOD("unmangleable", function(options){
|
||||
});
|
||||
|
||||
// labels are always mangleable
|
||||
AST_Label.DEFMETHOD("unmangleable", function(){
|
||||
return false;
|
||||
});
|
||||
AST_Label.DEFMETHOD("unmangleable", return_false);
|
||||
|
||||
AST_Symbol.DEFMETHOD("unreferenced", function(){
|
||||
return this.definition().references.length == 0
|
||||
@@ -453,13 +443,9 @@ AST_Symbol.DEFMETHOD("undeclared", function(){
|
||||
return this.definition().undeclared;
|
||||
});
|
||||
|
||||
AST_LabelRef.DEFMETHOD("undeclared", function(){
|
||||
return false;
|
||||
});
|
||||
AST_LabelRef.DEFMETHOD("undeclared", return_false);
|
||||
|
||||
AST_Label.DEFMETHOD("undeclared", function(){
|
||||
return false;
|
||||
});
|
||||
AST_Label.DEFMETHOD("undeclared", return_false);
|
||||
|
||||
AST_Symbol.DEFMETHOD("definition", function(){
|
||||
return this.thedef;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.0.11",
|
||||
"version": "3.0.12",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@ var args = process.argv.slice(2);
|
||||
if (!args.length) {
|
||||
args.push("-mc");
|
||||
}
|
||||
args.push("--stats");
|
||||
args.push("--timings");
|
||||
var urls = [
|
||||
"https://code.jquery.com/jquery-3.2.1.js",
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
|
||||
@@ -29,12 +29,7 @@ function done() {
|
||||
var info = results[url];
|
||||
console.log();
|
||||
console.log(url);
|
||||
var elapsed = 0;
|
||||
console.log(info.log.replace(/Elapsed: ([0-9]+)\s*/g, function(match, time) {
|
||||
elapsed += 1e-3 * parseInt(time);
|
||||
return "";
|
||||
}));
|
||||
console.log("Run-time:", elapsed.toFixed(3), "s");
|
||||
console.log(info.log);
|
||||
console.log("Original:", info.input, "bytes");
|
||||
console.log("Uglified:", info.output, "bytes");
|
||||
console.log("SHA1 sum:", info.sha1);
|
||||
|
||||
@@ -31,7 +31,7 @@ dead_code_2_should_warn: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
throw new Error("foo");
|
||||
// completely discarding the `if` would introduce some
|
||||
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
|
||||
// we copy any declarations to the upper scope.
|
||||
@@ -46,16 +46,60 @@ dead_code_2_should_warn: {
|
||||
})();
|
||||
}
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw "foo";
|
||||
throw new Error("foo");
|
||||
var x;
|
||||
function g(){};
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: "<=4"
|
||||
}
|
||||
|
||||
dead_code_2_should_warn_strict: {
|
||||
options = {
|
||||
dead_code: true
|
||||
};
|
||||
input: {
|
||||
"use strict";
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw new Error("foo");
|
||||
// completely discarding the `if` would introduce some
|
||||
// bugs. UglifyJS v1 doesn't deal with this issue; in v2
|
||||
// we copy any declarations to the upper scope.
|
||||
if (x) {
|
||||
y();
|
||||
var x;
|
||||
function g(){};
|
||||
// but nested declarations should not be kept.
|
||||
(function(){
|
||||
var q;
|
||||
function y(){};
|
||||
})();
|
||||
}
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f() {
|
||||
g();
|
||||
x = 10;
|
||||
throw new Error("foo");
|
||||
var x;
|
||||
}
|
||||
f();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: "=4"
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more: {
|
||||
@@ -78,6 +122,7 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
foo();
|
||||
var moo;
|
||||
}
|
||||
bar();
|
||||
}
|
||||
expect: {
|
||||
var foo;
|
||||
@@ -86,8 +131,46 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
// as for the for, it should keep:
|
||||
var x = 10, y;
|
||||
var moo;
|
||||
bar();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: "<=4"
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more_strict: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
loops : true,
|
||||
booleans : true,
|
||||
conditionals : true,
|
||||
evaluate : true,
|
||||
side_effects : true,
|
||||
};
|
||||
input: {
|
||||
"use strict";
|
||||
while (!((foo && bar) || (x + "0"))) {
|
||||
console.log("unreachable");
|
||||
var foo;
|
||||
function bar() {}
|
||||
}
|
||||
for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
|
||||
asdf();
|
||||
foo();
|
||||
var moo;
|
||||
}
|
||||
bar();
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var foo;
|
||||
// nothing for the while
|
||||
// as for the for, it should keep:
|
||||
var x = 10, y;
|
||||
var moo;
|
||||
bar();
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
dead_code_block_decls_die: {
|
||||
|
||||
@@ -167,3 +167,81 @@ function_returning_constant_literal: {
|
||||
}
|
||||
expect_stdout: "Hello there"
|
||||
}
|
||||
|
||||
hoist_funs: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
}
|
||||
input: {
|
||||
console.log(1, typeof f, typeof g);
|
||||
if (console.log(2, typeof f, typeof g))
|
||||
console.log(3, typeof f, typeof g);
|
||||
else {
|
||||
console.log(4, typeof f, typeof g);
|
||||
function f() {}
|
||||
console.log(5, typeof f, typeof g);
|
||||
}
|
||||
function g() {}
|
||||
console.log(6, typeof f, typeof g);
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
function g() {}
|
||||
console.log(1, typeof f, typeof g);
|
||||
if (console.log(2, typeof f, typeof g))
|
||||
console.log(3, typeof f, typeof g);
|
||||
else {
|
||||
console.log(4, typeof f, typeof g);
|
||||
console.log(5, typeof f, typeof g);
|
||||
}
|
||||
console.log(6, typeof f, typeof g);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 'function' 'function'",
|
||||
"2 'function' 'function'",
|
||||
"4 'function' 'function'",
|
||||
"5 'function' 'function'",
|
||||
"6 'function' 'function'",
|
||||
]
|
||||
node_version: "<=4"
|
||||
}
|
||||
|
||||
hoist_funs_strict: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
console.log(1, typeof f, typeof g);
|
||||
if (console.log(2, typeof f, typeof g))
|
||||
console.log(3, typeof f, typeof g);
|
||||
else {
|
||||
console.log(4, typeof f, typeof g);
|
||||
function f() {}
|
||||
console.log(5, typeof f, typeof g);
|
||||
}
|
||||
function g() {}
|
||||
console.log(6, typeof f, typeof g);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function g() {}
|
||||
console.log(1, typeof f, typeof g);
|
||||
if (console.log(2, typeof f, typeof g))
|
||||
console.log(3, typeof f, typeof g);
|
||||
else {
|
||||
console.log(4, typeof f, typeof g);
|
||||
function f() {}
|
||||
console.log(5, typeof f, typeof g);
|
||||
}
|
||||
console.log(6, typeof f, typeof g);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1 'undefined' 'function'",
|
||||
"2 'undefined' 'function'",
|
||||
"4 'function' 'function'",
|
||||
"5 'function' 'function'",
|
||||
"6 'undefined' 'function'",
|
||||
]
|
||||
node_version: "=4"
|
||||
}
|
||||
|
||||
@@ -116,3 +116,137 @@ non_hoisted_function_after_return_2b: {
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_strict: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar();
|
||||
not_called1();
|
||||
} else {
|
||||
return baz();
|
||||
not_called2();
|
||||
}
|
||||
function bar() { return 7; }
|
||||
return not_reached;
|
||||
function UnusedFunction() {}
|
||||
function baz() { return 8; }
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
return x ? bar() : baz();
|
||||
function bar() { return 7 }
|
||||
function baz() { return 8 }
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect_stdout: "8 7"
|
||||
expect_warnings: [
|
||||
'WARN: Dropping unreachable code [test/compress/issue-1034.js:131,16]',
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:134,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:137,12]",
|
||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:138,21]"
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2a_strict: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||
collapse_vars: false, passes: 2, warnings: "verbose"
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar(1);
|
||||
var a = not_called(1);
|
||||
} else {
|
||||
return bar(2);
|
||||
var b = not_called(2);
|
||||
}
|
||||
var c = bar(3);
|
||||
function bar(x) { return 7 - x; }
|
||||
function nope() {}
|
||||
return b || c;
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
return bar(x ? 1 : 2);
|
||||
function bar(x) {
|
||||
return 7 - x;
|
||||
}
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect_stdout: "5 6"
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:173,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:173,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:176,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:176,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:173,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:180,21]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:181,12]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:176,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:178,16]",
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2b_strict: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||
collapse_vars: false
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar(1);
|
||||
} else {
|
||||
return bar(2);
|
||||
var b;
|
||||
}
|
||||
var c = bar(3);
|
||||
function bar(x) {
|
||||
return 7 - x;
|
||||
}
|
||||
return b || c;
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function foo(x) {
|
||||
return bar(x ? 1 : 2);
|
||||
function bar(x) { return 7 - x; }
|
||||
}
|
||||
console.log(foo(0), foo(1));
|
||||
}
|
||||
expect_stdout: "5 6"
|
||||
expect_warnings: [
|
||||
// duplicate warnings no longer emitted
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:225,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:225,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:227,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:227,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,90 +1,91 @@
|
||||
multiple_functions: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function f() {}
|
||||
function g() {}
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
function f() {}
|
||||
function g() {}
|
||||
|
||||
// NOTE: other compression steps will reduce this
|
||||
// down to just `window`.
|
||||
if ( window );
|
||||
function f() {}
|
||||
function g() {}
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
single_function: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function f() {}
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
function f() {}
|
||||
|
||||
if ( window );
|
||||
function f() {}
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
deeply_nested: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function f() {}
|
||||
function g() {}
|
||||
|
||||
if ( !document ) {
|
||||
return;
|
||||
}
|
||||
|
||||
function h() {}
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
( function() {
|
||||
function f() {}
|
||||
function g() {}
|
||||
|
||||
function h() {}
|
||||
|
||||
// NOTE: other compression steps will reduce this
|
||||
// down to just `window`.
|
||||
if ( window )
|
||||
if (document);
|
||||
function f() {}
|
||||
function g() {}
|
||||
function h() {}
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
not_hoisted_when_already_nested: {
|
||||
options = { if_return: true, hoist_funs: false };
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
( function() {
|
||||
if ( !window ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( foo ) function f() {}
|
||||
|
||||
} )();
|
||||
}
|
||||
expect: {
|
||||
@@ -94,3 +95,48 @@ not_hoisted_when_already_nested: {
|
||||
} )();
|
||||
}
|
||||
}
|
||||
|
||||
defun_if_return: {
|
||||
options = {
|
||||
hoist_funs: false,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (!window) return;
|
||||
else function g() {}
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (window) function g() {}
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defun_hoist_funs: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
if_return: true,
|
||||
}
|
||||
input: {
|
||||
function e() {
|
||||
function f() {}
|
||||
if (!window) return;
|
||||
else function g() {}
|
||||
function h() {}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function e() {
|
||||
function f() {}
|
||||
function g() {}
|
||||
function h() {}
|
||||
!window;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ if (typeof phantom == "undefined") {
|
||||
if (!args.length) {
|
||||
args.push("-mc");
|
||||
}
|
||||
args.push("--stats");
|
||||
args.push("--timings");
|
||||
var child_process = require("child_process");
|
||||
try {
|
||||
require("phantomjs-prebuilt");
|
||||
|
||||
@@ -61,5 +61,5 @@ function describe_ast() {
|
||||
}
|
||||
};
|
||||
doitem(AST_Node);
|
||||
return out + "";
|
||||
return out + "\n";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user