Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5cb9275df | ||
|
|
17b81350d4 | ||
|
|
4d63d4f5b3 | ||
|
|
70d72ad806 | ||
|
|
fe9227a41b | ||
|
|
b49e142a26 | ||
|
|
ee3b39b909 | ||
|
|
9699ffb1af | ||
|
|
fdc9b9413b | ||
|
|
40ceddb48a | ||
|
|
7aa69117e1 | ||
|
|
bff7ad67bb | ||
|
|
c2334baa48 | ||
|
|
fb2b6c7c6f | ||
|
|
f5cbe19b75 | ||
|
|
b34fa11a13 |
@@ -621,7 +621,7 @@ function uglify(ast, options, mangle) {
|
|||||||
|
|
||||||
// Compression
|
// Compression
|
||||||
uAST.figure_out_scope();
|
uAST.figure_out_scope();
|
||||||
uAST = uAST.transform(UglifyJS.Compressor(options));
|
uAST = UglifyJS.Compressor(options).compress(uAST);
|
||||||
|
|
||||||
// Mangling (optional)
|
// Mangling (optional)
|
||||||
if (mangle) {
|
if (mangle) {
|
||||||
@@ -865,7 +865,7 @@ toplevel.figure_out_scope()
|
|||||||
Like this:
|
Like this:
|
||||||
```javascript
|
```javascript
|
||||||
var compressor = UglifyJS.Compressor(options);
|
var compressor = UglifyJS.Compressor(options);
|
||||||
var compressed_ast = toplevel.transform(compressor);
|
var compressed_ast = compressor.compress(toplevel);
|
||||||
```
|
```
|
||||||
|
|
||||||
The `options` can be missing. Available options are discussed above in
|
The `options` can be missing. Available options are discussed above in
|
||||||
|
|||||||
216
lib/compress.js
216
lib/compress.js
@@ -61,7 +61,7 @@ function Compressor(options, false_by_default) {
|
|||||||
booleans : !false_by_default,
|
booleans : !false_by_default,
|
||||||
loops : !false_by_default,
|
loops : !false_by_default,
|
||||||
unused : !false_by_default,
|
unused : !false_by_default,
|
||||||
toplevel : !!options["top_retain"],
|
toplevel : !!(options && options["top_retain"]),
|
||||||
top_retain : null,
|
top_retain : null,
|
||||||
hoist_funs : !false_by_default,
|
hoist_funs : !false_by_default,
|
||||||
keep_fargs : true,
|
keep_fargs : true,
|
||||||
@@ -70,7 +70,7 @@ function Compressor(options, false_by_default) {
|
|||||||
if_return : !false_by_default,
|
if_return : !false_by_default,
|
||||||
join_vars : !false_by_default,
|
join_vars : !false_by_default,
|
||||||
collapse_vars : !false_by_default,
|
collapse_vars : !false_by_default,
|
||||||
reduce_vars : false,
|
reduce_vars : !false_by_default,
|
||||||
cascade : !false_by_default,
|
cascade : !false_by_default,
|
||||||
side_effects : !false_by_default,
|
side_effects : !false_by_default,
|
||||||
pure_getters : false,
|
pure_getters : false,
|
||||||
@@ -179,38 +179,109 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
|
AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
|
||||||
var reduce_vars = rescan && compressor.option("reduce_vars");
|
var reduce_vars = rescan && compressor.option("reduce_vars");
|
||||||
var unsafe = compressor.option("unsafe");
|
var safe_ids = [];
|
||||||
|
push();
|
||||||
var tw = new TreeWalker(function(node){
|
var tw = new TreeWalker(function(node){
|
||||||
|
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
||||||
|
node._squeezed = false;
|
||||||
|
node._optimized = false;
|
||||||
|
}
|
||||||
if (reduce_vars) {
|
if (reduce_vars) {
|
||||||
if (node instanceof AST_Toplevel) node.globals.each(reset_def);
|
if (node instanceof AST_Toplevel) node.globals.each(reset_def);
|
||||||
if (node instanceof AST_Scope) node.variables.each(reset_def);
|
if (node instanceof AST_Scope) node.variables.each(reset_def);
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
var d = node.definition();
|
var d = node.definition();
|
||||||
d.references.push(node);
|
d.references.push(node);
|
||||||
if (!d.modified && (d.orig.length > 1 || isModified(node, 0))) {
|
if (!d.fixed || isModified(node, 0) || !is_safe(d)) {
|
||||||
d.modified = true;
|
d.fixed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Call && node.expression instanceof AST_Function) {
|
if (node instanceof AST_VarDef) {
|
||||||
node.expression.argnames.forEach(function(arg, i) {
|
var d = node.name.definition();
|
||||||
arg.definition().init = node.args[i] || make_node(AST_Undefined, node);
|
if (d.fixed === undefined) {
|
||||||
|
d.fixed = node.value || make_node(AST_Undefined, node);
|
||||||
|
mark_as_safe(d);
|
||||||
|
} else {
|
||||||
|
d.fixed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var iife;
|
||||||
|
if (node instanceof AST_Function
|
||||||
|
&& (iife = tw.parent()) instanceof AST_Call
|
||||||
|
&& iife.expression === node) {
|
||||||
|
node.argnames.forEach(function(arg, i) {
|
||||||
|
var d = arg.definition();
|
||||||
|
d.fixed = iife.args[i] || make_node(AST_Undefined, iife);
|
||||||
|
mark_as_safe(d);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
if (node instanceof AST_If || node instanceof AST_DWLoop) {
|
||||||
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
node.condition.walk(tw);
|
||||||
node._squeezed = false;
|
push();
|
||||||
node._optimized = false;
|
node.body.walk(tw);
|
||||||
|
pop();
|
||||||
|
if (node.alternative) {
|
||||||
|
push();
|
||||||
|
node.alternative.walk(tw);
|
||||||
|
pop();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_LabeledStatement) {
|
||||||
|
push();
|
||||||
|
node.body.walk(tw);
|
||||||
|
pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_For) {
|
||||||
|
if (node.init) node.init.walk(tw);
|
||||||
|
push();
|
||||||
|
if (node.condition) node.condition.walk(tw);
|
||||||
|
node.body.walk(tw);
|
||||||
|
if (node.step) node.step.walk(tw);
|
||||||
|
pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_ForIn) {
|
||||||
|
var sym = node.init;
|
||||||
|
if (sym instanceof AST_Var) {
|
||||||
|
sym = sym.definitions[0].name;
|
||||||
|
}
|
||||||
|
var d = sym.definition();
|
||||||
|
d.references.push(sym);
|
||||||
|
d.fixed = false;
|
||||||
|
node.object.walk(tw);
|
||||||
|
push();
|
||||||
|
node.body.walk(tw);
|
||||||
|
pop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
|
|
||||||
|
function mark_as_safe(def) {
|
||||||
|
safe_ids[safe_ids.length - 1][def.id] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_safe(def) {
|
||||||
|
for (var i = safe_ids.length, id = def.id; --i >= 0;) {
|
||||||
|
if (safe_ids[i][id]) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function push() {
|
||||||
|
safe_ids.push(Object.create(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
function pop() {
|
||||||
|
safe_ids.pop();
|
||||||
|
}
|
||||||
|
|
||||||
function reset_def(def) {
|
function reset_def(def) {
|
||||||
def.modified = false;
|
def.fixed = undefined;
|
||||||
def.references = [];
|
def.references = [];
|
||||||
def.should_replace = undefined;
|
def.should_replace = undefined;
|
||||||
if (unsafe && def.init) {
|
|
||||||
def.init._evaluated = undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isModified(node, level) {
|
function isModified(node, level) {
|
||||||
@@ -409,8 +480,12 @@ merge(Compressor.prototype, {
|
|||||||
// Constant single use vars can be replaced in any scope.
|
// Constant single use vars can be replaced in any scope.
|
||||||
if (var_decl.value.is_constant()) {
|
if (var_decl.value.is_constant()) {
|
||||||
var ctt = new TreeTransformer(function(node) {
|
var ctt = new TreeTransformer(function(node) {
|
||||||
if (node === ref)
|
if (node === ref) {
|
||||||
return replace_var(node, ctt.parent(), true);
|
var parent = ctt.parent();
|
||||||
|
if (!(parent instanceof AST_ForIn && parent.init === node)) {
|
||||||
|
return replace_var(node, parent, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
stat.transform(ctt);
|
stat.transform(ctt);
|
||||||
continue;
|
continue;
|
||||||
@@ -499,7 +574,7 @@ merge(Compressor.prototype, {
|
|||||||
// Further optimize statement after substitution.
|
// Further optimize statement after substitution.
|
||||||
stat.reset_opt_flags(compressor);
|
stat.reset_opt_flags(compressor);
|
||||||
|
|
||||||
compressor.warn("Replacing " + (is_constant ? "constant" : "variable") +
|
compressor.warn("Collapsing " + (is_constant ? "constant" : "variable") +
|
||||||
" " + var_name + " [{file}:{line},{col}]", node.start);
|
" " + var_name + " [{file}:{line},{col}]", node.start);
|
||||||
CHANGED = true;
|
CHANGED = true;
|
||||||
return value;
|
return value;
|
||||||
@@ -987,12 +1062,6 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Conditional, function(compressor){
|
def(AST_Conditional, function(compressor){
|
||||||
return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
|
return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
|
||||||
});
|
});
|
||||||
def(AST_Call, function(compressor){
|
|
||||||
return compressor.option("unsafe")
|
|
||||||
&& this.expression instanceof AST_SymbolRef
|
|
||||||
&& this.expression.name == "String"
|
|
||||||
&& this.expression.undeclared();
|
|
||||||
});
|
|
||||||
})(function(node, func){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("is_string", func);
|
node.DEFMETHOD("is_string", func);
|
||||||
});
|
});
|
||||||
@@ -1148,11 +1217,14 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Statement, function(){
|
def(AST_Statement, function(){
|
||||||
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
|
||||||
});
|
});
|
||||||
|
// XXX: AST_Accessor and AST_Function both inherit from AST_Scope,
|
||||||
|
// which itself inherits from AST_Statement; however, they aren't
|
||||||
|
// really statements. This could bite in other places too. :-(
|
||||||
|
// Wish JS had multiple inheritance.
|
||||||
|
def(AST_Accessor, function(){
|
||||||
|
throw def;
|
||||||
|
});
|
||||||
def(AST_Function, function(){
|
def(AST_Function, function(){
|
||||||
// XXX: AST_Function inherits from AST_Scope, which itself
|
|
||||||
// inherits from AST_Statement; however, an AST_Function
|
|
||||||
// isn't really a statement. This could byte in other
|
|
||||||
// places too. :-( Wish JS had multiple inheritance.
|
|
||||||
throw def;
|
throw def;
|
||||||
});
|
});
|
||||||
function ev(node, compressor) {
|
function ev(node, compressor) {
|
||||||
@@ -1180,7 +1252,9 @@ merge(Compressor.prototype, {
|
|||||||
for (var i = 0, len = this.properties.length; i < len; i++) {
|
for (var i = 0, len = this.properties.length; i < len; i++) {
|
||||||
var prop = this.properties[i];
|
var prop = this.properties[i];
|
||||||
var key = prop.key;
|
var key = prop.key;
|
||||||
if (key instanceof AST_Node) {
|
if (key instanceof AST_Symbol) {
|
||||||
|
key = key.name;
|
||||||
|
} else if (key instanceof AST_Node) {
|
||||||
key = ev(key, compressor);
|
key = ev(key, compressor);
|
||||||
}
|
}
|
||||||
if (typeof Object.prototype[key] === 'function') {
|
if (typeof Object.prototype[key] === 'function') {
|
||||||
@@ -1258,14 +1332,14 @@ merge(Compressor.prototype, {
|
|||||||
this._evaluating = true;
|
this._evaluating = true;
|
||||||
try {
|
try {
|
||||||
var d = this.definition();
|
var d = this.definition();
|
||||||
if (compressor.option("reduce_vars") && !d.modified && d.init) {
|
if (compressor.option("reduce_vars") && d.fixed) {
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
if (d.init._evaluated === undefined) {
|
if (!HOP(d.fixed, "_evaluated")) {
|
||||||
d.init._evaluated = ev(d.init, compressor);
|
d.fixed._evaluated = ev(d.fixed, compressor);
|
||||||
}
|
}
|
||||||
return d.init._evaluated;
|
return d.fixed._evaluated;
|
||||||
}
|
}
|
||||||
return ev(d.init, compressor);
|
return ev(d.fixed, compressor);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
this._evaluating = false;
|
this._evaluating = false;
|
||||||
@@ -1727,14 +1801,17 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (drop_vars && assign_as_unused
|
if (drop_vars && assign_as_unused) {
|
||||||
&& node instanceof AST_Assign
|
var n = node;
|
||||||
&& node.operator == "="
|
while (n instanceof AST_Assign
|
||||||
&& node.left instanceof AST_SymbolRef) {
|
&& n.operator == "="
|
||||||
var def = node.left.definition();
|
&& n.left instanceof AST_SymbolRef) {
|
||||||
if (!(def.id in in_use_ids) && self.variables.get(def.name) === def) {
|
var def = n.left.definition();
|
||||||
return node.right;
|
if (def.id in in_use_ids
|
||||||
|
|| self.variables.get(def.name) !== def) break;
|
||||||
|
n = n.right;
|
||||||
}
|
}
|
||||||
|
if (n !== node) return n;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_For) {
|
if (node instanceof AST_For) {
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
@@ -2066,7 +2143,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// self instanceof AST_Do
|
// self instanceof AST_Do
|
||||||
return self.body;
|
return self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self instanceof AST_While) {
|
if (self instanceof AST_While) {
|
||||||
@@ -2189,7 +2266,7 @@ merge(Compressor.prototype, {
|
|||||||
// here because they are only used in an equality comparison later on.
|
// here because they are only used in an equality comparison later on.
|
||||||
self.condition = negated;
|
self.condition = negated;
|
||||||
var tmp = self.body;
|
var tmp = self.body;
|
||||||
self.body = self.alternative || make_node(AST_EmptyStatement);
|
self.body = self.alternative || make_node(AST_EmptyStatement, self);
|
||||||
self.alternative = tmp;
|
self.alternative = tmp;
|
||||||
}
|
}
|
||||||
if (is_empty(self.body) && is_empty(self.alternative)) {
|
if (is_empty(self.body) && is_empty(self.alternative)) {
|
||||||
@@ -2415,6 +2492,20 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Call, function(self, compressor){
|
OPT(AST_Call, function(self, compressor){
|
||||||
|
if (compressor.option("unused")
|
||||||
|
&& self.expression instanceof AST_Function
|
||||||
|
&& !self.expression.uses_arguments
|
||||||
|
&& !self.expression.uses_eval
|
||||||
|
&& self.args.length > self.expression.argnames.length) {
|
||||||
|
var end = self.expression.argnames.length;
|
||||||
|
for (var i = end, len = self.args.length; i < len; i++) {
|
||||||
|
var node = self.args[i].drop_side_effect_free(compressor);
|
||||||
|
if (node) {
|
||||||
|
self.args[end++] = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.args.length = end;
|
||||||
|
}
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
var exp = self.expression;
|
var exp = self.expression;
|
||||||
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
|
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
|
||||||
@@ -2454,7 +2545,7 @@ merge(Compressor.prototype, {
|
|||||||
case "Boolean":
|
case "Boolean":
|
||||||
if (self.args.length == 0) return make_node(AST_False, self);
|
if (self.args.length == 0) return make_node(AST_False, self);
|
||||||
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
|
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
|
||||||
expression: make_node(AST_UnaryPrefix, null, {
|
expression: make_node(AST_UnaryPrefix, self, {
|
||||||
expression: self.args[0],
|
expression: self.args[0],
|
||||||
operator: "!"
|
operator: "!"
|
||||||
}),
|
}),
|
||||||
@@ -2610,6 +2701,12 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (self.args.length == 0
|
||||||
|
&& self.expression instanceof AST_Function
|
||||||
|
&& self.expression.body[0] instanceof AST_Return
|
||||||
|
&& self.expression.body[0].value.is_constant()) {
|
||||||
|
return self.expression.body[0].value;
|
||||||
|
}
|
||||||
if (compressor.option("negate_iife")
|
if (compressor.option("negate_iife")
|
||||||
&& compressor.parent() instanceof AST_SimpleStatement
|
&& compressor.parent() instanceof AST_SimpleStatement
|
||||||
&& is_iife_call(self)) {
|
&& is_iife_call(self)) {
|
||||||
@@ -2850,7 +2947,7 @@ merge(Compressor.prototype, {
|
|||||||
compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
|
compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
|
||||||
return make_node(AST_Seq, self, {
|
return make_node(AST_Seq, self, {
|
||||||
car: self.left,
|
car: self.left,
|
||||||
cdr: make_node(AST_False)
|
cdr: make_node(AST_False, self)
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (ll.length > 1 && ll[1]) {
|
if (ll.length > 1 && ll[1]) {
|
||||||
@@ -2913,10 +3010,25 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self.operator == "+" && self.right instanceof AST_String
|
if (self.operator == "+") {
|
||||||
&& self.right.getValue() === "" && self.left instanceof AST_Binary
|
if (self.right instanceof AST_String
|
||||||
&& self.left.operator == "+" && self.left.is_string(compressor)) {
|
&& self.right.getValue() == ""
|
||||||
return self.left;
|
&& self.left.is_string(compressor)) {
|
||||||
|
return self.left;
|
||||||
|
}
|
||||||
|
if (self.left instanceof AST_String
|
||||||
|
&& self.left.getValue() == ""
|
||||||
|
&& self.right.is_string(compressor)) {
|
||||||
|
return self.right;
|
||||||
|
}
|
||||||
|
if (self.left instanceof AST_Binary
|
||||||
|
&& self.left.operator == "+"
|
||||||
|
&& self.left.left instanceof AST_String
|
||||||
|
&& self.left.left.getValue() == ""
|
||||||
|
&& self.right.is_string(compressor)) {
|
||||||
|
self.left = self.left.right;
|
||||||
|
return self.transform(compressor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate")) {
|
if (compressor.option("evaluate")) {
|
||||||
switch (self.operator) {
|
switch (self.operator) {
|
||||||
@@ -3041,9 +3153,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
||||||
var d = self.definition();
|
var d = self.definition();
|
||||||
if (!d.modified && d.init) {
|
if (d.fixed) {
|
||||||
if (d.should_replace === undefined) {
|
if (d.should_replace === undefined) {
|
||||||
var init = d.init.evaluate(compressor);
|
var init = d.fixed.evaluate(compressor);
|
||||||
if (init.length > 1) {
|
if (init.length > 1) {
|
||||||
var value = init[0].print_to_string().length;
|
var value = init[0].print_to_string().length;
|
||||||
var name = d.name.length;
|
var name = d.name.length;
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ function push_uniq(array, el) {
|
|||||||
|
|
||||||
function string_template(text, props) {
|
function string_template(text, props) {
|
||||||
return text.replace(/\{(.+?)\}/g, function(str, p){
|
return text.replace(/\{(.+?)\}/g, function(str, p){
|
||||||
return props[p];
|
return props && props[p];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "2.8.1",
|
"version": "2.8.5",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1141,7 +1141,7 @@ collapse_vars_constants: {
|
|||||||
function f3(x) {
|
function f3(x) {
|
||||||
var b = x.prop;
|
var b = x.prop;
|
||||||
sideeffect1();
|
sideeffect1();
|
||||||
return b + (function() { return -9; })();
|
return b + -9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1315,3 +1315,17 @@ collapse_vars_regexp: {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1537: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var k = '';
|
||||||
|
for (k in {prop: 'val'}){}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var k = '';
|
||||||
|
for (k in {prop: 'val'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -164,3 +164,53 @@ concat_6: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
concat_7: {
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"" + 1,
|
||||||
|
"" + "1",
|
||||||
|
"" + 1 + 2,
|
||||||
|
"" + 1 + "2",
|
||||||
|
"" + "1" + 2,
|
||||||
|
"" + "1" + "2",
|
||||||
|
"" + (x += "foo")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"" + 1,
|
||||||
|
"1",
|
||||||
|
"" + 1 + 2,
|
||||||
|
1 + "2",
|
||||||
|
"1" + 2,
|
||||||
|
"1" + "2",
|
||||||
|
x += "foo"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
concat_8: {
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
1 + "",
|
||||||
|
"1" + "",
|
||||||
|
1 + 2 + "",
|
||||||
|
1 + "2" + "",
|
||||||
|
"1" + 2 + "",
|
||||||
|
"1" + "2" + "",
|
||||||
|
(x += "foo") + ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
1 + "",
|
||||||
|
"1",
|
||||||
|
1 + 2 + "",
|
||||||
|
1 + "2",
|
||||||
|
"1" + 2,
|
||||||
|
"1" + "2",
|
||||||
|
x += "foo"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -679,3 +679,24 @@ const_assign: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1539: {
|
||||||
|
options = {
|
||||||
|
cascade: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a, b;
|
||||||
|
a = b = 42;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -337,6 +337,32 @@ unsafe_object_repeated: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_object_accessor: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a = {
|
||||||
|
get b() {},
|
||||||
|
set b() {}
|
||||||
|
};
|
||||||
|
return {a:a};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var a = {
|
||||||
|
get b() {},
|
||||||
|
set b() {}
|
||||||
|
};
|
||||||
|
return {a:a};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe_function: {
|
unsafe_function: {
|
||||||
options = {
|
options = {
|
||||||
evaluate : true,
|
evaluate : true,
|
||||||
@@ -620,6 +646,29 @@ call_args: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
call_args_drop_param: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
const a = 1;
|
||||||
|
console.log(a);
|
||||||
|
+function(a) {
|
||||||
|
return a;
|
||||||
|
}(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
const a = 1;
|
||||||
|
console.log(1);
|
||||||
|
+function() {
|
||||||
|
return 1;
|
||||||
|
}(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
in_boolean_context: {
|
in_boolean_context: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
|||||||
@@ -6,3 +6,71 @@ non_ascii_function_identifier_name: {
|
|||||||
}
|
}
|
||||||
expect_exact: "function fooλ(δλ){}function λ(δλ){}(function λ(δλ){})();"
|
expect_exact: "function fooλ(δλ){}function λ(δλ){}(function λ(δλ){})();"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iifes_returning_constants_keep_fargs_true: {
|
||||||
|
options = {
|
||||||
|
keep_fargs : true,
|
||||||
|
side_effects : true,
|
||||||
|
evaluate : true,
|
||||||
|
unused : true,
|
||||||
|
dead_code : true,
|
||||||
|
conditionals : true,
|
||||||
|
comparisons : true,
|
||||||
|
booleans : true,
|
||||||
|
if_return : true,
|
||||||
|
join_vars : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
cascade : true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return -1.23; }());
|
||||||
|
console.log( function foo(){ return "okay"; }() );
|
||||||
|
console.log( function foo(x, y, z){ return 123; }() );
|
||||||
|
console.log( function(x, y, z){ return z; }() );
|
||||||
|
console.log( function(x, y, z){ if (x) return y; return z; }(1, 2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3, a(), b()) );
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("okay");
|
||||||
|
console.log(123);
|
||||||
|
console.log(void 0);
|
||||||
|
console.log(function(x,y,z){return 2}(1,2,3));
|
||||||
|
console.log(function(x,y){return 6}(2,3));
|
||||||
|
console.log(function(x, y){return 6}(2,3,a(),b()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iifes_returning_constants_keep_fargs_false: {
|
||||||
|
options = {
|
||||||
|
keep_fargs : false,
|
||||||
|
side_effects : true,
|
||||||
|
evaluate : true,
|
||||||
|
unused : true,
|
||||||
|
dead_code : true,
|
||||||
|
conditionals : true,
|
||||||
|
comparisons : true,
|
||||||
|
booleans : true,
|
||||||
|
if_return : true,
|
||||||
|
join_vars : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
cascade : true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(){ return -1.23; }());
|
||||||
|
console.log( function foo(){ return "okay"; }() );
|
||||||
|
console.log( function foo(x, y, z){ return 123; }() );
|
||||||
|
console.log( function(x, y, z){ return z; }() );
|
||||||
|
console.log( function(x, y, z){ if (x) return y; return z; }(1, 2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3) );
|
||||||
|
console.log( function(x, y){ return x * y; }(2, 3, a(), b()) );
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("okay");
|
||||||
|
console.log(123);
|
||||||
|
console.log(void 0);
|
||||||
|
console.log(2);
|
||||||
|
console.log(6);
|
||||||
|
console.log(function(){return 6}(a(),b()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -213,6 +213,30 @@ evaluate: {
|
|||||||
a();
|
a();
|
||||||
for(;;)
|
for(;;)
|
||||||
c();
|
c();
|
||||||
d();
|
// rule disabled due to issue_1532
|
||||||
|
do d(); while (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1532: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(x, y) {
|
||||||
|
do {
|
||||||
|
if (x) break;
|
||||||
|
foo();
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(x, y) {
|
||||||
|
do {
|
||||||
|
if (x) break;
|
||||||
|
foo();
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,10 @@ negate_iife_3: {
|
|||||||
conditionals: true
|
conditionals: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? console.log(false) : console.log(true);
|
!function(){ return t }() ? console.log(false) : console.log(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +51,10 @@ negate_iife_3_off: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? console.log(false) : console.log(true);
|
!function(){ return t }() ? console.log(false) : console.log(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,13 +65,13 @@ negate_iife_4: {
|
|||||||
sequences: true
|
sequences: true
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
(function(){
|
(function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
!function(){ return t }() ? console.log(false) : console.log(true), function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,7 @@ sequence_off: {
|
|||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
function f() {
|
function f() {
|
||||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
(function(){
|
(function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
})();
|
})();
|
||||||
@@ -95,19 +95,19 @@ sequence_off: {
|
|||||||
(function(){
|
(function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
})();
|
})();
|
||||||
(function(){ return true })() ? console.log(true) : console.log(false);
|
(function(){ return t })() ? console.log(true) : console.log(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f() {
|
function f() {
|
||||||
!function(){ return true }() ? console.log(false) : console.log(true), function(){
|
!function(){ return t }() ? console.log(false) : console.log(true), function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
function g() {
|
function g() {
|
||||||
(function(){
|
(function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
})(), function(){ return true }() ? console.log(true) : console.log(false);
|
})(), function(){ return t }() ? console.log(true) : console.log(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ negate_iife_5: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
if ((function(){ return true })()) {
|
if ((function(){ return t })()) {
|
||||||
foo(true);
|
foo(true);
|
||||||
} else {
|
} else {
|
||||||
bar(false);
|
bar(false);
|
||||||
@@ -129,7 +129,7 @@ negate_iife_5: {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? bar(false) : foo(true), function(){
|
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ negate_iife_5_off: {
|
|||||||
conditionals: true,
|
conditionals: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
if ((function(){ return true })()) {
|
if ((function(){ return t })()) {
|
||||||
foo(true);
|
foo(true);
|
||||||
} else {
|
} else {
|
||||||
bar(false);
|
bar(false);
|
||||||
@@ -152,7 +152,7 @@ negate_iife_5_off: {
|
|||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
!function(){ return true }() ? bar(false) : foo(true), function(){
|
!function(){ return t }() ? bar(false) : foo(true), function(){
|
||||||
console.log("something");
|
console.log("something");
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -470,3 +470,173 @@ multi_def_2: {
|
|||||||
var repeatLength = this.getBits(bitsLength) + bitsOffset;
|
var repeatLength = this.getBits(bitsLength) + bitsOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use_before_var: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(t);
|
||||||
|
var t = 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(t);
|
||||||
|
var t = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_var_if: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (f())
|
||||||
|
var t = 1;
|
||||||
|
if (!t)
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (f())
|
||||||
|
var t = 1;
|
||||||
|
if (!t)
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_var_label: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
l: {
|
||||||
|
if (f()) break l;
|
||||||
|
var t = 1;
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
l: {
|
||||||
|
if (f()) break l;
|
||||||
|
var t = 1;
|
||||||
|
}
|
||||||
|
console.log(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_var_for: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
x(a, b, d);
|
||||||
|
for (var b = 2, c = 3; x(a, b, c, d); x(a, b, c, d)) {
|
||||||
|
var d = 4, e = 5;
|
||||||
|
x(a, b, c, d, e);
|
||||||
|
}
|
||||||
|
x(a, b, c, d, e)
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
x(1, b, d);
|
||||||
|
for (var b = 2, c = 3; x(1, b, 3, d); x(1, b, 3, d)) {
|
||||||
|
var d = 4, e = 5;
|
||||||
|
x(1, b, 3, d, e);
|
||||||
|
}
|
||||||
|
x(1, b, 3, d, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_var_for_in_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
for (b in (function() {
|
||||||
|
return x(a, b, c);
|
||||||
|
})()) {
|
||||||
|
var c = 3, d = 4;
|
||||||
|
x(a, b, c, d);
|
||||||
|
}
|
||||||
|
x(a, b, c, d);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1, b = 2;
|
||||||
|
for (b in (function() {
|
||||||
|
return x(1, b, c);
|
||||||
|
})()) {
|
||||||
|
var c = 3, d = 4;
|
||||||
|
x(1, b, c, d);
|
||||||
|
}
|
||||||
|
x(1, b, c, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_var_for_in_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var long_name in {})
|
||||||
|
console.log(long_name);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var long_name in {})
|
||||||
|
console.log(long_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1533_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var id = "";
|
||||||
|
for (id in {break: "me"})
|
||||||
|
console.log(id);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var id = "";
|
||||||
|
for (id in {break: "me"})
|
||||||
|
console.log(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1533_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var id = "";
|
||||||
|
for (var id in {break: "me"})
|
||||||
|
console.log(id);
|
||||||
|
console.log(id);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var id = "";
|
||||||
|
for (var id in {break: "me"})
|
||||||
|
console.log(id);
|
||||||
|
console.log(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(code, "// comment1 comment2\nbar();");
|
assert.strictEqual(code, "// comment1 comment2\nbar();");
|
||||||
});
|
});
|
||||||
it("should not drop #__PURE__ hint if function is retained", function() {
|
it("should not drop #__PURE__ hint if function is retained", function() {
|
||||||
var result = Uglify.minify("var a = /*#__PURE__*/(function(){return 1})();", {
|
var result = Uglify.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
|
||||||
fromString: true,
|
fromString: true,
|
||||||
output: {
|
output: {
|
||||||
comments: "all",
|
comments: "all",
|
||||||
@@ -163,7 +163,7 @@ describe("minify", function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
var code = result.code;
|
var code = result.code;
|
||||||
assert.strictEqual(code, "var a=/*#__PURE__*/function(){return 1}();");
|
assert.strictEqual(code, "var a=/*#__PURE__*/function(){foo()}();");
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -182,4 +182,13 @@ describe("minify", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Compressor", function() {
|
||||||
|
it("should be backward compatible with ast.transform(compressor)", function() {
|
||||||
|
var ast = Uglify.parse("function f(a){for(var i=0;i<a;i++)console.log(i)}");
|
||||||
|
ast.figure_out_scope();
|
||||||
|
ast = ast.transform(Uglify.Compressor());
|
||||||
|
assert.strictEqual(ast.print_to_string(), "function f(a){for(var i=0;i<a;i++)console.log(i)}");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user