Compare commits
29 Commits
harmony-v2
...
harmony-v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7906033e82 | ||
|
|
4bf21ce5c1 | ||
|
|
44d6b47bdc | ||
|
|
30a75049f5 | ||
|
|
a3cc3a9b87 | ||
|
|
96f8befdd7 | ||
|
|
cd58635dcc | ||
|
|
274331d0ea | ||
|
|
129e449c8e | ||
|
|
75c3c8963f | ||
|
|
0489d6de64 | ||
|
|
fb092839c2 | ||
|
|
d26b7522d9 | ||
|
|
b7c112eefe | ||
|
|
b2b8a0d386 | ||
|
|
ac40301813 | ||
|
|
3563d8c09e | ||
|
|
5ae04b3545 | ||
|
|
a80b228d8b | ||
|
|
cf4bf4ceb1 | ||
|
|
8223b2e0db | ||
|
|
2fd86d3cb0 | ||
|
|
381bd3836e | ||
|
|
8f7ab602e2 | ||
|
|
1dd339f95e | ||
|
|
919d5e3482 | ||
|
|
e3a3db73ae | ||
|
|
d9344f30b8 | ||
|
|
be80f7e706 |
10
README.md
10
README.md
@@ -68,7 +68,8 @@ The available options are:
|
|||||||
--source-map-inline Write base64-encoded source map to the end of js output.
|
--source-map-inline Write base64-encoded source map to the end of js output.
|
||||||
--in-source-map Input source map, useful if you're compressing
|
--in-source-map Input source map, useful if you're compressing
|
||||||
JS that was generated from some other original
|
JS that was generated from some other original
|
||||||
code.
|
code. Specify "inline" if the source map is included
|
||||||
|
inline with the sources.
|
||||||
--screw-ie8 Use this flag if you don't wish to support
|
--screw-ie8 Use this flag if you don't wish to support
|
||||||
Internet Explorer 6/7/8.
|
Internet Explorer 6/7/8.
|
||||||
By default UglifyJS will not try to be IE-proof.
|
By default UglifyJS will not try to be IE-proof.
|
||||||
@@ -200,9 +201,10 @@ compressed JS by mapping every token in the compiled JS to its original
|
|||||||
location.
|
location.
|
||||||
|
|
||||||
To use this feature you need to pass `--in-source-map
|
To use this feature you need to pass `--in-source-map
|
||||||
/path/to/input/source.map`. Normally the input source map should also point
|
/path/to/input/source.map` or `--in-source-map inline` if the source map is
|
||||||
to the file containing the generated JS, so if that's correct you can omit
|
included inline with the sources. Normally the input source map should also
|
||||||
input files from the command line.
|
point to the file containing the generated JS, so if that's correct you can
|
||||||
|
omit input files from the command line.
|
||||||
|
|
||||||
## Mangler options
|
## Mangler options
|
||||||
|
|
||||||
|
|||||||
13
lib/ast.js
13
lib/ast.js
@@ -814,9 +814,6 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
|
|||||||
name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable",
|
name: "[AST_SymbolVar|AST_SymbolConst|AST_Destructuring] name of the variable",
|
||||||
value: "[AST_Node?] initializer, or null of there's no initializer"
|
value: "[AST_Node?] initializer, or null of there's no initializer"
|
||||||
},
|
},
|
||||||
is_destructuring: function() {
|
|
||||||
return this.name instanceof AST_Destructuring;
|
|
||||||
},
|
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
this.name._walk(visitor);
|
this.name._walk(visitor);
|
||||||
@@ -1323,11 +1320,13 @@ TreeWalker.prototype = {
|
|||||||
push: function (node) {
|
push: function (node) {
|
||||||
if (node instanceof AST_Lambda) {
|
if (node instanceof AST_Lambda) {
|
||||||
this.directives = Object.create(this.directives);
|
this.directives = Object.create(this.directives);
|
||||||
} else if (node instanceof AST_Directive) {
|
} else if (node instanceof AST_Directive && !this.directives[node.value]) {
|
||||||
this.directives[node.value] = this.directives[node.value] ? "up" : true;
|
this.directives[node.value] = node;
|
||||||
} else if (node instanceof AST_Class) {
|
} else if (node instanceof AST_Class) {
|
||||||
this.directives = Object.create(this.directives);
|
this.directives = Object.create(this.directives);
|
||||||
this.directives["use strict"] = this.directives["use strict"] ? "up" : true;
|
if (!this.directives["use strict"]) {
|
||||||
|
this.directives["use strict"] = node;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.stack.push(node);
|
this.stack.push(node);
|
||||||
},
|
},
|
||||||
@@ -1355,7 +1354,7 @@ TreeWalker.prototype = {
|
|||||||
for (var i = 0; i < node.body.length; ++i) {
|
for (var i = 0; i < node.body.length; ++i) {
|
||||||
var st = node.body[i];
|
var st = node.body[i];
|
||||||
if (!(st instanceof AST_Directive)) break;
|
if (!(st instanceof AST_Directive)) break;
|
||||||
if (st.value == type) return true;
|
if (st.value == type) return st;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
459
lib/compress.js
459
lib/compress.js
@@ -99,10 +99,10 @@ function Compressor(options, false_by_default) {
|
|||||||
this.top_retain = function(def) {
|
this.top_retain = function(def) {
|
||||||
return top_retain.test(def.name);
|
return top_retain.test(def.name);
|
||||||
};
|
};
|
||||||
} else if (typeof top_retain === "function") {
|
} else if (typeof top_retain == "function") {
|
||||||
this.top_retain = top_retain;
|
this.top_retain = top_retain;
|
||||||
} else if (top_retain) {
|
} else if (top_retain) {
|
||||||
if (typeof top_retain === "string") {
|
if (typeof top_retain == "string") {
|
||||||
top_retain = top_retain.split(/,/);
|
top_retain = top_retain.split(/,/);
|
||||||
}
|
}
|
||||||
this.top_retain = function(def) {
|
this.top_retain = function(def) {
|
||||||
@@ -152,14 +152,25 @@ merge(Compressor.prototype, {
|
|||||||
node = node.hoist_declarations(this);
|
node = node.hoist_declarations(this);
|
||||||
was_scope = true;
|
was_scope = true;
|
||||||
}
|
}
|
||||||
|
// Before https://github.com/mishoo/UglifyJS2/pull/1602 AST_Node.optimize()
|
||||||
|
// would call AST_Node.transform() if a different instance of AST_Node is
|
||||||
|
// produced after OPT().
|
||||||
|
// This corrupts TreeWalker.stack, which cause AST look-ups to malfunction.
|
||||||
|
// Migrate and defer all children's AST_Node.transform() to below, which
|
||||||
|
// will now happen after this parent AST_Node has been properly substituted
|
||||||
|
// thus gives a consistent AST snapshot.
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
node = node.optimize(this);
|
// Existing code relies on how AST_Node.optimize() worked, and omitting the
|
||||||
if (was_scope && node instanceof AST_Scope) {
|
// following replacement call would result in degraded efficiency of both
|
||||||
node.drop_unused(this);
|
// output and performance.
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
|
var opt = node.optimize(this);
|
||||||
|
if (was_scope && opt instanceof AST_Scope) {
|
||||||
|
opt.drop_unused(this);
|
||||||
|
descend(opt, this);
|
||||||
}
|
}
|
||||||
node._squeezed = true;
|
if (opt === node) opt._squeezed = true;
|
||||||
return node;
|
return opt;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -172,8 +183,7 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.has_directive("use asm")) return self;
|
if (compressor.has_directive("use asm")) return self;
|
||||||
var opt = optimizer(self, compressor);
|
var opt = optimizer(self, compressor);
|
||||||
opt._optimized = true;
|
opt._optimized = true;
|
||||||
if (opt === self) return opt;
|
return opt;
|
||||||
return opt.transform(compressor);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -284,6 +294,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
var iife;
|
var iife;
|
||||||
if (node instanceof AST_Function
|
if (node instanceof AST_Function
|
||||||
|
&& !node.name
|
||||||
&& (iife = tw.parent()) instanceof AST_Call
|
&& (iife = tw.parent()) instanceof AST_Call
|
||||||
&& iife.expression === node) {
|
&& iife.expression === node) {
|
||||||
// Virtually turn IIFE parameters into variable definitions:
|
// Virtually turn IIFE parameters into variable definitions:
|
||||||
@@ -388,7 +399,7 @@ merge(Compressor.prototype, {
|
|||||||
return new ctor(props);
|
return new ctor(props);
|
||||||
};
|
};
|
||||||
|
|
||||||
function make_node_from_constant(compressor, val, orig) {
|
function make_node_from_constant(val, orig) {
|
||||||
switch (typeof val) {
|
switch (typeof val) {
|
||||||
case "string":
|
case "string":
|
||||||
return make_node(AST_String, orig, {
|
return make_node(AST_String, orig, {
|
||||||
@@ -408,9 +419,9 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
return make_node(AST_Number, orig, { value: val });
|
return make_node(AST_Number, orig, { value: val });
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return make_node(val ? AST_True : AST_False, orig).transform(compressor);
|
return make_node(val ? AST_True : AST_False, orig);
|
||||||
case "undefined":
|
case "undefined":
|
||||||
return make_node(AST_Undefined, orig).transform(compressor);
|
return make_node(AST_Undefined, orig);
|
||||||
default:
|
default:
|
||||||
if (val === null) {
|
if (val === null) {
|
||||||
return make_node(AST_Null, orig, { value: null });
|
return make_node(AST_Null, orig, { value: null });
|
||||||
@@ -523,6 +534,7 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
var self = compressor.self();
|
var self = compressor.self();
|
||||||
var var_defs_removed = false;
|
var var_defs_removed = false;
|
||||||
|
var toplevel = compressor.option("toplevel");
|
||||||
for (var stat_index = statements.length; --stat_index >= 0;) {
|
for (var stat_index = statements.length; --stat_index >= 0;) {
|
||||||
var stat = statements[stat_index];
|
var stat = statements[stat_index];
|
||||||
if (stat instanceof AST_Definitions) continue;
|
if (stat instanceof AST_Definitions) continue;
|
||||||
@@ -560,7 +572,8 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
// Only interested in cases with just one reference to the variable.
|
// Only interested in cases with just one reference to the variable.
|
||||||
var def = self.find_variable && self.find_variable(var_name);
|
var def = self.find_variable && self.find_variable(var_name);
|
||||||
if (!def || !def.references || def.references.length !== 1 || var_name == "arguments") {
|
if (!def || !def.references || def.references.length !== 1
|
||||||
|
|| var_name == "arguments" || (!toplevel && def.global)) {
|
||||||
side_effects_encountered = true;
|
side_effects_encountered = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -936,7 +949,7 @@ merge(Compressor.prototype, {
|
|||||||
if (stat instanceof AST_LoopControl) {
|
if (stat instanceof AST_LoopControl) {
|
||||||
var lct = compressor.loopcontrol_target(stat.label);
|
var lct = compressor.loopcontrol_target(stat.label);
|
||||||
if ((stat instanceof AST_Break
|
if ((stat instanceof AST_Break
|
||||||
&& lct instanceof AST_BlockStatement
|
&& !(lct instanceof AST_IterationStatement)
|
||||||
&& loop_body(lct) === self) || (stat instanceof AST_Continue
|
&& loop_body(lct) === self) || (stat instanceof AST_Continue
|
||||||
&& loop_body(lct) === self)) {
|
&& loop_body(lct) === self)) {
|
||||||
if (stat.label) {
|
if (stat.label) {
|
||||||
@@ -1223,11 +1236,11 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
function to_node(compressor, value, orig) {
|
function to_node(value, orig) {
|
||||||
if (value instanceof AST_Node) return make_node(value.CTOR, orig, value);
|
if (value instanceof AST_Node) return make_node(value.CTOR, orig, value);
|
||||||
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
if (Array.isArray(value)) return make_node(AST_Array, orig, {
|
||||||
elements: value.map(function(value) {
|
elements: value.map(function(value) {
|
||||||
return to_node(compressor, value, orig);
|
return to_node(value, orig);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
if (value && typeof value == "object") {
|
if (value && typeof value == "object") {
|
||||||
@@ -1235,14 +1248,14 @@ merge(Compressor.prototype, {
|
|||||||
for (var key in value) {
|
for (var key in value) {
|
||||||
props.push(make_node(AST_ObjectKeyVal, orig, {
|
props.push(make_node(AST_ObjectKeyVal, orig, {
|
||||||
key: key,
|
key: key,
|
||||||
value: to_node(compressor, value[key], orig)
|
value: to_node(value[key], orig)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
return make_node(AST_Object, orig, {
|
return make_node(AST_Object, orig, {
|
||||||
properties: props
|
properties: props
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return make_node_from_constant(compressor, value, orig);
|
return make_node_from_constant(value, orig);
|
||||||
}
|
}
|
||||||
def(AST_Node, noop);
|
def(AST_Node, noop);
|
||||||
def(AST_Dot, function(compressor, suffix){
|
def(AST_Dot, function(compressor, suffix){
|
||||||
@@ -1253,7 +1266,7 @@ merge(Compressor.prototype, {
|
|||||||
var name;
|
var name;
|
||||||
var defines = compressor.option("global_defs");
|
var defines = compressor.option("global_defs");
|
||||||
if (defines && HOP(defines, (name = this.name + suffix))) {
|
if (defines && HOP(defines, (name = this.name + suffix))) {
|
||||||
var node = to_node(compressor, defines[name], this);
|
var node = to_node(defines[name], this);
|
||||||
var top = compressor.find_parent(AST_Toplevel);
|
var top = compressor.find_parent(AST_Toplevel);
|
||||||
node.walk(new TreeWalker(function(node) {
|
node.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
@@ -1268,45 +1281,40 @@ merge(Compressor.prototype, {
|
|||||||
node.DEFMETHOD("_find_defs", func);
|
node.DEFMETHOD("_find_defs", func);
|
||||||
});
|
});
|
||||||
|
|
||||||
function best_of(ast1, ast2) {
|
function best_of_expression(ast1, ast2) {
|
||||||
return ast1.print_to_string().length >
|
return ast1.print_to_string().length >
|
||||||
ast2.print_to_string().length
|
ast2.print_to_string().length
|
||||||
? ast2 : ast1;
|
? ast2 : ast1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function best_of_statement(ast1, ast2) {
|
function best_of_statement(ast1, ast2) {
|
||||||
return best_of(make_node(AST_SimpleStatement, ast1, {
|
return best_of_expression(make_node(AST_SimpleStatement, ast1, {
|
||||||
body: ast1
|
body: ast1
|
||||||
}), make_node(AST_SimpleStatement, ast2, {
|
}), make_node(AST_SimpleStatement, ast2, {
|
||||||
body: ast2
|
body: ast2
|
||||||
})).body;
|
})).body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function best_of(compressor, ast1, ast2) {
|
||||||
|
return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2);
|
||||||
|
}
|
||||||
|
|
||||||
// methods to evaluate a constant expression
|
// methods to evaluate a constant expression
|
||||||
(function (def){
|
(function (def){
|
||||||
// The evaluate method returns an array with one or two
|
// If the node has been successfully reduced to a constant,
|
||||||
// elements. If the node has been successfully reduced to a
|
// then its value is returned; otherwise the element itself
|
||||||
// constant, then the second element tells us the value;
|
// is returned.
|
||||||
// otherwise the second element is missing. The first element
|
// They can be distinguished as constant value is never a
|
||||||
// of the array is always an AST_Node descendant; if
|
// descendant of AST_Node.
|
||||||
// evaluation was successful it's a node that represents the
|
|
||||||
// constant; otherwise it's the original or a replacement node.
|
|
||||||
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
||||||
if (!compressor.option("evaluate")) return [ this ];
|
if (!compressor.option("evaluate")) return this;
|
||||||
var val;
|
|
||||||
try {
|
try {
|
||||||
val = this._eval(compressor);
|
var val = this._eval(compressor);
|
||||||
|
return !val || val instanceof RegExp || typeof val != "object" ? val : this;
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex !== def) throw ex;
|
if (ex !== def) throw ex;
|
||||||
return [ this ];
|
return this;
|
||||||
}
|
}
|
||||||
var node;
|
|
||||||
try {
|
|
||||||
node = make_node_from_constant(compressor, val, this);
|
|
||||||
} catch(ex) {
|
|
||||||
return [ this ];
|
|
||||||
}
|
|
||||||
return [ best_of(node, this), val ];
|
|
||||||
});
|
});
|
||||||
var unaryPrefix = makePredicate("! ~ - +");
|
var unaryPrefix = makePredicate("! ~ - +");
|
||||||
AST_Node.DEFMETHOD("is_constant", function(){
|
AST_Node.DEFMETHOD("is_constant", function(){
|
||||||
@@ -1344,8 +1352,8 @@ merge(Compressor.prototype, {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
var result = this.evaluate(compressor);
|
var result = this.evaluate(compressor);
|
||||||
if (result.length > 1) {
|
if (result !== this) {
|
||||||
return result[1];
|
return result;
|
||||||
}
|
}
|
||||||
throw new Error(string_template("Cannot evaluate constant [{file}:{line},{col}]", this.start));
|
throw new Error(string_template("Cannot evaluate constant [{file}:{line},{col}]", this.start));
|
||||||
});
|
});
|
||||||
@@ -1517,9 +1525,9 @@ merge(Compressor.prototype, {
|
|||||||
var stat = make_node(AST_SimpleStatement, alt, {
|
var stat = make_node(AST_SimpleStatement, alt, {
|
||||||
body: alt
|
body: alt
|
||||||
});
|
});
|
||||||
return best_of(negated, stat) === stat ? alt : negated;
|
return best_of_expression(negated, stat) === stat ? alt : negated;
|
||||||
}
|
}
|
||||||
return best_of(negated, alt);
|
return best_of_expression(negated, alt);
|
||||||
}
|
}
|
||||||
def(AST_Node, function(){
|
def(AST_Node, function(){
|
||||||
return basic_negation(this);
|
return basic_negation(this);
|
||||||
@@ -1686,8 +1694,8 @@ merge(Compressor.prototype, {
|
|||||||
return thing && thing.aborts();
|
return thing && thing.aborts();
|
||||||
};
|
};
|
||||||
(function(def){
|
(function(def){
|
||||||
def(AST_Statement, function(){ return null });
|
def(AST_Statement, return_null);
|
||||||
def(AST_Jump, function(){ return this });
|
def(AST_Jump, return_this);
|
||||||
function block_aborts(){
|
function block_aborts(){
|
||||||
var n = this.body.length;
|
var n = this.body.length;
|
||||||
return n > 0 && aborts(this.body[n - 1]);
|
return n > 0 && aborts(this.body[n - 1]);
|
||||||
@@ -1705,7 +1713,7 @@ merge(Compressor.prototype, {
|
|||||||
/* -----[ optimizers ]----- */
|
/* -----[ optimizers ]----- */
|
||||||
|
|
||||||
OPT(AST_Directive, function(self, compressor){
|
OPT(AST_Directive, function(self, compressor){
|
||||||
if (compressor.has_directive(self.value) === "up") {
|
if (compressor.has_directive(self.value) !== self) {
|
||||||
return make_node(AST_EmptyStatement, self);
|
return make_node(AST_EmptyStatement, self);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -1789,14 +1797,18 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_Definitions && scope === self) {
|
if (node instanceof AST_Definitions && scope === self) {
|
||||||
node.definitions.forEach(function(def){
|
node.definitions.forEach(function(def){
|
||||||
if (!drop_vars) {
|
if (!drop_vars) {
|
||||||
var node_def = def.name.definition();
|
def.name.walk(new TreeWalker(function(node) {
|
||||||
if (node_def.global && !(node_def.id in in_use_ids)) {
|
if (node instanceof AST_SymbolDeclaration) {
|
||||||
in_use_ids[node_def.id] = true;
|
var def = node.definition();
|
||||||
in_use.push(node_def);
|
if (def.global && !(def.id in in_use_ids)) {
|
||||||
|
in_use_ids[def.id] = true;
|
||||||
|
in_use.push(def);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
if (def.value) {
|
if (def.value) {
|
||||||
if (def.is_destructuring()) {
|
if (def.name instanceof AST_Destructuring) {
|
||||||
var destructuring_cache = destructuring_value;
|
var destructuring_cache = destructuring_value;
|
||||||
destructuring_value = def.value;
|
destructuring_value = def.value;
|
||||||
in_definition = true;
|
in_definition = true;
|
||||||
@@ -1907,7 +1919,10 @@ merge(Compressor.prototype, {
|
|||||||
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
for (var a = node.argnames, i = a.length; --i >= 0;) {
|
||||||
var sym = a[i];
|
var sym = a[i];
|
||||||
if (sym instanceof AST_Expansion) {
|
if (sym instanceof AST_Expansion) {
|
||||||
sym = sym.symbol;
|
sym = sym.expression;
|
||||||
|
}
|
||||||
|
if (sym instanceof AST_DefaultAssign) {
|
||||||
|
sym = sym.left;
|
||||||
}
|
}
|
||||||
// Do not drop destructuring arguments.
|
// Do not drop destructuring arguments.
|
||||||
// They constitute a type assertion, so dropping
|
// They constitute a type assertion, so dropping
|
||||||
@@ -1947,7 +1962,7 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
|
if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
|
||||||
var def = node.definitions.filter(function(def){
|
var def = node.definitions.filter(function(def){
|
||||||
if (def.value) def.value = def.value.transform(tt);
|
if (def.value) def.value = def.value.transform(tt);
|
||||||
if (def.is_destructuring()) return true;
|
if (def.name instanceof AST_Destructuring) return true;
|
||||||
if (def.name.definition().id in in_use_ids) return true;
|
if (def.name.definition().id in in_use_ids) return true;
|
||||||
if (!drop_vars && def.name.definition().global) return true;
|
if (!drop_vars && def.name.definition().global) return true;
|
||||||
|
|
||||||
@@ -2090,11 +2105,11 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_Var && hoist_vars) {
|
if (node instanceof AST_Var && hoist_vars) {
|
||||||
node.definitions.forEach(function(def){
|
node.definitions.forEach(function(def){
|
||||||
if (def.is_destructuring()) { return; }
|
if (def.name instanceof AST_Destructuring) return;
|
||||||
vars.set(def.name.name, def);
|
vars.set(def.name.name, def);
|
||||||
++vars_found;
|
++vars_found;
|
||||||
});
|
});
|
||||||
var seq = node.to_assignments();
|
var seq = node.to_assignments(compressor);
|
||||||
var p = tt.parent();
|
var p = tt.parent();
|
||||||
if (p instanceof AST_ForIn && p.init === node) {
|
if (p instanceof AST_ForIn && p.init === node) {
|
||||||
if (seq == null) {
|
if (seq == null) {
|
||||||
@@ -2190,14 +2205,6 @@ merge(Compressor.prototype, {
|
|||||||
// drop_side_effect_free()
|
// drop_side_effect_free()
|
||||||
// remove side-effect-free parts which only affects return value
|
// remove side-effect-free parts which only affects return value
|
||||||
(function(def){
|
(function(def){
|
||||||
function return_this() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
function return_null() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop side-effect-free elements from an array of expressions.
|
// Drop side-effect-free elements from an array of expressions.
|
||||||
// Returns an array of expressions with side-effects or null
|
// Returns an array of expressions with side-effects or null
|
||||||
// if all elements were dropped. Note: original array may be
|
// if all elements were dropped. Note: original array may be
|
||||||
@@ -2354,27 +2361,24 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_DWLoop, function(self, compressor){
|
OPT(AST_DWLoop, function(self, compressor){
|
||||||
var cond = self.condition.evaluate(compressor);
|
|
||||||
self.condition = cond[0];
|
|
||||||
if (!compressor.option("loops")) return self;
|
if (!compressor.option("loops")) return self;
|
||||||
if (cond.length > 1) {
|
var cond = self.condition.evaluate(compressor);
|
||||||
if (cond[1]) {
|
if (cond !== self.condition) {
|
||||||
|
if (cond) {
|
||||||
return make_node(AST_For, self, {
|
return make_node(AST_For, self, {
|
||||||
body: self.body
|
body: self.body
|
||||||
});
|
});
|
||||||
} else if (self instanceof AST_While) {
|
} else if (compressor.option("dead_code") && self instanceof AST_While) {
|
||||||
if (compressor.option("dead_code")) {
|
|
||||||
var a = [];
|
var a = [];
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
||||||
return make_node(AST_BlockStatement, self, { body: a });
|
return make_node(AST_BlockStatement, self, { body: a });
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// self instanceof AST_Do
|
cond = make_node_from_constant(cond, self.condition).transform(compressor);
|
||||||
return self;
|
self.condition = best_of_expression(cond, self.condition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self instanceof AST_While) {
|
if (self instanceof AST_While) {
|
||||||
return make_node(AST_For, self, self).transform(compressor);
|
return make_node(AST_For, self, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
@@ -2396,7 +2400,7 @@ merge(Compressor.prototype, {
|
|||||||
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
|
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
|
||||||
if (first instanceof AST_If) {
|
if (first instanceof AST_If) {
|
||||||
if (first.body instanceof AST_Break
|
if (first.body instanceof AST_Break
|
||||||
&& compressor.loopcontrol_target(first.body.label) === self) {
|
&& compressor.loopcontrol_target(first.body.label) === compressor.self()) {
|
||||||
if (self.condition) {
|
if (self.condition) {
|
||||||
self.condition = make_node(AST_Binary, self.condition, {
|
self.condition = make_node(AST_Binary, self.condition, {
|
||||||
left: self.condition,
|
left: self.condition,
|
||||||
@@ -2409,7 +2413,7 @@ merge(Compressor.prototype, {
|
|||||||
drop_it(first.alternative);
|
drop_it(first.alternative);
|
||||||
}
|
}
|
||||||
else if (first.alternative instanceof AST_Break
|
else if (first.alternative instanceof AST_Break
|
||||||
&& compressor.loopcontrol_target(first.alternative.label) === self) {
|
&& compressor.loopcontrol_target(first.alternative.label) === compressor.self()) {
|
||||||
if (self.condition) {
|
if (self.condition) {
|
||||||
self.condition = make_node(AST_Binary, self.condition, {
|
self.condition = make_node(AST_Binary, self.condition, {
|
||||||
left: self.condition,
|
left: self.condition,
|
||||||
@@ -2425,15 +2429,10 @@ merge(Compressor.prototype, {
|
|||||||
};
|
};
|
||||||
|
|
||||||
OPT(AST_For, function(self, compressor){
|
OPT(AST_For, function(self, compressor){
|
||||||
var cond = self.condition;
|
|
||||||
if (cond) {
|
|
||||||
cond = cond.evaluate(compressor);
|
|
||||||
self.condition = cond[0];
|
|
||||||
}
|
|
||||||
if (!compressor.option("loops")) return self;
|
if (!compressor.option("loops")) return self;
|
||||||
if (cond) {
|
if (self.condition) {
|
||||||
if (cond.length > 1 && !cond[1]) {
|
var cond = self.condition.evaluate(compressor);
|
||||||
if (compressor.option("dead_code")) {
|
if (compressor.option("dead_code") && !cond) {
|
||||||
var a = [];
|
var a = [];
|
||||||
if (self.init instanceof AST_Statement) {
|
if (self.init instanceof AST_Statement) {
|
||||||
a.push(self.init);
|
a.push(self.init);
|
||||||
@@ -2446,6 +2445,9 @@ merge(Compressor.prototype, {
|
|||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
||||||
return make_node(AST_BlockStatement, self, { body: a });
|
return make_node(AST_BlockStatement, self, { body: a });
|
||||||
}
|
}
|
||||||
|
if (cond !== self.condition) {
|
||||||
|
cond = make_node_from_constant(cond, self.condition).transform(compressor);
|
||||||
|
self.condition = best_of_expression(cond, self.condition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if_break_in_loop(self, compressor);
|
if_break_in_loop(self, compressor);
|
||||||
@@ -2461,9 +2463,8 @@ merge(Compressor.prototype, {
|
|||||||
// “has no side effects”; also it doesn't work for cases like
|
// “has no side effects”; also it doesn't work for cases like
|
||||||
// `x && true`, though it probably should.
|
// `x && true`, though it probably should.
|
||||||
var cond = self.condition.evaluate(compressor);
|
var cond = self.condition.evaluate(compressor);
|
||||||
self.condition = cond[0];
|
if (cond !== self.condition) {
|
||||||
if (cond.length > 1) {
|
if (cond) {
|
||||||
if (cond[1]) {
|
|
||||||
compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
|
compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
|
||||||
if (compressor.option("dead_code")) {
|
if (compressor.option("dead_code")) {
|
||||||
var a = [];
|
var a = [];
|
||||||
@@ -2471,7 +2472,7 @@ merge(Compressor.prototype, {
|
|||||||
extract_declarations_from_unreachable_code(compressor, self.alternative, a);
|
extract_declarations_from_unreachable_code(compressor, self.alternative, a);
|
||||||
}
|
}
|
||||||
a.push(self.body);
|
a.push(self.body);
|
||||||
return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
|
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
|
compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
|
||||||
@@ -2479,9 +2480,11 @@ merge(Compressor.prototype, {
|
|||||||
var a = [];
|
var a = [];
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
extract_declarations_from_unreachable_code(compressor, self.body, a);
|
||||||
if (self.alternative) a.push(self.alternative);
|
if (self.alternative) a.push(self.alternative);
|
||||||
return make_node(AST_BlockStatement, self, { body: a }).transform(compressor);
|
return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cond = make_node_from_constant(cond, self.condition).transform(compressor);
|
||||||
|
self.condition = best_of_expression(cond, self.condition);
|
||||||
}
|
}
|
||||||
var negated = self.condition.negate(compressor);
|
var negated = self.condition.negate(compressor);
|
||||||
var self_condition_length = self.condition.print_to_string().length;
|
var self_condition_length = self.condition.print_to_string().length;
|
||||||
@@ -2498,8 +2501,8 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (is_empty(self.body) && is_empty(self.alternative)) {
|
if (is_empty(self.body) && is_empty(self.alternative)) {
|
||||||
return make_node(AST_SimpleStatement, self.condition, {
|
return make_node(AST_SimpleStatement, self.condition, {
|
||||||
body: self.condition
|
body: self.condition.clone()
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_SimpleStatement
|
if (self.body instanceof AST_SimpleStatement
|
||||||
&& self.alternative instanceof AST_SimpleStatement) {
|
&& self.alternative instanceof AST_SimpleStatement) {
|
||||||
@@ -2509,7 +2512,7 @@ merge(Compressor.prototype, {
|
|||||||
consequent : statement_to_expression(self.body),
|
consequent : statement_to_expression(self.body),
|
||||||
alternative : statement_to_expression(self.alternative)
|
alternative : statement_to_expression(self.alternative)
|
||||||
})
|
})
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
|
if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
|
||||||
if (self_condition_length === negated_length && !negated_is_best
|
if (self_condition_length === negated_length && !negated_is_best
|
||||||
@@ -2525,14 +2528,14 @@ merge(Compressor.prototype, {
|
|||||||
left : negated,
|
left : negated,
|
||||||
right : statement_to_expression(self.body)
|
right : statement_to_expression(self.body)
|
||||||
})
|
})
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
return make_node(AST_SimpleStatement, self, {
|
return make_node(AST_SimpleStatement, self, {
|
||||||
body: make_node(AST_Binary, self, {
|
body: make_node(AST_Binary, self, {
|
||||||
operator : "&&",
|
operator : "&&",
|
||||||
left : self.condition,
|
left : self.condition,
|
||||||
right : statement_to_expression(self.body)
|
right : statement_to_expression(self.body)
|
||||||
})
|
})
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_EmptyStatement
|
if (self.body instanceof AST_EmptyStatement
|
||||||
&& self.alternative
|
&& self.alternative
|
||||||
@@ -2543,7 +2546,7 @@ merge(Compressor.prototype, {
|
|||||||
left : self.condition,
|
left : self.condition,
|
||||||
right : statement_to_expression(self.alternative)
|
right : statement_to_expression(self.alternative)
|
||||||
})
|
})
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_Exit
|
if (self.body instanceof AST_Exit
|
||||||
&& self.alternative instanceof AST_Exit
|
&& self.alternative instanceof AST_Exit
|
||||||
@@ -2553,18 +2556,21 @@ merge(Compressor.prototype, {
|
|||||||
condition : self.condition,
|
condition : self.condition,
|
||||||
consequent : self.body.value || make_node(AST_Undefined, self.body),
|
consequent : self.body.value || make_node(AST_Undefined, self.body),
|
||||||
alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
|
alternative : self.alternative.value || make_node(AST_Undefined, self.alternative)
|
||||||
})
|
}).transform(compressor)
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (self.body instanceof AST_If
|
if (self.body instanceof AST_If
|
||||||
&& !self.body.alternative
|
&& !self.body.alternative
|
||||||
&& !self.alternative) {
|
&& !self.alternative) {
|
||||||
self.condition = make_node(AST_Binary, self.condition, {
|
self = make_node(AST_If, self, {
|
||||||
|
condition: make_node(AST_Binary, self.condition, {
|
||||||
operator: "&&",
|
operator: "&&",
|
||||||
left: self.condition,
|
left: self.condition,
|
||||||
right: self.body.condition
|
right: self.body.condition
|
||||||
}).transform(compressor);
|
}),
|
||||||
self.body = self.body.body;
|
body: self.body.body,
|
||||||
|
alternative: null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (aborts(self.body)) {
|
if (aborts(self.body)) {
|
||||||
if (self.alternative) {
|
if (self.alternative) {
|
||||||
@@ -2572,7 +2578,7 @@ merge(Compressor.prototype, {
|
|||||||
self.alternative = null;
|
self.alternative = null;
|
||||||
return make_node(AST_BlockStatement, self, {
|
return make_node(AST_BlockStatement, self, {
|
||||||
body: [ self, alt ]
|
body: [ self, alt ]
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aborts(self.alternative)) {
|
if (aborts(self.alternative)) {
|
||||||
@@ -2582,7 +2588,7 @@ merge(Compressor.prototype, {
|
|||||||
self.alternative = null;
|
self.alternative = null;
|
||||||
return make_node(AST_BlockStatement, self, {
|
return make_node(AST_BlockStatement, self, {
|
||||||
body: [ self, body ]
|
body: [ self, body ]
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
@@ -2606,12 +2612,12 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var exp = self.expression.evaluate(compressor);
|
var value = self.expression.evaluate(compressor);
|
||||||
out: if (exp.length == 2) try {
|
out: if (value !== self.expression) try {
|
||||||
// constant expression
|
// constant expression
|
||||||
self.expression = exp[0];
|
var expression = make_node_from_constant(value, self.expression);
|
||||||
|
self.expression = best_of_expression(expression, self.expression);
|
||||||
if (!compressor.option("dead_code")) break out;
|
if (!compressor.option("dead_code")) break out;
|
||||||
var value = exp[1];
|
|
||||||
var in_if = false;
|
var in_if = false;
|
||||||
var in_block = false;
|
var in_block = false;
|
||||||
var started = false;
|
var started = false;
|
||||||
@@ -2658,11 +2664,11 @@ merge(Compressor.prototype, {
|
|||||||
if (stopped) return MAP.skip;
|
if (stopped) return MAP.skip;
|
||||||
if (node instanceof AST_Case) {
|
if (node instanceof AST_Case) {
|
||||||
var exp = node.expression.evaluate(compressor);
|
var exp = node.expression.evaluate(compressor);
|
||||||
if (exp.length < 2) {
|
if (exp === node.expression) {
|
||||||
// got a case with non-constant expression, baling out
|
// got a case with non-constant expression, baling out
|
||||||
throw self;
|
throw self;
|
||||||
}
|
}
|
||||||
if (exp[1] === value || started) {
|
if (exp === value || started) {
|
||||||
started = true;
|
started = true;
|
||||||
if (aborts(node)) stopped = true;
|
if (aborts(node)) stopped = true;
|
||||||
descend(node, this);
|
descend(node, this);
|
||||||
@@ -2696,15 +2702,17 @@ merge(Compressor.prototype, {
|
|||||||
this.definitions.forEach(function(def){ def.value = null });
|
this.definitions.forEach(function(def){ def.value = null });
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Definitions.DEFMETHOD("to_assignments", function(){
|
AST_Definitions.DEFMETHOD("to_assignments", function(compressor){
|
||||||
|
var reduce_vars = compressor.option("reduce_vars");
|
||||||
var assignments = this.definitions.reduce(function(a, def){
|
var assignments = this.definitions.reduce(function(a, def){
|
||||||
if (def.value && !def.is_destructuring()) {
|
if (def.value && !(def.name instanceof AST_Destructuring)) {
|
||||||
var name = make_node(AST_SymbolRef, def.name, def.name);
|
var name = make_node(AST_SymbolRef, def.name, def.name);
|
||||||
a.push(make_node(AST_Assign, def, {
|
a.push(make_node(AST_Assign, def, {
|
||||||
operator : "=",
|
operator : "=",
|
||||||
left : name,
|
left : name,
|
||||||
right : def.value
|
right : def.value
|
||||||
}));
|
}));
|
||||||
|
if (reduce_vars) name.definition().fixed = false;
|
||||||
} else if (def.value) {
|
} else if (def.value) {
|
||||||
// Because it's a destructuring, do not turn into an assignment.
|
// Because it's a destructuring, do not turn into an assignment.
|
||||||
var varDef = make_node(AST_VarDef, def, {
|
var varDef = make_node(AST_VarDef, def, {
|
||||||
@@ -2783,7 +2791,7 @@ merge(Compressor.prototype, {
|
|||||||
if (self.args.length != 1) {
|
if (self.args.length != 1) {
|
||||||
return make_node(AST_Array, self, {
|
return make_node(AST_Array, self, {
|
||||||
elements: self.args
|
elements: self.args
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Object":
|
case "Object":
|
||||||
@@ -2801,7 +2809,7 @@ merge(Compressor.prototype, {
|
|||||||
left: self.args[0],
|
left: self.args[0],
|
||||||
operator: "+",
|
operator: "+",
|
||||||
right: make_node(AST_String, self, { value: "" })
|
right: make_node(AST_String, self, { value: "" })
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
break;
|
break;
|
||||||
case "Number":
|
case "Number":
|
||||||
if (self.args.length == 0) return make_node(AST_Number, self, {
|
if (self.args.length == 0) return make_node(AST_Number, self, {
|
||||||
@@ -2810,7 +2818,7 @@ merge(Compressor.prototype, {
|
|||||||
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
|
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
|
||||||
expression: self.args[0],
|
expression: self.args[0],
|
||||||
operator: "+"
|
operator: "+"
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
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, {
|
||||||
@@ -2819,7 +2827,7 @@ merge(Compressor.prototype, {
|
|||||||
operator: "!"
|
operator: "!"
|
||||||
}),
|
}),
|
||||||
operator: "!"
|
operator: "!"
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
break;
|
break;
|
||||||
case "Function":
|
case "Function":
|
||||||
// new Function() => function(){}
|
// new Function() => function(){}
|
||||||
@@ -2889,21 +2897,20 @@ merge(Compressor.prototype, {
|
|||||||
left: make_node(AST_String, self, { value: "" }),
|
left: make_node(AST_String, self, { value: "" }),
|
||||||
operator: "+",
|
operator: "+",
|
||||||
right: exp.expression
|
right: exp.expression
|
||||||
}).transform(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
|
else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
|
||||||
var separator;
|
var separator;
|
||||||
if (self.args.length > 0) {
|
if (self.args.length > 0) {
|
||||||
separator = self.args[0].evaluate(compressor);
|
separator = self.args[0].evaluate(compressor);
|
||||||
if (separator.length < 2) break EXIT; // not a constant
|
if (separator === self.args[0]) break EXIT; // not a constant
|
||||||
separator = separator[1];
|
|
||||||
}
|
}
|
||||||
var elements = [];
|
var elements = [];
|
||||||
var consts = [];
|
var consts = [];
|
||||||
exp.expression.elements.forEach(function(el) {
|
exp.expression.elements.forEach(function(el) {
|
||||||
el = el.evaluate(compressor);
|
var value = el.evaluate(compressor);
|
||||||
if (el.length > 1) {
|
if (value !== el) {
|
||||||
consts.push(el[1]);
|
consts.push(value);
|
||||||
} else {
|
} else {
|
||||||
if (consts.length > 0) {
|
if (consts.length > 0) {
|
||||||
elements.push(make_node(AST_String, self, {
|
elements.push(make_node(AST_String, self, {
|
||||||
@@ -2911,7 +2918,7 @@ merge(Compressor.prototype, {
|
|||||||
}));
|
}));
|
||||||
consts.length = 0;
|
consts.length = 0;
|
||||||
}
|
}
|
||||||
elements.push(el[0]);
|
elements.push(el);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (consts.length > 0) {
|
if (consts.length > 0) {
|
||||||
@@ -2944,7 +2951,7 @@ merge(Compressor.prototype, {
|
|||||||
left : prev,
|
left : prev,
|
||||||
right : el
|
right : el
|
||||||
});
|
});
|
||||||
}, first).transform(compressor);
|
}, first).optimize(compressor);
|
||||||
}
|
}
|
||||||
// need this awkward cloning to not affect original element
|
// need this awkward cloning to not affect original element
|
||||||
// best_of will decide which one to get through.
|
// best_of will decide which one to get through.
|
||||||
@@ -2952,7 +2959,17 @@ merge(Compressor.prototype, {
|
|||||||
node.expression = node.expression.clone();
|
node.expression = node.expression.clone();
|
||||||
node.expression.expression = node.expression.expression.clone();
|
node.expression.expression = node.expression.expression.clone();
|
||||||
node.expression.expression.elements = elements;
|
node.expression.expression.elements = elements;
|
||||||
return best_of(self, node);
|
return best_of(compressor, self, node);
|
||||||
|
}
|
||||||
|
else if (exp instanceof AST_Dot && exp.expression.is_string(compressor) && exp.property == "charAt") {
|
||||||
|
var arg = self.args[0];
|
||||||
|
var index = arg ? arg.evaluate(compressor) : 0;
|
||||||
|
if (index !== arg) {
|
||||||
|
return make_node(AST_Sub, exp, {
|
||||||
|
expression: exp.expression,
|
||||||
|
property: make_node_from_constant(index | 0, arg || exp)
|
||||||
|
}).optimize(compressor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exp instanceof AST_Function && !self.expression.is_generator) {
|
if (exp instanceof AST_Function && !self.expression.is_generator) {
|
||||||
@@ -3098,8 +3115,7 @@ merge(Compressor.prototype, {
|
|||||||
return e.expression;
|
return e.expression;
|
||||||
}
|
}
|
||||||
if (e instanceof AST_Binary) {
|
if (e instanceof AST_Binary) {
|
||||||
var statement = first_in_statement(compressor);
|
self = best_of(compressor, self, e.negate(compressor, first_in_statement(compressor)));
|
||||||
self = (statement ? best_of_statement : best_of)(self, e.negate(compressor, statement));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "typeof":
|
case "typeof":
|
||||||
@@ -3112,16 +3128,16 @@ merge(Compressor.prototype, {
|
|||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.evaluate(compressor)[0];
|
// avoids infinite recursion of numerals
|
||||||
});
|
if (self.operator != "-" || !(self.expression instanceof AST_Number)) {
|
||||||
|
var ev = self.evaluate(compressor);
|
||||||
function has_side_effects_or_prop_access(node, compressor) {
|
if (ev !== self) {
|
||||||
var save_pure_getters = compressor.option("pure_getters");
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||||
compressor.options.pure_getters = false;
|
return best_of(compressor, ev, self);
|
||||||
var ret = node.has_side_effects(compressor);
|
|
||||||
compressor.options.pure_getters = save_pure_getters;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
|
AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
|
||||||
if (compressor.option("sequences")) {
|
if (compressor.option("sequences")) {
|
||||||
@@ -3130,18 +3146,23 @@ merge(Compressor.prototype, {
|
|||||||
var x = seq.to_array();
|
var x = seq.to_array();
|
||||||
this.left = x.pop();
|
this.left = x.pop();
|
||||||
x.push(this);
|
x.push(this);
|
||||||
seq = AST_Seq.from_array(x).transform(compressor);
|
return AST_Seq.from_array(x).optimize(compressor);
|
||||||
return seq;
|
}
|
||||||
|
if (this.right instanceof AST_Seq && !this.left.has_side_effects(compressor)) {
|
||||||
|
var assign = this.operator == "=" && this.left instanceof AST_SymbolRef;
|
||||||
|
var root = this.right;
|
||||||
|
var cursor, seq = root;
|
||||||
|
while (assign || !seq.car.has_side_effects(compressor)) {
|
||||||
|
cursor = seq;
|
||||||
|
if (seq.cdr instanceof AST_Seq) {
|
||||||
|
seq = seq.cdr;
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
if (cursor) {
|
||||||
|
this.right = cursor.cdr;
|
||||||
|
cursor.cdr = this;
|
||||||
|
return root.optimize(compressor);
|
||||||
}
|
}
|
||||||
if (this.right instanceof AST_Seq
|
|
||||||
&& this instanceof AST_Assign
|
|
||||||
&& !has_side_effects_or_prop_access(this.left, compressor)) {
|
|
||||||
var seq = this.right;
|
|
||||||
var x = seq.to_array();
|
|
||||||
this.right = x.pop();
|
|
||||||
x.push(this);
|
|
||||||
seq = AST_Seq.from_array(x).transform(compressor);
|
|
||||||
return seq;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@@ -3150,16 +3171,6 @@ merge(Compressor.prototype, {
|
|||||||
var commutativeOperators = makePredicate("== === != !== * & | ^");
|
var commutativeOperators = makePredicate("== === != !== * & | ^");
|
||||||
|
|
||||||
OPT(AST_Binary, function(self, compressor){
|
OPT(AST_Binary, function(self, compressor){
|
||||||
var lhs = self.left.evaluate(compressor);
|
|
||||||
var rhs = self.right.evaluate(compressor);
|
|
||||||
if (lhs.length > 1 && lhs[0].is_constant() !== self.left.is_constant()
|
|
||||||
|| rhs.length > 1 && rhs[0].is_constant() !== self.right.is_constant()) {
|
|
||||||
return make_node(AST_Binary, self, {
|
|
||||||
operator: self.operator,
|
|
||||||
left: lhs[0],
|
|
||||||
right: rhs[0]
|
|
||||||
}).optimize(compressor);
|
|
||||||
}
|
|
||||||
function reversible() {
|
function reversible() {
|
||||||
return self.left instanceof AST_Constant
|
return self.left instanceof AST_Constant
|
||||||
|| self.right instanceof AST_Constant
|
|| self.right instanceof AST_Constant
|
||||||
@@ -3186,32 +3197,6 @@ merge(Compressor.prototype, {
|
|||||||
reverse();
|
reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (/^[!=]==?$/.test(self.operator)) {
|
|
||||||
if (self.left instanceof AST_SymbolRef && self.right instanceof AST_Conditional) {
|
|
||||||
if (self.right.consequent instanceof AST_SymbolRef
|
|
||||||
&& self.right.consequent.definition() === self.left.definition()) {
|
|
||||||
if (/^==/.test(self.operator)) return self.right.condition;
|
|
||||||
if (/^!=/.test(self.operator)) return self.right.condition.negate(compressor);
|
|
||||||
}
|
|
||||||
if (self.right.alternative instanceof AST_SymbolRef
|
|
||||||
&& self.right.alternative.definition() === self.left.definition()) {
|
|
||||||
if (/^==/.test(self.operator)) return self.right.condition.negate(compressor);
|
|
||||||
if (/^!=/.test(self.operator)) return self.right.condition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (self.right instanceof AST_SymbolRef && self.left instanceof AST_Conditional) {
|
|
||||||
if (self.left.consequent instanceof AST_SymbolRef
|
|
||||||
&& self.left.consequent.definition() === self.right.definition()) {
|
|
||||||
if (/^==/.test(self.operator)) return self.left.condition;
|
|
||||||
if (/^!=/.test(self.operator)) return self.left.condition.negate(compressor);
|
|
||||||
}
|
|
||||||
if (self.left.alternative instanceof AST_SymbolRef
|
|
||||||
&& self.left.alternative.definition() === self.right.definition()) {
|
|
||||||
if (/^==/.test(self.operator)) return self.left.condition.negate(compressor);
|
|
||||||
if (/^!=/.test(self.operator)) return self.left.condition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
self = self.lift_sequences(compressor);
|
self = self.lift_sequences(compressor);
|
||||||
if (compressor.option("comparisons")) switch (self.operator) {
|
if (compressor.option("comparisons")) switch (self.operator) {
|
||||||
@@ -3244,48 +3229,48 @@ merge(Compressor.prototype, {
|
|||||||
case "&&":
|
case "&&":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.evaluate(compressor);
|
||||||
var rr = self.right.evaluate(compressor);
|
var rr = self.right.evaluate(compressor);
|
||||||
if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) {
|
if (!ll || !rr) {
|
||||||
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, self)
|
cdr: make_node(AST_False, self)
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (ll.length > 1 && ll[1]) {
|
if (ll !== self.left && ll) {
|
||||||
return rr[0];
|
return self.right.optimize(compressor);
|
||||||
}
|
}
|
||||||
if (rr.length > 1 && rr[1]) {
|
if (rr !== self.right && rr) {
|
||||||
return ll[0];
|
return self.left.optimize(compressor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "||":
|
case "||":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.evaluate(compressor);
|
||||||
var rr = self.right.evaluate(compressor);
|
var rr = self.right.evaluate(compressor);
|
||||||
if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) {
|
if (ll !== self.left && ll || rr !== self.right && rr) {
|
||||||
compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Boolean || always true [{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_True, self)
|
cdr: make_node(AST_True, self)
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (ll.length > 1 && !ll[1]) {
|
if (!ll) {
|
||||||
return rr[0];
|
return self.right.optimize(compressor);
|
||||||
}
|
}
|
||||||
if (rr.length > 1 && !rr[1]) {
|
if (!rr) {
|
||||||
return ll[0];
|
return self.left.optimize(compressor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "+":
|
case "+":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.evaluate(compressor);
|
||||||
var rr = self.right.evaluate(compressor);
|
var rr = self.right.evaluate(compressor);
|
||||||
if (ll.length > 1 && ll[0] instanceof AST_String && ll[1]) {
|
if (ll && typeof ll == "string") {
|
||||||
compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
|
compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
|
||||||
return make_node(AST_Seq, self, {
|
return make_node(AST_Seq, self, {
|
||||||
car: self.right,
|
car: self.right,
|
||||||
cdr: make_node(AST_True, self)
|
cdr: make_node(AST_True, self)
|
||||||
}).optimize(compressor);
|
}).optimize(compressor);
|
||||||
}
|
}
|
||||||
if (rr.length > 1 && rr[0] instanceof AST_String && rr[1]) {
|
if (rr && typeof rr == "string") {
|
||||||
compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
|
compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
|
||||||
return make_node(AST_Seq, self, {
|
return make_node(AST_Seq, self, {
|
||||||
car: self.left,
|
car: self.left,
|
||||||
@@ -3297,12 +3282,11 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.option("comparisons") && self.is_boolean()) {
|
if (compressor.option("comparisons") && self.is_boolean()) {
|
||||||
if (!(compressor.parent() instanceof AST_Binary)
|
if (!(compressor.parent() instanceof AST_Binary)
|
||||||
|| compressor.parent() instanceof AST_Assign) {
|
|| compressor.parent() instanceof AST_Assign) {
|
||||||
var statement = first_in_statement(compressor);
|
|
||||||
var negated = make_node(AST_UnaryPrefix, self, {
|
var negated = make_node(AST_UnaryPrefix, self, {
|
||||||
operator: "!",
|
operator: "!",
|
||||||
expression: self.negate(compressor, statement)
|
expression: self.negate(compressor, first_in_statement(compressor))
|
||||||
});
|
});
|
||||||
self = (statement ? best_of_statement : best_of)(self, negated);
|
self = best_of(compressor, self, negated);
|
||||||
}
|
}
|
||||||
if (compressor.option("unsafe_comps")) {
|
if (compressor.option("unsafe_comps")) {
|
||||||
switch (self.operator) {
|
switch (self.operator) {
|
||||||
@@ -3454,9 +3438,9 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
if (self.right instanceof AST_Constant
|
if (self.right instanceof AST_Constant
|
||||||
&& !(self.left instanceof AST_Constant)) {
|
&& !(self.left instanceof AST_Constant)) {
|
||||||
self = best_of(reversed, self);
|
self = best_of(compressor, reversed, self);
|
||||||
} else {
|
} else {
|
||||||
self = best_of(self, reversed);
|
self = best_of(compressor, self, reversed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (associative && self.is_number(compressor)) {
|
if (associative && self.is_number(compressor)) {
|
||||||
@@ -3553,7 +3537,12 @@ merge(Compressor.prototype, {
|
|||||||
self.right = self.right.right;
|
self.right = self.right.right;
|
||||||
return self.transform(compressor);
|
return self.transform(compressor);
|
||||||
}
|
}
|
||||||
return self.evaluate(compressor)[0];
|
var ev = self.evaluate(compressor);
|
||||||
|
if (ev !== self) {
|
||||||
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||||
|
return best_of(compressor, ev, self);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_SymbolRef, function(self, compressor){
|
OPT(AST_SymbolRef, function(self, compressor){
|
||||||
@@ -3568,11 +3557,11 @@ merge(Compressor.prototype, {
|
|||||||
&& (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
|
&& (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
|
||||||
switch (self.name) {
|
switch (self.name) {
|
||||||
case "undefined":
|
case "undefined":
|
||||||
return make_node(AST_Undefined, self).transform(compressor);
|
return make_node(AST_Undefined, self).optimize(compressor);
|
||||||
case "NaN":
|
case "NaN":
|
||||||
return make_node(AST_NaN, self).transform(compressor);
|
return make_node(AST_NaN, self).optimize(compressor);
|
||||||
case "Infinity":
|
case "Infinity":
|
||||||
return make_node(AST_Infinity, self).transform(compressor);
|
return make_node(AST_Infinity, self).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
if (compressor.option("evaluate") && compressor.option("reduce_vars")) {
|
||||||
@@ -3580,18 +3569,20 @@ merge(Compressor.prototype, {
|
|||||||
if (d.fixed) {
|
if (d.fixed) {
|
||||||
if (d.should_replace === undefined) {
|
if (d.should_replace === undefined) {
|
||||||
var init = d.fixed.evaluate(compressor);
|
var init = d.fixed.evaluate(compressor);
|
||||||
if (init.length > 1) {
|
if (init !== d.fixed) {
|
||||||
var value = init[0].print_to_string().length;
|
init = make_node_from_constant(init, d.fixed).optimize(compressor);
|
||||||
|
init = best_of_expression(init, d.fixed);
|
||||||
|
var value = init.print_to_string().length;
|
||||||
var name = d.name.length;
|
var name = d.name.length;
|
||||||
var freq = d.references.length;
|
var freq = d.references.length;
|
||||||
var overhead = d.global || !freq ? 0 : (name + 2 + value) / freq;
|
var overhead = d.global || !freq ? 0 : (name + 2 + value) / freq;
|
||||||
d.should_replace = value <= name + overhead ? init[0] : false;
|
d.should_replace = value <= name + overhead ? init : false;
|
||||||
} else {
|
} else {
|
||||||
d.should_replace = false;
|
d.should_replace = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (d.should_replace) {
|
if (d.should_replace) {
|
||||||
return d.should_replace;
|
return d.should_replace.clone(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3655,10 +3646,11 @@ merge(Compressor.prototype, {
|
|||||||
var evaluateRight = self.right.evaluate(compressor);
|
var evaluateRight = self.right.evaluate(compressor);
|
||||||
|
|
||||||
// `[x = undefined] = foo` ---> `[x] = foo`
|
// `[x = undefined] = foo` ---> `[x] = foo`
|
||||||
if (evaluateRight.length > 1 && evaluateRight[1] === undefined) {
|
if (evaluateRight === undefined) {
|
||||||
self = self.left;
|
self = self.left;
|
||||||
} else {
|
} else if (evaluateRight !== self.right) {
|
||||||
self.right = evaluateRight[0];
|
evaluateRight = make_node_from_constant(evaluateRight, self.right);
|
||||||
|
self.right = best_of_expression(evaluateRight, self.right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -3672,8 +3664,8 @@ merge(Compressor.prototype, {
|
|||||||
return AST_Seq.cons(car, self);
|
return AST_Seq.cons(car, self);
|
||||||
}
|
}
|
||||||
var cond = self.condition.evaluate(compressor);
|
var cond = self.condition.evaluate(compressor);
|
||||||
if (cond.length > 1) {
|
if (cond !== self.condition) {
|
||||||
if (cond[1]) {
|
if (cond) {
|
||||||
compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
|
compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor.parent(), self, self.consequent);
|
return maintain_this_binding(compressor.parent(), self, self.consequent);
|
||||||
} else {
|
} else {
|
||||||
@@ -3681,9 +3673,8 @@ merge(Compressor.prototype, {
|
|||||||
return maintain_this_binding(compressor.parent(), self, self.alternative);
|
return maintain_this_binding(compressor.parent(), self, self.alternative);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var statement = first_in_statement(compressor);
|
var negated = cond.negate(compressor, first_in_statement(compressor));
|
||||||
var negated = cond[0].negate(compressor, statement);
|
if (best_of(compressor, cond, negated) === negated) {
|
||||||
if ((statement ? best_of_statement : best_of)(cond[0], negated) === negated) {
|
|
||||||
self = make_node(AST_Conditional, self, {
|
self = make_node(AST_Conditional, self, {
|
||||||
condition: negated,
|
condition: negated,
|
||||||
consequent: self.alternative,
|
consequent: self.alternative,
|
||||||
@@ -3863,7 +3854,12 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.evaluate(compressor)[0];
|
var ev = self.evaluate(compressor);
|
||||||
|
if (ev !== self) {
|
||||||
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||||
|
return best_of(compressor, ev, self);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Dot, function(self, compressor){
|
OPT(AST_Dot, function(self, compressor){
|
||||||
@@ -3902,13 +3898,17 @@ merge(Compressor.prototype, {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self.evaluate(compressor)[0];
|
var ev = self.evaluate(compressor);
|
||||||
|
if (ev !== self) {
|
||||||
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
||||||
|
return best_of(compressor, ev, self);
|
||||||
|
}
|
||||||
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
function literals_in_boolean_context(self, compressor) {
|
function literals_in_boolean_context(self, compressor) {
|
||||||
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
if (compressor.option("booleans") && compressor.in_boolean_context()) {
|
||||||
var best = first_in_statement(compressor) ? best_of_statement : best_of;
|
return best_of(compressor, self, make_node(AST_Seq, self, {
|
||||||
return best(self, make_node(AST_Seq, self, {
|
|
||||||
car: self,
|
car: self,
|
||||||
cdr: make_node(AST_True, self)
|
cdr: make_node(AST_True, self)
|
||||||
}).optimize(compressor));
|
}).optimize(compressor));
|
||||||
@@ -3954,24 +3954,19 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
var segments = [];
|
var segments = [];
|
||||||
for (var i = 0; i < self.segments.length; i++) {
|
for (var i = 0; i < self.segments.length; i++) {
|
||||||
if (self.segments[i] instanceof AST_Node) {
|
var segment = self.segments[i];
|
||||||
var result = self.segments[i].evaluate(compressor);
|
if (segment instanceof AST_Node) {
|
||||||
// No result[1] means nothing to stringify
|
var result = segment.evaluate(compressor);
|
||||||
if (result.length === 1) {
|
// Evaluate to constant value
|
||||||
segments.push(result[0]);
|
// Constant value shorter than ${segment}
|
||||||
continue;
|
if (result !== segment && (result + "").length <= segment.print_to_string().length + "${}".length) {
|
||||||
}
|
|
||||||
// Evaluate length
|
|
||||||
if (result[0].print_to_string().length + 3 /* ${} */ < (result[1]+"").length) {
|
|
||||||
segments.push(result[0]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// There should always be a previous and next segment if segment is a node
|
// There should always be a previous and next segment if segment is a node
|
||||||
segments[segments.length - 1].value = segments[segments.length - 1].value + result[1] + self.segments[++i].value;
|
segments[segments.length - 1].value = segments[segments.length - 1].value + result + self.segments[++i].value;
|
||||||
} else {
|
continue;
|
||||||
segments.push(self.segments[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
segments.push(segment);
|
||||||
|
}
|
||||||
self.segments = segments;
|
self.segments = segments;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -1998,7 +1998,6 @@ function parse($TEXT, options) {
|
|||||||
// allow trailing comma
|
// allow trailing comma
|
||||||
break;
|
break;
|
||||||
start = S.token;
|
start = S.token;
|
||||||
var type = start.type;
|
|
||||||
var name = as_property_name();
|
var name = as_property_name();
|
||||||
var value;
|
var value;
|
||||||
|
|
||||||
@@ -2009,9 +2008,6 @@ function parse($TEXT, options) {
|
|||||||
a.push(concise);
|
a.push(concise);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(start.type !== name)) {
|
|
||||||
unexpected(S.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
value = new AST_SymbolRef({
|
value = new AST_SymbolRef({
|
||||||
start: prev(),
|
start: prev(),
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
if (node instanceof AST_SymbolCatch) {
|
if (node instanceof AST_SymbolCatch) {
|
||||||
var name = node.name;
|
var name = node.name;
|
||||||
var refs = node.thedef.references;
|
var refs = node.thedef.references;
|
||||||
var scope = node.thedef.scope.parent_scope;
|
var scope = node.thedef.scope.parent_scope.parent_scope;
|
||||||
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
|
||||||
refs.forEach(function(ref) {
|
refs.forEach(function(ref) {
|
||||||
ref.thedef = def;
|
ref.thedef = def;
|
||||||
|
|||||||
@@ -126,9 +126,11 @@ function merge(obj, ext) {
|
|||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
function noop() {};
|
function noop() {}
|
||||||
function return_false() { return false; }
|
function return_false() { return false; }
|
||||||
function return_true() { return true; }
|
function return_true() { return true; }
|
||||||
|
function return_this() { return this; }
|
||||||
|
function return_null() { return null; }
|
||||||
|
|
||||||
var MAP = (function(){
|
var MAP = (function(){
|
||||||
function MAP(a, f, backwards) {
|
function MAP(a, f, backwards) {
|
||||||
|
|||||||
@@ -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.11",
|
"version": "2.8.14",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ collapse_vars_side_effects_1: {
|
|||||||
z = i += 4;
|
z = i += 4;
|
||||||
log(x, z, y, i);
|
log(x, z, y, i);
|
||||||
}
|
}
|
||||||
|
f1(), f2(), f3(), f4();
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
function f1() {
|
function f1() {
|
||||||
@@ -73,7 +74,9 @@ collapse_vars_side_effects_1: {
|
|||||||
y = i += 3;
|
y = i += 3;
|
||||||
log(x, i += 4, y, i);
|
log(x, i += 4, y, i);
|
||||||
}
|
}
|
||||||
|
f1(), f2(), f3(), f4();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_side_effects_2: {
|
collapse_vars_side_effects_2: {
|
||||||
@@ -823,6 +826,7 @@ collapse_vars_repeated: {
|
|||||||
console.log(e + "!");
|
console.log(e + "!");
|
||||||
})("!");
|
})("!");
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_closures: {
|
collapse_vars_closures: {
|
||||||
@@ -1109,6 +1113,7 @@ collapse_vars_eval_and_with: {
|
|||||||
return function() { with (o) console.log(a) };
|
return function() { with (o) console.log(a) };
|
||||||
})()();
|
})()();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_constants: {
|
collapse_vars_constants: {
|
||||||
@@ -1152,7 +1157,8 @@ collapse_vars_arguments: {
|
|||||||
options = {
|
options = {
|
||||||
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
|
||||||
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
|
||||||
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
|
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true,
|
||||||
|
toplevel:true
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var outer = function() {
|
var outer = function() {
|
||||||
@@ -1167,6 +1173,7 @@ collapse_vars_arguments: {
|
|||||||
(function(){console.log(arguments);})(7, 1);
|
(function(){console.log(arguments);})(7, 1);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
collapse_vars_short_circuit: {
|
collapse_vars_short_circuit: {
|
||||||
@@ -1316,11 +1323,13 @@ collapse_vars_regexp: {
|
|||||||
console.log(result[0]);
|
console.log(result[0]);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1537: {
|
issue_1537: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var k = '';
|
var k = '';
|
||||||
@@ -1335,6 +1344,7 @@ issue_1537: {
|
|||||||
issue_1537_for_of: {
|
issue_1537_for_of: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var k = '';
|
var k = '';
|
||||||
@@ -1349,6 +1359,7 @@ issue_1537_for_of: {
|
|||||||
issue_1537_destructuring_1: {
|
issue_1537_destructuring_1: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = 1, y = 2;
|
var x = 1, y = 2;
|
||||||
@@ -1363,6 +1374,7 @@ issue_1537_destructuring_1: {
|
|||||||
issue_1537_destructuring_2: {
|
issue_1537_destructuring_2: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = foo();
|
var x = foo();
|
||||||
@@ -1377,6 +1389,7 @@ issue_1537_destructuring_2: {
|
|||||||
issue_1537_destructuring_3: {
|
issue_1537_destructuring_3: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = Math.random();
|
var x = Math.random();
|
||||||
@@ -1391,6 +1404,7 @@ issue_1537_destructuring_3: {
|
|||||||
issue_1537_destructuring_for_in: {
|
issue_1537_destructuring_for_in: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = 1, y = 2;
|
var x = 1, y = 2;
|
||||||
@@ -1409,6 +1423,7 @@ issue_1537_destructuring_for_in: {
|
|||||||
issue_1537_destructuring_for_of: {
|
issue_1537_destructuring_for_of: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var x = 1, y = 2;
|
var x = 1, y = 2;
|
||||||
@@ -1427,6 +1442,7 @@ issue_1537_destructuring_for_of: {
|
|||||||
issue_1562: {
|
issue_1562: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
var v = 1, B = 2;
|
var v = 1, B = 2;
|
||||||
@@ -1455,3 +1471,46 @@ issue_1562: {
|
|||||||
for (; f(z + 2) ;) bar(30);
|
for (; f(z + 2) ;) bar(30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1605_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo(x) {
|
||||||
|
var y = x;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
var o = new Object;
|
||||||
|
o.p = 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
var o = new Object;
|
||||||
|
o.p = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1605_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
toplevel: "vars",
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo(x) {
|
||||||
|
var y = x;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
var o = new Object;
|
||||||
|
o.p = 1;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
(new Object).p = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ concat_2: {
|
|||||||
"1" + "2" + "3"
|
"1" + "2" + "3"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
concat_3: {
|
concat_3: {
|
||||||
@@ -79,6 +80,7 @@ concat_3: {
|
|||||||
1 + 2 + "3" + "4" + "5"
|
1 + 2 + "3" + "4" + "5"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
concat_4: {
|
concat_4: {
|
||||||
@@ -107,6 +109,7 @@ concat_4: {
|
|||||||
1 + "2" + "3" + "4" + "5"
|
1 + "2" + "3" + "4" + "5"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
concat_5: {
|
concat_5: {
|
||||||
@@ -135,6 +138,7 @@ concat_5: {
|
|||||||
"1" + 2 + "3" + "4" + "5"
|
"1" + 2 + "3" + "4" + "5"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
concat_6: {
|
concat_6: {
|
||||||
@@ -163,6 +167,7 @@ concat_6: {
|
|||||||
"1" + "2" + "3" + "4" + "5"
|
"1" + "2" + "3" + "4" + "5"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
concat_7: {
|
concat_7: {
|
||||||
@@ -188,6 +193,7 @@ concat_7: {
|
|||||||
x += "foo"
|
x += "foo"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
concat_8: {
|
concat_8: {
|
||||||
@@ -213,4 +219,5 @@ concat_8: {
|
|||||||
x += "foo"
|
x += "foo"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -797,3 +797,99 @@ no_evaluate: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
equality_conditionals_false: {
|
||||||
|
options = {
|
||||||
|
conditionals: false,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a == (b ? a : a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
a != (b ? a : a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
a === (b ? a : a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
a !== (b ? a : a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0);
|
||||||
|
f(0, true, 0);
|
||||||
|
f(1, 2, 3);
|
||||||
|
f(1, null, 3);
|
||||||
|
f(NaN);
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a == (b ? a : a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
a != (b ? a : a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
a === (b ? a : a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
a !== (b ? a : a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0),
|
||||||
|
f(0, true, 0),
|
||||||
|
f(1, 2, 3),
|
||||||
|
f(1, null, 3),
|
||||||
|
f(NaN),
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
equality_conditionals_true: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
a == (b ? a : a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
a != (b ? a : a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
a === (b ? a : a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
a !== (b ? a : a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0);
|
||||||
|
f(0, true, 0);
|
||||||
|
f(1, 2, 3);
|
||||||
|
f(1, null, 3);
|
||||||
|
f(NaN);
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
console.log(
|
||||||
|
(b, a == a),
|
||||||
|
a == (b ? a : c),
|
||||||
|
(b, a != a),
|
||||||
|
a != (b ? a : c),
|
||||||
|
(b, a === a),
|
||||||
|
a === (b ? a : c),
|
||||||
|
(b, a !== a),
|
||||||
|
a !== (b ? a : c)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
f(0, 0, 0),
|
||||||
|
f(0, true, 0),
|
||||||
|
f(1, 2, 3),
|
||||||
|
f(1, null, 3),
|
||||||
|
f(NaN),
|
||||||
|
f(NaN, "foo");
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -162,4 +162,5 @@ regexp_literal_not_const: {
|
|||||||
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
|
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ dead_code_constant_boolean_should_warn_more: {
|
|||||||
var x = 10, y;
|
var x = 10, y;
|
||||||
var moo;
|
var moo;
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_block_decls_die: {
|
dead_code_block_decls_die: {
|
||||||
@@ -135,6 +136,7 @@ dead_code_const_declaration: {
|
|||||||
var moo;
|
var moo;
|
||||||
function bar() {}
|
function bar() {}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_const_annotation: {
|
dead_code_const_annotation: {
|
||||||
@@ -162,6 +164,7 @@ dead_code_const_annotation: {
|
|||||||
var moo;
|
var moo;
|
||||||
function bar() {}
|
function bar() {}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_const_annotation_regex: {
|
dead_code_const_annotation_regex: {
|
||||||
@@ -185,6 +188,7 @@ dead_code_const_annotation_regex: {
|
|||||||
var CONST_FOO_ANN = !1;
|
var CONST_FOO_ANN = !1;
|
||||||
CONST_FOO_ANN && console.log('reachable');
|
CONST_FOO_ANN && console.log('reachable');
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_const_annotation_complex_scope: {
|
dead_code_const_annotation_complex_scope: {
|
||||||
@@ -230,4 +234,5 @@ dead_code_const_annotation_complex_scope: {
|
|||||||
var meat = 'beef';
|
var meat = 'beef';
|
||||||
var pork = 'bad';
|
var pork = 'bad';
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,3 +293,17 @@ reduce_vars: {
|
|||||||
for ([x,y] in pairs);
|
for ([x,y] in pairs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unused: {
|
||||||
|
options = {
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
let { foo: [, , ...a] } = { foo: [1, 2, 3, 4], bar: 5 };
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ negative_zero: {
|
|||||||
1 / (-0)
|
1 / (-0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
positive_zero: {
|
positive_zero: {
|
||||||
@@ -220,6 +221,7 @@ positive_zero: {
|
|||||||
1 / (0)
|
1 / (0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
pow: {
|
pow: {
|
||||||
@@ -337,6 +339,7 @@ unsafe_constant: {
|
|||||||
(void 0).a
|
(void 0).a
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_object: {
|
unsafe_object: {
|
||||||
@@ -360,6 +363,7 @@ unsafe_object: {
|
|||||||
1..b + 1
|
1..b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_object_nested: {
|
unsafe_object_nested: {
|
||||||
@@ -383,6 +387,7 @@ unsafe_object_nested: {
|
|||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_object_complex: {
|
unsafe_object_complex: {
|
||||||
@@ -406,6 +411,7 @@ unsafe_object_complex: {
|
|||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_object_repeated: {
|
unsafe_object_repeated: {
|
||||||
@@ -429,6 +435,7 @@ unsafe_object_repeated: {
|
|||||||
1..b + 1
|
1..b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_object_accessor: {
|
unsafe_object_accessor: {
|
||||||
@@ -478,6 +485,7 @@ unsafe_function: {
|
|||||||
({a:{b:1},b:function(){}}).a.b + 1
|
({a:{b:1},b:function(){}}).a.b + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_integer_key: {
|
unsafe_integer_key: {
|
||||||
@@ -505,6 +513,7 @@ unsafe_integer_key: {
|
|||||||
1["1"] + 1
|
1["1"] + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_integer_key_complex: {
|
unsafe_integer_key_complex: {
|
||||||
@@ -532,6 +541,7 @@ unsafe_integer_key_complex: {
|
|||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_float_key: {
|
unsafe_float_key: {
|
||||||
@@ -559,6 +569,7 @@ unsafe_float_key: {
|
|||||||
1["3.14"] + 1
|
1["3.14"] + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_float_key_complex: {
|
unsafe_float_key_complex: {
|
||||||
@@ -586,6 +597,7 @@ unsafe_float_key_complex: {
|
|||||||
2
|
2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_array: {
|
unsafe_array: {
|
||||||
@@ -621,6 +633,7 @@ unsafe_array: {
|
|||||||
(void 0)[1] + 1
|
(void 0)[1] + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_string: {
|
unsafe_string: {
|
||||||
@@ -648,6 +661,7 @@ unsafe_string: {
|
|||||||
"11"
|
"11"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_array_bad_index: {
|
unsafe_array_bad_index: {
|
||||||
@@ -669,6 +683,7 @@ unsafe_array_bad_index: {
|
|||||||
[1, 2, 3, 4][3.14] + 1
|
[1, 2, 3, 4][3.14] + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_string_bad_index: {
|
unsafe_string_bad_index: {
|
||||||
@@ -690,6 +705,7 @@ unsafe_string_bad_index: {
|
|||||||
"1234"[3.14] + 1
|
"1234"[3.14] + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe_prototype_function: {
|
unsafe_prototype_function: {
|
||||||
@@ -736,6 +752,7 @@ call_args: {
|
|||||||
console.log(1);
|
console.log(1);
|
||||||
+(1, 1);
|
+(1, 1);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
call_args_drop_param: {
|
call_args_drop_param: {
|
||||||
@@ -757,6 +774,7 @@ call_args_drop_param: {
|
|||||||
console.log(1);
|
console.log(1);
|
||||||
+(b, 1);
|
+(b, 1);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
in_boolean_context: {
|
in_boolean_context: {
|
||||||
@@ -794,4 +812,74 @@ in_boolean_context: {
|
|||||||
(foo(), !1)
|
(foo(), !1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_charAt: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234" + 1,
|
||||||
|
"1234".charAt(0) + 1,
|
||||||
|
"1234".charAt(6 - 5) + 1,
|
||||||
|
("12" + "34").charAt(0) + 1,
|
||||||
|
("12" + "34").charAt(6 - 5) + 1,
|
||||||
|
[1, 2, 3, 4].join("").charAt(0) + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"12341",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_charAt_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234".charAt() + 1,
|
||||||
|
"1234".charAt("a") + 1,
|
||||||
|
"1234".charAt(3.14) + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"11",
|
||||||
|
"11",
|
||||||
|
"41"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_charAt_noop: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
s.charAt(0),
|
||||||
|
"string".charAt(x)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
s.charAt(0),
|
||||||
|
"string".charAt(x)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ iifes_returning_constants_keep_fargs_true: {
|
|||||||
console.log(6);
|
console.log(6);
|
||||||
console.log((a(), b(), 6));
|
console.log((a(), b(), 6));
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
iifes_returning_constants_keep_fargs_false: {
|
iifes_returning_constants_keep_fargs_false: {
|
||||||
@@ -73,6 +74,7 @@ iifes_returning_constants_keep_fargs_false: {
|
|||||||
console.log(6);
|
console.log(6);
|
||||||
console.log((a(), b(), 6));
|
console.log((a(), b(), 6));
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_485_crashing_1530: {
|
issue_485_crashing_1530: {
|
||||||
|
|||||||
@@ -286,3 +286,48 @@ fat_arrow_as_param: {
|
|||||||
}
|
}
|
||||||
expect_exact: "foo(x=>x);foo(x=>x,y=>y);foo(x=>(x,x));foo(x=>(x,x),y=>(y,y));"
|
expect_exact: "foo(x=>x);foo(x=>x,y=>y);foo(x=>(x,x));foo(x=>(x,x),y=>(y,y));"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default_assign: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b = 3) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expansion: {
|
||||||
|
options = {
|
||||||
|
keep_fargs: false,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, ...b) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1613: {
|
||||||
|
mangle = { toplevel: true };
|
||||||
|
input: {
|
||||||
|
const name = 1;
|
||||||
|
const foo = {
|
||||||
|
name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect_exact: "const n=1;const c={name:n};"
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,4 +49,3 @@ mangle_keep_fnames_true: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,4 +46,5 @@ string_plus_optimization: {
|
|||||||
}
|
}
|
||||||
foo();
|
foo();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ issue_1321_no_debug: {
|
|||||||
x["a"] = 2 * x.b;
|
x["a"] = 2 * x.b;
|
||||||
console.log(x.b, x["a"]);
|
console.log(x.b, x["a"]);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1321_debug: {
|
issue_1321_debug: {
|
||||||
@@ -33,6 +34,7 @@ issue_1321_debug: {
|
|||||||
x["_$foo$_"] = 2 * x.a;
|
x["_$foo$_"] = 2 * x.a;
|
||||||
console.log(x.a, x["_$foo$_"]);
|
console.log(x.a, x["_$foo$_"]);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1321_with_quoted: {
|
issue_1321_with_quoted: {
|
||||||
@@ -51,4 +53,5 @@ issue_1321_with_quoted: {
|
|||||||
x["b"] = 2 * x.a;
|
x["b"] = 2 * x.a;
|
||||||
console.log(x.a, x["b"]);
|
console.log(x.a, x["b"]);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,4 +42,5 @@ conditional_false_stray_else_in_loop: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
|
expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ same_variable_in_multiple_for_loop: {
|
|||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
collapse_vars: true
|
collapse_vars: true,
|
||||||
};
|
}
|
||||||
mangle = {};
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
let a = 100;
|
let a = 100;
|
||||||
@@ -38,6 +38,7 @@ same_variable_in_multiple_for_loop: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
same_variable_in_multiple_forOf: {
|
same_variable_in_multiple_forOf: {
|
||||||
@@ -55,9 +56,9 @@ same_variable_in_multiple_forOf: {
|
|||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
collapse_vars: true
|
collapse_vars: true,
|
||||||
};
|
}
|
||||||
mangle = {};
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
var test = [ "a", "b", "c" ];
|
var test = [ "a", "b", "c" ];
|
||||||
for (let tmp of test) {
|
for (let tmp of test) {
|
||||||
@@ -79,6 +80,7 @@ same_variable_in_multiple_forOf: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
same_variable_in_multiple_forIn: {
|
same_variable_in_multiple_forIn: {
|
||||||
@@ -96,9 +98,9 @@ same_variable_in_multiple_forIn: {
|
|||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
collapse_vars: true
|
collapse_vars: true,
|
||||||
};
|
}
|
||||||
mangle = {};
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
var test = [ "a", "b", "c" ];
|
var test = [ "a", "b", "c" ];
|
||||||
for (let tmp in test) {
|
for (let tmp in test) {
|
||||||
@@ -120,6 +122,7 @@ same_variable_in_multiple_forIn: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
different_variable_in_multiple_for_loop: {
|
different_variable_in_multiple_for_loop: {
|
||||||
@@ -137,9 +140,9 @@ different_variable_in_multiple_for_loop: {
|
|||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
collapse_vars: true
|
collapse_vars: true,
|
||||||
};
|
}
|
||||||
mangle = {};
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
let a = 100;
|
let a = 100;
|
||||||
@@ -162,6 +165,7 @@ different_variable_in_multiple_for_loop: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
different_variable_in_multiple_forOf: {
|
different_variable_in_multiple_forOf: {
|
||||||
@@ -179,9 +183,9 @@ different_variable_in_multiple_forOf: {
|
|||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
collapse_vars: true
|
collapse_vars: true,
|
||||||
};
|
}
|
||||||
mangle = {};
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
var test = [ "a", "b", "c" ];
|
var test = [ "a", "b", "c" ];
|
||||||
for (let tmp of test) {
|
for (let tmp of test) {
|
||||||
@@ -203,6 +207,7 @@ different_variable_in_multiple_forOf: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
different_variable_in_multiple_forIn: {
|
different_variable_in_multiple_forIn: {
|
||||||
@@ -220,9 +225,9 @@ different_variable_in_multiple_forIn: {
|
|||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
collapse_vars: true
|
collapse_vars: true,
|
||||||
};
|
}
|
||||||
mangle = {};
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
var test = [ "a", "b", "c" ];
|
var test = [ "a", "b", "c" ];
|
||||||
for (let tmp in test) {
|
for (let tmp in test) {
|
||||||
@@ -244,6 +249,7 @@ different_variable_in_multiple_forIn: {
|
|||||||
console.log(o);
|
console.log(o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
more_variable_in_multiple_for: {
|
more_variable_in_multiple_for: {
|
||||||
@@ -261,9 +267,9 @@ more_variable_in_multiple_for: {
|
|||||||
join_vars: true,
|
join_vars: true,
|
||||||
cascade: true,
|
cascade: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
collapse_vars: true
|
collapse_vars: true,
|
||||||
};
|
}
|
||||||
mangle = {};
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
for (let a = 9, i = 0; i < 20; i += a) {
|
for (let a = 9, i = 0; i < 20; i += a) {
|
||||||
let b = a++ + i;
|
let b = a++ + i;
|
||||||
@@ -281,5 +287,5 @@ more_variable_in_multiple_for: {
|
|||||||
console.log(o, c, e, l, f);
|
console.log(o, c, e, l, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
99
test/compress/issue-1588.js
Normal file
99
test/compress/issue-1588.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
screw_ie8: {
|
||||||
|
options = {
|
||||||
|
screw_ie8: true,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
screw_ie8: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try { throw "foo"; } catch (x) { console.log(x); }
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"foo"}catch(o){console.log(o)}'
|
||||||
|
expect_stdout: [
|
||||||
|
"foo"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
support_ie8: {
|
||||||
|
options = {
|
||||||
|
screw_ie8: false,
|
||||||
|
}
|
||||||
|
mangle = {
|
||||||
|
screw_ie8: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
try { throw "foo"; } catch (x) { console.log(x); }
|
||||||
|
}
|
||||||
|
expect_exact: 'try{throw"foo"}catch(x){console.log(x)}'
|
||||||
|
expect_stdout: "foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
safe_undefined: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
unsafe: false,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(undefined) {
|
||||||
|
return function() {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
}(1)());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(n) {
|
||||||
|
return function() {
|
||||||
|
return a ? b : c ? d : void 0;
|
||||||
|
};
|
||||||
|
}(1)());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_undefined: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(undefined) {
|
||||||
|
return function() {
|
||||||
|
if (a)
|
||||||
|
return b;
|
||||||
|
if (c)
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
}()());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a, c;
|
||||||
|
console.log(function(n) {
|
||||||
|
return function() {
|
||||||
|
return a ? b : c ? d : n;
|
||||||
|
};
|
||||||
|
}()());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_error: {
|
||||||
|
input: {
|
||||||
|
const a = 1;
|
||||||
|
console.log(a++);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
const a = 1;
|
||||||
|
console.log(a++);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
56
test/compress/issue-1609.js
Normal file
56
test/compress/issue-1609.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
chained_evaluation_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
var b = a, c;
|
||||||
|
c = f(b);
|
||||||
|
c.bar = b;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
var c;
|
||||||
|
c = f(1);
|
||||||
|
c.bar = 1;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chained_evaluation_2: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var a = "long piece of string";
|
||||||
|
(function() {
|
||||||
|
var b = a, c;
|
||||||
|
c = f(b);
|
||||||
|
c.bar = b;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var a = "long piece of string";
|
||||||
|
(function() {
|
||||||
|
var c;
|
||||||
|
c = f(a);
|
||||||
|
c.bar = a;
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,6 +48,7 @@ dead_code_const_annotation_regex: {
|
|||||||
var CONST_FOO_ANN = !1;
|
var CONST_FOO_ANN = !1;
|
||||||
if (CONST_FOO_ANN) console.log('reachable');
|
if (CONST_FOO_ANN) console.log('reachable');
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_console_2: {
|
drop_console_2: {
|
||||||
@@ -225,6 +226,7 @@ issue_1254_negate_iife_true: {
|
|||||||
})()();
|
})()();
|
||||||
}
|
}
|
||||||
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1254_negate_iife_nested: {
|
issue_1254_negate_iife_nested: {
|
||||||
@@ -240,6 +242,7 @@ issue_1254_negate_iife_nested: {
|
|||||||
})()()()()();
|
})()()()()();
|
||||||
}
|
}
|
||||||
expect_exact: '(function(){return function(){console.log("test")}})()()()()();'
|
expect_exact: '(function(){return function(){console.log("test")}})()()()()();'
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
conditional: {
|
conditional: {
|
||||||
|
|||||||
@@ -29,4 +29,5 @@ dont_mangle_arguments: {
|
|||||||
})(5,6,7);
|
})(5,6,7);
|
||||||
}
|
}
|
||||||
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ this_binding_conditionals: {
|
|||||||
this_binding_collapse_vars: {
|
this_binding_collapse_vars: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
toplevel: true,
|
||||||
};
|
};
|
||||||
input: {
|
input: {
|
||||||
var c = a; c();
|
var c = a; c();
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ eval_collapse_vars: {
|
|||||||
eval("console.log(a);");
|
eval("console.log(a);");
|
||||||
})(eval);
|
})(eval);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_unused: {
|
eval_unused: {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ labels_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
foo || console.log("bar");
|
foo || console.log("bar");
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
labels_2: {
|
labels_2: {
|
||||||
@@ -40,6 +41,7 @@ labels_3: {
|
|||||||
for (var i = 0; i < 5; ++i)
|
for (var i = 0; i < 5; ++i)
|
||||||
i < 3 || console.log(i);
|
i < 3 || console.log(i);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
labels_4: {
|
labels_4: {
|
||||||
@@ -54,6 +56,7 @@ labels_4: {
|
|||||||
for (var i = 0; i < 5; ++i)
|
for (var i = 0; i < 5; ++i)
|
||||||
i < 3 || console.log(i);
|
i < 3 || console.log(i);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
labels_5: {
|
labels_5: {
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ keep_collapse_const_in_own_block_scope: {
|
|||||||
console.log(i);
|
console.log(i);
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
keep_collapse_const_in_own_block_scope_2: {
|
keep_collapse_const_in_own_block_scope_2: {
|
||||||
@@ -186,6 +187,7 @@ keep_collapse_const_in_own_block_scope_2: {
|
|||||||
console.log(i);
|
console.log(i);
|
||||||
console.log(c);
|
console.log(c);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate: {
|
evaluate: {
|
||||||
@@ -295,7 +297,15 @@ issue_186_beautify: {
|
|||||||
else
|
else
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
expect_exact: 'var x = 3;\n\nif (foo()) do {\n do {\n alert(x);\n } while (--x);\n} while (x); else bar();'
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
'} while (x); else bar();',
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_186_beautify_ie8: {
|
issue_186_beautify_ie8: {
|
||||||
@@ -314,7 +324,17 @@ issue_186_beautify_ie8: {
|
|||||||
else
|
else
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
expect_exact: 'var x = 3;\n\nif (foo()) {\n do {\n do {\n alert(x);\n } while (--x);\n } while (x);\n} else bar();'
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) {',
|
||||||
|
' do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
' } while (x);',
|
||||||
|
'} else bar();',
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_186_bracketize: {
|
issue_186_bracketize: {
|
||||||
@@ -374,7 +394,19 @@ issue_186_beautify_bracketize: {
|
|||||||
else
|
else
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
expect_exact: 'var x = 3;\n\nif (foo()) {\n do {\n do {\n alert(x);\n } while (--x);\n } while (x);\n} else {\n bar();\n}'
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) {',
|
||||||
|
' do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
' } while (x);',
|
||||||
|
'} else {',
|
||||||
|
' bar();',
|
||||||
|
'}',
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_186_beautify_bracketize_ie8: {
|
issue_186_beautify_bracketize_ie8: {
|
||||||
@@ -394,5 +426,17 @@ issue_186_beautify_bracketize_ie8: {
|
|||||||
else
|
else
|
||||||
bar();
|
bar();
|
||||||
}
|
}
|
||||||
expect_exact: 'var x = 3;\n\nif (foo()) {\n do {\n do {\n alert(x);\n } while (--x);\n } while (x);\n} else {\n bar();\n}'
|
expect_exact: [
|
||||||
|
'var x = 3;',
|
||||||
|
'',
|
||||||
|
'if (foo()) {',
|
||||||
|
' do {',
|
||||||
|
' do {',
|
||||||
|
' alert(x);',
|
||||||
|
' } while (--x);',
|
||||||
|
' } while (x);',
|
||||||
|
'} else {',
|
||||||
|
' bar();',
|
||||||
|
'}',
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,13 @@ too_short: {
|
|||||||
return { c: 42, d: a(), e: "foo"};
|
return { c: 42, d: a(), e: "foo"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: 'function f(a){\nreturn{\nc:42,\nd:a(),\ne:"foo"}}'
|
expect_exact: [
|
||||||
|
'function f(a){',
|
||||||
|
'return{',
|
||||||
|
'c:42,',
|
||||||
|
'd:a(),',
|
||||||
|
'e:"foo"}}',
|
||||||
|
]
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Output exceeds 10 characters"
|
"WARN: Output exceeds 10 characters"
|
||||||
]
|
]
|
||||||
@@ -22,7 +28,12 @@ just_enough: {
|
|||||||
return { c: 42, d: a(), e: "foo"};
|
return { c: 42, d: a(), e: "foo"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: 'function f(a){\nreturn{c:42,\nd:a(),e:"foo"}\n}'
|
expect_exact: [
|
||||||
|
'function f(a){',
|
||||||
|
'return{c:42,',
|
||||||
|
'd:a(),e:"foo"}',
|
||||||
|
'}',
|
||||||
|
]
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ negate_iife_3_evaluate: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(true);
|
console.log(true);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_3_side_effects: {
|
negate_iife_3_side_effects: {
|
||||||
@@ -111,6 +112,7 @@ negate_iife_3_off_evaluate: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(true);
|
console.log(true);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_4: {
|
negate_iife_4: {
|
||||||
@@ -243,6 +245,7 @@ negate_iife_nested: {
|
|||||||
}(7);
|
}(7);
|
||||||
}).f();
|
}).f();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_nested_off: {
|
negate_iife_nested_off: {
|
||||||
@@ -275,6 +278,7 @@ negate_iife_nested_off: {
|
|||||||
})(7);
|
})(7);
|
||||||
}).f();
|
}).f();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
negate_iife_issue_1073: {
|
negate_iife_issue_1073: {
|
||||||
@@ -299,6 +303,7 @@ negate_iife_issue_1073: {
|
|||||||
};
|
};
|
||||||
}(7))();
|
}(7))();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1254_negate_iife_false: {
|
issue_1254_negate_iife_false: {
|
||||||
@@ -313,6 +318,7 @@ issue_1254_negate_iife_false: {
|
|||||||
})()();
|
})()();
|
||||||
}
|
}
|
||||||
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
expect_exact: '(function(){return function(){console.log("test")}})()();'
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1254_negate_iife_true: {
|
issue_1254_negate_iife_true: {
|
||||||
@@ -327,6 +333,7 @@ issue_1254_negate_iife_true: {
|
|||||||
})()();
|
})()();
|
||||||
}
|
}
|
||||||
expect_exact: '!function(){return function(){console.log("test")}}()();'
|
expect_exact: '!function(){return function(){console.log("test")}}()();'
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1254_negate_iife_nested: {
|
issue_1254_negate_iife_nested: {
|
||||||
@@ -341,6 +348,7 @@ issue_1254_negate_iife_nested: {
|
|||||||
})()()()()();
|
})()()()()();
|
||||||
}
|
}
|
||||||
expect_exact: '!function(){return function(){console.log("test")}}()()()()();'
|
expect_exact: '!function(){return function(){console.log("test")}}()()()()();'
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1288: {
|
issue_1288: {
|
||||||
|
|||||||
@@ -157,17 +157,21 @@ computed_property_names_evaluated_2: {
|
|||||||
|
|
||||||
shorthand_properties: {
|
shorthand_properties: {
|
||||||
mangle = true;
|
mangle = true;
|
||||||
input: (function() {
|
input: {
|
||||||
|
(function() {
|
||||||
var prop = 1;
|
var prop = 1;
|
||||||
const value = {prop};
|
const value = {prop};
|
||||||
return value;
|
return value;
|
||||||
})();
|
})();
|
||||||
expect: (function() {
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
var n = 1;
|
var n = 1;
|
||||||
const r = {prop:n};
|
const r = {prop:n};
|
||||||
return r;
|
return r;
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
concise_methods: {
|
concise_methods: {
|
||||||
beautify = {
|
beautify = {
|
||||||
@@ -233,9 +237,7 @@ concise_methods_with_computed_property2: {
|
|||||||
};
|
};
|
||||||
doSomething(foo[[1]]());
|
doSomething(foo[[1]]());
|
||||||
}
|
}
|
||||||
expect_exact: {
|
expect_exact: 'var foo={[[1]](){return"success"}};doSomething(foo[[1]]());'
|
||||||
'var foo={[[1]](){return"success"}};doSomething(foo[[1]]());'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
concise_methods_with_various_property_names: {
|
concise_methods_with_various_property_names: {
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ reduce_vars: {
|
|||||||
})();
|
})();
|
||||||
console.log(2);
|
console.log(2);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
modified: {
|
modified: {
|
||||||
@@ -401,6 +402,7 @@ iife: {
|
|||||||
console.log(0, 1 * b, 5);
|
console.log(0, 1 * b, 5);
|
||||||
}(1, 2, 3);
|
}(1, 2, 3);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
iife_new: {
|
iife_new: {
|
||||||
@@ -420,6 +422,7 @@ iife_new: {
|
|||||||
console.log(0, 1 * b, 5);
|
console.log(0, 1 * b, 5);
|
||||||
}(1, 2, 3);
|
}(1, 2, 3);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
multi_def: {
|
multi_def: {
|
||||||
@@ -707,6 +710,7 @@ toplevel_on: {
|
|||||||
expect: {
|
expect: {
|
||||||
console.log(3);
|
console.log(3);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
toplevel_off: {
|
toplevel_off: {
|
||||||
@@ -724,6 +728,7 @@ toplevel_off: {
|
|||||||
var x = 3;
|
var x = 3;
|
||||||
console.log(x);
|
console.log(x);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
toplevel_on_loops_1: {
|
toplevel_on_loops_1: {
|
||||||
@@ -751,6 +756,7 @@ toplevel_on_loops_1: {
|
|||||||
})();
|
})();
|
||||||
while (x);
|
while (x);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
toplevel_off_loops_1: {
|
toplevel_off_loops_1: {
|
||||||
@@ -779,6 +785,7 @@ toplevel_off_loops_1: {
|
|||||||
bar();
|
bar();
|
||||||
while (x);
|
while (x);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
toplevel_on_loops_2: {
|
toplevel_on_loops_2: {
|
||||||
@@ -1121,6 +1128,7 @@ defun_label: {
|
|||||||
}(2));
|
}(2));
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
double_reference: {
|
double_reference: {
|
||||||
@@ -1164,6 +1172,7 @@ iife_arguments_1: {
|
|||||||
return f;
|
return f;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
iife_arguments_2: {
|
iife_arguments_2: {
|
||||||
@@ -1186,6 +1195,7 @@ iife_arguments_2: {
|
|||||||
}() === arguments[0]);
|
}() === arguments[0]);
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
iife_eval_1: {
|
iife_eval_1: {
|
||||||
@@ -1207,6 +1217,7 @@ iife_eval_1: {
|
|||||||
return f;
|
return f;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
iife_eval_2: {
|
iife_eval_2: {
|
||||||
@@ -1230,6 +1241,7 @@ iife_eval_2: {
|
|||||||
console.log(x() === eval("x"));
|
console.log(x() === eval("x"));
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
iife_func_side_effects: {
|
iife_func_side_effects: {
|
||||||
@@ -1252,3 +1264,103 @@ iife_func_side_effects: {
|
|||||||
})(x(), 0, z());
|
})(x(), 0, z());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_1595_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f(a) {
|
||||||
|
return f(a + 1);
|
||||||
|
})(2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function f(a) {
|
||||||
|
return f(a + 1);
|
||||||
|
})(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1595_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f(a) {
|
||||||
|
return g(a + 1);
|
||||||
|
})(2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
return g(a + 1);
|
||||||
|
})(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1595_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function f(a) {
|
||||||
|
return g(a + 1);
|
||||||
|
})(2);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
return g(3);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1595_4: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function iife(a, b, c) {
|
||||||
|
console.log(a, b, c);
|
||||||
|
if (a) iife(a - 1, b, c);
|
||||||
|
})(3, 4, 5);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function iife(a, b, c) {
|
||||||
|
console.log(a, b, c);
|
||||||
|
if (a) iife(a - 1, b, c);
|
||||||
|
})(3, 4, 5);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_1606: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
hoist_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
var a;
|
||||||
|
function g(){};
|
||||||
|
var b = 2;
|
||||||
|
x(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
var a, b;
|
||||||
|
function g(){};
|
||||||
|
b = 2;
|
||||||
|
x(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
do_screw: {
|
do_screw: {
|
||||||
options = { screw_ie8: true };
|
options = {
|
||||||
|
screw_ie8: true,
|
||||||
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
screw_ie8: true,
|
screw_ie8: true,
|
||||||
ascii_only: true
|
ascii_only: true,
|
||||||
};
|
}
|
||||||
|
input: {
|
||||||
input: f("\v");
|
f("\v");
|
||||||
expect_exact: 'f("\\v");';
|
}
|
||||||
|
expect_exact: 'f("\\v");'
|
||||||
}
|
}
|
||||||
|
|
||||||
dont_screw: {
|
dont_screw: {
|
||||||
options = { screw_ie8: false };
|
options = {
|
||||||
beautify = { screw_ie8: false, ascii_only: true };
|
screw_ie8: false,
|
||||||
|
}
|
||||||
input: f("\v");
|
beautify = {
|
||||||
expect_exact: 'f("\\x0B");';
|
screw_ie8: false,
|
||||||
|
ascii_only: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
f("\v");
|
||||||
|
}
|
||||||
|
expect_exact: 'f("\\x0B");'
|
||||||
}
|
}
|
||||||
|
|
||||||
do_screw_constants: {
|
do_screw_constants: {
|
||||||
@@ -119,6 +128,7 @@ do_screw_try_catch_undefined: {
|
|||||||
return void 0===o
|
return void 0===o
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
dont_screw_try_catch_undefined: {
|
dont_screw_try_catch_undefined: {
|
||||||
@@ -147,6 +157,7 @@ dont_screw_try_catch_undefined: {
|
|||||||
return n === undefined
|
return n === undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
reduce_vars: {
|
reduce_vars: {
|
||||||
@@ -199,6 +210,7 @@ issue_1586_1: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: "function f(){try{}catch(c){console.log(c.message)}}"
|
expect_exact: "function f(){try{}catch(c){console.log(c.message)}}"
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1586_2: {
|
issue_1586_2: {
|
||||||
@@ -217,4 +229,5 @@ issue_1586_2: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_exact: "function f(){try{}catch(c){console.log(c.message)}}"
|
expect_exact: "function f(){try{}catch(c){console.log(c.message)}}"
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ make_sequences_4: {
|
|||||||
switch (x = 5, y) {}
|
switch (x = 5, y) {}
|
||||||
with (x = 5, obj);
|
with (x = 5, obj);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
lift_sequences_1: {
|
lift_sequences_1: {
|
||||||
@@ -103,15 +104,18 @@ lift_sequences_1: {
|
|||||||
lift_sequences_2: {
|
lift_sequences_2: {
|
||||||
options = { sequences: true, evaluate: true };
|
options = { sequences: true, evaluate: true };
|
||||||
input: {
|
input: {
|
||||||
var foo, bar;
|
var foo = 1, bar;
|
||||||
foo.x = (foo = {}, 10);
|
foo.x = (foo = {}, 10);
|
||||||
bar = (bar = {}, 10);
|
bar = (bar = {}, 10);
|
||||||
|
console.log(foo, bar);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
var foo, bar;
|
var foo = 1, bar;
|
||||||
foo.x = (foo = {}, 10),
|
foo.x = (foo = {}, 10),
|
||||||
bar = {}, bar = 10;
|
bar = {}, bar = 10,
|
||||||
|
console.log(foo, bar);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
lift_sequences_3: {
|
lift_sequences_3: {
|
||||||
@@ -138,6 +142,23 @@ lift_sequences_4: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lift_sequences_5: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 2, b;
|
||||||
|
a *= (b, a = 4, 3);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 2, b;
|
||||||
|
b, a *= (a = 4, 3),
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "6"
|
||||||
|
}
|
||||||
|
|
||||||
for_sequences: {
|
for_sequences: {
|
||||||
options = { sequences: true };
|
options = { sequences: true };
|
||||||
input: {
|
input: {
|
||||||
@@ -230,6 +251,7 @@ negate_iife_for: {
|
|||||||
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
|
for (!function() {}(), i = 0; i < 5; i++) console.log(i);
|
||||||
for (function() {}(); i < 5; i++) console.log(i);
|
for (function() {}(); i < 5; i++) console.log(i);
|
||||||
}
|
}
|
||||||
|
expect_stdout: true
|
||||||
}
|
}
|
||||||
|
|
||||||
iife: {
|
iife: {
|
||||||
|
|||||||
131
test/compress/transform.js
Normal file
131
test/compress/transform.js
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
booleans_evaluate: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof void 0 != "undefined");
|
||||||
|
console.log(1 == 1, 1 === 1)
|
||||||
|
console.log(1 != 1, 1 !== 1)
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!1);
|
||||||
|
console.log(!0, !0);
|
||||||
|
console.log(!1, !1);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
booleans_global_defs: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
global_defs: {
|
||||||
|
A: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(A == 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(!0);
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
condition_evaluate: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
dead_code: false,
|
||||||
|
evaluate: true,
|
||||||
|
loops: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (1 === 2);
|
||||||
|
for (; 1 == true;);
|
||||||
|
if (void 0 == null);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (!1);
|
||||||
|
for (; !0;);
|
||||||
|
if (!0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if_else_empty: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
if ({} ? a : b); else {}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
!{} ? b : a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label_if_break: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L: if (true) {
|
||||||
|
a;
|
||||||
|
break L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while_if_break: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
loops: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (a) {
|
||||||
|
if (b) if(c) d;
|
||||||
|
if (e) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for(; a && (b && c && d, !e););
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if_return: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(w, x, y, z) {
|
||||||
|
if (x) return;
|
||||||
|
if (w) {
|
||||||
|
if (y) return;
|
||||||
|
} else if (z) return;
|
||||||
|
if (x == y) return true;
|
||||||
|
|
||||||
|
if (x) w();
|
||||||
|
if (y) z();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(w, x, y, z) {
|
||||||
|
if (!x) {
|
||||||
|
if (w) {
|
||||||
|
if (y) return;
|
||||||
|
} else if (z) return;
|
||||||
|
return x == y || (x && w(), y && z(), !0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -152,7 +152,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("Should process inline source map", function(done) {
|
it("Should process inline source map", function(done) {
|
||||||
var command = uglifyjscmd + ' test/input/issue-520/input.js -cm toplevel --in-source-map inline --source-map-inline';
|
var command = uglifyjscmd + ' test/input/issue-520/input.js -mc toplevel --in-source-map inline --source-map-inline';
|
||||||
|
|
||||||
exec(command, function (err, stdout) {
|
exec(command, function (err, stdout) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ describe("Directives", function() {
|
|||||||
if (node instanceof uglify.AST_Symbol && node.name === "_check_") {
|
if (node instanceof uglify.AST_Symbol && node.name === "_check_") {
|
||||||
checked = true;
|
checked = true;
|
||||||
for (var j = 0; j < tests[i].directives.length; j++) {
|
for (var j = 0; j < tests[i].directives.length; j++) {
|
||||||
assert.equal(checkWalker.has_directive(tests[i].directives[j]), true,
|
assert.ok(checkWalker.has_directive(tests[i].directives[j]),
|
||||||
"Did not found directive '" + tests[i].directives[j] + "' in test " + tests[i].input)
|
"Did not found directive '" + tests[i].directives[j] + "' in test " + tests[i].input)
|
||||||
}
|
}
|
||||||
for (var k = 0; k < tests[i].non_directives.length; k++) {
|
for (var k = 0; k < tests[i].non_directives.length; k++) {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ describe("minify", function() {
|
|||||||
});
|
});
|
||||||
it("Should process inline source map", function() {
|
it("Should process inline source map", function() {
|
||||||
var code = Uglify.minify("./test/input/issue-520/input.js", {
|
var code = Uglify.minify("./test/input/issue-520/input.js", {
|
||||||
|
compress: { toplevel: true },
|
||||||
inSourceMap: "inline",
|
inSourceMap: "inline",
|
||||||
sourceMapInline: true
|
sourceMapInline: true
|
||||||
}).code + "\n";
|
}).code + "\n";
|
||||||
|
|||||||
@@ -6,10 +6,22 @@ var U = require("../tools/node");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
var vm = require("vm");
|
||||||
|
|
||||||
var tests_dir = path.dirname(module.filename);
|
var tests_dir = path.dirname(module.filename);
|
||||||
var failures = 0;
|
var failures = 0;
|
||||||
var failed_files = {};
|
var failed_files = {};
|
||||||
|
var same_stdout = ~process.version.lastIndexOf("v0.12.", 0) ? function(expected, actual) {
|
||||||
|
if (typeof expected != typeof actual) return false;
|
||||||
|
if (typeof expected != "string") {
|
||||||
|
if (expected.name != actual.name) return false;
|
||||||
|
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||||
|
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||||
|
}
|
||||||
|
return expected == actual;
|
||||||
|
} : function(expected, actual) {
|
||||||
|
return typeof expected == typeof actual && expected.toString() == actual.toString();
|
||||||
|
};
|
||||||
|
|
||||||
run_compress_tests();
|
run_compress_tests();
|
||||||
if (failures) {
|
if (failures) {
|
||||||
@@ -71,10 +83,15 @@ function test_directory(dir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function as_toplevel(input, mangle_options) {
|
function as_toplevel(input, mangle_options) {
|
||||||
if (input instanceof U.AST_BlockStatement) input = input.body;
|
if (!(input instanceof U.AST_BlockStatement))
|
||||||
else if (input instanceof U.AST_Statement) input = [ input ];
|
throw new Error("Unsupported input syntax");
|
||||||
else throw new Error("Unsupported input syntax");
|
for (var i = 0; i < input.body.length; i++) {
|
||||||
var toplevel = new U.AST_Toplevel({ body: input });
|
var stat = input.body[i];
|
||||||
|
if (stat instanceof U.AST_SimpleStatement && stat.body instanceof U.AST_String)
|
||||||
|
input.body[i] = new U.AST_Directive(stat.body);
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
var toplevel = new U.AST_Toplevel(input);
|
||||||
toplevel.figure_out_scope(mangle_options);
|
toplevel.figure_out_scope(mangle_options);
|
||||||
return toplevel;
|
return toplevel;
|
||||||
}
|
}
|
||||||
@@ -165,6 +182,36 @@ function run_compress_tests() {
|
|||||||
failed_files[file] = 1;
|
failed_files[file] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (test.expect_stdout) {
|
||||||
|
var stdout = run_code(make_code(input, output_options));
|
||||||
|
if (test.expect_stdout === true) {
|
||||||
|
test.expect_stdout = stdout;
|
||||||
|
}
|
||||||
|
if (!same_stdout(test.expect_stdout, stdout)) {
|
||||||
|
log("!!! Invalid input or expected stdout\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
||||||
|
input: input_code,
|
||||||
|
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
||||||
|
expected: test.expect_stdout,
|
||||||
|
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
|
||||||
|
actual: stdout,
|
||||||
|
});
|
||||||
|
failures++;
|
||||||
|
failed_files[file] = 1;
|
||||||
|
} else {
|
||||||
|
stdout = run_code(output);
|
||||||
|
if (!same_stdout(test.expect_stdout, stdout)) {
|
||||||
|
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED {expected_type}---\n{expected}\n---ACTUAL {actual_type}---\n{actual}\n\n", {
|
||||||
|
input: input_code,
|
||||||
|
expected_type: typeof test.expect_stdout == "string" ? "STDOUT" : "ERROR",
|
||||||
|
expected: test.expect_stdout,
|
||||||
|
actual_type: typeof stdout == "string" ? "STDOUT" : "ERROR",
|
||||||
|
actual: stdout,
|
||||||
|
});
|
||||||
|
failures++;
|
||||||
|
failed_files[file] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var tests = parse_test(path.resolve(dir, file));
|
var tests = parse_test(path.resolve(dir, file));
|
||||||
@@ -214,6 +261,23 @@ function parse_test(file) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function read_string(stat) {
|
||||||
|
if (stat.TYPE == "SimpleStatement") {
|
||||||
|
var body = stat.body;
|
||||||
|
switch(body.TYPE) {
|
||||||
|
case "String":
|
||||||
|
return body.value;
|
||||||
|
case "Array":
|
||||||
|
return body.elements.map(function(element) {
|
||||||
|
if (element.TYPE !== "String")
|
||||||
|
throw new Error("Should be array of strings");
|
||||||
|
return element.value;
|
||||||
|
}).join("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error("Should be string or array of strings");
|
||||||
|
}
|
||||||
|
|
||||||
function get_one_test(name, block) {
|
function get_one_test(name, block) {
|
||||||
var test = { name: name, options: {} };
|
var test = { name: name, options: {} };
|
||||||
var tw = new U.TreeWalker(function(node, descend){
|
var tw = new U.TreeWalker(function(node, descend){
|
||||||
@@ -226,28 +290,26 @@ function parse_test(file) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof U.AST_LabeledStatement) {
|
if (node instanceof U.AST_LabeledStatement) {
|
||||||
|
var label = node.label;
|
||||||
assert.ok(
|
assert.ok(
|
||||||
["input", "expect", "expect_exact", "expect_warnings"].indexOf(node.label.name) >= 0,
|
["input", "expect", "expect_exact", "expect_warnings", "expect_stdout"].indexOf(label.name) >= 0,
|
||||||
tmpl("Unsupported label {name} [{line},{col}]", {
|
tmpl("Unsupported label {name} [{line},{col}]", {
|
||||||
name: node.label.name,
|
name: label.name,
|
||||||
line: node.label.start.line,
|
line: label.start.line,
|
||||||
col: node.label.start.col
|
col: label.start.col
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
var stat = node.body;
|
var stat = node.body;
|
||||||
if (stat instanceof U.AST_BlockStatement) {
|
if (label.name == "expect_exact") {
|
||||||
if (stat.body.length == 1) stat = stat.body[0];
|
test[label.name] = read_string(stat);
|
||||||
else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
|
} else if (label.name == "expect_stdout") {
|
||||||
}
|
if (stat.TYPE == "SimpleStatement" && stat.body instanceof U.AST_Boolean) {
|
||||||
if (node.label.name === "expect_exact") {
|
test[label.name] = stat.body.value;
|
||||||
if (!(stat.TYPE === "SimpleStatement" && stat.body.TYPE === "String")) {
|
|
||||||
throw new Error(
|
|
||||||
"The value of the expect_exact clause should be a string, " +
|
|
||||||
"like `expect_exact: \"some.exact.javascript;\"`");
|
|
||||||
}
|
|
||||||
test[node.label.name] = stat.body.start.value
|
|
||||||
} else {
|
} else {
|
||||||
test[node.label.name] = stat;
|
test[label.name] = read_string(stat) + "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
test[label.name] = stat;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -269,3 +331,19 @@ function evaluate(code) {
|
|||||||
code = make_code(code, { beautify: true });
|
code = make_code(code, { beautify: true });
|
||||||
return new Function("return(" + code + ")")();
|
return new Function("return(" + code + ")")();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function run_code(code) {
|
||||||
|
var stdout = "";
|
||||||
|
var original_write = process.stdout.write;
|
||||||
|
process.stdout.write = function(chunk) {
|
||||||
|
stdout += chunk;
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
new vm.Script(code).runInNewContext({ console: console }, { timeout: 5000 });
|
||||||
|
return stdout;
|
||||||
|
} catch (ex) {
|
||||||
|
return ex;
|
||||||
|
} finally {
|
||||||
|
process.stdout.write = original_write;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user