Compare commits
69 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e595171b9 | ||
|
|
6973abbfe1 | ||
|
|
4eb4cb656c | ||
|
|
193612ac67 | ||
|
|
95cfce68ea | ||
|
|
e0461dc3c8 | ||
|
|
ec4202590d | ||
|
|
5e2cd07d6f | ||
|
|
bea9dbd812 | ||
|
|
bc01a85ba0 | ||
|
|
c7c7960b5f | ||
|
|
fc98d212db | ||
|
|
13accdd745 | ||
|
|
287ec730f7 | ||
|
|
06166df999 | ||
|
|
e2dc9cf091 | ||
|
|
069df27bf1 | ||
|
|
3e7873217c | ||
|
|
e21bab7ce6 | ||
|
|
ac9a168fba | ||
|
|
81b64549ce | ||
|
|
082e004b87 | ||
|
|
983e69128b | ||
|
|
b335912e86 | ||
|
|
cc07f3b806 | ||
|
|
07e4b64f3a | ||
|
|
d3ce2bc9e7 | ||
|
|
cff3bf4914 | ||
|
|
4f57d8746b | ||
|
|
79cfac77bd | ||
|
|
224c14d49d | ||
|
|
7857354d85 | ||
|
|
b4aef753e7 | ||
|
|
424173d311 | ||
|
|
ec7cd1dcf7 | ||
|
|
7def684730 | ||
|
|
10f961c27b | ||
|
|
b483678ca7 | ||
|
|
cbbe6fad60 | ||
|
|
f96929c031 | ||
|
|
2b6657e967 | ||
|
|
1b2e6b81a2 | ||
|
|
f9e9898dc1 | ||
|
|
7c0c92943f | ||
|
|
62a66dfff4 | ||
|
|
c44d78db55 | ||
|
|
8c763bf2b5 | ||
|
|
2cab348341 | ||
|
|
aa1786dedf | ||
|
|
0d5df271a1 | ||
|
|
b56e1f178f | ||
|
|
9acace2cb6 | ||
|
|
0f2be1456c | ||
|
|
460218a3f8 | ||
|
|
e49416e4aa | ||
|
|
d4d7d99b70 | ||
|
|
6a696d0a7b | ||
|
|
1c9e13f47d | ||
|
|
b757450cd8 | ||
|
|
23ec484806 | ||
|
|
f1e1bb419a | ||
|
|
6a0af85c8b | ||
|
|
1eb15f46f1 | ||
|
|
09269be974 | ||
|
|
137cb73d1f | ||
|
|
bf832cde16 | ||
|
|
2972d58dbb | ||
|
|
2e22d38a02 | ||
|
|
ce27bcd69a |
11
README.md
11
README.md
@@ -67,7 +67,7 @@ a double dash to prevent input files being used as option arguments:
|
||||
`debug` Add debug prefix and suffix.
|
||||
`domprops` Mangle property names that overlaps
|
||||
with DOM properties.
|
||||
`keep_quoted` Only mangle unquoted properies.
|
||||
`keep_quoted` Only mangle unquoted properties.
|
||||
`regex` Only mangle matched property names.
|
||||
`reserved` List of names that should not be mangled.
|
||||
-b, --beautify [options] Beautify output/specify output options:
|
||||
@@ -782,7 +782,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
comparison are switching. Compression only works if both `comparisons` and
|
||||
`unsafe_comps` are both set to true.
|
||||
|
||||
- `unsafe_Func` (default: `false`) -- compress and mangle `Function(args, code)`
|
||||
- `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)`
|
||||
when both `args` and `code` are string literals.
|
||||
|
||||
- `unsafe_math` (default: `false`) -- optimize numerical expressions like
|
||||
@@ -801,6 +801,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
|
||||
`RegExp` values the same way as if they are constants.
|
||||
|
||||
- `unsafe_undefined` (default: `false`) -- substitute `void 0` if there is a
|
||||
variable named `undefined` in scope (variable name will be mangled, typically
|
||||
reduced to a single character)
|
||||
|
||||
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
||||
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
||||
|
||||
@@ -993,9 +997,6 @@ when this flag is on:
|
||||
- `new Object()` → `{}`
|
||||
- `String(exp)` or `exp.toString()` → `"" + exp`
|
||||
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
||||
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
||||
scope; we do it because the variable name will be mangled, typically
|
||||
reduced to a single character)
|
||||
|
||||
### Conditional compilation
|
||||
|
||||
|
||||
34
bin/uglifyjs
34
bin/uglifyjs
@@ -11,7 +11,7 @@ var path = require("path");
|
||||
var program = require("commander");
|
||||
var UglifyJS = require("../tools/node");
|
||||
|
||||
var skip_keys = [ "cname", "enclosed", "inlined", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
|
||||
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
||||
var files = {};
|
||||
var options = {
|
||||
compress: false,
|
||||
@@ -45,6 +45,7 @@ program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
||||
program.option("--keep-classnames", "Do not mangle/drop class names.");
|
||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||
program.option("--rename", "Force symbol expansion.");
|
||||
program.option("--no-rename", "Disable symbol expansion.");
|
||||
program.option("--safari10", "Support non-standard Safari 10.");
|
||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||
@@ -65,14 +66,12 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
||||
"compress",
|
||||
"ie8",
|
||||
"mangle",
|
||||
"rename",
|
||||
"safari10",
|
||||
"sourceMap",
|
||||
"toplevel",
|
||||
"wrap"
|
||||
].forEach(function(name) {
|
||||
if (name in program) {
|
||||
if (name == "rename" && program[name]) return;
|
||||
options[name] = program[name];
|
||||
}
|
||||
});
|
||||
@@ -132,6 +131,11 @@ if (program.parse) {
|
||||
fatal("ERROR: inline source map only works with built-in parser");
|
||||
}
|
||||
}
|
||||
if (~program.rawArgs.indexOf("--rename")) {
|
||||
options.rename = true;
|
||||
} else if (!program.rename) {
|
||||
options.rename = false;
|
||||
}
|
||||
var convert_path = function(name) {
|
||||
return name;
|
||||
};
|
||||
@@ -234,7 +238,20 @@ function run() {
|
||||
}
|
||||
fatal(ex);
|
||||
} else if (program.output == "ast") {
|
||||
if (!options.compress && !options.mangle) {
|
||||
result.ast.figure_out_scope({});
|
||||
}
|
||||
print(JSON.stringify(result.ast, function(key, value) {
|
||||
if (value) switch (key) {
|
||||
case "thedef":
|
||||
return symdef(value);
|
||||
case "enclosed":
|
||||
return value.length ? value.map(symdef) : undefined;
|
||||
case "variables":
|
||||
case "functions":
|
||||
case "globals":
|
||||
return value.size() ? value.map(symdef) : undefined;
|
||||
}
|
||||
if (skip_key(key)) return;
|
||||
if (value instanceof UglifyJS.AST_Token) return;
|
||||
if (value instanceof UglifyJS.Dictionary) return;
|
||||
@@ -242,6 +259,11 @@ function run() {
|
||||
var result = {
|
||||
_class: "AST_" + value.TYPE
|
||||
};
|
||||
if (value.block_scope) {
|
||||
result.variables = value.block_scope.variables;
|
||||
result.functions = value.block_scope.functions;
|
||||
result.enclosed = value.block_scope.enclosed;
|
||||
}
|
||||
value.CTOR.PROPS.forEach(function(prop) {
|
||||
result[prop] = value[prop];
|
||||
});
|
||||
@@ -388,6 +410,12 @@ function skip_key(key) {
|
||||
return skip_keys.indexOf(key) >= 0;
|
||||
}
|
||||
|
||||
function symdef(def) {
|
||||
var ret = (1e6 + def.id) + " " + def.name;
|
||||
if (def.mangled_name) ret += " " + def.mangled_name;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function format_object(obj) {
|
||||
var lines = [];
|
||||
var padding = "";
|
||||
|
||||
14
lib/ast.js
14
lib/ast.js
@@ -267,11 +267,10 @@ var AST_For = DEFNODE("For", "init condition step", {
|
||||
}
|
||||
}, AST_IterationStatement);
|
||||
|
||||
var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
||||
var AST_ForIn = DEFNODE("ForIn", "init object", {
|
||||
$documentation: "A `for ... in` statement",
|
||||
$propdoc: {
|
||||
init: "[AST_Node] the `for/in` initialization code",
|
||||
name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
|
||||
object: "[AST_Node] the object that we're looping through"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
@@ -319,6 +318,13 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
|
||||
self = self.parent_scope;
|
||||
}
|
||||
return self;
|
||||
},
|
||||
clone: function(deep) {
|
||||
var node = this._clone(deep);
|
||||
if (this.variables) node.variables = this.variables.clone();
|
||||
if (this.functions) node.functions = this.functions.clone();
|
||||
if (this.enclosed) node.enclosed = this.enclosed.slice();
|
||||
return node;
|
||||
}
|
||||
}, AST_Block);
|
||||
|
||||
@@ -863,8 +869,8 @@ var AST_Object = DEFNODE("Object", "properties", {
|
||||
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||
$documentation: "Base class for literal object properties",
|
||||
$propdoc: {
|
||||
key: "[string|AST_Node] the property name converted to a string for ObjectKeyVal. For setters, getters and computed property this is an arbitrary AST_Node",
|
||||
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
|
||||
key: "[string|AST_Node] property name. For ObjectKeyVal this is a string. For getters, setters and computed property this is an AST_Node.",
|
||||
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor."
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
|
||||
579
lib/compress.js
579
lib/compress.js
@@ -89,11 +89,12 @@ function Compressor(options, false_by_default) {
|
||||
unsafe : false,
|
||||
unsafe_arrows : false,
|
||||
unsafe_comps : false,
|
||||
unsafe_Func : false,
|
||||
unsafe_Function: false,
|
||||
unsafe_math : false,
|
||||
unsafe_methods: false,
|
||||
unsafe_proto : false,
|
||||
unsafe_regexp : false,
|
||||
unsafe_undefined: false,
|
||||
unused : !false_by_default,
|
||||
warnings : false,
|
||||
}, true);
|
||||
@@ -178,7 +179,8 @@ merge(Compressor.prototype, {
|
||||
node.process_expression(true);
|
||||
}
|
||||
var passes = +this.options.passes || 1;
|
||||
var last_count = 1 / 0;
|
||||
var min_count = 1 / 0;
|
||||
var stopping = false;
|
||||
var mangle = { ie8: this.option("ie8") };
|
||||
for (var pass = 0; pass < passes; pass++) {
|
||||
node.figure_out_scope(mangle);
|
||||
@@ -190,9 +192,15 @@ merge(Compressor.prototype, {
|
||||
node.walk(new TreeWalker(function() {
|
||||
count++;
|
||||
}));
|
||||
this.info("pass " + pass + ": last_count: " + last_count + ", count: " + count);
|
||||
if (count >= last_count) break;
|
||||
last_count = count;
|
||||
this.info("pass " + pass + ": last_count: " + min_count + ", count: " + count);
|
||||
if (count < min_count) {
|
||||
min_count = count;
|
||||
stopping = false;
|
||||
} else if (stopping) {
|
||||
break;
|
||||
} else {
|
||||
stopping = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.option("expression")) {
|
||||
@@ -411,14 +419,15 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
function read_property(obj, key) {
|
||||
if (key instanceof AST_Constant) key = key.getValue();
|
||||
if (key instanceof AST_Node) return null;
|
||||
key = get_value(key);
|
||||
if (key instanceof AST_Node) return;
|
||||
var value;
|
||||
if (obj instanceof AST_Array) {
|
||||
var elements = obj.elements;
|
||||
if (key == "length") return make_node_from_constant(elements.length, obj);
|
||||
if (typeof key == "number" && key in elements) value = elements[key];
|
||||
} else if (obj instanceof AST_Object) {
|
||||
key = "" + key;
|
||||
var props = obj.properties;
|
||||
for (var i = props.length; --i >= 0;) {
|
||||
var prop = props[i];
|
||||
@@ -489,8 +498,9 @@ merge(Compressor.prototype, {
|
||||
if (node instanceof AST_SymbolRef) d.references.push(node);
|
||||
d.fixed = false;
|
||||
});
|
||||
def(AST_Accessor, function(tw, descend) {
|
||||
def(AST_Accessor, function(tw, descend, compressor) {
|
||||
push(tw);
|
||||
reset_variables(tw, compressor, this);
|
||||
descend();
|
||||
pop(tw);
|
||||
return true;
|
||||
@@ -917,9 +927,8 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
function loop_body(x) {
|
||||
if (x instanceof AST_Switch) return x;
|
||||
if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
|
||||
return (x.body instanceof AST_BlockStatement ? x.body : x);
|
||||
if (x instanceof AST_IterationStatement) {
|
||||
return x.body instanceof AST_BlockStatement ? x.body : x;
|
||||
}
|
||||
return x;
|
||||
};
|
||||
@@ -947,6 +956,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
function tighten_body(statements, compressor) {
|
||||
var scope = compressor.find_parent(AST_Scope).get_defun_scope();
|
||||
var CHANGED, max_iter = 10;
|
||||
do {
|
||||
CHANGED = false;
|
||||
@@ -962,7 +972,7 @@ merge(Compressor.prototype, {
|
||||
sequencesize_2(statements, compressor);
|
||||
}
|
||||
if (compressor.option("join_vars")) {
|
||||
join_consecutive_vars(statements, compressor);
|
||||
join_consecutive_vars(statements);
|
||||
}
|
||||
if (compressor.option("collapse_vars")) {
|
||||
collapse(statements, compressor);
|
||||
@@ -978,7 +988,6 @@ merge(Compressor.prototype, {
|
||||
// Will not attempt to collapse assignments into or past code blocks
|
||||
// which are not sequentially executed, e.g. loops and conditionals.
|
||||
function collapse(statements, compressor) {
|
||||
var scope = compressor.find_parent(AST_Scope).get_defun_scope();
|
||||
if (scope.uses_eval || scope.uses_with) return statements;
|
||||
var args;
|
||||
var candidates = [];
|
||||
@@ -1280,14 +1289,31 @@ merge(Compressor.prototype, {
|
||||
expr.definitions.forEach(extract_candidates);
|
||||
} else if (expr instanceof AST_DWLoop) {
|
||||
extract_candidates(expr.condition);
|
||||
if (!(expr.body instanceof AST_Block)) {
|
||||
extract_candidates(expr.body);
|
||||
}
|
||||
} else if (expr instanceof AST_Exit) {
|
||||
if (expr.value) extract_candidates(expr.value);
|
||||
} else if (expr instanceof AST_For) {
|
||||
if (expr.init) extract_candidates(expr.init);
|
||||
if (expr.condition) extract_candidates(expr.condition);
|
||||
if (expr.step) extract_candidates(expr.step);
|
||||
if (!(expr.body instanceof AST_Block)) {
|
||||
extract_candidates(expr.body);
|
||||
}
|
||||
} else if (expr instanceof AST_ForIn) {
|
||||
extract_candidates(expr.object);
|
||||
if (!(expr.body instanceof AST_Block)) {
|
||||
extract_candidates(expr.body);
|
||||
}
|
||||
} else if (expr instanceof AST_If) {
|
||||
extract_candidates(expr.condition);
|
||||
if (!(expr.body instanceof AST_Block)) {
|
||||
extract_candidates(expr.body);
|
||||
}
|
||||
if (expr.alternative && !(expr.alternative instanceof AST_Block)) {
|
||||
extract_candidates(expr.alternative);
|
||||
}
|
||||
} else if (expr instanceof AST_Sequence) {
|
||||
expr.expressions.forEach(extract_candidates);
|
||||
} else if (expr instanceof AST_SimpleStatement) {
|
||||
@@ -1314,10 +1340,12 @@ merge(Compressor.prototype, {
|
||||
if (parent instanceof AST_Call) return node;
|
||||
if (parent instanceof AST_Case) return node;
|
||||
if (parent instanceof AST_Conditional) return node;
|
||||
if (parent instanceof AST_Definitions) return find_stop(parent, level + 1);
|
||||
if (parent instanceof AST_Exit) return node;
|
||||
if (parent instanceof AST_If) return node;
|
||||
if (parent instanceof AST_IterationStatement) return node;
|
||||
if (parent instanceof AST_Sequence) return find_stop(parent, level + 1);
|
||||
if (parent instanceof AST_SimpleStatement) return find_stop(parent, level + 1);
|
||||
if (parent instanceof AST_Switch) return node;
|
||||
if (parent instanceof AST_VarDef) return node;
|
||||
return null;
|
||||
@@ -1640,7 +1668,7 @@ merge(Compressor.prototype, {
|
||||
function next_index(i) {
|
||||
for (var j = i + 1, len = statements.length; j < len; j++) {
|
||||
var stat = statements[j];
|
||||
if (!(stat instanceof AST_Definitions && declarations_only(stat))) {
|
||||
if (!(stat instanceof AST_Var && declarations_only(stat))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1650,7 +1678,7 @@ merge(Compressor.prototype, {
|
||||
function prev_index(i) {
|
||||
for (var j = i; --j >= 0;) {
|
||||
var stat = statements[j];
|
||||
if (!(stat instanceof AST_Definitions && declarations_only(stat))) {
|
||||
if (!(stat instanceof AST_Var && declarations_only(stat))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1731,7 +1759,7 @@ merge(Compressor.prototype, {
|
||||
var stat = null;
|
||||
for (var i = 0, len = block.body.length; i < len; i++) {
|
||||
var line = block.body[i];
|
||||
if (line instanceof AST_Definitions && declarations_only(line)) {
|
||||
if (line instanceof AST_Var && declarations_only(line)) {
|
||||
decls.push(line);
|
||||
} else if (stat) {
|
||||
return false;
|
||||
@@ -1753,37 +1781,36 @@ merge(Compressor.prototype, {
|
||||
for (var i = 0; i < statements.length; i++) {
|
||||
var stat = statements[i];
|
||||
if (prev) {
|
||||
if (stat instanceof AST_For && !(stat.init instanceof AST_Definitions)) {
|
||||
var abort = false;
|
||||
prev.body.walk(new TreeWalker(function(node) {
|
||||
if (abort || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_Binary && node.operator == "in") {
|
||||
abort = true;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
if (!abort) {
|
||||
if (stat.init) stat.init = cons_seq(stat.init);
|
||||
else {
|
||||
stat.init = prev.body;
|
||||
n--;
|
||||
CHANGED = true;
|
||||
if (stat instanceof AST_Exit) {
|
||||
stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat).transform(compressor));
|
||||
} else if (stat instanceof AST_For) {
|
||||
if (!(stat.init instanceof AST_Definitions)) {
|
||||
var abort = false;
|
||||
prev.body.walk(new TreeWalker(function(node) {
|
||||
if (abort || node instanceof AST_Scope) return true;
|
||||
if (node instanceof AST_Binary && node.operator == "in") {
|
||||
abort = true;
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
if (!abort) {
|
||||
if (stat.init) stat.init = cons_seq(stat.init);
|
||||
else {
|
||||
stat.init = prev.body;
|
||||
n--;
|
||||
CHANGED = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stat instanceof AST_If) {
|
||||
} else if (stat instanceof AST_ForIn) {
|
||||
if (!(stat.init instanceof AST_Const) && !(stat.init instanceof AST_Let)) {
|
||||
stat.object = cons_seq(stat.object);
|
||||
}
|
||||
} else if (stat instanceof AST_If) {
|
||||
stat.condition = cons_seq(stat.condition);
|
||||
}
|
||||
else if (stat instanceof AST_With) {
|
||||
} else if (stat instanceof AST_Switch) {
|
||||
stat.expression = cons_seq(stat.expression);
|
||||
}
|
||||
else if (stat instanceof AST_Exit && stat.value) {
|
||||
stat.value = cons_seq(stat.value);
|
||||
}
|
||||
else if (stat instanceof AST_Exit) {
|
||||
stat.value = cons_seq(make_node(AST_Undefined, stat).transform(compressor));
|
||||
}
|
||||
else if (stat instanceof AST_Switch) {
|
||||
} else if (stat instanceof AST_With) {
|
||||
stat.expression = cons_seq(stat.expression);
|
||||
}
|
||||
}
|
||||
@@ -1813,7 +1840,49 @@ merge(Compressor.prototype, {
|
||||
statements.length = n;
|
||||
}
|
||||
|
||||
function join_consecutive_vars(statements, compressor) {
|
||||
function join_object_assignments(defn, body) {
|
||||
if (!(defn instanceof AST_Definitions)) return;
|
||||
var def = defn.definitions[defn.definitions.length - 1];
|
||||
if (!(def.value instanceof AST_Object)) return;
|
||||
var exprs;
|
||||
if (body instanceof AST_Assign) {
|
||||
exprs = [ body ];
|
||||
} else if (body instanceof AST_Sequence) {
|
||||
exprs = body.expressions.slice();
|
||||
}
|
||||
if (!exprs) return;
|
||||
var trimmed = false;
|
||||
do {
|
||||
var node = exprs[0];
|
||||
if (!(node instanceof AST_Assign)) break;
|
||||
if (node.operator != "=") break;
|
||||
if (!(node.left instanceof AST_PropAccess)) break;
|
||||
var sym = node.left.expression;
|
||||
if (!(sym instanceof AST_SymbolRef)) break;
|
||||
if (def.name.name != sym.name) break;
|
||||
if (!node.right.is_constant_expression(scope)) break;
|
||||
var prop = node.left.property;
|
||||
if (prop instanceof AST_Node) {
|
||||
prop = prop.evaluate(compressor);
|
||||
}
|
||||
if (prop instanceof AST_Node) break;
|
||||
prop = "" + prop;
|
||||
if (compressor.option("ecma") < 6 && compressor.has_directive("use strict")) {
|
||||
if (!all(def.value.properties, function(node) {
|
||||
return node.key != prop && node.key.name != prop;
|
||||
})) break;
|
||||
}
|
||||
def.value.properties.push(make_node(AST_ObjectKeyVal, node, {
|
||||
key: prop,
|
||||
value: node.right
|
||||
}));
|
||||
exprs.shift();
|
||||
trimmed = true;
|
||||
} while (exprs.length);
|
||||
return trimmed && exprs;
|
||||
}
|
||||
|
||||
function join_consecutive_vars(statements) {
|
||||
var defs;
|
||||
for (var i = 0, j = -1, len = statements.length; i < len; i++) {
|
||||
var stat = statements[i];
|
||||
@@ -1829,8 +1898,15 @@ merge(Compressor.prototype, {
|
||||
statements[++j] = stat;
|
||||
defs = stat;
|
||||
}
|
||||
} else if (stat instanceof AST_Exit) {
|
||||
stat.value = extract_object_assignments(stat.value);
|
||||
} else if (stat instanceof AST_For) {
|
||||
if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
|
||||
var exprs = join_object_assignments(prev, stat.init);
|
||||
if (exprs) {
|
||||
CHANGED = true;
|
||||
stat.init = exprs.length ? make_sequence(stat.init, exprs) : null;
|
||||
statements[++j] = stat;
|
||||
} else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
|
||||
if (stat.init) {
|
||||
prev.definitions = prev.definitions.concat(stat.init.definitions);
|
||||
}
|
||||
@@ -1845,11 +1921,43 @@ merge(Compressor.prototype, {
|
||||
} else {
|
||||
statements[++j] = stat;
|
||||
}
|
||||
} else if (stat instanceof AST_ForIn) {
|
||||
stat.object = extract_object_assignments(stat.object);
|
||||
} else if (stat instanceof AST_If) {
|
||||
stat.condition = extract_object_assignments(stat.condition);
|
||||
} else if (stat instanceof AST_SimpleStatement) {
|
||||
var exprs = join_object_assignments(prev, stat.body);
|
||||
if (exprs) {
|
||||
CHANGED = true;
|
||||
if (!exprs.length) continue;
|
||||
stat.body = make_sequence(stat.body, exprs);
|
||||
}
|
||||
statements[++j] = stat;
|
||||
} else if (stat instanceof AST_Switch) {
|
||||
stat.expression = extract_object_assignments(stat.expression);
|
||||
} else if (stat instanceof AST_With) {
|
||||
stat.expression = extract_object_assignments(stat.expression);
|
||||
} else {
|
||||
statements[++j] = stat;
|
||||
}
|
||||
}
|
||||
statements.length = j + 1;
|
||||
|
||||
function extract_object_assignments(value) {
|
||||
statements[++j] = stat;
|
||||
var exprs = join_object_assignments(prev, value);
|
||||
if (exprs) {
|
||||
CHANGED = true;
|
||||
if (exprs.length) {
|
||||
return make_sequence(value, exprs);
|
||||
} else if (value instanceof AST_Sequence) {
|
||||
return value.tail_node().left;
|
||||
} else {
|
||||
return value.left;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1881,6 +1989,18 @@ merge(Compressor.prototype, {
|
||||
}));
|
||||
};
|
||||
|
||||
function get_value(key) {
|
||||
if (key instanceof AST_Constant) {
|
||||
return key.getValue();
|
||||
}
|
||||
if (key instanceof AST_UnaryPrefix
|
||||
&& key.operator == "void"
|
||||
&& key.expression instanceof AST_Constant) {
|
||||
return;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
function is_undefined(node, compressor) {
|
||||
return node.is_undefined
|
||||
|| node instanceof AST_Undefined
|
||||
@@ -2129,6 +2249,95 @@ merge(Compressor.prototype, {
|
||||
return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2);
|
||||
}
|
||||
|
||||
function convert_to_predicate(obj) {
|
||||
for (var key in obj) {
|
||||
obj[key] = makePredicate(obj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
var object_fns = [
|
||||
"constructor",
|
||||
"toString",
|
||||
"valueOf",
|
||||
];
|
||||
var native_fns = {
|
||||
Array: [
|
||||
"indexOf",
|
||||
"join",
|
||||
"lastIndexOf",
|
||||
"slice",
|
||||
].concat(object_fns),
|
||||
Boolean: object_fns,
|
||||
Number: [
|
||||
"toExponential",
|
||||
"toFixed",
|
||||
"toPrecision",
|
||||
].concat(object_fns),
|
||||
Object: object_fns,
|
||||
RegExp: [
|
||||
"test",
|
||||
].concat(object_fns),
|
||||
String: [
|
||||
"charAt",
|
||||
"charCodeAt",
|
||||
"concat",
|
||||
"indexOf",
|
||||
"italics",
|
||||
"lastIndexOf",
|
||||
"match",
|
||||
"replace",
|
||||
"search",
|
||||
"slice",
|
||||
"split",
|
||||
"substr",
|
||||
"substring",
|
||||
"trim",
|
||||
].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",
|
||||
],
|
||||
Object: [
|
||||
"create",
|
||||
"getOwnPropertyDescriptor",
|
||||
"getOwnPropertyNames",
|
||||
"getPrototypeOf",
|
||||
"isExtensible",
|
||||
"isFrozen",
|
||||
"isSealed",
|
||||
"keys",
|
||||
],
|
||||
String: [
|
||||
"fromCharCode",
|
||||
],
|
||||
};
|
||||
convert_to_predicate(static_fns);
|
||||
|
||||
// methods to evaluate a constant expression
|
||||
(function(def){
|
||||
// If the node has been successfully reduced to a constant,
|
||||
@@ -2171,7 +2380,10 @@ merge(Compressor.prototype, {
|
||||
var elements = [];
|
||||
for (var i = 0, len = this.elements.length; i < len; i++) {
|
||||
var element = this.elements[i];
|
||||
if (element instanceof AST_Function) continue;
|
||||
if (element instanceof AST_Function) {
|
||||
elements.push(element);
|
||||
continue;
|
||||
}
|
||||
var value = element._eval(compressor, depth);
|
||||
if (element === value) return this;
|
||||
elements.push(value);
|
||||
@@ -2301,13 +2513,9 @@ merge(Compressor.prototype, {
|
||||
Array: Array,
|
||||
Math: Math,
|
||||
Number: Number,
|
||||
Object: Object,
|
||||
String: String,
|
||||
};
|
||||
function convert_to_predicate(obj) {
|
||||
for (var key in obj) {
|
||||
obj[key] = makePredicate(obj[key]);
|
||||
}
|
||||
}
|
||||
var static_values = {
|
||||
Math: [
|
||||
"E",
|
||||
@@ -2348,77 +2556,6 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return this;
|
||||
});
|
||||
var object_fns = [
|
||||
"constructor",
|
||||
"toString",
|
||||
"valueOf",
|
||||
];
|
||||
var native_fns = {
|
||||
Array: [
|
||||
"indexOf",
|
||||
"join",
|
||||
"lastIndexOf",
|
||||
"slice",
|
||||
].concat(object_fns),
|
||||
Boolean: object_fns,
|
||||
Number: [
|
||||
"toExponential",
|
||||
"toFixed",
|
||||
"toPrecision",
|
||||
].concat(object_fns),
|
||||
RegExp: [
|
||||
"test",
|
||||
].concat(object_fns),
|
||||
String: [
|
||||
"charAt",
|
||||
"charCodeAt",
|
||||
"concat",
|
||||
"indexOf",
|
||||
"italics",
|
||||
"lastIndexOf",
|
||||
"match",
|
||||
"replace",
|
||||
"search",
|
||||
"slice",
|
||||
"split",
|
||||
"substr",
|
||||
"substring",
|
||||
"trim",
|
||||
].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, depth) {
|
||||
var exp = this.expression;
|
||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||
@@ -2443,7 +2580,16 @@ merge(Compressor.prototype, {
|
||||
if (arg === value) return this;
|
||||
args.push(value);
|
||||
}
|
||||
return val[key].apply(val, args);
|
||||
try {
|
||||
return val[key].apply(val, args);
|
||||
} catch (ex) {
|
||||
compressor.warn("Error evaluating {code} [{file}:{line},{col}]", {
|
||||
code: this.print_to_string(),
|
||||
file: this.start.file,
|
||||
line: this.start.line,
|
||||
col: this.start.col
|
||||
});
|
||||
}
|
||||
}
|
||||
return this;
|
||||
});
|
||||
@@ -2537,9 +2683,34 @@ merge(Compressor.prototype, {
|
||||
if (compressor.option("unsafe")) {
|
||||
var expr = this.expression;
|
||||
if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
|
||||
if (expr instanceof AST_Dot
|
||||
&& is_undeclared_ref(expr.expression)
|
||||
&& (static_fns[expr.expression.name] || return_false)(expr.property)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return this.pure || !compressor.pure_funcs(this);
|
||||
});
|
||||
AST_Node.DEFMETHOD("is_call_pure", return_false);
|
||||
AST_Dot.DEFMETHOD("is_call_pure", function(compressor) {
|
||||
if (!compressor.option("unsafe")) return;
|
||||
var expr = this.expression;
|
||||
var fns = return_false;
|
||||
if (expr instanceof AST_Array) {
|
||||
fns = native_fns.Array;
|
||||
} else if (expr.is_boolean()) {
|
||||
fns = native_fns.Boolean;
|
||||
} else if (expr.is_number(compressor)) {
|
||||
fns = native_fns.Number;
|
||||
} else if (expr instanceof AST_RegExp) {
|
||||
fns = native_fns.RegExp;
|
||||
} else if (expr.is_string(compressor)) {
|
||||
fns = native_fns.String;
|
||||
} else if (!this.may_throw_on_access(compressor)) {
|
||||
fns = native_fns.Object;
|
||||
}
|
||||
return fns(this.property);
|
||||
});
|
||||
|
||||
// determine if expression has side effects
|
||||
(function(def){
|
||||
@@ -2560,8 +2731,12 @@ merge(Compressor.prototype, {
|
||||
return any(this.body, compressor);
|
||||
});
|
||||
def(AST_Call, function(compressor){
|
||||
return !this.is_expr_pure(compressor)
|
||||
|| any(this.args, compressor);
|
||||
if (!this.is_expr_pure(compressor)
|
||||
&& (!this.expression.is_call_pure(compressor)
|
||||
|| this.expression.has_side_effects(compressor))) {
|
||||
return true;
|
||||
}
|
||||
return any(this.args, compressor);
|
||||
});
|
||||
def(AST_Switch, function(compressor){
|
||||
return this.expression.has_side_effects(compressor)
|
||||
@@ -2952,7 +3127,7 @@ merge(Compressor.prototype, {
|
||||
var node_def = def.name.definition();;
|
||||
initializations.add(node_def.id, def.value);
|
||||
if (def.name.fixed_value() === def.value) {
|
||||
fixed_ids[node_def.id] = true;
|
||||
fixed_ids[node_def.id] = def;
|
||||
}
|
||||
}
|
||||
if (def.value.has_side_effects(compressor)) {
|
||||
@@ -2988,9 +3163,7 @@ merge(Compressor.prototype, {
|
||||
var def = sym.definition();
|
||||
var in_use = def.id in in_use_ids;
|
||||
if (node instanceof AST_Assign) {
|
||||
if (!in_use
|
||||
|| def.id in fixed_ids
|
||||
&& node.left.fixed_value() !== node.right) {
|
||||
if (!in_use || def.id in fixed_ids && fixed_ids[def.id] !== node) {
|
||||
return maintain_this_binding(parent, node, node.right.transform(tt));
|
||||
}
|
||||
} else if (!in_use) return make_node(AST_Number, node, {
|
||||
@@ -3059,25 +3232,31 @@ merge(Compressor.prototype, {
|
||||
var sym = def.name.definition();
|
||||
if (drop_block && sym.global) return tail.push(def);
|
||||
if (!(drop_vars || drop_block) || sym.id in in_use_ids) {
|
||||
if (def.value && sym.id in fixed_ids && fixed_ids[sym.id] !== def) {
|
||||
def.value = def.value.drop_side_effect_free(compressor);
|
||||
}
|
||||
if (def.name instanceof AST_SymbolVar) {
|
||||
var var_defs = var_defs_by_id.get(sym.id);
|
||||
if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
|
||||
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
||||
if (def.value) {
|
||||
side_effects.push(make_node(AST_Assign, def, {
|
||||
var ref = make_node(AST_SymbolRef, def.name, def.name);
|
||||
sym.references.push(ref);
|
||||
var assign = make_node(AST_Assign, def, {
|
||||
operator: "=",
|
||||
left: make_node(AST_SymbolRef, def.name, def.name),
|
||||
left: ref,
|
||||
right: def.value
|
||||
}).transform(tt));
|
||||
});
|
||||
if (fixed_ids[sym.id] === def) {
|
||||
fixed_ids[sym.id] = assign;
|
||||
}
|
||||
side_effects.push(assign.transform(tt));
|
||||
}
|
||||
remove(var_defs, def);
|
||||
sym.eliminated++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (def.value && sym.id in fixed_ids && def.name.fixed_value() !== def.value) {
|
||||
def.value = def.value.drop_side_effect_free(compressor);
|
||||
}
|
||||
if (def.value) {
|
||||
if (side_effects.length > 0) {
|
||||
if (tail.length > 0) {
|
||||
@@ -3196,7 +3375,7 @@ merge(Compressor.prototype, {
|
||||
if (node instanceof AST_Assign) {
|
||||
node.right.walk(tw);
|
||||
if (node.left.fixed_value() === node.right) {
|
||||
fixed_ids[node_def.id] = true;
|
||||
fixed_ids[node_def.id] = node;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -3415,9 +3594,7 @@ merge(Compressor.prototype, {
|
||||
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
||||
var defs = defs_by_id[node.expression.definition().id];
|
||||
if (defs) {
|
||||
var key = node.property;
|
||||
if (key instanceof AST_Node) key = key.getValue();
|
||||
var def = defs.get(key);
|
||||
var def = defs.get(get_value(node.property));
|
||||
var sym = make_node(AST_SymbolRef, node, {
|
||||
name: def.name,
|
||||
scope: node.expression.scope,
|
||||
@@ -3469,6 +3646,12 @@ merge(Compressor.prototype, {
|
||||
def(AST_This, return_null);
|
||||
def(AST_Call, function(compressor, first_in_statement){
|
||||
if (!this.is_expr_pure(compressor)) {
|
||||
if (this.expression.is_call_pure(compressor)) {
|
||||
var exprs = this.args.slice();
|
||||
exprs.unshift(this.expression.expression);
|
||||
exprs = trim(exprs, compressor, first_in_statement);
|
||||
return exprs && make_sequence(this, exprs);
|
||||
}
|
||||
if (is_func_expr(this.expression)
|
||||
&& (!this.expression.name || !this.expression.name.definition().references.length)) {
|
||||
var node = this.clone();
|
||||
@@ -3513,8 +3696,10 @@ merge(Compressor.prototype, {
|
||||
while (left instanceof AST_PropAccess) {
|
||||
left = left.expression;
|
||||
}
|
||||
if (left instanceof AST_Symbol) return this;
|
||||
return this.right.drop_side_effect_free(compressor);
|
||||
if (left.is_constant_expression(compressor.find_parent(AST_Scope))) {
|
||||
return this.right.drop_side_effect_free(compressor);
|
||||
}
|
||||
return this;
|
||||
});
|
||||
def(AST_Conditional, function(compressor){
|
||||
var consequent = this.consequent.drop_side_effect_free(compressor);
|
||||
@@ -3648,23 +3833,28 @@ merge(Compressor.prototype, {
|
||||
});
|
||||
|
||||
function if_break_in_loop(self, compressor) {
|
||||
function drop_it(rest) {
|
||||
rest = as_statement_array(rest);
|
||||
if (self.body instanceof AST_BlockStatement) {
|
||||
self.body = self.body.clone();
|
||||
self.body.body = rest.concat(self.body.body.slice(1));
|
||||
self.body = self.body.transform(compressor);
|
||||
} else {
|
||||
self.body = make_node(AST_BlockStatement, self.body, {
|
||||
body: rest
|
||||
}).transform(compressor);
|
||||
}
|
||||
if_break_in_loop(self, compressor);
|
||||
}
|
||||
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
|
||||
if (compressor.option("dead_code") && is_break(first)) {
|
||||
var body = [];
|
||||
if (self.init instanceof AST_Statement) {
|
||||
body.push(self.init);
|
||||
} else if (self.init) {
|
||||
body.push(make_node(AST_SimpleStatement, self.init, {
|
||||
body: self.init
|
||||
}));
|
||||
}
|
||||
if (self.condition) {
|
||||
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||
body: self.condition
|
||||
}));
|
||||
}
|
||||
extract_declarations_from_unreachable_code(compressor, self.body, body);
|
||||
return make_node(AST_BlockStatement, self, {
|
||||
body: body
|
||||
});
|
||||
}
|
||||
if (first instanceof AST_If) {
|
||||
if (first.body instanceof AST_Break
|
||||
&& compressor.loopcontrol_target(first.body) === compressor.self()) {
|
||||
if (is_break(first.body)) {
|
||||
if (self.condition) {
|
||||
self.condition = make_node(AST_Binary, self.condition, {
|
||||
left: self.condition,
|
||||
@@ -3675,9 +3865,7 @@ merge(Compressor.prototype, {
|
||||
self.condition = first.condition.negate(compressor);
|
||||
}
|
||||
drop_it(first.alternative);
|
||||
}
|
||||
else if (first.alternative instanceof AST_Break
|
||||
&& compressor.loopcontrol_target(first.alternative) === compressor.self()) {
|
||||
} else if (is_break(first.alternative)) {
|
||||
if (self.condition) {
|
||||
self.condition = make_node(AST_Binary, self.condition, {
|
||||
left: self.condition,
|
||||
@@ -3690,7 +3878,27 @@ merge(Compressor.prototype, {
|
||||
drop_it(first.body);
|
||||
}
|
||||
}
|
||||
};
|
||||
return self;
|
||||
|
||||
function is_break(node) {
|
||||
return node instanceof AST_Break
|
||||
&& compressor.loopcontrol_target(node) === compressor.self();
|
||||
}
|
||||
|
||||
function drop_it(rest) {
|
||||
rest = as_statement_array(rest);
|
||||
if (self.body instanceof AST_BlockStatement) {
|
||||
self.body = self.body.clone();
|
||||
self.body.body = rest.concat(self.body.body.slice(1));
|
||||
self.body = self.body.transform(compressor);
|
||||
} else {
|
||||
self.body = make_node(AST_BlockStatement, self.body, {
|
||||
body: rest
|
||||
}).transform(compressor);
|
||||
}
|
||||
self = if_break_in_loop(self, compressor);
|
||||
}
|
||||
}
|
||||
|
||||
OPT(AST_For, function(self, compressor){
|
||||
if (!compressor.option("loops")) return self;
|
||||
@@ -3726,8 +3934,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
}
|
||||
if_break_in_loop(self, compressor);
|
||||
return self;
|
||||
return if_break_in_loop(self, compressor);
|
||||
});
|
||||
|
||||
OPT(AST_If, function(self, compressor){
|
||||
@@ -3983,9 +4190,20 @@ merge(Compressor.prototype, {
|
||||
OPT(AST_Try, function(self, compressor){
|
||||
tighten_body(self.body, compressor);
|
||||
if (self.bcatch && self.bfinally && all(self.bfinally.body, is_empty)) self.bfinally = null;
|
||||
if (all(self.body, is_empty)) {
|
||||
if (compressor.option("dead_code") && all(self.body, is_empty)) {
|
||||
var body = [];
|
||||
if (self.bcatch) extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
|
||||
if (self.bcatch) {
|
||||
extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
|
||||
body.forEach(function(stat) {
|
||||
if (!(stat instanceof AST_Definitions)) return;
|
||||
stat.definitions.forEach(function(var_def) {
|
||||
var def = var_def.name.definition().redefined();
|
||||
if (!def) return;
|
||||
var_def.name = var_def.name.clone();
|
||||
var_def.name.thedef = def;
|
||||
});
|
||||
});
|
||||
}
|
||||
if (self.bfinally) body = body.concat(self.bfinally.body);
|
||||
return make_node(AST_BlockStatement, self, {
|
||||
body: body
|
||||
@@ -4171,11 +4389,13 @@ merge(Compressor.prototype, {
|
||||
return self;
|
||||
} else if (exp instanceof AST_Dot) switch(exp.property) {
|
||||
case "toString":
|
||||
if (self.args.length == 0) return make_node(AST_Binary, self, {
|
||||
left: make_node(AST_String, self, { value: "" }),
|
||||
operator: "+",
|
||||
right: exp.expression
|
||||
}).optimize(compressor);
|
||||
if (self.args.length == 0 && !exp.expression.may_throw_on_access(compressor)) {
|
||||
return make_node(AST_Binary, self, {
|
||||
left: make_node(AST_String, self, { value: "" }),
|
||||
operator: "+",
|
||||
right: exp.expression
|
||||
}).optimize(compressor);
|
||||
}
|
||||
break;
|
||||
case "join":
|
||||
if (exp.expression instanceof AST_Array) EXIT: {
|
||||
@@ -4285,7 +4505,7 @@ merge(Compressor.prototype, {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (compressor.option("unsafe_Func")
|
||||
if (compressor.option("unsafe_Function")
|
||||
&& is_undeclared_ref(exp)
|
||||
&& exp.name == "Function") {
|
||||
// new Function() => function(){}
|
||||
@@ -5238,6 +5458,7 @@ merge(Compressor.prototype, {
|
||||
fixed = make_node(AST_ClassExpression, fixed, fixed);
|
||||
}
|
||||
if (fixed instanceof AST_Defun) {
|
||||
fixed._squeezed = true;
|
||||
fixed = make_node(AST_Function, fixed, fixed);
|
||||
}
|
||||
var value;
|
||||
@@ -5325,7 +5546,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
|
||||
OPT(AST_Undefined, function(self, compressor){
|
||||
if (compressor.option("unsafe")) {
|
||||
if (compressor.option("unsafe_undefined")) {
|
||||
var undef = find_variable(compressor, "undefined");
|
||||
if (undef) {
|
||||
var ref = make_node(AST_SymbolRef, self, {
|
||||
@@ -5576,6 +5797,20 @@ merge(Compressor.prototype, {
|
||||
consequent
|
||||
]).optimize(compressor);
|
||||
}
|
||||
// x ? y || z : z --> x && y || z
|
||||
if (consequent instanceof AST_Binary
|
||||
&& consequent.operator == "||"
|
||||
&& consequent.right.equivalent_to(alternative)) {
|
||||
return make_node(AST_Binary, self, {
|
||||
operator: "||",
|
||||
left: make_node(AST_Binary, self, {
|
||||
operator: "&&",
|
||||
left: self.condition,
|
||||
right: consequent.left
|
||||
}),
|
||||
right: alternative
|
||||
}).optimize(compressor);
|
||||
}
|
||||
var in_bool = compressor.in_boolean_context();
|
||||
if (is_true(self.consequent)) {
|
||||
if (is_false(self.alternative)) {
|
||||
@@ -5841,6 +6076,7 @@ merge(Compressor.prototype, {
|
||||
if (def) {
|
||||
return def.optimize(compressor);
|
||||
}
|
||||
if (is_lhs(self, compressor.parent())) return self;
|
||||
if (compressor.option("unsafe_proto")
|
||||
&& self.expression instanceof AST_Dot
|
||||
&& self.expression.property == "prototype") {
|
||||
@@ -5879,7 +6115,6 @@ merge(Compressor.prototype, {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_lhs(self, compressor.parent())) return self;
|
||||
var sub = self.flatten_object(self.property, compressor);
|
||||
if (sub) return sub.optimize(compressor);
|
||||
var ev = self.evaluate(compressor);
|
||||
|
||||
@@ -151,7 +151,9 @@ function minify(files, options) {
|
||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||
}
|
||||
if (timings) timings.rename = Date.now();
|
||||
if (options.rename) {
|
||||
// disable rename on harmony due to expand_names bug in for-of loops
|
||||
// https://github.com/mishoo/UglifyJS2/issues/2794
|
||||
if (0 && options.rename) {
|
||||
toplevel.figure_out_scope(options.mangle);
|
||||
toplevel.expand_names(options.mangle);
|
||||
}
|
||||
|
||||
201
lib/output.js
201
lib/output.js
@@ -472,83 +472,87 @@ function OutputStream(options) {
|
||||
return OUTPUT;
|
||||
};
|
||||
|
||||
function has_nlb() {
|
||||
var index = OUTPUT.lastIndexOf("\n");
|
||||
return /^ *$/.test(OUTPUT.slice(index + 1));
|
||||
}
|
||||
|
||||
function prepend_comments(node) {
|
||||
var self = this;
|
||||
var start = node.start;
|
||||
if (!start) return;
|
||||
if (!(start.comments_before && start.comments_before._dumped === self)) {
|
||||
var comments = start.comments_before;
|
||||
if (!comments) {
|
||||
comments = start.comments_before = [];
|
||||
}
|
||||
comments._dumped = self;
|
||||
if (start.comments_before && start.comments_before._dumped === self) return;
|
||||
var comments = start.comments_before;
|
||||
if (!comments) {
|
||||
comments = start.comments_before = [];
|
||||
}
|
||||
comments._dumped = self;
|
||||
|
||||
if (node instanceof AST_Exit && node.value) {
|
||||
var tw = new TreeWalker(function(node) {
|
||||
var parent = tw.parent();
|
||||
if (parent instanceof AST_Exit
|
||||
|| parent instanceof AST_Binary && parent.left === node
|
||||
|| parent.TYPE == "Call" && parent.expression === node
|
||||
|| parent instanceof AST_Conditional && parent.condition === node
|
||||
|| parent instanceof AST_Dot && parent.expression === node
|
||||
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|
||||
|| parent instanceof AST_Sub && parent.expression === node
|
||||
|| parent instanceof AST_UnaryPostfix) {
|
||||
if (!node.start) return;
|
||||
var text = node.start.comments_before;
|
||||
if (text && text._dumped !== self) {
|
||||
text._dumped = self;
|
||||
comments = comments.concat(text);
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
if (node instanceof AST_Exit && node.value) {
|
||||
var tw = new TreeWalker(function(node) {
|
||||
var parent = tw.parent();
|
||||
if (parent instanceof AST_Exit
|
||||
|| parent instanceof AST_Binary && parent.left === node
|
||||
|| parent.TYPE == "Call" && parent.expression === node
|
||||
|| parent instanceof AST_Conditional && parent.condition === node
|
||||
|| parent instanceof AST_Dot && parent.expression === node
|
||||
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|
||||
|| parent instanceof AST_Sub && parent.expression === node
|
||||
|| parent instanceof AST_UnaryPostfix) {
|
||||
if (!node.start) return;
|
||||
var text = node.start.comments_before;
|
||||
if (text && text._dumped !== self) {
|
||||
text._dumped = self;
|
||||
comments = comments.concat(text);
|
||||
}
|
||||
});
|
||||
tw.push(node);
|
||||
node.value.walk(tw);
|
||||
}
|
||||
|
||||
if (current_pos == 0) {
|
||||
if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
|
||||
print("#!" + comments.shift().value + "\n");
|
||||
indent();
|
||||
}
|
||||
var preamble = options.preamble;
|
||||
if (preamble) {
|
||||
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
comments = comments.filter(comment_filter, node);
|
||||
if (comments.length == 0) return;
|
||||
var last_nlb = /(^|\n) *$/.test(OUTPUT);
|
||||
comments.forEach(function(c, i) {
|
||||
if (!last_nlb) {
|
||||
if (c.nlb) {
|
||||
print("\n");
|
||||
indent();
|
||||
last_nlb = true;
|
||||
} else if (i > 0) {
|
||||
space();
|
||||
}
|
||||
}
|
||||
if (/comment[134]/.test(c.type)) {
|
||||
print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
|
||||
indent();
|
||||
last_nlb = true;
|
||||
} else if (c.type == "comment2") {
|
||||
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
||||
last_nlb = false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
tw.push(node);
|
||||
node.value.walk(tw);
|
||||
}
|
||||
|
||||
if (current_pos == 0) {
|
||||
if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
|
||||
print("#!" + comments.shift().value + "\n");
|
||||
indent();
|
||||
}
|
||||
var preamble = options.preamble;
|
||||
if (preamble) {
|
||||
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
comments = comments.filter(comment_filter, node);
|
||||
if (comments.length == 0) return;
|
||||
var last_nlb = has_nlb();
|
||||
comments.forEach(function(c, i) {
|
||||
if (!last_nlb) {
|
||||
if (start.nlb) {
|
||||
if (c.nlb) {
|
||||
print("\n");
|
||||
indent();
|
||||
} else {
|
||||
last_nlb = true;
|
||||
} else if (i > 0) {
|
||||
space();
|
||||
}
|
||||
}
|
||||
if (/comment[134]/.test(c.type)) {
|
||||
print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
|
||||
indent();
|
||||
last_nlb = true;
|
||||
} else if (c.type == "comment2") {
|
||||
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
||||
last_nlb = false;
|
||||
}
|
||||
});
|
||||
if (!last_nlb) {
|
||||
if (start.nlb) {
|
||||
print("\n");
|
||||
indent();
|
||||
} else {
|
||||
space();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,35 +561,33 @@ function OutputStream(options) {
|
||||
var token = node.end;
|
||||
if (!token) return;
|
||||
var comments = token[tail ? "comments_before" : "comments_after"];
|
||||
if (comments
|
||||
&& comments._dumped !== self
|
||||
&& (node instanceof AST_Statement || all(comments, function(c) {
|
||||
return !/comment[134]/.test(c.type);
|
||||
}))) {
|
||||
comments._dumped = self;
|
||||
var insert = OUTPUT.length;
|
||||
comments.filter(comment_filter, node).forEach(function(c, i) {
|
||||
need_space = false;
|
||||
if (need_newline_indented) {
|
||||
print("\n");
|
||||
indent();
|
||||
need_newline_indented = false;
|
||||
} else if (c.nlb && (i > 0 || !/(^|\n) *$/.test(OUTPUT))) {
|
||||
print("\n");
|
||||
indent();
|
||||
} else if (i > 0 || !tail) {
|
||||
space();
|
||||
}
|
||||
if (/comment[134]/.test(c.type)) {
|
||||
print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
|
||||
need_newline_indented = true;
|
||||
} else if (c.type == "comment2") {
|
||||
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
||||
need_space = true;
|
||||
}
|
||||
});
|
||||
if (OUTPUT.length > insert) newline_insert = insert;
|
||||
}
|
||||
if (!comments || comments._dumped === self) return;
|
||||
if (!(node instanceof AST_Statement || all(comments, function(c) {
|
||||
return !/comment[134]/.test(c.type);
|
||||
}))) return;
|
||||
comments._dumped = self;
|
||||
var insert = OUTPUT.length;
|
||||
comments.filter(comment_filter, node).forEach(function(c, i) {
|
||||
need_space = false;
|
||||
if (need_newline_indented) {
|
||||
print("\n");
|
||||
indent();
|
||||
need_newline_indented = false;
|
||||
} else if (c.nlb && (i > 0 || !has_nlb())) {
|
||||
print("\n");
|
||||
indent();
|
||||
} else if (i > 0 || !tail) {
|
||||
space();
|
||||
}
|
||||
if (/comment[134]/.test(c.type)) {
|
||||
print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
|
||||
need_newline_indented = true;
|
||||
} else if (c.type == "comment2") {
|
||||
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
||||
need_space = true;
|
||||
}
|
||||
});
|
||||
if (OUTPUT.length > insert) newline_insert = insert;
|
||||
}
|
||||
|
||||
var stack = [];
|
||||
@@ -769,6 +771,8 @@ function OutputStream(options) {
|
||||
|| p instanceof AST_Arrow // x => (x, x)
|
||||
|| p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
|
||||
|| p instanceof AST_Expansion // [...(a, b)]
|
||||
|| p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
|
||||
|| p instanceof AST_Yield // yield (foo, bar)
|
||||
;
|
||||
});
|
||||
|
||||
@@ -1049,11 +1053,7 @@ function OutputStream(options) {
|
||||
output.with_parens(function(){
|
||||
self.init.print(output);
|
||||
output.space();
|
||||
if (self instanceof AST_ForOf) {
|
||||
output.print("of");
|
||||
} else {
|
||||
output.print("in");
|
||||
}
|
||||
output.print(self instanceof AST_ForOf ? "of" : "in");
|
||||
output.space();
|
||||
self.object.print(output);
|
||||
});
|
||||
@@ -1683,11 +1683,8 @@ function OutputStream(options) {
|
||||
|
||||
function print_property_name(key, quote, output) {
|
||||
if (output.option("quote_keys")) {
|
||||
output.print_string(key + "");
|
||||
} else if ((typeof key == "number"
|
||||
|| !output.option("beautify")
|
||||
&& +key + "" == key)
|
||||
&& parseFloat(key) >= 0) {
|
||||
output.print_string(key);
|
||||
} else if ("" + +key == key && key >= 0) {
|
||||
output.print(make_num(key));
|
||||
} else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
|
||||
if (quote && output.option("keep_quoted_props")) {
|
||||
|
||||
@@ -1276,12 +1276,10 @@ function parse($TEXT, options) {
|
||||
};
|
||||
|
||||
function for_in(init) {
|
||||
var lhs = init instanceof AST_Definitions ? init.definitions[0].name : null;
|
||||
var obj = expression(true);
|
||||
expect(")");
|
||||
return new AST_ForIn({
|
||||
init : init,
|
||||
name : lhs,
|
||||
object : obj,
|
||||
body : in_loop(statement)
|
||||
});
|
||||
@@ -1862,7 +1860,7 @@ function parse($TEXT, options) {
|
||||
name : as_symbol(sym_type),
|
||||
value : is("operator", "=")
|
||||
? (next(), expression(false, no_in))
|
||||
: !no_in && kind === "const" && S.input.has_directive("use strict")
|
||||
: !no_in && kind === "const"
|
||||
? croak("Missing initializer in const declaration") : null,
|
||||
end : prev()
|
||||
});
|
||||
@@ -2226,7 +2224,7 @@ function parse($TEXT, options) {
|
||||
a.push(new AST_ObjectKeyVal({
|
||||
start: start,
|
||||
quote: start.quote,
|
||||
key: name,
|
||||
key: name instanceof AST_Node ? name : "" + name,
|
||||
value: value,
|
||||
end: prev()
|
||||
}));
|
||||
@@ -2283,7 +2281,7 @@ function parse($TEXT, options) {
|
||||
if (typeof name === "string" || typeof name === "number") {
|
||||
return new AST_SymbolMethod({
|
||||
start: token,
|
||||
name: name,
|
||||
name: "" + name,
|
||||
end: prev()
|
||||
});
|
||||
} else if (name === null) {
|
||||
|
||||
65
lib/scope.js
65
lib/scope.js
@@ -202,7 +202,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
||||
|| node instanceof AST_SymbolConst) {
|
||||
var def;
|
||||
if (node instanceof AST_SymbolBlockDeclaration) {
|
||||
def = scope.def_variable(node);
|
||||
def = scope.def_variable(node, null);
|
||||
} else {
|
||||
def = defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
||||
}
|
||||
@@ -411,7 +411,7 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
|
||||
|
||||
AST_Scope.DEFMETHOD("def_function", function(symbol, init){
|
||||
var def = this.def_variable(symbol, init);
|
||||
if (!def.init) def.init = init;
|
||||
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
||||
this.functions.set(symbol.name, def);
|
||||
return def;
|
||||
});
|
||||
@@ -550,24 +550,23 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
node.variables.each(collect);
|
||||
return;
|
||||
}
|
||||
if (node.is_block_scope()) {
|
||||
node.block_scope.variables.each(collect);
|
||||
return;
|
||||
}
|
||||
if (node instanceof AST_Label) {
|
||||
var name;
|
||||
do name = base54(++lname); while (!is_identifier(name));
|
||||
node.mangled_name = name;
|
||||
return true;
|
||||
}
|
||||
var mangle_with_block_scope =
|
||||
(!options.ie8 && node instanceof AST_SymbolCatch) ||
|
||||
node instanceof AST_SymbolBlockDeclaration;
|
||||
if (mangle_with_block_scope && options.reserved.indexOf(node.name) < 0) {
|
||||
if (!options.ie8 && node instanceof AST_SymbolCatch) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.walk(tw);
|
||||
to_mangle.forEach(function(def){
|
||||
def.mangle(options);
|
||||
});
|
||||
to_mangle.forEach(function(def){ def.mangle(options) });
|
||||
|
||||
function collect(symbol) {
|
||||
if (!member(symbol.name, options.reserved)) {
|
||||
@@ -576,59 +575,55 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("find_unique_prefix", function(options) {
|
||||
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
|
||||
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||
var cache = options.cache && options.cache.props;
|
||||
var prefixes = Object.create(null);
|
||||
options.reserved.forEach(add_prefix);
|
||||
var avoid = Object.create(null);
|
||||
options.reserved.forEach(to_avoid);
|
||||
this.globals.each(add_def);
|
||||
this.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Scope) node.variables.each(add_def);
|
||||
if (node instanceof AST_SymbolCatch) add_def(node.definition());
|
||||
}));
|
||||
var prefix, i = 0;
|
||||
do {
|
||||
prefix = create_name(i++);
|
||||
} while (prefixes[prefix]);
|
||||
return prefix;
|
||||
return avoid;
|
||||
|
||||
function add_prefix(name) {
|
||||
if (/[0-9]$/.test(name)) {
|
||||
prefixes[name.replace(/[0-9]+$/, "")] = true;
|
||||
}
|
||||
function to_avoid(name) {
|
||||
avoid[name] = true;
|
||||
}
|
||||
|
||||
function add_def(def) {
|
||||
var name = def.name;
|
||||
if (def.global && cache && cache.has(name)) name = cache.get(name);
|
||||
else if (!def.unmangleable(options)) return;
|
||||
add_prefix(name);
|
||||
}
|
||||
|
||||
function create_name(num) {
|
||||
var name = "";
|
||||
do {
|
||||
name += letters[num % letters.length];
|
||||
num = Math.floor(num / letters.length);
|
||||
} while (num);
|
||||
return name;
|
||||
to_avoid(name);
|
||||
}
|
||||
});
|
||||
|
||||
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
||||
base54.reset();
|
||||
base54.sort();
|
||||
options = this._default_mangler_options(options);
|
||||
var prefix = this.find_unique_prefix(options);
|
||||
var avoid = this.find_colliding_names(options);
|
||||
var cname = 0;
|
||||
this.globals.each(rename);
|
||||
this.walk(new TreeWalker(function(node) {
|
||||
if (node instanceof AST_Scope) node.variables.each(rename);
|
||||
if (node instanceof AST_SymbolCatch) rename(node.definition());
|
||||
}));
|
||||
|
||||
function next_name() {
|
||||
var name;
|
||||
do {
|
||||
name = base54(cname++);
|
||||
} while (avoid[name] || !is_identifier(name));
|
||||
return name;
|
||||
}
|
||||
|
||||
function rename(def) {
|
||||
if (def.global || def.unmangleable(options)) return;
|
||||
if (def.global && options.cache) return;
|
||||
if (def.unmangleable(options)) return;
|
||||
if (member(def.name, options.reserved)) return;
|
||||
var d = def.redefined();
|
||||
def.name = d ? d.name : prefix + def.id;
|
||||
def.name = d ? d.name : next_name();
|
||||
def.orig.forEach(function(sym) {
|
||||
sym.name = def.name;
|
||||
});
|
||||
|
||||
@@ -303,6 +303,13 @@ Dictionary.prototype = {
|
||||
ret.push(f(this._values[i], i.substr(1)));
|
||||
return ret;
|
||||
},
|
||||
clone: function() {
|
||||
var ret = new Dictionary();
|
||||
for (var i in this._values)
|
||||
ret._values[i] = this._values[i];
|
||||
ret._size = this._size;
|
||||
return ret;
|
||||
},
|
||||
toObject: function() { return this._values }
|
||||
};
|
||||
Dictionary.fromObject = function(obj) {
|
||||
|
||||
12
package.json
12
package.json
@@ -4,17 +4,15 @@
|
||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.3.5",
|
||||
"version": "3.3.9",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"maintainers": [
|
||||
"Alex Lam <alexlamsl@gmail.com>",
|
||||
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
||||
],
|
||||
"repository": "git+https://github.com/mishoo/UglifyJS2.git#harmony",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mishoo/UglifyJS2/issues"
|
||||
},
|
||||
"repository": "https://github.com/mishoo/UglifyJS2.git#harmony",
|
||||
"main": "tools/node.js",
|
||||
"bin": {
|
||||
"uglifyjs": "bin/uglifyjs"
|
||||
@@ -26,11 +24,11 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "~2.12.1",
|
||||
"commander": "~2.13.0",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "~5.2.1",
|
||||
"acorn": "~5.3.0",
|
||||
"mocha": "~3.5.1",
|
||||
"semver": "~5.4.1"
|
||||
},
|
||||
|
||||
@@ -41,7 +41,7 @@ do_not_remove_anon_blocks_if_they_have_decls: {
|
||||
var x;
|
||||
}
|
||||
{
|
||||
const y;
|
||||
const y = 1;
|
||||
class Zee {};
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ do_not_remove_anon_blocks_if_they_have_decls: {
|
||||
}
|
||||
var x;
|
||||
{
|
||||
const y;
|
||||
const y = 1;
|
||||
class Zee {}
|
||||
}
|
||||
}
|
||||
@@ -77,12 +77,12 @@ remove_unused_in_global_block: {
|
||||
input: {
|
||||
{
|
||||
let x;
|
||||
const y;
|
||||
const y = 1;
|
||||
class Zee {};
|
||||
var w;
|
||||
}
|
||||
let ex;
|
||||
const why;
|
||||
const why = 2;
|
||||
class Zed {};
|
||||
var wut;
|
||||
console.log(x, y, Zee);
|
||||
@@ -90,7 +90,7 @@ remove_unused_in_global_block: {
|
||||
expect: {
|
||||
var w;
|
||||
let ex;
|
||||
const why;
|
||||
const why = 2;
|
||||
class Zed {};
|
||||
var wut;
|
||||
console.log(x, y, Zee);
|
||||
|
||||
@@ -75,6 +75,7 @@ issue_1664: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
node_version: ">=6"
|
||||
reminify: false // FIXME - block scoped function
|
||||
}
|
||||
|
||||
issue_1672_for: {
|
||||
|
||||
@@ -2296,6 +2296,7 @@ toplevel_single_reference: {
|
||||
unused_orig: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
dead_code: true,
|
||||
passes: 2,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
@@ -2323,7 +2324,7 @@ unused_orig: {
|
||||
var c = b;
|
||||
for (var d in c) {
|
||||
var a;
|
||||
return --b + (a = c[0]);
|
||||
return --b + c[0];
|
||||
}
|
||||
a && a.NaN;
|
||||
}([2]), a);
|
||||
@@ -4313,3 +4314,103 @@ replace_all_var: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
cascade_statement: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
function f1(a, b) {
|
||||
var c;
|
||||
if (a)
|
||||
return c = b, c || a;
|
||||
else
|
||||
c = a, c(b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
var c;
|
||||
while (a)
|
||||
c = b, a = c + b;
|
||||
do
|
||||
throw c = a + b, c;
|
||||
while (c);
|
||||
}
|
||||
function f3(a, b) {
|
||||
for (; a < b; a++)
|
||||
if (c = a, c && b)
|
||||
var c = (c = b(a), c);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1(a, b) {
|
||||
var c;
|
||||
if (a)
|
||||
return (c = b) || a;
|
||||
else
|
||||
(c = a)(b);
|
||||
}
|
||||
function f2(a, b) {
|
||||
var c;
|
||||
while (a)
|
||||
a = (c = b) + b;
|
||||
do
|
||||
throw c = a + b;
|
||||
while (c);
|
||||
}
|
||||
function f3(a, b) {
|
||||
for (; a < b; a++)
|
||||
if ((c = a) && b)
|
||||
var c = c = b(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cascade_forin: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
function f(b) {
|
||||
return [ b, b, b ];
|
||||
}
|
||||
for (var c in a = console, f(a))
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
function f(b) {
|
||||
return [ b, b, b ];
|
||||
}
|
||||
for (var c in f(a = console))
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
}
|
||||
|
||||
unsafe_builtin: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: "strict",
|
||||
unsafe: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a) {
|
||||
var b = Math.abs(a);
|
||||
return Math.pow(b, 2);
|
||||
}
|
||||
console.log(f(-1), f(2));
|
||||
}
|
||||
expect: {
|
||||
function f(a) {
|
||||
return Math.pow(Math.abs(a), 2);
|
||||
}
|
||||
console.log(f(-1), f(2));
|
||||
}
|
||||
expect_stdout: "1 4"
|
||||
}
|
||||
|
||||
@@ -1224,3 +1224,46 @@ hoist_decl: {
|
||||
x() ? y() : z();
|
||||
}
|
||||
}
|
||||
|
||||
to_and_or: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
}
|
||||
input: {
|
||||
var values = [
|
||||
0,
|
||||
null,
|
||||
true,
|
||||
"foo",
|
||||
false,
|
||||
-1 / 0,
|
||||
void 0,
|
||||
];
|
||||
values.forEach(function(x) {
|
||||
values.forEach(function(y) {
|
||||
values.forEach(function(z) {
|
||||
console.log(x ? y || z : z);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
expect: {
|
||||
var values = [
|
||||
0,
|
||||
null,
|
||||
true,
|
||||
"foo",
|
||||
false,
|
||||
-1 / 0,
|
||||
void 0,
|
||||
];
|
||||
values.forEach(function(x) {
|
||||
values.forEach(function(y) {
|
||||
values.forEach(function(z) {
|
||||
console.log(x && y || z);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ dead_code_2_should_warn: {
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
reminify: false // FIXME - block scoped function
|
||||
}
|
||||
|
||||
dead_code_2_should_warn_strict: {
|
||||
@@ -100,6 +101,7 @@ dead_code_2_should_warn_strict: {
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=4"
|
||||
reminify: false // FIXME - block scoped function
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more: {
|
||||
@@ -135,6 +137,7 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
reminify: false // FIXME - block scoped function
|
||||
}
|
||||
|
||||
dead_code_constant_boolean_should_warn_more_strict: {
|
||||
@@ -171,6 +174,7 @@ dead_code_constant_boolean_should_warn_more_strict: {
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=4"
|
||||
reminify: false // FIXME - block scoped function
|
||||
}
|
||||
|
||||
dead_code_block_decls_die: {
|
||||
@@ -1128,3 +1132,49 @@ issue_2701: {
|
||||
}
|
||||
expect_stdout: "function"
|
||||
}
|
||||
|
||||
issue_2749: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
inline: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = 2, c = "PASS";
|
||||
while (a--)
|
||||
(function() {
|
||||
return b ? c = "FAIL" : b = 1;
|
||||
try {
|
||||
} catch (b) {
|
||||
var b;
|
||||
}
|
||||
})();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var a = 2, c = "PASS";
|
||||
while (a--)
|
||||
b = void 0, b ? c = "FAIL" : b = 1;
|
||||
var b;
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
unsafe_builtin: {
|
||||
options = {
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
(!w).constructor(x);
|
||||
Math.abs(y);
|
||||
[ 1, 2, z ].valueOf();
|
||||
}
|
||||
expect: {
|
||||
w, x;
|
||||
y;
|
||||
z;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ unused_block_decls: {
|
||||
input: {
|
||||
function foo() {
|
||||
{
|
||||
const x;
|
||||
const x = 1;
|
||||
}
|
||||
{
|
||||
let y;
|
||||
@@ -2018,3 +2018,78 @@ cascade_drop_assign: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
chained_3: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a, b) {
|
||||
var c = a, c = b;
|
||||
b++;
|
||||
return c;
|
||||
}(1, 2));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a, b) {
|
||||
var c = b;
|
||||
b++;
|
||||
return c;
|
||||
}(0, 2));
|
||||
}
|
||||
expect_stdout: "2"
|
||||
}
|
||||
|
||||
issue_2768: {
|
||||
options = {
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a = "FAIL", c = 1;
|
||||
var c = function(b) {
|
||||
var d = b = a;
|
||||
var e = --b + (d && (a = "PASS"));
|
||||
}();
|
||||
console.log(a, typeof c);
|
||||
}
|
||||
expect: {
|
||||
var a = "FAIL";
|
||||
var c = (d = a, 0, void (d && (a = "PASS")));
|
||||
var d;
|
||||
console.log(a, typeof c);
|
||||
}
|
||||
expect_stdout: "PASS undefined"
|
||||
}
|
||||
|
||||
issue_2846: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
var a = 0;
|
||||
b && b(a);
|
||||
return a++;
|
||||
}
|
||||
var c = f();
|
||||
console.log(c);
|
||||
}
|
||||
expect: {
|
||||
var c = function(a, b) {
|
||||
a = 0;
|
||||
b && b(a);
|
||||
return a++;
|
||||
}();
|
||||
console.log(c);
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
@@ -1287,6 +1287,9 @@ issue_2231_1: {
|
||||
console.log(Object.keys(void 0));
|
||||
}
|
||||
expect_stdout: true
|
||||
expect_warnings: [
|
||||
"WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1284,20]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2231_2: {
|
||||
@@ -1301,6 +1304,23 @@ issue_2231_2: {
|
||||
console.log(Object.getOwnPropertyNames(null));
|
||||
}
|
||||
expect_stdout: true
|
||||
expect_warnings: [
|
||||
"WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1301,20]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2231_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log(Object.keys({ foo: "bar" })[0]);
|
||||
}
|
||||
expect: {
|
||||
console.log("foo");
|
||||
}
|
||||
expect_stdout: "foo"
|
||||
}
|
||||
|
||||
self_comparison_1: {
|
||||
@@ -1423,13 +1443,27 @@ issue_2535_3: {
|
||||
}
|
||||
expect_stdout: true
|
||||
expect_warnings: [
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1409,20]",
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1410,20]",
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1411,20]",
|
||||
"WARN: Condition left of && always false [test/compress/evaluate.js:1411,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1412,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1413,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1414,20]",
|
||||
"WARN: Condition left of || always true [test/compress/evaluate.js:1414,20]",
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1429,20]",
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1430,20]",
|
||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1431,20]",
|
||||
"WARN: Condition left of && always false [test/compress/evaluate.js:1431,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1432,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1433,20]",
|
||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1434,20]",
|
||||
"WARN: Condition left of || always true [test/compress/evaluate.js:1434,20]",
|
||||
]
|
||||
}
|
||||
|
||||
issue_2822: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
console.log([ function() {}, "PASS", "FAIL" ][1]);
|
||||
}
|
||||
expect: {
|
||||
console.log("PASS");
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ issue_203: {
|
||||
options = {
|
||||
keep_fargs: false,
|
||||
side_effects: true,
|
||||
unsafe_Func: true,
|
||||
unsafe_Function: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
@@ -2117,3 +2117,41 @@ issue_2737_2: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2783: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
return g;
|
||||
function f(a) {
|
||||
var b = a.b;
|
||||
if (b) return b;
|
||||
return a;
|
||||
}
|
||||
function g(o, i) {
|
||||
while (i--) {
|
||||
console.log(f(o));
|
||||
}
|
||||
}
|
||||
})()({ b: "PASS" }, 1);
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
return function(o,i) {
|
||||
while (i--) console.log(f(o));
|
||||
};
|
||||
function f(a) {
|
||||
var b = a.b;
|
||||
return b || a;
|
||||
}
|
||||
})()({ b: "PASS" },1);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -1212,3 +1212,230 @@ issue_2676: {
|
||||
(class {}).a = 42;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2762: {
|
||||
mangle = {}
|
||||
input: {
|
||||
var bar = 1, T = true;
|
||||
(function() {
|
||||
if (T) {
|
||||
const a = function() {
|
||||
var foo = bar;
|
||||
console.log(foo, a.prop, b.prop);
|
||||
};
|
||||
a.prop = 2;
|
||||
const b = { prop: 3 };
|
||||
a();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
var bar = 1, T = true;
|
||||
(function() {
|
||||
if (T) {
|
||||
const o = function() {
|
||||
var p = bar;
|
||||
console.log(p, o.prop, r.prop);
|
||||
};
|
||||
o.prop = 2;
|
||||
const r = { prop: 3 };
|
||||
o();
|
||||
}
|
||||
})();
|
||||
}
|
||||
expect_stdout: "1 2 3"
|
||||
}
|
||||
|
||||
issue_2794_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 1,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
for (const a of func(value)) {
|
||||
console.log(a);
|
||||
}
|
||||
function func(va) {
|
||||
return doSomething(va);
|
||||
}
|
||||
}
|
||||
function doSomething(x) {
|
||||
return [ x, 2 * x, 3 * x ];
|
||||
}
|
||||
const value = 10;
|
||||
foo();
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
for (const a of doSomething(value)) console.log(a);
|
||||
}
|
||||
function doSomething(x) {
|
||||
return [ x, 2 * x, 3 * x ];
|
||||
}
|
||||
const value = 10;
|
||||
foo();
|
||||
}
|
||||
expect_stdout: [
|
||||
"10",
|
||||
"20",
|
||||
"30",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2794_2: {
|
||||
mangle = {
|
||||
toplevel: false,
|
||||
}
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 1,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: false,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
for (const a of func(value)) {
|
||||
console.log(a);
|
||||
}
|
||||
function func(va) {
|
||||
return doSomething(va);
|
||||
}
|
||||
}
|
||||
function doSomething(x) {
|
||||
return [ x, 2 * x, 3 * x ];
|
||||
}
|
||||
const value = 10;
|
||||
foo();
|
||||
}
|
||||
expect: {
|
||||
function foo() {
|
||||
for (const o of doSomething(value)) console.log(o);
|
||||
}
|
||||
function doSomething(o) {
|
||||
return [ o, 2 * o, 3 * o ];
|
||||
}
|
||||
const value = 10;
|
||||
foo();
|
||||
}
|
||||
expect_stdout: [
|
||||
"10",
|
||||
"20",
|
||||
"30",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2794_3: {
|
||||
mangle = {
|
||||
toplevel: true,
|
||||
}
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
evaluate: true,
|
||||
inline: 3,
|
||||
passes: 3,
|
||||
properties: true,
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function foo() {
|
||||
for (const a of func(value)) {
|
||||
console.log(a);
|
||||
}
|
||||
function func(va) {
|
||||
return doSomething(va);
|
||||
}
|
||||
}
|
||||
function doSomething(x) {
|
||||
return [ x, 2 * x, 3 * x ];
|
||||
}
|
||||
const value = 10;
|
||||
foo();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
for (const o of [ 10, 20, 30 ]) console.log(o);
|
||||
})();
|
||||
}
|
||||
expect_stdout: [
|
||||
"10",
|
||||
"20",
|
||||
"30",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2794_4: {
|
||||
options = {}
|
||||
input: {
|
||||
for (var x of ([1, 2], [3, 4])) {
|
||||
console.log(x);
|
||||
}
|
||||
}
|
||||
expect_exact: "for(var x of([1,2],[3,4]))console.log(x);"
|
||||
expect_stdout: [
|
||||
"3",
|
||||
"4",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2794_5: {
|
||||
mangle = {}
|
||||
options = {
|
||||
evaluate: true,
|
||||
passes: 1,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
for (var x of ([1, 2], [3, 4])) {
|
||||
console.log(x);
|
||||
}
|
||||
}
|
||||
expect_exact: "for(var x of[3,4])console.log(x);"
|
||||
expect_stdout: [
|
||||
"3",
|
||||
"4",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2794_6: {
|
||||
options = {
|
||||
}
|
||||
input: {
|
||||
// TODO (or not): have parser flag invalid for-of expression.
|
||||
// Consider it an uglify extension in the meantime.
|
||||
for (let e of [1,2], [3,4,5]) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
expect_exact: "for(let e of([1,2],[3,4,5]))console.log(e);"
|
||||
expect_stdout: [
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -897,3 +897,25 @@ toplevel_var: {
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
undefined_key: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
join_vars: true,
|
||||
passes: 4,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a, o = {};
|
||||
o[a] = 1;
|
||||
o.b = 2;
|
||||
console.log(o[a] + o.b);
|
||||
}
|
||||
expect: {
|
||||
console.log(3);
|
||||
}
|
||||
expect_stdout: "3"
|
||||
}
|
||||
|
||||
@@ -454,3 +454,39 @@ if_if_return_return: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue_2747: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
function f(baz) {
|
||||
if (baz === 0) {
|
||||
return null;
|
||||
}
|
||||
let r;
|
||||
if (baz > 2) {
|
||||
r = 4;
|
||||
} else {
|
||||
r = 5;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
console.log(f(0), f(1), f(3));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
function f(baz) {
|
||||
if (0 === baz) return null;
|
||||
let r;
|
||||
return r = baz > 2 ? 4 : 5, r;
|
||||
}
|
||||
console.log(f(0), f(1), f(3));
|
||||
}
|
||||
expect_stdout: "null 5 4"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ unsafe_undefined: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
unsafe: true
|
||||
unsafe_undefined: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
@@ -30,7 +30,7 @@ keep_fnames: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
unsafe: true
|
||||
unsafe_undefined: true,
|
||||
}
|
||||
mangle = {
|
||||
keep_fnames: true
|
||||
|
||||
@@ -38,6 +38,7 @@ same_variable_in_multiple_for_loop: {
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forOf: {
|
||||
@@ -79,6 +80,7 @@ same_variable_in_multiple_forOf: {
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forIn: {
|
||||
@@ -120,6 +122,7 @@ same_variable_in_multiple_forIn: {
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
different_variable_in_multiple_for_loop: {
|
||||
@@ -162,6 +165,7 @@ different_variable_in_multiple_for_loop: {
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
different_variable_in_multiple_forOf: {
|
||||
@@ -203,6 +207,7 @@ different_variable_in_multiple_forOf: {
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
different_variable_in_multiple_forIn: {
|
||||
@@ -244,6 +249,175 @@ different_variable_in_multiple_forIn: {
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forOf_sequences_let: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: true,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let tmp of test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (let tmp of dd) {
|
||||
console.log(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let o of test) {
|
||||
let e;
|
||||
console.log(o), e = [ "e", "f", "g" ];
|
||||
for (let o of e)
|
||||
console.log(o);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forOf_sequences_const: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: true,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (const tmp of test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (const tmp of dd) {
|
||||
console.log(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (const o of test) {
|
||||
let t;
|
||||
console.log(o), t = [ "e", "f", "g" ];
|
||||
for (const o of t)
|
||||
console.log(o);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forIn_sequences_let: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: false,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let tmp in test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (let tmp in test) {
|
||||
console.log(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (let e in test) {
|
||||
let t;
|
||||
console.log(e), t = [ "e", "f", "g" ];
|
||||
for (let e in test)
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
same_variable_in_multiple_forIn_sequences_const: {
|
||||
options = {
|
||||
hoist_funs: true,
|
||||
dead_code: true,
|
||||
conditionals: true,
|
||||
comparisons: true,
|
||||
evaluate: true,
|
||||
booleans: true,
|
||||
loops: true,
|
||||
unused: false,
|
||||
keep_fargs: true,
|
||||
if_return: true,
|
||||
join_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
collapse_vars: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (const tmp in test) {
|
||||
console.log(tmp);
|
||||
let dd;
|
||||
dd = [ "e", "f", "g" ];
|
||||
for (const tmp in test) {
|
||||
console.log(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
var test = [ "a", "b", "c" ];
|
||||
for (const o in test) {
|
||||
let t;
|
||||
console.log(o), t = [ "e", "f", "g" ];
|
||||
for (const o in test)
|
||||
console.log(o);
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
more_variable_in_multiple_for: {
|
||||
@@ -281,4 +455,5 @@ more_variable_in_multiple_for: {
|
||||
}
|
||||
}
|
||||
expect_stdout: true
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ unsafe_undefined: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
if_return: true,
|
||||
unsafe: true,
|
||||
unsafe_undefined: true,
|
||||
}
|
||||
mangle = {}
|
||||
input: {
|
||||
|
||||
@@ -84,12 +84,12 @@ numeric_literal: {
|
||||
' 0: 0,',
|
||||
' "-0": 1,',
|
||||
' 42: 2,',
|
||||
' "42": 3,',
|
||||
' 42: 3,',
|
||||
' 37: 4,',
|
||||
' o: 5,',
|
||||
' 1e42: 6,',
|
||||
' b: 7,',
|
||||
' "1e+42": 8',
|
||||
' 1e42: 8',
|
||||
'};',
|
||||
'',
|
||||
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
compress_new_function: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
unsafe_Function: true,
|
||||
}
|
||||
input: {
|
||||
new Function("aa, bb", 'return aa;');
|
||||
@@ -15,7 +15,7 @@ compress_new_function: {
|
||||
compress_new_function_with_destruct: {
|
||||
options = {
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
unsafe_Function: true,
|
||||
ecma: 6
|
||||
}
|
||||
beautify = {
|
||||
@@ -38,7 +38,7 @@ compress_new_function_with_destruct_arrows: {
|
||||
arrows: true,
|
||||
unsafe_arrows: true,
|
||||
unsafe: true,
|
||||
unsafe_Func: true,
|
||||
unsafe_Function: true,
|
||||
ecma: 6,
|
||||
}
|
||||
beautify = {
|
||||
|
||||
@@ -536,3 +536,182 @@ dead_code_condition: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2740_1: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
for (; ; ) break;
|
||||
for (a(); ; ) break;
|
||||
for (; b(); ) break;
|
||||
for (c(); d(); ) break;
|
||||
for (; ; e()) break;
|
||||
for (f(); ; g()) break;
|
||||
for (; h(); i()) break;
|
||||
for (j(); k(); l()) break;
|
||||
}
|
||||
expect: {
|
||||
a();
|
||||
b();
|
||||
c();
|
||||
d();
|
||||
f();
|
||||
h();
|
||||
j();
|
||||
k();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2740_2: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
}
|
||||
input: {
|
||||
L1: while (x()) {
|
||||
break L1;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
issue_2740_3: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
L2: for (var y = 0; y < 2; y++) {
|
||||
break L1;
|
||||
}
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect: {
|
||||
L1: for (var x = 0; x < 3; x++)
|
||||
for (var y = 0; y < 2; y++)
|
||||
break L1;
|
||||
console.log(x, y);
|
||||
}
|
||||
expect_stdout: "0 0"
|
||||
}
|
||||
|
||||
issue_2740_4: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
L2: for (var y = 0; y < 2; y++) {
|
||||
break L2;
|
||||
}
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect: {
|
||||
for (var x = 0; x < 3; x++) {
|
||||
var y = 0;
|
||||
y < 2;
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect_stdout: "3 0"
|
||||
}
|
||||
|
||||
issue_2740_5: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
passes: 2,
|
||||
}
|
||||
input: {
|
||||
L1: for (var x = 0; x < 3; x++) {
|
||||
break L1;
|
||||
L2: for (var y = 0; y < 2; y++) {
|
||||
break L2;
|
||||
}
|
||||
}
|
||||
console.log(x, y);
|
||||
}
|
||||
expect: {
|
||||
var x = 0;
|
||||
x < 3;
|
||||
var y;
|
||||
console.log(x,y);
|
||||
}
|
||||
expect_stdout: "0 undefined"
|
||||
}
|
||||
|
||||
issue_2740_6: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
const a = 9, b = 0;
|
||||
for (const a = 1; a < 3; ++b) break;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
const a = 9, b = 0;
|
||||
{
|
||||
const a = 1;
|
||||
a < 3;
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "9 0"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2740_7: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
let a = 9, b = 0;
|
||||
for (const a = 1; a < 3; ++b) break;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
let a = 9, b = 0;
|
||||
{
|
||||
const a = 1;
|
||||
a < 3;
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "9 0"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2740_8: {
|
||||
options = {
|
||||
dead_code: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
var a = 9, b = 0;
|
||||
for (const a = 1; a < 3; ++b) break;
|
||||
console.log(a, b);
|
||||
}
|
||||
expect: {
|
||||
var a = 9, b = 0;
|
||||
{
|
||||
const a = 1;
|
||||
a < 3;
|
||||
}
|
||||
console.log(a, b);
|
||||
}
|
||||
expect_stdout: "9 0"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
@@ -585,6 +585,25 @@ native_prototype: {
|
||||
}
|
||||
}
|
||||
|
||||
native_prototype_lhs: {
|
||||
options = {
|
||||
unsafe_proto: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
Function.prototype.bar = "PASS";
|
||||
return function() {};
|
||||
}().bar);
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
Function.prototype.bar = "PASS";
|
||||
return function() {};
|
||||
}().bar);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
accessor_boolean: {
|
||||
input: {
|
||||
var a = 1;
|
||||
@@ -1377,3 +1396,501 @@ const_prop_assign_pure: {
|
||||
x();
|
||||
}
|
||||
}
|
||||
|
||||
join_object_assignments_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var x = {
|
||||
a: 1,
|
||||
c: (console.log("c"), "C"),
|
||||
};
|
||||
x.b = 2;
|
||||
x[3] = function() {
|
||||
console.log(x);
|
||||
},
|
||||
x["a"] = /foo/,
|
||||
x.bar = x;
|
||||
return x;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var x = {
|
||||
a: 1,
|
||||
c: (console.log("c"), "C"),
|
||||
b: 2,
|
||||
3: function() {
|
||||
console.log(x);
|
||||
},
|
||||
a: /foo/,
|
||||
};
|
||||
x.bar = x;
|
||||
return x;
|
||||
}());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
join_object_assignments_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
hoist_props: true,
|
||||
join_vars: true,
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var o = {
|
||||
foo: 1,
|
||||
};
|
||||
o.bar = 2;
|
||||
o.baz = 3;
|
||||
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
|
||||
}
|
||||
expect: {
|
||||
console.log(1, 4, 6);
|
||||
}
|
||||
expect_stdout: "1 4 6"
|
||||
}
|
||||
|
||||
join_object_assignments_3: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
a: "PASS",
|
||||
}, a = o.a;
|
||||
o.a = "FAIL";
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
a: "PASS",
|
||||
}, a = o.a;
|
||||
o.a = "FAIL";
|
||||
return a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
join_object_assignments_return_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
return o.q = "foo";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3,
|
||||
q: "foo"
|
||||
};
|
||||
return o.q;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "foo"
|
||||
}
|
||||
|
||||
join_object_assignments_return_2: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
return o.q = /foo/,
|
||||
o.r = "bar";
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3,
|
||||
q: /foo/,
|
||||
r: "bar"
|
||||
};
|
||||
return o.r;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "bar"
|
||||
}
|
||||
|
||||
join_object_assignments_return_3: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
return o.q = "foo",
|
||||
o.p += "",
|
||||
console.log(o.q),
|
||||
o.p;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3,
|
||||
q: "foo"
|
||||
};
|
||||
return o.p += "",
|
||||
console.log(o.q),
|
||||
o.p;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"3",
|
||||
]
|
||||
}
|
||||
|
||||
join_object_assignments_for: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {
|
||||
p: 3
|
||||
};
|
||||
for (o.q = "foo"; console.log(o.q););
|
||||
return o.p;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
for (var o = {
|
||||
p: 3,
|
||||
q: "foo"
|
||||
}; console.log(o.q););
|
||||
return o.p;
|
||||
}());
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"3",
|
||||
]
|
||||
}
|
||||
|
||||
join_object_assignments_if: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {};
|
||||
if (o.a = "PASS") return o.a;
|
||||
}())
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = { a: "PASS" };
|
||||
if (o.a) return o.a;
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
join_object_assignments_forin: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var o = {};
|
||||
for (var a in o.a = "PASS", o)
|
||||
return o[a];
|
||||
}())
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
var o = { a: "PASS" };
|
||||
for (var a in o)
|
||||
return o[a];
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
join_object_assignments_negative: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[0] = 0;
|
||||
o[-0] = 1;
|
||||
o[-1] = 2;
|
||||
console.log(o[0], o[-0], o[-1]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
0: 0,
|
||||
0: 1,
|
||||
"-1": 2
|
||||
};
|
||||
console.log(o[0], o[-0], o[-1]);
|
||||
}
|
||||
expect_stdout: "1 1 2"
|
||||
}
|
||||
|
||||
join_object_assignments_NaN_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[NaN] = 1;
|
||||
o[0/0] = 2;
|
||||
console.log(o[NaN], o[NaN]);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o[NaN] = 1;
|
||||
o[0/0] = 2;
|
||||
console.log(o[NaN], o[NaN]);
|
||||
}
|
||||
expect_stdout: "2 2"
|
||||
}
|
||||
|
||||
join_object_assignments_NaN_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[NaN] = 1;
|
||||
o[0/0] = 2;
|
||||
console.log(o[NaN], o[NaN]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
NaN: 1,
|
||||
NaN: 2
|
||||
};
|
||||
console.log(o.NaN, o.NaN);
|
||||
}
|
||||
expect_stdout: "2 2"
|
||||
}
|
||||
|
||||
join_object_assignments_null_0: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[null] = 1;
|
||||
console.log(o[null]);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o[null] = 1;
|
||||
console.log(o[null]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_null_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[null] = 1;
|
||||
console.log(o[null]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
null: 1
|
||||
};
|
||||
console.log(o.null);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_void_0: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[void 0] = 1;
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
undefined: 1
|
||||
};
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_undefined_1: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[undefined] = 1;
|
||||
console.log(o[undefined]);
|
||||
}
|
||||
expect: {
|
||||
var o = {};
|
||||
o[void 0] = 1;
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_undefined_2: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[undefined] = 1;
|
||||
console.log(o[undefined]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
undefined : 1
|
||||
};
|
||||
console.log(o[void 0]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
join_object_assignments_Infinity: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[Infinity] = 1;
|
||||
o[1/0] = 2;
|
||||
o[-Infinity] = 3;
|
||||
o[-1/0] = 4;
|
||||
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
Infinity: 1,
|
||||
Infinity: 2,
|
||||
"-Infinity": 3,
|
||||
"-Infinity": 4
|
||||
};
|
||||
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
|
||||
}
|
||||
expect_stdout: "2 2 4 4"
|
||||
}
|
||||
|
||||
join_object_assignments_regex: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
join_vars: true,
|
||||
properties: true,
|
||||
}
|
||||
input: {
|
||||
var o = {};
|
||||
o[/rx/] = 1;
|
||||
console.log(o[/rx/]);
|
||||
}
|
||||
expect: {
|
||||
var o = {
|
||||
"/rx/": 1
|
||||
};
|
||||
console.log(o[/rx/]);
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
issue_2816: {
|
||||
options = {
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1
|
||||
};
|
||||
o.b = 2;
|
||||
o.a = 3;
|
||||
o.c = 4;
|
||||
console.log(o.a, o.b, o.c);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2
|
||||
};
|
||||
o.a = 3;
|
||||
o.c = 4;
|
||||
console.log(o.a, o.b, o.c);
|
||||
}
|
||||
expect_stdout: "3 2 4"
|
||||
}
|
||||
|
||||
issue_2816_ecma6: {
|
||||
options = {
|
||||
ecma: "6",
|
||||
join_vars: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1
|
||||
};
|
||||
o.b = 2;
|
||||
o.a = 3;
|
||||
o.c = 4;
|
||||
console.log(o.a, o.b, o.c);
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
var o = {
|
||||
a: 1,
|
||||
b: 2,
|
||||
a: 3,
|
||||
c: 4
|
||||
};
|
||||
console.log(o.a, o.b, o.c);
|
||||
}
|
||||
expect_stdout: "3 2 4"
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -818,3 +818,30 @@ issue_2678: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2838: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f(a, b) {
|
||||
(a || b).c = "PASS";
|
||||
(function() {
|
||||
return f(a, b);
|
||||
}).prototype.foo = "bar";
|
||||
}
|
||||
var o = {};
|
||||
f(null, o);
|
||||
console.log(o.c);
|
||||
}
|
||||
expect: {
|
||||
function f(a, b) {
|
||||
(a || b).c = "PASS";
|
||||
}
|
||||
var o = {};
|
||||
f(null, o);
|
||||
console.log(o.c);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -5809,3 +5809,167 @@ duplicate_lambda_defun_name_2: {
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_2757_1: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
let u;
|
||||
(function() {
|
||||
let v;
|
||||
console.log(u, v);
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
let u;
|
||||
console.log(u, void 0);
|
||||
}
|
||||
expect_stdout: "undefined undefined"
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2757_2: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
inline: true,
|
||||
passes: 2,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
let bar;
|
||||
const unused = function() {
|
||||
bar = true;
|
||||
};
|
||||
if (!bar) {
|
||||
console.log(1);
|
||||
}
|
||||
console.log(2);
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(1),
|
||||
console.log(2);
|
||||
}
|
||||
expect_stdout: [
|
||||
"1",
|
||||
"2",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
issue_2774: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log({
|
||||
get a() {
|
||||
var b;
|
||||
(b = true) && b.c;
|
||||
b = void 0;
|
||||
}
|
||||
}.a);
|
||||
}
|
||||
expect: {
|
||||
console.log({
|
||||
get a() {
|
||||
var b;
|
||||
(b = true) && b.c;
|
||||
b = void 0;
|
||||
}
|
||||
}.a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
issue_2799_1: {
|
||||
options = {
|
||||
reduce_funcs: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
return f;
|
||||
function f(n) {
|
||||
function g(i) {
|
||||
return i && i + g(i - 1);
|
||||
}
|
||||
function h(j) {
|
||||
return g(j);
|
||||
}
|
||||
return h(n);
|
||||
}
|
||||
}()(5));
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
return function(n) {
|
||||
return function(j) {
|
||||
return function g(i) {
|
||||
return i && i + g(i - 1);
|
||||
}(j);
|
||||
}(n);
|
||||
}
|
||||
}()(5));
|
||||
}
|
||||
expect_stdout: "15"
|
||||
}
|
||||
|
||||
issue_2799_2: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
unsafe_proto: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
(function() {
|
||||
function foo() {
|
||||
Function.prototype.call.apply(console.log, [ null, "PASS" ]);
|
||||
}
|
||||
foo();
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
(function() {
|
||||
(function() {}).call.apply(console.log, [ null, "PASS" ]);
|
||||
})();
|
||||
})();
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
issue_2836: {
|
||||
options = {
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "FAIL";
|
||||
}
|
||||
console.log(f());
|
||||
function f() {
|
||||
return "PASS";
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
return "PASS";
|
||||
}());
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ unsafe_undefined: {
|
||||
if_return: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
unsafe: true,
|
||||
unsafe_undefined: true,
|
||||
}
|
||||
input: {
|
||||
function f(undefined) {
|
||||
@@ -883,3 +883,21 @@ for_init_var: {
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
forin: {
|
||||
options = {
|
||||
sequences: true,
|
||||
}
|
||||
input: {
|
||||
var o = [];
|
||||
o.push("PASS");
|
||||
for (var a in o)
|
||||
console.log(o[a]);
|
||||
}
|
||||
expect: {
|
||||
var o = [];
|
||||
for (var a in o.push("PASS"), o)
|
||||
console.log(o[a]);
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
@@ -211,3 +211,43 @@ issue_2689: {
|
||||
}
|
||||
expect_exact: "function*y(){return new(yield x())}"
|
||||
}
|
||||
|
||||
issue_2832: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function* gen(i) {
|
||||
const result = yield (x = i, -x);
|
||||
var x;
|
||||
console.log(x);
|
||||
console.log(result);
|
||||
yield 2;
|
||||
}
|
||||
var x = gen(1);
|
||||
console.log(x.next("first").value);
|
||||
console.log(x.next("second").value);
|
||||
}
|
||||
expect_exact: [
|
||||
"function* gen(i) {",
|
||||
" const result = yield (x = i, -x);",
|
||||
" var x;",
|
||||
" console.log(x);",
|
||||
" console.log(result);",
|
||||
" yield 2;",
|
||||
"}",
|
||||
"",
|
||||
"var x = gen(1);",
|
||||
"",
|
||||
'console.log(x.next("first").value);',
|
||||
"",
|
||||
'console.log(x.next("second").value);',
|
||||
]
|
||||
expect_stdout: [
|
||||
"-1",
|
||||
"1",
|
||||
"second",
|
||||
"2",
|
||||
]
|
||||
node_version: ">=4"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
function f() {
|
||||
const a;
|
||||
}
|
||||
|
||||
function g() {
|
||||
"use strict";
|
||||
const a;
|
||||
}
|
||||
|
||||
6
test/input/rename/input.js
Normal file
6
test/input/rename/input.js
Normal file
@@ -0,0 +1,6 @@
|
||||
function f(x) {
|
||||
return g(x);
|
||||
function g(x) {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,24 @@
|
||||
var Mocha = require('mocha'),
|
||||
fs = require('fs'),
|
||||
path = require('path');
|
||||
var fs = require("fs");
|
||||
var Mocha = require("mocha");
|
||||
var path = require("path");
|
||||
|
||||
// Instantiate a Mocha instance.
|
||||
var mocha = new Mocha({});
|
||||
// Instantiate a Mocha instance
|
||||
var mocha = new Mocha({
|
||||
timeout: 5000
|
||||
});
|
||||
var testDir = __dirname + "/mocha/";
|
||||
|
||||
var testDir = __dirname + '/mocha/';
|
||||
|
||||
// Add each .js file to the mocha instance
|
||||
fs.readdirSync(testDir).filter(function(file){
|
||||
// Only keep the .js files
|
||||
return file.substr(-3) === '.js';
|
||||
|
||||
}).forEach(function(file){
|
||||
mocha.addFile(
|
||||
path.join(testDir, file)
|
||||
);
|
||||
// Add each .js file to the Mocha instance
|
||||
fs.readdirSync(testDir).filter(function(file) {
|
||||
return /\.js$/.test(file);
|
||||
}).forEach(function(file) {
|
||||
mocha.addFile(path.join(testDir, file));
|
||||
});
|
||||
|
||||
module.exports = function() {
|
||||
mocha.run(function(failures) {
|
||||
if (failures !== 0) {
|
||||
process.on('exit', function () {
|
||||
process.exit(failures);
|
||||
});
|
||||
}
|
||||
if (failures) process.on("exit", function() {
|
||||
process.exit(failures);
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@@ -408,7 +408,7 @@ describe("bin/uglifyjs", function () {
|
||||
assert.ok(err);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||
"Parse error at test/input/invalid/const.js:7,11",
|
||||
"Parse error at test/input/invalid/const.js:2,11",
|
||||
" const a;",
|
||||
" ^",
|
||||
"ERROR: Missing initializer in const declaration"
|
||||
|
||||
@@ -404,4 +404,19 @@ describe("minify", function() {
|
||||
assert.strictEqual(stat.print_to_string(), "a=x()");
|
||||
});
|
||||
});
|
||||
|
||||
// rename is disabled on harmony due to expand_names bug in for-of loops
|
||||
if (0) describe("rename", function() {
|
||||
it("Should be repeatable", function() {
|
||||
var code = "!function(x){return x(x)}(y);";
|
||||
for (var i = 0; i < 2; i++) {
|
||||
assert.strictEqual(Uglify.minify(code, {
|
||||
compress: {
|
||||
toplevel: true,
|
||||
},
|
||||
rename: true,
|
||||
}).code, "var a;(a=y)(a);");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -208,6 +208,9 @@ function run_compress_tests() {
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (test.reminify && !reminify(test.options, input_code, input_formatted, test.expect_stdout)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -261,6 +264,16 @@ function parse_test(file) {
|
||||
}));
|
||||
}
|
||||
|
||||
function read_boolean(stat) {
|
||||
if (stat.TYPE == "SimpleStatement") {
|
||||
var body = stat.body;
|
||||
if (body instanceof U.AST_Boolean) {
|
||||
return body.value;
|
||||
}
|
||||
}
|
||||
throw new Error("Should be boolean");
|
||||
}
|
||||
|
||||
function read_string(stat) {
|
||||
if (stat.TYPE == "SimpleStatement") {
|
||||
var body = stat.body;
|
||||
@@ -279,7 +292,11 @@ function parse_test(file) {
|
||||
}
|
||||
|
||||
function get_one_test(name, block) {
|
||||
var test = { name: name, options: {} };
|
||||
var test = {
|
||||
name: name,
|
||||
options: {},
|
||||
reminify: true,
|
||||
};
|
||||
var tw = new U.TreeWalker(function(node, descend){
|
||||
if (node instanceof U.AST_Assign) {
|
||||
if (!(node.left instanceof U.AST_SymbolRef)) {
|
||||
@@ -299,6 +316,7 @@ function parse_test(file) {
|
||||
"expect_warnings",
|
||||
"expect_stdout",
|
||||
"node_version",
|
||||
"reminify",
|
||||
].indexOf(label.name) >= 0,
|
||||
tmpl("Unsupported label {name} [{line},{col}]", {
|
||||
name: label.name,
|
||||
@@ -309,6 +327,9 @@ function parse_test(file) {
|
||||
var stat = node.body;
|
||||
if (label.name == "expect_exact" || label.name == "node_version") {
|
||||
test[label.name] = read_string(stat);
|
||||
} else if (label.name == "reminify") {
|
||||
var value = read_boolean(stat);
|
||||
test.reminify = value == null || value;
|
||||
} else if (label.name == "expect_stdout") {
|
||||
var body = stat.body;
|
||||
if (body instanceof U.AST_Boolean) {
|
||||
@@ -358,14 +379,17 @@ function evaluate(code) {
|
||||
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
||||
for (var i = 0; i < minify_options.length; i++) {
|
||||
var options = JSON.parse(minify_options[i]);
|
||||
if (options.compress) [
|
||||
"keep_fargs",
|
||||
"keep_fnames",
|
||||
].forEach(function(name) {
|
||||
if (name in orig_options) {
|
||||
options.compress[name] = orig_options[name];
|
||||
}
|
||||
});
|
||||
options.keep_fnames = orig_options.keep_fnames;
|
||||
options.keep_classnames = orig_options.keep_classnames;
|
||||
if (orig_options.compress) {
|
||||
options.compress.keep_classnames = orig_options.compress.keep_classnames;
|
||||
options.compress.keep_fargs = orig_options.compress.keep_fargs;
|
||||
options.compress.keep_fnames = orig_options.compress.keep_fnames;
|
||||
}
|
||||
if (orig_options.mangle) {
|
||||
options.mangle.keep_classnames = orig_options.mangle.keep_classnames;
|
||||
options.mangle.keep_fnames = orig_options.mangle.keep_fnames;
|
||||
}
|
||||
var options_formatted = JSON.stringify(options, null, 4);
|
||||
var result = U.minify(input_code, options);
|
||||
if (result.error) {
|
||||
|
||||
@@ -17,24 +17,30 @@ function safe_log(arg, level) {
|
||||
return arg;
|
||||
}
|
||||
|
||||
function strip_func_ids(text) {
|
||||
return text.toString().replace(/F[0-9]{6}N/g, "<F<>N>");
|
||||
}
|
||||
|
||||
var FUNC_TOSTRING = [
|
||||
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) {",
|
||||
" f.toString = Function.prototype.toString;",
|
||||
" f.valueOf = Function.prototype.valueOf;",
|
||||
"});",
|
||||
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
||||
" var id = 100000;",
|
||||
" return function() {",
|
||||
' if (this === Array) return "[Function: Array]";',
|
||||
' if (this === Object) return "[Function: Object]";',
|
||||
" var i = this.name;",
|
||||
' if (typeof i != "number") {',
|
||||
" i = ++id;",
|
||||
" var n = this.name;",
|
||||
' if (!/^F[0-9]{6}N$/.test(n)) {',
|
||||
' n = "F" + ++id + "N";',
|
||||
].concat(Object.getOwnPropertyDescriptor(Function.prototype, "name").configurable ? [
|
||||
' Object.defineProperty(this, "name", {',
|
||||
" get: function() {",
|
||||
" return i;",
|
||||
" return n;",
|
||||
" }",
|
||||
" });",
|
||||
] : [], [
|
||||
" }",
|
||||
' return "[Function: " + i + "]";',
|
||||
' return "[Function: " + n + "]";',
|
||||
" }",
|
||||
"}();",
|
||||
'Object.defineProperty(Function.prototype, "valueOf", { enumerable: false });',
|
||||
@@ -77,7 +83,7 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
|
||||
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||
}
|
||||
return expected == actual;
|
||||
return strip_func_ids(expected) == strip_func_ids(actual);
|
||||
} : function(expected, actual) {
|
||||
return typeof expected == typeof actual && expected.toString() == actual.toString();
|
||||
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
||||
};
|
||||
|
||||
82
test/travis-ufuzz.js
Normal file
82
test/travis-ufuzz.js
Normal file
@@ -0,0 +1,82 @@
|
||||
"use strict";
|
||||
|
||||
var child_process = require("child_process");
|
||||
var https = require("https");
|
||||
var url = require("url");
|
||||
|
||||
var period = 45 * 60 * 1000;
|
||||
var wait = 2 * 60 * 1000;
|
||||
var ping = 5 * 60 * 1000;
|
||||
if (process.argv[2] == "run") {
|
||||
var endTime = Date.now() + period;
|
||||
for (var i = 0; i < 2; i++) spawn(endTime);
|
||||
} else if (process.argv.length > 2) {
|
||||
var token = process.argv[2];
|
||||
var branch = process.argv[3] || "v" + require("../package.json").version;
|
||||
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
|
||||
var concurrency = process.argv[5] || 1;
|
||||
(function request() {
|
||||
setTimeout(request, (period + wait) / concurrency);
|
||||
var options = url.parse("https://api.travis-ci.org/repo/" + repository + "/requests");
|
||||
options.method = "POST";
|
||||
options.headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Travis-API-Version": 3,
|
||||
"Authorization": "token " + token
|
||||
};
|
||||
https.request(options, function(res) {
|
||||
console.log("HTTP", res.statusCode);
|
||||
console.log(JSON.stringify(res.headers, null, 2));
|
||||
console.log();
|
||||
res.setEncoding("utf8");
|
||||
res.on("data", console.log);
|
||||
}).on("error", console.error).end(JSON.stringify({
|
||||
request: {
|
||||
message: "ufuzz testing (when idle)",
|
||||
branch: branch,
|
||||
config: {
|
||||
merge_mode: "replace",
|
||||
language: "node_js",
|
||||
node_js: "9",
|
||||
sudo: false,
|
||||
script: "node test/travis-ufuzz run"
|
||||
}
|
||||
}
|
||||
}));
|
||||
})();
|
||||
} else {
|
||||
console.log("Usage: test/travis-ufuzz.js <token> [branch] [repository] [concurrency]");
|
||||
}
|
||||
|
||||
function spawn(endTime) {
|
||||
var child = child_process.spawn("node", [
|
||||
"--max-old-space-size=2048",
|
||||
"test/ufuzz"
|
||||
], {
|
||||
stdio: [ "ignore", "pipe", "pipe" ]
|
||||
}).on("exit", respawn);
|
||||
var line = "";
|
||||
child.stdout.on("data", function(data) {
|
||||
line += data;
|
||||
});
|
||||
child.stderr.on("data", function() {
|
||||
process.exitCode = 1;
|
||||
}).pipe(process.stdout);
|
||||
var keepAlive = setInterval(function() {
|
||||
var end = line.lastIndexOf("\r");
|
||||
console.log(line.slice(line.lastIndexOf("\r", end - 1) + 1, end));
|
||||
line = line.slice(end + 1);
|
||||
}, ping);
|
||||
var timer = setTimeout(function() {
|
||||
clearInterval(keepAlive);
|
||||
child.removeListener("exit", respawn);
|
||||
child.kill();
|
||||
}, endTime - Date.now());
|
||||
|
||||
function respawn() {
|
||||
console.log(line);
|
||||
clearInterval(keepAlive);
|
||||
clearTimeout(timer);
|
||||
spawn(endTime);
|
||||
}
|
||||
}
|
||||
@@ -998,10 +998,11 @@ function log_suspects(minify_options, component) {
|
||||
if (typeof options != "object") options = {};
|
||||
var defs = default_options[component];
|
||||
var suspects = Object.keys(defs).filter(function(name) {
|
||||
if ((name in options ? options : defs)[name]) {
|
||||
var flip = name == "keep_fargs";
|
||||
if (flip ? name in options : (name in options ? options : defs)[name]) {
|
||||
var m = JSON.parse(JSON.stringify(minify_options));
|
||||
var o = JSON.parse(JSON.stringify(options));
|
||||
o[name] = false;
|
||||
o[name] = flip;
|
||||
m[component] = o;
|
||||
var result = UglifyJS.minify(original_code, m);
|
||||
if (result.error) {
|
||||
@@ -1022,6 +1023,24 @@ function log_suspects(minify_options, component) {
|
||||
}
|
||||
}
|
||||
|
||||
function log_rename(options) {
|
||||
if (!options.rename) return;
|
||||
var m = JSON.parse(JSON.stringify(options));
|
||||
m.rename = false;
|
||||
var result = UglifyJS.minify(original_code, m);
|
||||
if (result.error) {
|
||||
errorln("Error testing options.rename");
|
||||
errorln(result.error.stack);
|
||||
} else {
|
||||
var r = sandbox.run_code(result.code);
|
||||
if (sandbox.same_stdout(original_result, r)) {
|
||||
errorln("Suspicious options:");
|
||||
errorln(" rename");
|
||||
errorln();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function log(options) {
|
||||
if (!ok) errorln('\n\n\n\n\n\n!!!!!!!!!!\n\n\n');
|
||||
errorln("//=============================================================");
|
||||
@@ -1056,6 +1075,7 @@ function log(options) {
|
||||
errorln();
|
||||
if (!ok && typeof uglify_code == "string") {
|
||||
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
||||
log_rename(options);
|
||||
errorln("!!!!!! Failed... round " + round);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"output": {
|
||||
"beautify": true,
|
||||
"bracketize": true
|
||||
}
|
||||
},
|
||||
"rename": true
|
||||
},
|
||||
{
|
||||
"compress": false
|
||||
@@ -20,7 +21,13 @@
|
||||
{
|
||||
"compress": {
|
||||
"keep_fargs": false,
|
||||
"passes": 100
|
||||
"passes": 1e6,
|
||||
"sequences": 1e6,
|
||||
"unsafe": true,
|
||||
"unsafe_Function": true,
|
||||
"unsafe_math": true,
|
||||
"unsafe_proto": true,
|
||||
"unsafe_regexp": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user