Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc61deeca9 | ||
|
|
6a5e74b44e | ||
|
|
54446341ee | ||
|
|
4e12a6f740 | ||
|
|
b35dfc2599 | ||
|
|
9e1da9235e | ||
|
|
a5ffe2c23f | ||
|
|
9282e7b0c6 | ||
|
|
5229cb2b1b | ||
|
|
458e3e15f0 | ||
|
|
c615a1e80a | ||
|
|
10a938cb79 | ||
|
|
4956ad311b | ||
|
|
145874e504 | ||
|
|
bd7be07c38 | ||
|
|
71ee91e716 | ||
|
|
4f70d2e28c | ||
|
|
4b6ca5e742 | ||
|
|
9306da3c58 | ||
|
|
1ac25fc032 | ||
|
|
5f046c724b | ||
|
|
af0262b7e5 | ||
|
|
6b3aeff1d8 | ||
|
|
20e4f8277f | ||
|
|
f3a487a368 |
34
README.md
34
README.md
@@ -644,6 +644,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `booleans` -- various optimizations for boolean context, for example `!!a
|
- `booleans` -- various optimizations for boolean context, for example `!!a
|
||||||
? b : c → a ? b : c`
|
? b : c → a ? b : c`
|
||||||
|
|
||||||
|
- `typeofs` -- default `true`. Transforms `typeof foo == "undefined"` into
|
||||||
|
`foo === void 0`. Note: recommend to set this value to `false` for IE10 and
|
||||||
|
earlier versions due to known issues.
|
||||||
|
|
||||||
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
- `loops` -- optimizations for `do`, `while` and `for` loops when we can
|
||||||
statically determine the condition
|
statically determine the condition
|
||||||
|
|
||||||
@@ -717,7 +721,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
compressor from discarding function names. Useful for code relying on
|
compressor from discarding function names. Useful for code relying on
|
||||||
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
|
||||||
|
|
||||||
- `passes` -- default `1`. Number of times to run compress with a maximum of 3.
|
- `passes` -- default `1`. The maximum number of times to run compress.
|
||||||
In some cases more than one pass leads to further compressed code. Keep in
|
In some cases more than one pass leads to further compressed code. Keep in
|
||||||
mind more passes will take more time.
|
mind more passes will take more time.
|
||||||
|
|
||||||
@@ -873,7 +877,6 @@ when this flag is on:
|
|||||||
- `new Object()` → `{}`
|
- `new Object()` → `{}`
|
||||||
- `String(exp)` or `exp.toString()` → `"" + exp`
|
- `String(exp)` or `exp.toString()` → `"" + exp`
|
||||||
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
||||||
- `typeof foo == "undefined"` → `foo === void 0`
|
|
||||||
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
||||||
scope; we do it because the variable name will be mangled, typically
|
scope; we do it because the variable name will be mangled, typically
|
||||||
reduced to a single character)
|
reduced to a single character)
|
||||||
@@ -1026,3 +1029,30 @@ in total it's a bit more than just using UglifyJS's own parser.
|
|||||||
|
|
||||||
[acorn]: https://github.com/ternjs/acorn
|
[acorn]: https://github.com/ternjs/acorn
|
||||||
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
|
[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
|
||||||
|
|
||||||
|
### Uglify Fast Minify Mode
|
||||||
|
|
||||||
|
It's not well known, but whitespace removal and symbol mangling accounts
|
||||||
|
for 95% of the size reduction in minified code for most javascript - not
|
||||||
|
elaborate code transforms. One can simply disable `compress` to speed up
|
||||||
|
Uglify builds by 3 to 4 times. In this fast `mangle`-only mode Uglify has
|
||||||
|
comparable minify speeds and gzip sizes to
|
||||||
|
[`butternut`](https://www.npmjs.com/package/butternut):
|
||||||
|
|
||||||
|
| d3.js | minify size | gzip size | minify time (seconds) |
|
||||||
|
| --- | ---: | ---: | ---: |
|
||||||
|
| original | 451,131 | 108,733 | - |
|
||||||
|
| uglify-js@3.0.24 mangle=false, compress=false | 316,600 | 85,245 | 0.70 |
|
||||||
|
| uglify-js@3.0.24 mangle=true, compress=false | 220,216 | 72,730 | 1.13 |
|
||||||
|
| butternut@0.4.6 | 217,568 | 72,738 | 1.41 |
|
||||||
|
| uglify-js@3.0.24 mangle=true, compress=true | 212,511 | 71,560 | 3.36 |
|
||||||
|
| babili@0.1.4 | 210,713 | 72,140 | 12.64 |
|
||||||
|
|
||||||
|
To enable fast minify mode from the CLI use:
|
||||||
|
```
|
||||||
|
uglifyjs file.js -m
|
||||||
|
```
|
||||||
|
To enable fast minify mode with the API use:
|
||||||
|
```js
|
||||||
|
UglifyJS.minify(code, { compress: false, mangle: true });
|
||||||
|
```
|
||||||
|
|||||||
20
bin/uglifyjs
20
bin/uglifyjs
@@ -35,11 +35,11 @@ else if (process.argv.indexOf("options") >= 0) program.helpInformation = functio
|
|||||||
}
|
}
|
||||||
return text.join("\n");
|
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());
|
||||||
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());
|
||||||
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());
|
||||||
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js("mangle-props", true));
|
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
|
||||||
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js("beautify", true));
|
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
|
||||||
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
program.option("-o, --output <file>", "Output file (default STDOUT).");
|
||||||
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
program.option("--comments [filter]", "Preserve copyright comments in the output.");
|
||||||
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
program.option("--config-file <file>", "Read minify() options from JSON file.");
|
||||||
@@ -310,7 +310,7 @@ function read_file(path, default_value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse_js(flag, constants) {
|
function parse_js(flag) {
|
||||||
return function(value, options) {
|
return function(value, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
try {
|
try {
|
||||||
@@ -328,7 +328,7 @@ function parse_js(flag, constants) {
|
|||||||
if (node instanceof UglifyJS.AST_Assign) {
|
if (node instanceof UglifyJS.AST_Assign) {
|
||||||
var name = node.left.print_to_string();
|
var name = node.left.print_to_string();
|
||||||
var value = node.right;
|
var value = node.right;
|
||||||
if (!constants) {
|
if (flag) {
|
||||||
options[name] = value;
|
options[name] = value;
|
||||||
} else if (value instanceof UglifyJS.AST_Array) {
|
} else if (value instanceof UglifyJS.AST_Array) {
|
||||||
options[name] = value.elements.map(to_string);
|
options[name] = value.elements.map(to_string);
|
||||||
@@ -351,14 +351,18 @@ function parse_js(flag, constants) {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
|
if (flag) {
|
||||||
|
fatal("Error parsing arguments for '" + flag + "': " + value);
|
||||||
|
} else {
|
||||||
options[value] = null;
|
options[value] = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse_source_map() {
|
function parse_source_map() {
|
||||||
var parse = parse_js("sourceMap", true);
|
var parse = parse_js();
|
||||||
return function(value, options) {
|
return function(value, options) {
|
||||||
var hasContent = options && "content" in options;
|
var hasContent = options && "content" in options;
|
||||||
var settings = parse(value, options);
|
var settings = parse(value, options);
|
||||||
|
|||||||
@@ -859,7 +859,7 @@ TreeWalker.prototype = {
|
|||||||
if (!ret && descend) {
|
if (!ret && descend) {
|
||||||
descend.call(node);
|
descend.call(node);
|
||||||
}
|
}
|
||||||
this.pop(node);
|
this.pop();
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
parent: function(n) {
|
parent: function(n) {
|
||||||
@@ -873,9 +873,8 @@ TreeWalker.prototype = {
|
|||||||
}
|
}
|
||||||
this.stack.push(node);
|
this.stack.push(node);
|
||||||
},
|
},
|
||||||
pop: function(node) {
|
pop: function() {
|
||||||
this.stack.pop();
|
if (this.stack.pop() instanceof AST_Lambda) {
|
||||||
if (node instanceof AST_Lambda) {
|
|
||||||
this.directives = Object.getPrototypeOf(this.directives);
|
this.directives = Object.getPrototypeOf(this.directives);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
532
lib/compress.js
532
lib/compress.js
@@ -80,6 +80,7 @@ function Compressor(options, false_by_default) {
|
|||||||
switches : !false_by_default,
|
switches : !false_by_default,
|
||||||
top_retain : null,
|
top_retain : null,
|
||||||
toplevel : !!(options && options["top_retain"]),
|
toplevel : !!(options && options["top_retain"]),
|
||||||
|
typeofs : !false_by_default,
|
||||||
unsafe : false,
|
unsafe : false,
|
||||||
unsafe_comps : false,
|
unsafe_comps : false,
|
||||||
unsafe_Func : false,
|
unsafe_Func : false,
|
||||||
@@ -147,10 +148,20 @@ merge(Compressor.prototype, {
|
|||||||
node.process_expression(true);
|
node.process_expression(true);
|
||||||
}
|
}
|
||||||
var passes = +this.options.passes || 1;
|
var passes = +this.options.passes || 1;
|
||||||
for (var pass = 0; pass < passes && pass < 3; ++pass) {
|
var last_count = 1 / 0;
|
||||||
|
for (var pass = 0; pass < passes; pass++) {
|
||||||
if (pass > 0 || this.option("reduce_vars"))
|
if (pass > 0 || this.option("reduce_vars"))
|
||||||
node.reset_opt_flags(this, true);
|
node.reset_opt_flags(this, true);
|
||||||
node = node.transform(this);
|
node = node.transform(this);
|
||||||
|
if (passes > 1) {
|
||||||
|
var count = 0;
|
||||||
|
node.walk(new TreeWalker(function() {
|
||||||
|
count++;
|
||||||
|
}));
|
||||||
|
this.info("pass " + pass + ": last_count: " + last_count + ", count: " + count);
|
||||||
|
if (count >= last_count) break;
|
||||||
|
last_count = count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.option("expression")) {
|
if (this.option("expression")) {
|
||||||
node.process_expression(false);
|
node.process_expression(false);
|
||||||
@@ -678,6 +689,16 @@ merge(Compressor.prototype, {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function is_undeclared_ref(node) {
|
||||||
|
return node instanceof AST_SymbolRef && node.definition().undeclared;
|
||||||
|
}
|
||||||
|
|
||||||
|
var global_names = makePredicate("Array Boolean console Error Function Math Number RegExp Object String");
|
||||||
|
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
|
||||||
|
return !this.definition().undeclared
|
||||||
|
|| compressor.option("unsafe") && global_names(this.name);
|
||||||
|
});
|
||||||
|
|
||||||
function tighten_body(statements, compressor) {
|
function tighten_body(statements, compressor) {
|
||||||
var CHANGED, max_iter = 10;
|
var CHANGED, max_iter = 10;
|
||||||
do {
|
do {
|
||||||
@@ -747,7 +768,7 @@ merge(Compressor.prototype, {
|
|||||||
|| node instanceof AST_Call && lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression)
|
|| node instanceof AST_Call && lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression)
|
||||||
|| node instanceof AST_Debugger
|
|| node instanceof AST_Debugger
|
||||||
|| node instanceof AST_IterationStatement && !(node instanceof AST_For)
|
|| node instanceof AST_IterationStatement && !(node instanceof AST_For)
|
||||||
|| node instanceof AST_SymbolRef && node.undeclared()
|
|| node instanceof AST_SymbolRef && !node.is_declared(compressor)
|
||||||
|| node instanceof AST_Try
|
|| node instanceof AST_Try
|
||||||
|| node instanceof AST_With
|
|| node instanceof AST_With
|
||||||
|| parent instanceof AST_For && node !== parent.init) {
|
|| parent instanceof AST_For && node !== parent.init) {
|
||||||
@@ -779,6 +800,7 @@ merge(Compressor.prototype, {
|
|||||||
right: candidate.value
|
right: candidate.value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
candidate.write_only = false;
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
// These node types have child nodes that execute sequentially,
|
// These node types have child nodes that execute sequentially,
|
||||||
@@ -819,10 +841,15 @@ merge(Compressor.prototype, {
|
|||||||
&& !fn.uses_eval
|
&& !fn.uses_eval
|
||||||
&& (iife = compressor.parent()) instanceof AST_Call
|
&& (iife = compressor.parent()) instanceof AST_Call
|
||||||
&& iife.expression === fn) {
|
&& iife.expression === fn) {
|
||||||
fn.argnames.forEach(function(sym, i) {
|
var names = Object.create(null);
|
||||||
|
for (var i = fn.argnames.length; --i >= 0;) {
|
||||||
|
var sym = fn.argnames[i];
|
||||||
|
if (sym.name in names) continue;
|
||||||
|
names[sym.name] = true;
|
||||||
var arg = iife.args[i];
|
var arg = iife.args[i];
|
||||||
if (!arg) arg = make_node(AST_Undefined, sym);
|
if (!arg) arg = make_node(AST_Undefined, sym);
|
||||||
else arg.walk(new TreeWalker(function(node) {
|
else {
|
||||||
|
var tw = new TreeWalker(function(node) {
|
||||||
if (!arg) return true;
|
if (!arg) return true;
|
||||||
if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
|
if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) {
|
||||||
var s = node.definition().scope;
|
var s = node.definition().scope;
|
||||||
@@ -831,12 +858,18 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
arg = null;
|
arg = null;
|
||||||
}
|
}
|
||||||
}));
|
if (node instanceof AST_This && !tw.find_parent(AST_Scope)) {
|
||||||
if (arg) candidates.push(make_node(AST_VarDef, sym, {
|
arg = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
arg.walk(tw);
|
||||||
|
}
|
||||||
|
if (arg) candidates.unshift(make_node(AST_VarDef, sym, {
|
||||||
name: sym,
|
name: sym,
|
||||||
value: arg
|
value: arg
|
||||||
}));
|
}));
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1198,21 +1231,21 @@ merge(Compressor.prototype, {
|
|||||||
for (var i = 0, len = statements.length; i < len; i++) {
|
for (var i = 0, len = statements.length; i < len; i++) {
|
||||||
var stat = statements[i];
|
var stat = statements[i];
|
||||||
if (prev) {
|
if (prev) {
|
||||||
if (stat instanceof AST_For) {
|
if (stat instanceof AST_For && !(stat.init instanceof AST_Definitions)) {
|
||||||
try {
|
var abort = false;
|
||||||
prev.body.walk(new TreeWalker(function(node) {
|
prev.body.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Binary && node.operator == "in")
|
if (abort || node instanceof AST_Scope) return true;
|
||||||
throw cons_seq;
|
if (node instanceof AST_Binary && node.operator == "in") {
|
||||||
}));
|
abort = true;
|
||||||
if (stat.init && !(stat.init instanceof AST_Definitions)) {
|
return true;
|
||||||
stat.init = cons_seq(stat.init);
|
|
||||||
}
|
}
|
||||||
else if (!stat.init) {
|
}));
|
||||||
|
if (!abort) {
|
||||||
|
if (stat.init) stat.init = cons_seq(stat.init);
|
||||||
|
else {
|
||||||
stat.init = prev.body.drop_side_effect_free(compressor);
|
stat.init = prev.body.drop_side_effect_free(compressor);
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
} catch(ex) {
|
|
||||||
if (ex !== cons_seq) throw ex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (stat instanceof AST_If) {
|
else if (stat instanceof AST_If) {
|
||||||
@@ -1297,12 +1330,12 @@ merge(Compressor.prototype, {
|
|||||||
// returns true if this node may be null, undefined or contain `AST_Accessor`
|
// returns true if this node may be null, undefined or contain `AST_Accessor`
|
||||||
(function(def) {
|
(function(def) {
|
||||||
AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
|
AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
|
||||||
var pure_getters = compressor.option("pure_getters");
|
return !compressor.option("pure_getters")
|
||||||
return !pure_getters || this._throw_on_access(pure_getters);
|
|| this._dot_throw(compressor);
|
||||||
});
|
});
|
||||||
|
|
||||||
function is_strict(pure_getters) {
|
function is_strict(compressor) {
|
||||||
return /strict/.test(pure_getters);
|
return /strict/.test(compressor.option("pure_getters"));
|
||||||
}
|
}
|
||||||
|
|
||||||
def(AST_Node, is_strict);
|
def(AST_Node, is_strict);
|
||||||
@@ -1310,8 +1343,8 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Undefined, return_true);
|
def(AST_Undefined, return_true);
|
||||||
def(AST_Constant, return_false);
|
def(AST_Constant, return_false);
|
||||||
def(AST_Array, return_false);
|
def(AST_Array, return_false);
|
||||||
def(AST_Object, function(pure_getters) {
|
def(AST_Object, function(compressor) {
|
||||||
if (!is_strict(pure_getters)) return false;
|
if (!is_strict(compressor)) return false;
|
||||||
for (var i = this.properties.length; --i >=0;)
|
for (var i = this.properties.length; --i >=0;)
|
||||||
if (this.properties[i].value instanceof AST_Accessor) return true;
|
if (this.properties[i].value instanceof AST_Accessor) return true;
|
||||||
return false;
|
return false;
|
||||||
@@ -1321,37 +1354,38 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_UnaryPrefix, function() {
|
def(AST_UnaryPrefix, function() {
|
||||||
return this.operator == "void";
|
return this.operator == "void";
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(pure_getters) {
|
def(AST_Binary, function(compressor) {
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
return this.left._throw_on_access(pure_getters);
|
return this.left._dot_throw(compressor);
|
||||||
case "||":
|
case "||":
|
||||||
return this.left._throw_on_access(pure_getters)
|
return this.left._dot_throw(compressor)
|
||||||
&& this.right._throw_on_access(pure_getters);
|
&& this.right._dot_throw(compressor);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
def(AST_Assign, function(pure_getters) {
|
def(AST_Assign, function(compressor) {
|
||||||
return this.operator == "="
|
return this.operator == "="
|
||||||
&& this.right._throw_on_access(pure_getters);
|
&& this.right._dot_throw(compressor);
|
||||||
})
|
})
|
||||||
def(AST_Conditional, function(pure_getters) {
|
def(AST_Conditional, function(compressor) {
|
||||||
return this.consequent._throw_on_access(pure_getters)
|
return this.consequent._dot_throw(compressor)
|
||||||
|| this.alternative._throw_on_access(pure_getters);
|
|| this.alternative._dot_throw(compressor);
|
||||||
})
|
})
|
||||||
def(AST_Sequence, function(pure_getters) {
|
def(AST_Sequence, function(compressor) {
|
||||||
return this.expressions[this.expressions.length - 1]._throw_on_access(pure_getters);
|
return this.expressions[this.expressions.length - 1]._dot_throw(compressor);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(pure_getters) {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
if (this.is_undefined) return true;
|
if (this.is_undefined) return true;
|
||||||
if (!is_strict(pure_getters)) return false;
|
if (!is_strict(compressor)) return false;
|
||||||
|
if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
|
||||||
if (this.is_immutable()) return false;
|
if (this.is_immutable()) return false;
|
||||||
var fixed = this.fixed_value();
|
var fixed = this.fixed_value();
|
||||||
return !fixed || fixed._throw_on_access(pure_getters);
|
return !fixed || fixed._dot_throw(compressor);
|
||||||
});
|
});
|
||||||
})(function(node, func) {
|
})(function(node, func) {
|
||||||
node.DEFMETHOD("_throw_on_access", func);
|
node.DEFMETHOD("_dot_throw", func);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -----[ boolean/negation helpers ]----- */
|
/* -----[ boolean/negation helpers ]----- */
|
||||||
@@ -1532,13 +1566,8 @@ merge(Compressor.prototype, {
|
|||||||
// descendant of AST_Node.
|
// descendant of AST_Node.
|
||||||
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
||||||
if (!compressor.option("evaluate")) return this;
|
if (!compressor.option("evaluate")) return this;
|
||||||
try {
|
|
||||||
var val = this._eval(compressor);
|
var val = this._eval(compressor);
|
||||||
return !val || val instanceof RegExp || typeof val != "object" ? val : this;
|
return !val || val instanceof RegExp || typeof val != "object" ? val : this;
|
||||||
} catch(ex) {
|
|
||||||
if (ex !== def) throw ex;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
var unaryPrefix = makePredicate("! ~ - + void");
|
var unaryPrefix = makePredicate("! ~ - + void");
|
||||||
AST_Node.DEFMETHOD("is_constant", function(){
|
AST_Node.DEFMETHOD("is_constant", function(){
|
||||||
@@ -1584,27 +1613,28 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Statement, function(){
|
def(AST_Statement, function(){
|
||||||
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
||||||
});
|
});
|
||||||
def(AST_Lambda, function(){
|
def(AST_Lambda, return_this);
|
||||||
throw def;
|
|
||||||
});
|
|
||||||
function ev(node, compressor) {
|
function ev(node, compressor) {
|
||||||
if (!compressor) throw new Error("Compressor must be passed");
|
if (!compressor) throw new Error("Compressor must be passed");
|
||||||
|
|
||||||
return node._eval(compressor);
|
return node._eval(compressor);
|
||||||
};
|
};
|
||||||
def(AST_Node, function(){
|
def(AST_Node, return_this);
|
||||||
throw def; // not constant
|
|
||||||
});
|
|
||||||
def(AST_Constant, function(){
|
def(AST_Constant, function(){
|
||||||
return this.getValue();
|
return this.getValue();
|
||||||
});
|
});
|
||||||
def(AST_Array, function(compressor){
|
def(AST_Array, function(compressor){
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
return this.elements.map(function(element) {
|
var elements = [];
|
||||||
return ev(element, compressor);
|
for (var i = 0, len = this.elements.length; i < len; i++) {
|
||||||
});
|
var element = this.elements[i];
|
||||||
|
var value = ev(element, compressor);
|
||||||
|
if (element === value) return this;
|
||||||
|
elements.push(value);
|
||||||
}
|
}
|
||||||
throw def;
|
return elements;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
});
|
});
|
||||||
def(AST_Object, function(compressor){
|
def(AST_Object, function(compressor){
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
@@ -1616,163 +1646,255 @@ merge(Compressor.prototype, {
|
|||||||
key = key.name;
|
key = key.name;
|
||||||
} else if (key instanceof AST_Node) {
|
} else if (key instanceof AST_Node) {
|
||||||
key = ev(key, compressor);
|
key = ev(key, compressor);
|
||||||
|
if (key === prop.key) return this;
|
||||||
}
|
}
|
||||||
if (typeof Object.prototype[key] === 'function') {
|
if (typeof Object.prototype[key] === 'function') {
|
||||||
throw def;
|
return this;
|
||||||
}
|
}
|
||||||
val[key] = ev(prop.value, compressor);
|
val[key] = ev(prop.value, compressor);
|
||||||
|
if (val[key] === prop.value) return this;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
throw def;
|
return this;
|
||||||
});
|
});
|
||||||
def(AST_UnaryPrefix, function(compressor){
|
def(AST_UnaryPrefix, function(compressor){
|
||||||
var e = this.expression;
|
|
||||||
switch (this.operator) {
|
|
||||||
case "!": return !ev(e, compressor);
|
|
||||||
case "typeof":
|
|
||||||
// Function would be evaluated to an array and so typeof would
|
// Function would be evaluated to an array and so typeof would
|
||||||
// incorrectly return 'object'. Hence making is a special case.
|
// incorrectly return 'object'. Hence making is a special case.
|
||||||
if (e instanceof AST_Function) return typeof function(){};
|
if (this.operator == "typeof" && this.expression instanceof AST_Function) {
|
||||||
|
return typeof function(){};
|
||||||
e = ev(e, compressor);
|
}
|
||||||
|
var e = ev(this.expression, compressor);
|
||||||
|
if (e === this.expression) return this;
|
||||||
|
switch (this.operator) {
|
||||||
|
case "!": return !e;
|
||||||
|
case "typeof":
|
||||||
// typeof <RegExp> returns "object" or "function" on different platforms
|
// typeof <RegExp> returns "object" or "function" on different platforms
|
||||||
// so cannot evaluate reliably
|
// so cannot evaluate reliably
|
||||||
if (e instanceof RegExp) throw def;
|
if (e instanceof RegExp) return this;
|
||||||
|
|
||||||
return typeof e;
|
return typeof e;
|
||||||
case "void": return void ev(e, compressor);
|
case "void": return void e;
|
||||||
case "~": return ~ev(e, compressor);
|
case "~": return ~e;
|
||||||
case "-": return -ev(e, compressor);
|
case "-": return -e;
|
||||||
case "+": return +ev(e, compressor);
|
case "+": return +e;
|
||||||
}
|
}
|
||||||
throw def;
|
return this;
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(c){
|
def(AST_Binary, function(compressor){
|
||||||
var left = this.left, right = this.right, result;
|
var left = ev(this.left, compressor);
|
||||||
|
if (left === this.left) return this;
|
||||||
|
var right = ev(this.right, compressor);
|
||||||
|
if (right === this.right) return this;
|
||||||
|
var result;
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case "&&" : result = ev(left, c) && ev(right, c); break;
|
case "&&" : result = left && right; break;
|
||||||
case "||" : result = ev(left, c) || ev(right, c); break;
|
case "||" : result = left || right; break;
|
||||||
case "|" : result = ev(left, c) | ev(right, c); break;
|
case "|" : result = left | right; break;
|
||||||
case "&" : result = ev(left, c) & ev(right, c); break;
|
case "&" : result = left & right; break;
|
||||||
case "^" : result = ev(left, c) ^ ev(right, c); break;
|
case "^" : result = left ^ right; break;
|
||||||
case "+" : result = ev(left, c) + ev(right, c); break;
|
case "+" : result = left + right; break;
|
||||||
case "*" : result = ev(left, c) * ev(right, c); break;
|
case "*" : result = left * right; break;
|
||||||
case "/" : result = ev(left, c) / ev(right, c); break;
|
case "/" : result = left / right; break;
|
||||||
case "%" : result = ev(left, c) % ev(right, c); break;
|
case "%" : result = left % right; break;
|
||||||
case "-" : result = ev(left, c) - ev(right, c); break;
|
case "-" : result = left - right; break;
|
||||||
case "<<" : result = ev(left, c) << ev(right, c); break;
|
case "<<" : result = left << right; break;
|
||||||
case ">>" : result = ev(left, c) >> ev(right, c); break;
|
case ">>" : result = left >> right; break;
|
||||||
case ">>>" : result = ev(left, c) >>> ev(right, c); break;
|
case ">>>" : result = left >>> right; break;
|
||||||
case "==" : result = ev(left, c) == ev(right, c); break;
|
case "==" : result = left == right; break;
|
||||||
case "===" : result = ev(left, c) === ev(right, c); break;
|
case "===" : result = left === right; break;
|
||||||
case "!=" : result = ev(left, c) != ev(right, c); break;
|
case "!=" : result = left != right; break;
|
||||||
case "!==" : result = ev(left, c) !== ev(right, c); break;
|
case "!==" : result = left !== right; break;
|
||||||
case "<" : result = ev(left, c) < ev(right, c); break;
|
case "<" : result = left < right; break;
|
||||||
case "<=" : result = ev(left, c) <= ev(right, c); break;
|
case "<=" : result = left <= right; break;
|
||||||
case ">" : result = ev(left, c) > ev(right, c); break;
|
case ">" : result = left > right; break;
|
||||||
case ">=" : result = ev(left, c) >= ev(right, c); break;
|
case ">=" : result = left >= right; break;
|
||||||
default:
|
default:
|
||||||
throw def;
|
return this;
|
||||||
}
|
}
|
||||||
if (isNaN(result) && c.find_parent(AST_With)) {
|
if (isNaN(result) && compressor.find_parent(AST_With)) {
|
||||||
// leave original expression as is
|
// leave original expression as is
|
||||||
throw def;
|
return this;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
def(AST_Conditional, function(compressor){
|
def(AST_Conditional, function(compressor){
|
||||||
return ev(this.condition, compressor)
|
var condition = ev(this.condition, compressor);
|
||||||
? ev(this.consequent, compressor)
|
if (condition === this.condition) return this;
|
||||||
: ev(this.alternative, compressor);
|
var node = condition ? this.consequent : this.alternative;
|
||||||
|
var value = ev(node, compressor);
|
||||||
|
return value === node ? this : value;
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor){
|
def(AST_SymbolRef, function(compressor){
|
||||||
if (!compressor.option("reduce_vars") || this._evaluating) throw def;
|
if (!compressor.option("reduce_vars")) return this;
|
||||||
this._evaluating = true;
|
|
||||||
try {
|
|
||||||
var fixed = this.fixed_value();
|
var fixed = this.fixed_value();
|
||||||
if (!fixed) throw def;
|
if (!fixed) return this;
|
||||||
|
this._eval = return_this;
|
||||||
var value = ev(fixed, compressor);
|
var value = ev(fixed, compressor);
|
||||||
|
if (value === fixed) {
|
||||||
|
delete this._eval;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
if (!HOP(fixed, "_eval")) fixed._eval = function() {
|
if (!HOP(fixed, "_eval")) fixed._eval = function() {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
if (value && typeof value == "object" && this.definition().escaped) throw def;
|
if (value && typeof value == "object" && this.definition().escaped) {
|
||||||
return value;
|
delete this._eval;
|
||||||
} finally {
|
return this;
|
||||||
this._evaluating = false;
|
|
||||||
}
|
}
|
||||||
|
this._eval = fixed._eval;
|
||||||
|
return value;
|
||||||
});
|
});
|
||||||
|
var global_objs = {
|
||||||
|
Array: Array,
|
||||||
|
Math: Math,
|
||||||
|
Number: Number,
|
||||||
|
String: String,
|
||||||
|
};
|
||||||
|
function convert_to_predicate(obj) {
|
||||||
|
for (var key in obj) {
|
||||||
|
obj[key] = makePredicate(obj[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var static_values = {
|
||||||
|
Math: [
|
||||||
|
"E",
|
||||||
|
"LN10",
|
||||||
|
"LN2",
|
||||||
|
"LOG2E",
|
||||||
|
"LOG10E",
|
||||||
|
"PI",
|
||||||
|
"SQRT1_2",
|
||||||
|
"SQRT2",
|
||||||
|
],
|
||||||
|
Number: [
|
||||||
|
"MAX_VALUE",
|
||||||
|
"MIN_VALUE",
|
||||||
|
"NaN",
|
||||||
|
"NEGATIVE_INFINITY",
|
||||||
|
"POSITIVE_INFINITY",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
convert_to_predicate(static_values);
|
||||||
def(AST_PropAccess, function(compressor){
|
def(AST_PropAccess, function(compressor){
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
var key = this.property;
|
var key = this.property;
|
||||||
if (key instanceof AST_Node) {
|
if (key instanceof AST_Node) {
|
||||||
key = ev(key, compressor);
|
key = ev(key, compressor);
|
||||||
|
if (key === this.property) return this;
|
||||||
|
}
|
||||||
|
var exp = this.expression;
|
||||||
|
var val;
|
||||||
|
if (is_undeclared_ref(exp)) {
|
||||||
|
if (!(static_values[exp.name] || return_false)(key)) return this;
|
||||||
|
val = global_objs[exp.name];
|
||||||
|
} else {
|
||||||
|
val = ev(exp, compressor);
|
||||||
|
if (!val || val === exp || !HOP(val, key)) return this;
|
||||||
}
|
}
|
||||||
var val = ev(this.expression, compressor);
|
|
||||||
if (val && HOP(val, key)) {
|
|
||||||
return val[key];
|
return val[key];
|
||||||
}
|
}
|
||||||
}
|
return this;
|
||||||
throw def;
|
|
||||||
});
|
});
|
||||||
var object_fns = [
|
var object_fns = [
|
||||||
'constructor',
|
"constructor",
|
||||||
'toString',
|
"toString",
|
||||||
'valueOf',
|
"valueOf",
|
||||||
];
|
];
|
||||||
var native_fns = {
|
var native_fns = {
|
||||||
Array: makePredicate([
|
Array: [
|
||||||
'indexOf',
|
"indexOf",
|
||||||
'join',
|
"join",
|
||||||
'lastIndexOf',
|
"lastIndexOf",
|
||||||
'slice',
|
"slice",
|
||||||
].concat(object_fns)),
|
].concat(object_fns),
|
||||||
Boolean: makePredicate(object_fns),
|
Boolean: object_fns,
|
||||||
Number: makePredicate([
|
Number: [
|
||||||
'toExponential',
|
"toExponential",
|
||||||
'toFixed',
|
"toFixed",
|
||||||
'toPrecision',
|
"toPrecision",
|
||||||
].concat(object_fns)),
|
].concat(object_fns),
|
||||||
RegExp: makePredicate([
|
RegExp: [
|
||||||
'test',
|
"test",
|
||||||
].concat(object_fns)),
|
].concat(object_fns),
|
||||||
String: makePredicate([
|
String: [
|
||||||
'charAt',
|
"charAt",
|
||||||
'charCodeAt',
|
"charCodeAt",
|
||||||
'concat',
|
"concat",
|
||||||
'indexOf',
|
"indexOf",
|
||||||
'italics',
|
"italics",
|
||||||
'lastIndexOf',
|
"lastIndexOf",
|
||||||
'match',
|
"match",
|
||||||
'replace',
|
"replace",
|
||||||
'search',
|
"search",
|
||||||
'slice',
|
"slice",
|
||||||
'split',
|
"split",
|
||||||
'substr',
|
"substr",
|
||||||
'substring',
|
"substring",
|
||||||
'trim',
|
"trim",
|
||||||
].concat(object_fns)),
|
].concat(object_fns),
|
||||||
};
|
};
|
||||||
|
convert_to_predicate(native_fns);
|
||||||
|
var static_fns = {
|
||||||
|
Array: [
|
||||||
|
"isArray",
|
||||||
|
],
|
||||||
|
Math: [
|
||||||
|
"abs",
|
||||||
|
"acos",
|
||||||
|
"asin",
|
||||||
|
"atan",
|
||||||
|
"ceil",
|
||||||
|
"cos",
|
||||||
|
"exp",
|
||||||
|
"floor",
|
||||||
|
"log",
|
||||||
|
"round",
|
||||||
|
"sin",
|
||||||
|
"sqrt",
|
||||||
|
"tan",
|
||||||
|
"atan2",
|
||||||
|
"pow",
|
||||||
|
"max",
|
||||||
|
"min"
|
||||||
|
],
|
||||||
|
Number: [
|
||||||
|
"isFinite",
|
||||||
|
"isNaN",
|
||||||
|
],
|
||||||
|
String: [
|
||||||
|
"fromCharCode",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
convert_to_predicate(static_fns);
|
||||||
def(AST_Call, function(compressor){
|
def(AST_Call, function(compressor){
|
||||||
var exp = this.expression;
|
var exp = this.expression;
|
||||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||||
var key = exp.property;
|
var key = exp.property;
|
||||||
if (key instanceof AST_Node) {
|
if (key instanceof AST_Node) {
|
||||||
key = ev(key, compressor);
|
key = ev(key, compressor);
|
||||||
|
if (key === exp.property) return this;
|
||||||
}
|
}
|
||||||
var val = ev(exp.expression, compressor);
|
var val;
|
||||||
if ((val && native_fns[val.constructor.name] || return_false)(key)) {
|
var e = exp.expression;
|
||||||
return val[key].apply(val, this.args.map(function(arg) {
|
if (is_undeclared_ref(e)) {
|
||||||
return ev(arg, compressor);
|
if (!(static_fns[e.name] || return_false)(key)) return this;
|
||||||
}));
|
val = global_objs[e.name];
|
||||||
|
} else {
|
||||||
|
val = ev(e, compressor);
|
||||||
|
if (val === e || !(val && native_fns[val.constructor.name] || return_false)(key)) return this;
|
||||||
}
|
}
|
||||||
|
var args = [];
|
||||||
|
for (var i = 0, len = this.args.length; i < len; i++) {
|
||||||
|
var arg = this.args[i];
|
||||||
|
var value = ev(arg, compressor);
|
||||||
|
if (arg === value) return this;
|
||||||
|
args.push(value);
|
||||||
}
|
}
|
||||||
throw def;
|
return val[key].apply(val, args);
|
||||||
});
|
}
|
||||||
def(AST_New, function(compressor){
|
return this;
|
||||||
throw def;
|
|
||||||
});
|
});
|
||||||
|
def(AST_New, return_this);
|
||||||
})(function(node, func){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("_eval", func);
|
node.DEFMETHOD("_eval", func);
|
||||||
});
|
});
|
||||||
@@ -1936,7 +2058,7 @@ merge(Compressor.prototype, {
|
|||||||
|| this.expression.has_side_effects(compressor);
|
|| this.expression.has_side_effects(compressor);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor){
|
def(AST_SymbolRef, function(compressor){
|
||||||
return this.undeclared();
|
return !this.is_declared(compressor);
|
||||||
});
|
});
|
||||||
def(AST_SymbolDeclaration, return_false);
|
def(AST_SymbolDeclaration, return_false);
|
||||||
def(AST_Object, function(compressor){
|
def(AST_Object, function(compressor){
|
||||||
@@ -2060,7 +2182,12 @@ merge(Compressor.prototype, {
|
|||||||
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
|
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
|
||||||
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
|
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
|
||||||
if (!drop_funcs && !drop_vars) return;
|
if (!drop_funcs && !drop_vars) return;
|
||||||
var assign_as_unused = !/keep_assign/.test(compressor.option("unused"));
|
var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node) {
|
||||||
|
if (node instanceof AST_Assign && (node.write_only || node.operator == "=")) {
|
||||||
|
return node.left;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Unary && node.write_only) return node.expression;
|
||||||
|
};
|
||||||
var in_use = [];
|
var in_use = [];
|
||||||
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
|
||||||
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
||||||
@@ -2110,12 +2237,8 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (assign_as_unused
|
if (assign_as_unused(node) instanceof AST_SymbolRef && scope === self) {
|
||||||
&& node instanceof AST_Assign
|
if (node instanceof AST_Assign) node.right.walk(tw);
|
||||||
&& node.operator == "="
|
|
||||||
&& node.left instanceof AST_SymbolRef
|
|
||||||
&& scope === self) {
|
|
||||||
node.right.walk(tw);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
@@ -2279,15 +2402,18 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (drop_vars && assign_as_unused
|
if (drop_vars) {
|
||||||
&& node instanceof AST_Assign
|
var def = assign_as_unused(node);
|
||||||
&& node.operator == "="
|
if (def instanceof AST_SymbolRef
|
||||||
&& node.left instanceof AST_SymbolRef) {
|
&& !((def = def.definition()).id in in_use_ids)
|
||||||
var def = node.left.definition();
|
|
||||||
if (!(def.id in in_use_ids)
|
|
||||||
&& self.variables.get(def.name) === def) {
|
&& self.variables.get(def.name) === def) {
|
||||||
|
if (node instanceof AST_Assign) {
|
||||||
return maintain_this_binding(tt.parent(), node, node.right.transform(tt));
|
return maintain_this_binding(tt.parent(), node, node.right.transform(tt));
|
||||||
}
|
}
|
||||||
|
return make_node(AST_Number, node, {
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// certain combination of unused name + side effect leads to:
|
// certain combination of unused name + side effect leads to:
|
||||||
// https://github.com/mishoo/UglifyJS2/issues/44
|
// https://github.com/mishoo/UglifyJS2/issues/44
|
||||||
@@ -2525,7 +2651,10 @@ merge(Compressor.prototype, {
|
|||||||
return make_sequence(this, [ left, right ]);
|
return make_sequence(this, [ left, right ]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
def(AST_Assign, return_this);
|
def(AST_Assign, function(compressor){
|
||||||
|
this.write_only = !this.left.has_side_effects(compressor);
|
||||||
|
return this;
|
||||||
|
});
|
||||||
def(AST_Conditional, function(compressor){
|
def(AST_Conditional, function(compressor){
|
||||||
var consequent = this.consequent.drop_side_effect_free(compressor);
|
var consequent = this.consequent.drop_side_effect_free(compressor);
|
||||||
var alternative = this.alternative.drop_side_effect_free(compressor);
|
var alternative = this.alternative.drop_side_effect_free(compressor);
|
||||||
@@ -2546,7 +2675,10 @@ merge(Compressor.prototype, {
|
|||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
def(AST_Unary, function(compressor, first_in_statement){
|
def(AST_Unary, function(compressor, first_in_statement){
|
||||||
if (unary_side_effects(this.operator)) return this;
|
if (unary_side_effects(this.operator)) {
|
||||||
|
this.write_only = !this.expression.has_side_effects(compressor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null;
|
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null;
|
||||||
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (first_in_statement
|
if (first_in_statement
|
||||||
@@ -2560,8 +2692,8 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return expression;
|
return expression;
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function() {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
return this.undeclared() ? this : null;
|
return this.is_declared(compressor) ? null : this;
|
||||||
});
|
});
|
||||||
def(AST_Object, function(compressor, first_in_statement){
|
def(AST_Object, function(compressor, first_in_statement){
|
||||||
var values = trim(this.properties, compressor, first_in_statement);
|
var values = trim(this.properties, compressor, first_in_statement);
|
||||||
@@ -3023,7 +3155,7 @@ merge(Compressor.prototype, {
|
|||||||
self.args.length = last;
|
self.args.length = last;
|
||||||
}
|
}
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
|
if (is_undeclared_ref(exp)) {
|
||||||
switch (exp.name) {
|
switch (exp.name) {
|
||||||
case "Array":
|
case "Array":
|
||||||
if (self.args.length != 1) {
|
if (self.args.length != 1) {
|
||||||
@@ -3150,8 +3282,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("unsafe_Func")
|
if (compressor.option("unsafe_Func")
|
||||||
&& exp instanceof AST_SymbolRef
|
&& is_undeclared_ref(exp)
|
||||||
&& exp.undeclared()
|
|
||||||
&& exp.name == "Function") {
|
&& exp.name == "Function") {
|
||||||
// new Function() => function(){}
|
// new Function() => function(){}
|
||||||
if (self.args.length == 0) return make_node(AST_Function, self, {
|
if (self.args.length == 0) return make_node(AST_Function, self, {
|
||||||
@@ -3268,9 +3399,7 @@ merge(Compressor.prototype, {
|
|||||||
while (name.expression) {
|
while (name.expression) {
|
||||||
name = name.expression;
|
name = name.expression;
|
||||||
}
|
}
|
||||||
if (name instanceof AST_SymbolRef
|
if (is_undeclared_ref(name) && name.name == "console") {
|
||||||
&& name.name == "console"
|
|
||||||
&& name.undeclared()) {
|
|
||||||
return make_node(AST_Undefined, self).optimize(compressor);
|
return make_node(AST_Undefined, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3291,7 +3420,7 @@ merge(Compressor.prototype, {
|
|||||||
OPT(AST_New, function(self, compressor){
|
OPT(AST_New, function(self, compressor){
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
var exp = self.expression;
|
var exp = self.expression;
|
||||||
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
|
if (is_undeclared_ref(exp)) {
|
||||||
switch (exp.name) {
|
switch (exp.name) {
|
||||||
case "Object":
|
case "Object":
|
||||||
case "RegExp":
|
case "RegExp":
|
||||||
@@ -3368,6 +3497,8 @@ merge(Compressor.prototype, {
|
|||||||
operator: car.operator,
|
operator: car.operator,
|
||||||
expression: left
|
expression: left
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
car.write_only = false;
|
||||||
}
|
}
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent[field] = car;
|
parent[field] = car;
|
||||||
@@ -3577,12 +3708,13 @@ merge(Compressor.prototype, {
|
|||||||
case "==":
|
case "==":
|
||||||
case "!=":
|
case "!=":
|
||||||
// "undefined" == typeof x => undefined === x
|
// "undefined" == typeof x => undefined === x
|
||||||
if (self.left instanceof AST_String
|
if (compressor.option("typeofs")
|
||||||
|
&& self.left instanceof AST_String
|
||||||
&& self.left.value == "undefined"
|
&& self.left.value == "undefined"
|
||||||
&& self.right instanceof AST_UnaryPrefix
|
&& self.right instanceof AST_UnaryPrefix
|
||||||
&& self.right.operator == "typeof") {
|
&& self.right.operator == "typeof") {
|
||||||
var expr = self.right.expression;
|
var expr = self.right.expression;
|
||||||
if (expr instanceof AST_SymbolRef ? !expr.undeclared()
|
if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
|
||||||
: !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
|
: !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
|
||||||
self.right = expr;
|
self.right = expr;
|
||||||
self.left = make_node(AST_Undefined, self.left).optimize(compressor);
|
self.left = make_node(AST_Undefined, self.left).optimize(compressor);
|
||||||
@@ -3908,7 +4040,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
// testing against !self.scope.uses_with first is an optimization
|
// testing against !self.scope.uses_with first is an optimization
|
||||||
if (!compressor.option("ie8")
|
if (!compressor.option("ie8")
|
||||||
&& self.undeclared()
|
&& is_undeclared_ref(self)
|
||||||
&& (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
|
&& (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
|
||||||
switch (self.name) {
|
switch (self.name) {
|
||||||
case "undefined":
|
case "undefined":
|
||||||
@@ -4263,7 +4395,7 @@ merge(Compressor.prototype, {
|
|||||||
var prop = self.property;
|
var prop = self.property;
|
||||||
if (prop instanceof AST_String && compressor.option("properties")) {
|
if (prop instanceof AST_String && compressor.option("properties")) {
|
||||||
prop = prop.getValue();
|
prop = prop.getValue();
|
||||||
if (RESERVED_WORDS(prop) ? !compressor.option("ie8") : is_identifier_string(prop)) {
|
if (is_identifier_string(prop)) {
|
||||||
return make_node(AST_Dot, self, {
|
return make_node(AST_Dot, self, {
|
||||||
expression : self.expression,
|
expression : self.expression,
|
||||||
property : prop
|
property : prop
|
||||||
@@ -4284,25 +4416,41 @@ merge(Compressor.prototype, {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AST_Lambda.DEFMETHOD("contains_this", function() {
|
||||||
|
var result;
|
||||||
|
var self = this;
|
||||||
|
self.walk(new TreeWalker(function(node) {
|
||||||
|
if (result) return true;
|
||||||
|
if (node instanceof AST_This) return result = true;
|
||||||
|
if (node !== self && node instanceof AST_Scope) return true;
|
||||||
|
}));
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
OPT(AST_Dot, function(self, compressor){
|
OPT(AST_Dot, function(self, compressor){
|
||||||
var def = self.resolve_defines(compressor);
|
var def = self.resolve_defines(compressor);
|
||||||
if (def) {
|
if (def) {
|
||||||
return def.optimize(compressor);
|
return def.optimize(compressor);
|
||||||
}
|
}
|
||||||
var prop = self.property;
|
if (compressor.option("unsafe") && self.expression instanceof AST_Object) {
|
||||||
if (RESERVED_WORDS(prop) && compressor.option("ie8")) {
|
var values = self.expression.properties;
|
||||||
return make_node(AST_Sub, self, {
|
for (var i = values.length; --i >= 0;) {
|
||||||
expression : self.expression,
|
if (values[i].key === self.property) {
|
||||||
property : make_node(AST_String, self, {
|
var value = values[i].value;
|
||||||
value: prop
|
if (value instanceof AST_Function ? !value.contains_this() : !value.has_side_effects(compressor)) {
|
||||||
})
|
var obj = self.expression.clone();
|
||||||
}).optimize(compressor);
|
obj.properties = obj.properties.slice();
|
||||||
|
obj.properties.splice(i, 1);
|
||||||
|
return make_sequence(self, [ obj, value ]).optimize(compressor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("unsafe_proto")
|
if (compressor.option("unsafe_proto")
|
||||||
&& self.expression instanceof AST_Dot
|
&& self.expression instanceof AST_Dot
|
||||||
&& self.expression.property == "prototype") {
|
&& self.expression.property == "prototype") {
|
||||||
var exp = self.expression.expression;
|
var exp = self.expression.expression;
|
||||||
if (exp instanceof AST_SymbolRef && exp.undeclared()) switch (exp.name) {
|
if (is_undeclared_ref(exp)) switch (exp.name) {
|
||||||
case "Array":
|
case "Array":
|
||||||
self.expression = make_node(AST_Array, self.expression, {
|
self.expression = make_node(AST_Array, self.expression, {
|
||||||
elements: []
|
elements: []
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ function OutputStream(options) {
|
|||||||
var current_pos = 0;
|
var current_pos = 0;
|
||||||
var OUTPUT = "";
|
var OUTPUT = "";
|
||||||
|
|
||||||
function to_ascii(str, identifier) {
|
var to_utf8 = options.ascii_only ? function(str, identifier) {
|
||||||
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
|
||||||
var code = ch.charCodeAt(0).toString(16);
|
var code = ch.charCodeAt(0).toString(16);
|
||||||
if (code.length <= 2 && !identifier) {
|
if (code.length <= 2 && !identifier) {
|
||||||
@@ -120,6 +120,12 @@ function OutputStream(options) {
|
|||||||
return "\\u" + code;
|
return "\\u" + code;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} : function(str) {
|
||||||
|
return str.replace(/[\ud800-\udbff](?![\udc00-\udfff])/g, function(ch) {
|
||||||
|
return "\\u" + ch.charCodeAt(0).toString(16);
|
||||||
|
}).replace(/(^|[^\ud800-\udbff])([\udc00-\udfff])/g, function(match, prefix, ch) {
|
||||||
|
return prefix + "\\u" + ch.charCodeAt(0).toString(16);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function make_string(str, quote) {
|
function make_string(str, quote) {
|
||||||
@@ -150,7 +156,7 @@ function OutputStream(options) {
|
|||||||
function quote_double() {
|
function quote_double() {
|
||||||
return '"' + str.replace(/\x22/g, '\\"') + '"';
|
return '"' + str.replace(/\x22/g, '\\"') + '"';
|
||||||
}
|
}
|
||||||
if (options.ascii_only) str = to_ascii(str);
|
str = to_utf8(str);
|
||||||
switch (options.quote_style) {
|
switch (options.quote_style) {
|
||||||
case 1:
|
case 1:
|
||||||
return quote_single();
|
return quote_single();
|
||||||
@@ -175,8 +181,7 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function make_name(name) {
|
function make_name(name) {
|
||||||
name = name.toString();
|
name = name.toString();
|
||||||
if (options.ascii_only)
|
name = to_utf8(name, true);
|
||||||
name = to_ascii(name, true);
|
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -433,7 +438,7 @@ function OutputStream(options) {
|
|||||||
last : function() { return last },
|
last : function() { return last },
|
||||||
semicolon : semicolon,
|
semicolon : semicolon,
|
||||||
force_semicolon : force_semicolon,
|
force_semicolon : force_semicolon,
|
||||||
to_ascii : to_ascii,
|
to_utf8 : to_utf8,
|
||||||
print_name : function(name) { print(make_name(name)) },
|
print_name : function(name) { print(make_name(name)) },
|
||||||
print_string : function(str, quote, escape_directive) {
|
print_string : function(str, quote, escape_directive) {
|
||||||
var encoded = encode_string(str, quote);
|
var encoded = encode_string(str, quote);
|
||||||
@@ -672,14 +677,15 @@ function OutputStream(options) {
|
|||||||
// parens around it too, otherwise the call will be
|
// parens around it too, otherwise the call will be
|
||||||
// interpreted as passing the arguments to the upper New
|
// interpreted as passing the arguments to the upper New
|
||||||
// expression.
|
// expression.
|
||||||
try {
|
var parens = false;
|
||||||
this.walk(new TreeWalker(function(node) {
|
this.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Call) throw p;
|
if (parens || node instanceof AST_Scope) return true;
|
||||||
}));
|
if (node instanceof AST_Call) {
|
||||||
} catch(ex) {
|
parens = true;
|
||||||
if (ex !== p) throw ex;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}));
|
||||||
|
return parens;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1073,19 +1079,17 @@ function OutputStream(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function parenthesize_for_noin(node, output, noin) {
|
function parenthesize_for_noin(node, output, noin) {
|
||||||
if (!noin) node.print(output);
|
var parens = false;
|
||||||
else try {
|
|
||||||
// need to take some precautions here:
|
// need to take some precautions here:
|
||||||
// https://github.com/mishoo/UglifyJS2/issues/60
|
// https://github.com/mishoo/UglifyJS2/issues/60
|
||||||
node.walk(new TreeWalker(function(node){
|
if (noin) node.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Binary && node.operator == "in")
|
if (parens || node instanceof AST_Scope) return true;
|
||||||
throw output;
|
if (node instanceof AST_Binary && node.operator == "in") {
|
||||||
}));
|
parens = true;
|
||||||
node.print(output);
|
return true;
|
||||||
} catch(ex) {
|
|
||||||
if (ex !== output) throw ex;
|
|
||||||
node.print(output, true);
|
|
||||||
}
|
}
|
||||||
|
}));
|
||||||
|
node.print(output, parens);
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFPRINT(AST_VarDef, function(self, output){
|
DEFPRINT(AST_VarDef, function(self, output){
|
||||||
@@ -1105,6 +1109,9 @@ function OutputStream(options) {
|
|||||||
self.expression.print(output);
|
self.expression.print(output);
|
||||||
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
if (self instanceof AST_New && !need_constructor_parens(self, output))
|
||||||
return;
|
return;
|
||||||
|
if (self.expression instanceof AST_Lambda) {
|
||||||
|
output.add_mapping(self.start);
|
||||||
|
}
|
||||||
output.with_parens(function(){
|
output.with_parens(function(){
|
||||||
self.args.forEach(function(expr, i){
|
self.args.forEach(function(expr, i){
|
||||||
if (i) output.comma();
|
if (i) output.comma();
|
||||||
@@ -1144,6 +1151,13 @@ function OutputStream(options) {
|
|||||||
DEFPRINT(AST_Dot, function(self, output){
|
DEFPRINT(AST_Dot, function(self, output){
|
||||||
var expr = self.expression;
|
var expr = self.expression;
|
||||||
expr.print(output);
|
expr.print(output);
|
||||||
|
var prop = self.property;
|
||||||
|
if (output.option("ie8") && RESERVED_WORDS(prop)) {
|
||||||
|
output.print("[");
|
||||||
|
output.add_mapping(self.end);
|
||||||
|
output.print_string(prop);
|
||||||
|
output.print("]");
|
||||||
|
} else {
|
||||||
if (expr instanceof AST_Number && expr.getValue() >= 0) {
|
if (expr instanceof AST_Number && expr.getValue() >= 0) {
|
||||||
if (!/[xa-f.)]/i.test(output.last())) {
|
if (!/[xa-f.)]/i.test(output.last())) {
|
||||||
output.print(".");
|
output.print(".");
|
||||||
@@ -1152,7 +1166,8 @@ function OutputStream(options) {
|
|||||||
output.print(".");
|
output.print(".");
|
||||||
// the name after dot would be mapped about here.
|
// the name after dot would be mapped about here.
|
||||||
output.add_mapping(self.end);
|
output.add_mapping(self.end);
|
||||||
output.print_name(self.property);
|
output.print_name(prop);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
DEFPRINT(AST_Sub, function(self, output){
|
DEFPRINT(AST_Sub, function(self, output){
|
||||||
self.expression.print(output);
|
self.expression.print(output);
|
||||||
@@ -1308,9 +1323,7 @@ function OutputStream(options) {
|
|||||||
if (regexp.raw_source) {
|
if (regexp.raw_source) {
|
||||||
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
str = "/" + regexp.raw_source + str.slice(str.lastIndexOf("/"));
|
||||||
}
|
}
|
||||||
if (output.option("ascii_only")) {
|
str = output.to_utf8(str);
|
||||||
str = output.to_ascii(str);
|
|
||||||
}
|
|
||||||
output.print(str);
|
output.print(str);
|
||||||
var p = output.parent();
|
var p = output.parent();
|
||||||
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function mangle_properties(ast, options) {
|
|||||||
only_cache: false,
|
only_cache: false,
|
||||||
regex: null,
|
regex: null,
|
||||||
reserved: null,
|
reserved: null,
|
||||||
});
|
}, true);
|
||||||
|
|
||||||
var reserved = options.reserved;
|
var reserved = options.reserved;
|
||||||
if (!Array.isArray(reserved)) reserved = [];
|
if (!Array.isArray(reserved)) reserved = [];
|
||||||
|
|||||||
@@ -373,14 +373,6 @@ AST_Symbol.DEFMETHOD("unreferenced", function(){
|
|||||||
&& !(this.scope.uses_eval || this.scope.uses_with);
|
&& !(this.scope.uses_eval || this.scope.uses_with);
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("undeclared", function(){
|
|
||||||
return this.definition().undeclared;
|
|
||||||
});
|
|
||||||
|
|
||||||
AST_LabelRef.DEFMETHOD("undeclared", return_false);
|
|
||||||
|
|
||||||
AST_Label.DEFMETHOD("undeclared", return_false);
|
|
||||||
|
|
||||||
AST_Symbol.DEFMETHOD("definition", function(){
|
AST_Symbol.DEFMETHOD("definition", function(){
|
||||||
return this.thedef;
|
return this.thedef;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
if (y !== undefined) x = y;
|
if (y !== undefined) x = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tw.pop(this);
|
tw.pop();
|
||||||
return x;
|
return x;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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.23",
|
"version": "3.0.26",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
@@ -29,12 +29,12 @@
|
|||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "~2.9.0",
|
"commander": "~2.11.0",
|
||||||
"source-map": "~0.5.1"
|
"source-map": "~0.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~5.0.3",
|
"acorn": "~5.1.1",
|
||||||
"mocha": "~2.3.4",
|
"mocha": "~3.4.2",
|
||||||
"semver": "~5.3.0"
|
"semver": "~5.3.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
var createHash = require("crypto").createHash;
|
var createHash = require("crypto").createHash;
|
||||||
var fetch = require("./fetch");
|
var fetch = require("./fetch");
|
||||||
var fork = require("child_process").fork;
|
var fork = require("child_process").fork;
|
||||||
|
var zlib = require("zlib");
|
||||||
var args = process.argv.slice(2);
|
var args = process.argv.slice(2);
|
||||||
if (!args.length) {
|
if (!args.length) {
|
||||||
args.push("-mc");
|
args.push("-mc");
|
||||||
@@ -33,6 +34,7 @@ function done() {
|
|||||||
console.log(info.log);
|
console.log(info.log);
|
||||||
console.log("Original:", info.input, "bytes");
|
console.log("Original:", info.input, "bytes");
|
||||||
console.log("Uglified:", info.output, "bytes");
|
console.log("Uglified:", info.output, "bytes");
|
||||||
|
console.log("GZipped: ", info.gzip, "bytes");
|
||||||
console.log("SHA1 sum:", info.sha1);
|
console.log("SHA1 sum:", info.sha1);
|
||||||
if (info.code) {
|
if (info.code) {
|
||||||
failures.push(url);
|
failures.push(url);
|
||||||
@@ -51,6 +53,7 @@ urls.forEach(function(url) {
|
|||||||
results[url] = {
|
results[url] = {
|
||||||
input: 0,
|
input: 0,
|
||||||
output: 0,
|
output: 0,
|
||||||
|
gzip: 0,
|
||||||
log: ""
|
log: ""
|
||||||
};
|
};
|
||||||
fetch(url, function(err, res) {
|
fetch(url, function(err, res) {
|
||||||
@@ -61,6 +64,10 @@ urls.forEach(function(url) {
|
|||||||
}).pipe(uglifyjs.stdin);
|
}).pipe(uglifyjs.stdin);
|
||||||
uglifyjs.stdout.on("data", function(data) {
|
uglifyjs.stdout.on("data", function(data) {
|
||||||
results[url].output += data.length;
|
results[url].output += data.length;
|
||||||
|
}).pipe(zlib.createGzip({
|
||||||
|
level: zlib.Z_BEST_COMPRESSION
|
||||||
|
})).on("data", function(data) {
|
||||||
|
results[url].gzip += data.length;
|
||||||
}).pipe(createHash("sha1")).on("data", function(data) {
|
}).pipe(createHash("sha1")).on("data", function(data) {
|
||||||
results[url].sha1 = data.toString("hex");
|
results[url].sha1 = data.toString("hex");
|
||||||
done();
|
done();
|
||||||
|
|||||||
@@ -863,7 +863,7 @@ collapse_vars_unary: {
|
|||||||
input: {
|
input: {
|
||||||
function f0(o, p) {
|
function f0(o, p) {
|
||||||
var x = o[p];
|
var x = o[p];
|
||||||
delete x;
|
return delete x;
|
||||||
}
|
}
|
||||||
function f1(n) {
|
function f1(n) {
|
||||||
var k = !!n;
|
var k = !!n;
|
||||||
@@ -893,7 +893,7 @@ collapse_vars_unary: {
|
|||||||
expect: {
|
expect: {
|
||||||
function f0(o, p) {
|
function f0(o, p) {
|
||||||
var x = o[p];
|
var x = o[p];
|
||||||
delete x;
|
return delete x;
|
||||||
}
|
}
|
||||||
function f1(n) {
|
function f1(n) {
|
||||||
return n > +!!n
|
return n > +!!n
|
||||||
@@ -2256,3 +2256,89 @@ issue_2187_3: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2203_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = "FAIL";
|
||||||
|
console.log({
|
||||||
|
a: "PASS",
|
||||||
|
b: function() {
|
||||||
|
return function(c) {
|
||||||
|
return c.a;
|
||||||
|
}((String, (Object, this)));
|
||||||
|
}
|
||||||
|
}.b());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = "FAIL";
|
||||||
|
console.log({
|
||||||
|
a: "PASS",
|
||||||
|
b: function() {
|
||||||
|
return function(c) {
|
||||||
|
return c.a;
|
||||||
|
}((String, (Object, this)));
|
||||||
|
}
|
||||||
|
}.b());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2203_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = "PASS";
|
||||||
|
console.log({
|
||||||
|
a: "FAIL",
|
||||||
|
b: function() {
|
||||||
|
return function(c) {
|
||||||
|
return c.a;
|
||||||
|
}((String, (Object, function() {
|
||||||
|
return this;
|
||||||
|
}())));
|
||||||
|
}
|
||||||
|
}.b());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = "PASS";
|
||||||
|
console.log({
|
||||||
|
a: "FAIL",
|
||||||
|
b: function() {
|
||||||
|
return function(c) {
|
||||||
|
return (String, (Object, function() {
|
||||||
|
return this;
|
||||||
|
}())).a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.b());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_argname: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() { return "PASS"; }
|
||||||
|
console.log(function(a, a) {
|
||||||
|
f++;
|
||||||
|
return a;
|
||||||
|
}("FAIL", f()));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() { return "PASS"; }
|
||||||
|
console.log(function(a, a) {
|
||||||
|
f++;
|
||||||
|
return a;
|
||||||
|
}("FAIL", f()));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -230,3 +230,82 @@ accessor: {
|
|||||||
}
|
}
|
||||||
expect: {}
|
expect: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2233_1: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
Array.isArray;
|
||||||
|
Boolean;
|
||||||
|
console.log;
|
||||||
|
Error.name;
|
||||||
|
Function.length;
|
||||||
|
Math.random;
|
||||||
|
Number.isNaN;
|
||||||
|
RegExp;
|
||||||
|
Object.defineProperty;
|
||||||
|
String.fromCharCode;
|
||||||
|
}
|
||||||
|
expect: {}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_2: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var RegExp;
|
||||||
|
Array.isArray;
|
||||||
|
RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Math.sin;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2233_3: {
|
||||||
|
options = {
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var RegExp;
|
||||||
|
Array.isArray;
|
||||||
|
RegExp;
|
||||||
|
UndeclaredGlobal;
|
||||||
|
function foo() {
|
||||||
|
var Number;
|
||||||
|
AnotherUndeclaredGlobal;
|
||||||
|
Math.sin;
|
||||||
|
Number.isNaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
UndeclaredGlobal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1090,6 +1090,7 @@ var_catch_toplevel: {
|
|||||||
a--;
|
a--;
|
||||||
try {
|
try {
|
||||||
a++;
|
a++;
|
||||||
|
x();
|
||||||
} catch(a) {
|
} catch(a) {
|
||||||
if (a) var a;
|
if (a) var a;
|
||||||
var a = 10;
|
var a = 10;
|
||||||
@@ -1099,9 +1100,8 @@ var_catch_toplevel: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function() {
|
!function() {
|
||||||
a--;
|
|
||||||
try {
|
try {
|
||||||
a++;
|
x();
|
||||||
} catch(a) {
|
} catch(a) {
|
||||||
var a;
|
var a;
|
||||||
}
|
}
|
||||||
@@ -1153,3 +1153,89 @@ issue_2105: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2226_1: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1() {
|
||||||
|
var a = b;
|
||||||
|
a += c;
|
||||||
|
}
|
||||||
|
function f2(a) {
|
||||||
|
a <<= b;
|
||||||
|
}
|
||||||
|
function f3(a) {
|
||||||
|
--a;
|
||||||
|
}
|
||||||
|
function f4() {
|
||||||
|
var a = b;
|
||||||
|
return a *= c;
|
||||||
|
}
|
||||||
|
function f5(a) {
|
||||||
|
x(a /= b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1() {
|
||||||
|
b;
|
||||||
|
c;
|
||||||
|
}
|
||||||
|
function f2(a) {
|
||||||
|
b;
|
||||||
|
}
|
||||||
|
function f3(a) {
|
||||||
|
0;
|
||||||
|
}
|
||||||
|
function f4() {
|
||||||
|
var a = b;
|
||||||
|
return a *= c;
|
||||||
|
}
|
||||||
|
function f5(a) {
|
||||||
|
x(a /= b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2226_2: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
a += b;
|
||||||
|
return a;
|
||||||
|
}(1, 2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
return a += b;
|
||||||
|
}(1, 2));
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2226_3: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
a += b;
|
||||||
|
return a;
|
||||||
|
}(1, 2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
return a += 2;
|
||||||
|
}(1));
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
}
|
||||||
|
|||||||
@@ -251,21 +251,25 @@ unsafe_constant: {
|
|||||||
unsafe_object: {
|
unsafe_object: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
unsafe : true
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var o = { a: 1 };
|
||||||
console.log(
|
console.log(
|
||||||
({a:1}) + 1,
|
o + 1,
|
||||||
({a:1}).a + 1,
|
o.a + 1,
|
||||||
({a:1}).b + 1,
|
o.b + 1,
|
||||||
({a:1}).a.b + 1
|
o.a.b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
var o = { a: 1 };
|
||||||
console.log(
|
console.log(
|
||||||
({a:1}) + 1,
|
o + 1,
|
||||||
2,
|
2,
|
||||||
({a:1}).b + 1,
|
o.b + 1,
|
||||||
1..b + 1
|
1..b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -275,21 +279,25 @@ unsafe_object: {
|
|||||||
unsafe_object_nested: {
|
unsafe_object_nested: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
unsafe : true
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var o = { a: { b: 1 } };
|
||||||
console.log(
|
console.log(
|
||||||
({a:{b:1}}) + 1,
|
o + 1,
|
||||||
({a:{b:1}}).a + 1,
|
o.a + 1,
|
||||||
({a:{b:1}}).b + 1,
|
o.b + 1,
|
||||||
({a:{b:1}}).a.b + 1
|
o.a.b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
var o = { a: { b: 1 } };
|
||||||
console.log(
|
console.log(
|
||||||
({a:{b:1}}) + 1,
|
o + 1,
|
||||||
({a:{b:1}}).a + 1,
|
o.a + 1,
|
||||||
({a:{b:1}}).b + 1,
|
o.b + 1,
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -299,20 +307,24 @@ unsafe_object_nested: {
|
|||||||
unsafe_object_complex: {
|
unsafe_object_complex: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
unsafe : true
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var o = { a: { b: 1 }, b: 1 };
|
||||||
console.log(
|
console.log(
|
||||||
({a:{b:1},b:1}) + 1,
|
o + 1,
|
||||||
({a:{b:1},b:1}).a + 1,
|
o.a + 1,
|
||||||
({a:{b:1},b:1}).b + 1,
|
o.b + 1,
|
||||||
({a:{b:1},b:1}).a.b + 1
|
o.a.b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
var o = { a: { b: 1 }, b: 1 };
|
||||||
console.log(
|
console.log(
|
||||||
({a:{b:1},b:1}) + 1,
|
o + 1,
|
||||||
({a:{b:1},b:1}).a + 1,
|
o.a + 1,
|
||||||
2,
|
2,
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
@@ -323,21 +335,25 @@ unsafe_object_complex: {
|
|||||||
unsafe_object_repeated: {
|
unsafe_object_repeated: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true,
|
evaluate: true,
|
||||||
unsafe : true
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
var o = { a: { b: 1 }, a: 1 };
|
||||||
console.log(
|
console.log(
|
||||||
({a:{b:1},a:1}) + 1,
|
o + 1,
|
||||||
({a:{b:1},a:1}).a + 1,
|
o.a + 1,
|
||||||
({a:{b:1},a:1}).b + 1,
|
o.b + 1,
|
||||||
({a:{b:1},a:1}).a.b + 1
|
o.a.b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
|
var o = { a: { b: 1 }, a: 1 };
|
||||||
console.log(
|
console.log(
|
||||||
({a:{b:1},a:1}) + 1,
|
o + 1,
|
||||||
2,
|
2,
|
||||||
({a:{b:1},a:1}).b + 1,
|
o.b + 1,
|
||||||
1..b + 1
|
1..b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -386,9 +402,9 @@ unsafe_function: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(
|
console.log(
|
||||||
({a:{b:1},b:function(){}}) + 1,
|
({a:{b:1},b:function(){}}) + 1,
|
||||||
({a:{b:1},b:function(){}}).a + 1,
|
({b:function(){}}, {b:1}) + 1,
|
||||||
({a:{b:1},b:function(){}}).b + 1,
|
({a:{b:1}}, function(){}) + 1,
|
||||||
({a:{b:1},b:function(){}}).a.b + 1
|
({b:function(){}}, {b:1}).b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
@@ -636,8 +652,8 @@ unsafe_prototype_function: {
|
|||||||
var d = ({toString: 0}) + "";
|
var d = ({toString: 0}) + "";
|
||||||
var e = (({valueOf: 0}) + "")[2];
|
var e = (({valueOf: 0}) + "")[2];
|
||||||
var f = (({toString: 0}) + "")[2];
|
var f = (({toString: 0}) + "")[2];
|
||||||
var g = ({valueOf: 0}).valueOf();
|
var g = ({}, 0)();
|
||||||
var h = "" + ({toString: 0});
|
var h = ({}, 0)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,3 +1085,103 @@ string_charCodeAt: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "NaN"
|
expect_stdout: "NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2207_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(String.fromCharCode(65));
|
||||||
|
console.log(Math.max(3, 6, 2, 7, 3, 4));
|
||||||
|
console.log(Math.cos(1.2345));
|
||||||
|
console.log(Math.cos(1.2345) - Math.sin(4.321));
|
||||||
|
console.log(Math.pow(Math.PI, Math.E - Math.LN10));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("A");
|
||||||
|
console.log(7);
|
||||||
|
console.log(Math.cos(1.2345));
|
||||||
|
console.log(1.2543732512566947);
|
||||||
|
console.log(1.6093984514472044);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2207_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Math.E);
|
||||||
|
console.log(Math.LN10);
|
||||||
|
console.log(Math.LN2);
|
||||||
|
console.log(Math.LOG2E);
|
||||||
|
console.log(Math.LOG10E);
|
||||||
|
console.log(Math.PI);
|
||||||
|
console.log(Math.SQRT1_2);
|
||||||
|
console.log(Math.SQRT2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(Math.E);
|
||||||
|
console.log(Math.LN10);
|
||||||
|
console.log(Math.LN2);
|
||||||
|
console.log(Math.LOG2E);
|
||||||
|
console.log(Math.LOG10E);
|
||||||
|
console.log(Math.PI);
|
||||||
|
console.log(Math.SQRT1_2);
|
||||||
|
console.log(Math.SQRT2);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2207_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Number.MAX_VALUE);
|
||||||
|
console.log(Number.MIN_VALUE);
|
||||||
|
console.log(Number.NaN);
|
||||||
|
console.log(Number.NEGATIVE_INFINITY);
|
||||||
|
console.log(Number.POSITIVE_INFINITY);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(Number.MAX_VALUE);
|
||||||
|
console.log(5e-324);
|
||||||
|
console.log(NaN);
|
||||||
|
console.log(-1/0);
|
||||||
|
console.log(1/0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2231_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Object.keys(void 0));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(Object.keys(void 0));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2231_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Object.getOwnPropertyNames(null));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(Object.getOwnPropertyNames(null));
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ object: {
|
|||||||
VALUE: 42,
|
VALUE: 42,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
side_effects: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -140,9 +141,9 @@ mixed: {
|
|||||||
console.log(CONFIG);
|
console.log(CONFIG);
|
||||||
}
|
}
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
|
|
||||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
|
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
|
||||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
|
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:128,22]',
|
||||||
|
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:130,8]',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,11 +71,13 @@ non_hoisted_function_after_return_2a: {
|
|||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
|
||||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
|
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
|
||||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
|
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
|
||||||
|
"WARN: pass 0: last_count: Infinity, count: 37",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
|
||||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
|
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
|
||||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
|
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
|
||||||
|
"WARN: pass 1: last_count: 37, count: 18",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,11 +111,11 @@ non_hoisted_function_after_return_2b: {
|
|||||||
}
|
}
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
// duplicate warnings no longer emitted
|
// duplicate warnings no longer emitted
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,16]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,12]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,10 +153,10 @@ non_hoisted_function_after_return_strict: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "8 7"
|
expect_stdout: "8 7"
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
'WARN: Dropping unreachable code [test/compress/issue-1034.js:131,16]',
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:133,16]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:134,16]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:137,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]",
|
||||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:138,21]"
|
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,17 +196,19 @@ non_hoisted_function_after_return_2a_strict: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "5 6"
|
expect_stdout: "5 6"
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:173,16]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:175,16]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:173,16]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:176,16]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:176,16]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]",
|
||||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:173,20]",
|
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]",
|
||||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:180,21]",
|
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,12]",
|
"WARN: pass 0: last_count: Infinity, count: 48",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,12]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:180,12]",
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:181,12]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]",
|
||||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:176,20]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]",
|
||||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:178,16]",
|
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]",
|
||||||
|
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]",
|
||||||
|
"WARN: pass 1: last_count: 48, count: 29",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,10 +247,10 @@ non_hoisted_function_after_return_2b_strict: {
|
|||||||
expect_stdout: "5 6"
|
expect_stdout: "5 6"
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
// duplicate warnings no longer emitted
|
// duplicate warnings no longer emitted
|
||||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:225,16]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]",
|
||||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:225,16]",
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,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]",
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]",
|
||||||
|
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]",
|
||||||
|
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,12]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
typeof_eq_undefined: {
|
typeof_eq_undefined: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true
|
comparisons: true,
|
||||||
|
typeofs: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = typeof b != "undefined";
|
var a = typeof b != "undefined";
|
||||||
@@ -24,6 +25,7 @@ typeof_eq_undefined_ie8: {
|
|||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
ie8: true,
|
ie8: true,
|
||||||
|
typeofs: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var a = typeof b != "undefined";
|
var a = typeof b != "undefined";
|
||||||
@@ -45,7 +47,8 @@ typeof_eq_undefined_ie8: {
|
|||||||
|
|
||||||
undefined_redefined: {
|
undefined_redefined: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true
|
comparisons: true,
|
||||||
|
typeofs: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(undefined) {
|
function f(undefined) {
|
||||||
@@ -58,7 +61,8 @@ undefined_redefined: {
|
|||||||
|
|
||||||
undefined_redefined_mangle: {
|
undefined_redefined_mangle: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true
|
comparisons: true,
|
||||||
|
typeofs: true,
|
||||||
}
|
}
|
||||||
mangle = {}
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -436,3 +436,17 @@ do_switch: {
|
|||||||
} while (false);
|
} while (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in_parenthesis_1: {
|
||||||
|
input: {
|
||||||
|
for (("foo" in {});0;);
|
||||||
|
}
|
||||||
|
expect_exact: 'for(("foo"in{});0;);'
|
||||||
|
}
|
||||||
|
|
||||||
|
in_parenthesis_2: {
|
||||||
|
input: {
|
||||||
|
for ((function(){ "foo" in {}; });0;);
|
||||||
|
}
|
||||||
|
expect_exact: 'for(function(){"foo"in{}};0;);'
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,3 +82,19 @@ new_with_unary_prefix: {
|
|||||||
}
|
}
|
||||||
expect_exact: 'var bar=(+new Date).toString(32);';
|
expect_exact: 'var bar=(+new Date).toString(32);';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dot_parenthesis_1: {
|
||||||
|
input: {
|
||||||
|
console.log(new (Math.random().constructor) instanceof Number);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(new(Math.random().constructor)instanceof Number);"
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
dot_parenthesis_2: {
|
||||||
|
input: {
|
||||||
|
console.log(typeof new function(){Math.random()}.constructor);
|
||||||
|
}
|
||||||
|
expect_exact: "console.log(typeof new function(){Math.random()}.constructor);"
|
||||||
|
expect_stdout: "function"
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ keep_properties: {
|
|||||||
dot_properties: {
|
dot_properties: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
ie8: true,
|
ie8: true,
|
||||||
};
|
}
|
||||||
input: {
|
input: {
|
||||||
a["foo"] = "bar";
|
a["foo"] = "bar";
|
||||||
a["if"] = "if";
|
a["if"] = "if";
|
||||||
@@ -36,8 +38,10 @@ dot_properties: {
|
|||||||
dot_properties_es5: {
|
dot_properties_es5: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
|
}
|
||||||
|
beautify = {
|
||||||
ie8: false,
|
ie8: false,
|
||||||
};
|
}
|
||||||
input: {
|
input: {
|
||||||
a["foo"] = "bar";
|
a["foo"] = "bar";
|
||||||
a["if"] = "if";
|
a["if"] = "if";
|
||||||
@@ -657,3 +661,116 @@ accessor_this: {
|
|||||||
expect_exact: 'var a=1;var b={get this(){return a},set this(c){a=c}};console.log(b.this,b.this=2,b.this);'
|
expect_exact: 'var a=1;var b={get this(){return a},set this(c){a=c}};console.log(b.this,b.this=2,b.this);'
|
||||||
expect_stdout: "1 2 2"
|
expect_stdout: "1 2 2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2208_1: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(42);
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2208_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log({
|
||||||
|
a: 42,
|
||||||
|
p: function() {
|
||||||
|
return this.a;
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({
|
||||||
|
a: 42,
|
||||||
|
p: function() {
|
||||||
|
return this.a;
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2208_3: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
a = 42;
|
||||||
|
console.log({
|
||||||
|
p: function() {
|
||||||
|
return function() {
|
||||||
|
return this.a;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 42;
|
||||||
|
console.log(function() {
|
||||||
|
return this.a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2208_4: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {}
|
||||||
|
console.log({
|
||||||
|
a: foo(),
|
||||||
|
p: function() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {}
|
||||||
|
console.log((foo(), function() {
|
||||||
|
return 42;
|
||||||
|
})());
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2208_5: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log({
|
||||||
|
p: "FAIL",
|
||||||
|
p: function() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}.p());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(42);
|
||||||
|
}
|
||||||
|
expect_stdout: "42"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1469,6 +1469,7 @@ issue_1670_1: {
|
|||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
|
typeofs: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -1532,6 +1533,7 @@ issue_1670_3: {
|
|||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
|
typeofs: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -176,6 +176,11 @@ for_sequences: {
|
|||||||
// 4
|
// 4
|
||||||
x = (foo in bar);
|
x = (foo in bar);
|
||||||
for (y = 5; false;);
|
for (y = 5; false;);
|
||||||
|
// 5
|
||||||
|
x = function() {
|
||||||
|
foo in bar;
|
||||||
|
};
|
||||||
|
for (y = 5; false;);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
// 1
|
// 1
|
||||||
@@ -188,6 +193,10 @@ for_sequences: {
|
|||||||
// 4
|
// 4
|
||||||
x = (foo in bar);
|
x = (foo in bar);
|
||||||
for (y = 5; false;);
|
for (y = 5; false;);
|
||||||
|
// 5
|
||||||
|
for (x = function() {
|
||||||
|
foo in bar;
|
||||||
|
}, y = 5; false;);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,3 +15,43 @@ unicode_parse_variables: {
|
|||||||
var l০ = 3;
|
var l০ = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2242_1: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\ud83d","\\ude00","\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2242_2: {
|
||||||
|
beautify = {
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d", "\ude00", "\ud83d\ude00", "\ud83d@\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\ud83d","\\ude00","\\ud83d\\ude00","\\ud83d@\\ude00");'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2242_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\\ud83d"+"\\ude00","\\ud83d"+"@"+"\\ude00");'
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2242_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("\ud83d" + "\ude00", "\ud83d" + "@" + "\ude00");
|
||||||
|
}
|
||||||
|
expect_exact: 'console.log("\ud83d\ude00","\\ud83d@\\ude00");'
|
||||||
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|
||||||
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=\n");
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==\n");
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -192,7 +192,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
|
|
||||||
assert.strictEqual(stdout, [
|
assert.strictEqual(stdout, [
|
||||||
"var bar=function(){function foo(bar){return bar}return foo}();",
|
"var bar=function(){function foo(bar){return bar}return foo}();",
|
||||||
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=",
|
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
|
||||||
"",
|
"",
|
||||||
].join("\n"));
|
].join("\n"));
|
||||||
assert.strictEqual(stderr, "WARN: inline source map not found\n");
|
assert.strictEqual(stderr, "WARN: inline source map not found\n");
|
||||||
@@ -594,7 +594,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should work with --mangle reserved=[]", function(done) {
|
it("Should work with --mangle reserved=[]", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=[callback]';
|
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]";
|
||||||
|
|
||||||
exec(command, function (err, stdout) {
|
exec(command, function (err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@@ -604,7 +604,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should work with --mangle reserved=false", function(done) {
|
it("Should work with --mangle reserved=false", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=false';
|
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false";
|
||||||
|
|
||||||
exec(command, function (err, stdout) {
|
exec(command, function (err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
@@ -613,4 +613,22 @@ describe("bin/uglifyjs", function () {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it("Should fail with --mangle-props reserved=[in]", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]";
|
||||||
|
exec(command, function (err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.strictEqual(stdout, "");
|
||||||
|
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it("Should fail with --define a-b", function(done) {
|
||||||
|
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
|
||||||
|
exec(command, function (err, stdout, stderr) {
|
||||||
|
assert.ok(err);
|
||||||
|
assert.strictEqual(stdout, "");
|
||||||
|
assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ var Uglify = require('../../');
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
|
||||||
describe("let", function() {
|
describe("let", function() {
|
||||||
it("Should not produce reserved keywords as variable name in mangle", function(done) {
|
this.timeout(30000);
|
||||||
this.timeout(10000);
|
it("Should not produce reserved keywords as variable name in mangle", function() {
|
||||||
|
|
||||||
// Produce a lot of variables in a function and run it through mangle.
|
// Produce a lot of variables in a function and run it through mangle.
|
||||||
var s = '"dddddeeeeelllllooooottttt"; function foo() {';
|
var s = '"dddddeeeeelllllooooottttt"; function foo() {';
|
||||||
for (var i = 0; i < 18000; i++) {
|
for (var i = 0; i < 18000; i++) {
|
||||||
s += "var v" + i + "=0;";
|
s += "var v" + i + "=0;";
|
||||||
}
|
}
|
||||||
s += '}';
|
s += '}';
|
||||||
var result = Uglify.minify(s, {compress: false});
|
var result = Uglify.minify(s, {
|
||||||
|
compress: false
|
||||||
|
}).code;
|
||||||
|
|
||||||
// Verify that select keywords and reserved keywords not produced
|
// Verify that select keywords and reserved keywords not produced
|
||||||
[
|
[
|
||||||
@@ -19,7 +20,7 @@ describe("let", function() {
|
|||||||
"let",
|
"let",
|
||||||
"var",
|
"var",
|
||||||
].forEach(function(name) {
|
].forEach(function(name) {
|
||||||
assert.strictEqual(result.code.indexOf("var " + name + "="), -1);
|
assert.strictEqual(result.indexOf("var " + name + "="), -1);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify that the variable names that appeared immediately before
|
// Verify that the variable names that appeared immediately before
|
||||||
@@ -30,9 +31,27 @@ describe("let", function() {
|
|||||||
"eet", "fet",
|
"eet", "fet",
|
||||||
"rar", "oar",
|
"rar", "oar",
|
||||||
].forEach(function(name) {
|
].forEach(function(name) {
|
||||||
assert.ok(result.code.indexOf("var " + name + "=") >= 0);
|
assert.notStrictEqual(result.indexOf("var " + name + "="), -1);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
done();
|
it("Should quote mangled properties that are reserved keywords", function() {
|
||||||
|
var s = '"rrrrrnnnnniiiiiaaaaa";';
|
||||||
|
for (var i = 0; i < 18000; i++) {
|
||||||
|
s += "v.b" + i + ";";
|
||||||
|
}
|
||||||
|
var result = Uglify.minify(s, {
|
||||||
|
compress: false,
|
||||||
|
ie8: true,
|
||||||
|
mangle: {
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
}).code;
|
||||||
|
[
|
||||||
|
"in",
|
||||||
|
"var",
|
||||||
|
].forEach(function(name) {
|
||||||
|
assert.notStrictEqual(result.indexOf(name), -1);
|
||||||
|
assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -78,4 +78,41 @@ describe("String literals", function() {
|
|||||||
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\08";');
|
assert.equal(UglifyJS.parse('"use strict";"\\08"').print_to_string(), '"use strict";"\\08";');
|
||||||
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\09";');
|
assert.equal(UglifyJS.parse('"use strict";"\\09"').print_to_string(), '"use strict";"\\09";');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should not unescape unpaired surrogates", function() {
|
||||||
|
var code = [];
|
||||||
|
for (var i = 0; i <= 0xF; i++) {
|
||||||
|
code.push("\\u000" + i.toString(16));
|
||||||
|
}
|
||||||
|
for (;i <= 0xFF; i++) {
|
||||||
|
code.push("\\u00" + i.toString(16));
|
||||||
|
}
|
||||||
|
for (;i <= 0xFFF; i++) {
|
||||||
|
code.push("\\u0" + i.toString(16));
|
||||||
|
}
|
||||||
|
for (; i <= 0xFFFF; i++) {
|
||||||
|
code.push("\\u" + i.toString(16));
|
||||||
|
}
|
||||||
|
code = '"' + code.join() + '"';
|
||||||
|
var normal = UglifyJS.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
ascii_only: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (normal.error) throw normal.error;
|
||||||
|
assert.ok(code.length > normal.code.length);
|
||||||
|
assert.strictEqual(eval(code), eval(normal.code));
|
||||||
|
var ascii = UglifyJS.minify(code, {
|
||||||
|
compress: false,
|
||||||
|
mangle: false,
|
||||||
|
output: {
|
||||||
|
ascii_only: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (ascii.error) throw ascii.error;
|
||||||
|
assert.ok(code.length > ascii.code.length);
|
||||||
|
assert.strictEqual(eval(code), eval(ascii.code));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user