Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
642ba2e92c | ||
|
|
089ac908b7 | ||
|
|
0d3fd2ef30 | ||
|
|
e98119496a | ||
|
|
bdfcbf496b | ||
|
|
dba8da4800 | ||
|
|
60c0f40250 | ||
|
|
e02771a5f2 | ||
|
|
f96f796f71 | ||
|
|
a9fa178f86 | ||
|
|
53355bdb24 | ||
|
|
f05c99d89f | ||
|
|
b49230ab8d | ||
|
|
78856a3dab | ||
|
|
1e5e13ed81 |
24
README.md
24
README.md
@@ -14,7 +14,7 @@ Install
|
|||||||
|
|
||||||
From NPM:
|
From NPM:
|
||||||
|
|
||||||
npm install uglify-js2
|
npm install uglify-js
|
||||||
|
|
||||||
From Git:
|
From Git:
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ From Git:
|
|||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
uglifyjs2 [input files] [options]
|
uglifyjs [input files] [options]
|
||||||
|
|
||||||
UglifyJS2 can take multiple input files. It's recommended that you pass the
|
UglifyJS2 can take multiple input files. It's recommended that you pass the
|
||||||
input files first, then pass the options. UglifyJS will parse input files
|
input files first, then pass the options. UglifyJS will parse input files
|
||||||
@@ -98,12 +98,12 @@ map.
|
|||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
uglifyjs2 /home/doe/work/foo/src/js/file1.js \
|
uglifyjs /home/doe/work/foo/src/js/file1.js \
|
||||||
/home/doe/work/foo/src/js/file2.js \
|
/home/doe/work/foo/src/js/file2.js \
|
||||||
-o foo.min.js \
|
-o foo.min.js \
|
||||||
--source-map foo.min.js.map \
|
--source-map foo.min.js.map \
|
||||||
--source-map-root http://foo.com/src \
|
--source-map-root http://foo.com/src \
|
||||||
-p 5 -c -m
|
-p 5 -c -m
|
||||||
|
|
||||||
The above will compress and mangle `file1.js` and `file2.js`, will drop the
|
The above will compress and mangle `file1.js` and `file2.js`, will drop the
|
||||||
output in `foo.min.js` and the source map in `foo.min.js.map`. The source
|
output in `foo.min.js` and the source map in `foo.min.js.map`. The source
|
||||||
@@ -140,7 +140,7 @@ When mangling is enabled but you want to prevent certain names from being
|
|||||||
mangled, you can declare those names with `--reserved` (`-r`) — pass a
|
mangled, you can declare those names with `--reserved` (`-r`) — pass a
|
||||||
comma-separated list of names. For example:
|
comma-separated list of names. For example:
|
||||||
|
|
||||||
uglifyjs2 ... -m -r '$,require,exports'
|
uglifyjs ... -m -r '$,require,exports'
|
||||||
|
|
||||||
to prevent the `require`, `exports` and `$` names from being changed.
|
to prevent the `require`, `exports` and `$` names from being changed.
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ separate file and include it into the build. For example you can have a
|
|||||||
|
|
||||||
and build your code like this:
|
and build your code like this:
|
||||||
|
|
||||||
uglifyjs2 build/defines.js js/foo.js js/bar.js... -c
|
uglifyjs build/defines.js js/foo.js js/bar.js... -c
|
||||||
|
|
||||||
UglifyJS will notice the constants and, since they cannot be altered, it
|
UglifyJS will notice the constants and, since they cannot be altered, it
|
||||||
will evaluate references to them to the value itself and drop unreachable
|
will evaluate references to them to the value itself and drop unreachable
|
||||||
@@ -288,7 +288,7 @@ SpiderMonkey AST. It has a small CLI utility that parses one file and dumps
|
|||||||
the AST in JSON on the standard output. To use UglifyJS to mangle and
|
the AST in JSON on the standard output. To use UglifyJS to mangle and
|
||||||
compress that:
|
compress that:
|
||||||
|
|
||||||
acorn file.js | uglifyjs2 --spidermonkey -m -c
|
acorn file.js | uglifyjs --spidermonkey -m -c
|
||||||
|
|
||||||
The `--spidermonkey` option tells UglifyJS that all input files are not
|
The `--spidermonkey` option tells UglifyJS that all input files are not
|
||||||
JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
|
JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
|
||||||
@@ -310,7 +310,7 @@ API Reference
|
|||||||
Assuming installation via NPM, you can load UglifyJS in your application
|
Assuming installation via NPM, you can load UglifyJS in your application
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
var UglifyJS = require("uglify-js2");
|
var UglifyJS = require("uglify-js");
|
||||||
|
|
||||||
It exports a lot of names, but I'll discuss here the basics that are needed
|
It exports a lot of names, but I'll discuss here the basics that are needed
|
||||||
for parsing, mangling and compressing a piece of code. The sequence is (1)
|
for parsing, mangling and compressing a piece of code. The sequence is (1)
|
||||||
|
|||||||
@@ -810,7 +810,7 @@ var AST_SymbolRef = DEFNODE("SymbolRef", null, {
|
|||||||
|
|
||||||
var AST_LabelRef = DEFNODE("LabelRef", null, {
|
var AST_LabelRef = DEFNODE("LabelRef", null, {
|
||||||
$documentation: "Reference to a label symbol",
|
$documentation: "Reference to a label symbol",
|
||||||
}, AST_SymbolRef);
|
}, AST_Symbol);
|
||||||
|
|
||||||
var AST_This = DEFNODE("This", null, {
|
var AST_This = DEFNODE("This", null, {
|
||||||
$documentation: "The `this` symbol",
|
$documentation: "The `this` symbol",
|
||||||
|
|||||||
155
lib/compress.js
155
lib/compress.js
@@ -554,12 +554,24 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_UnaryPrefix, function(){
|
def(AST_UnaryPrefix, function(){
|
||||||
return this.operator == "typeof";
|
return this.operator == "typeof";
|
||||||
});
|
});
|
||||||
def(AST_Binary, function(){
|
def(AST_Binary, function(compressor){
|
||||||
return this.operator == "+" &&
|
return this.operator == "+" &&
|
||||||
(this.left.is_string() || this.right.is_string());
|
(this.left.is_string(compressor) || this.right.is_string(compressor));
|
||||||
});
|
});
|
||||||
def(AST_Assign, function(){
|
def(AST_Assign, function(compressor){
|
||||||
return this.operator == "=" && this.right.is_string();
|
return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
|
||||||
|
});
|
||||||
|
def(AST_Seq, function(compressor){
|
||||||
|
return this.cdr.is_string(compressor);
|
||||||
|
});
|
||||||
|
def(AST_Conditional, function(compressor){
|
||||||
|
return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
|
||||||
|
});
|
||||||
|
def(AST_Call, function(compressor){
|
||||||
|
return compressor.option("unsafe")
|
||||||
|
&& this.expression instanceof AST_SymbolRef
|
||||||
|
&& this.expression.name == "String"
|
||||||
|
&& this.expression.undeclared();
|
||||||
});
|
});
|
||||||
})(function(node, func){
|
})(function(node, func){
|
||||||
node.DEFMETHOD("is_string", func);
|
node.DEFMETHOD("is_string", func);
|
||||||
@@ -814,10 +826,12 @@ merge(Compressor.prototype, {
|
|||||||
(function(def){
|
(function(def){
|
||||||
def(AST_Statement, function(){ return null });
|
def(AST_Statement, function(){ return null });
|
||||||
def(AST_Jump, function(){ return this });
|
def(AST_Jump, function(){ return this });
|
||||||
def(AST_BlockStatement, function(){
|
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]);
|
||||||
});
|
};
|
||||||
|
def(AST_BlockStatement, block_aborts);
|
||||||
|
def(AST_SwitchBranch, block_aborts);
|
||||||
def(AST_If, function(){
|
def(AST_If, function(){
|
||||||
return this.alternative && aborts(this.body) && aborts(this.alternative);
|
return this.alternative && aborts(this.body) && aborts(this.alternative);
|
||||||
});
|
});
|
||||||
@@ -885,7 +899,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef && !(node instanceof AST_LabelRef)) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
push_uniq(in_use, node.definition());
|
push_uniq(in_use, node.definition());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -908,8 +922,7 @@ merge(Compressor.prototype, {
|
|||||||
if (decl instanceof AST_SymbolDeclaration) {
|
if (decl instanceof AST_SymbolDeclaration) {
|
||||||
decl.init.forEach(function(init){
|
decl.init.forEach(function(init){
|
||||||
var tw = new TreeWalker(function(node){
|
var tw = new TreeWalker(function(node){
|
||||||
if (node instanceof AST_SymbolRef
|
if (node instanceof AST_SymbolRef) {
|
||||||
&& !(node instanceof AST_LabelRef)) {
|
|
||||||
push_uniq(in_use, node.definition());
|
push_uniq(in_use, node.definition());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -920,7 +933,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
// pass 3: we should drop declarations not in_use
|
// pass 3: we should drop declarations not in_use
|
||||||
var tt = new TreeTransformer(
|
var tt = new TreeTransformer(
|
||||||
function before(node, descend) {
|
function before(node, descend, in_list) {
|
||||||
if (node instanceof AST_Lambda) {
|
if (node instanceof AST_Lambda) {
|
||||||
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];
|
||||||
@@ -1011,6 +1024,19 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
if (node instanceof AST_For && node.init instanceof AST_BlockStatement) {
|
||||||
|
descend(node, this);
|
||||||
|
// certain combination of unused name + side effect leads to:
|
||||||
|
// https://github.com/mishoo/UglifyJS2/issues/44
|
||||||
|
// that's an invalid AST.
|
||||||
|
// We fix it at this stage by moving the `var` outside the `for`.
|
||||||
|
var body = node.init.body.slice(0, -1);
|
||||||
|
node.init = node.init.body.slice(-1)[0].body;
|
||||||
|
body.push(node);
|
||||||
|
return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
|
||||||
|
body: body
|
||||||
|
});
|
||||||
|
}
|
||||||
if (node instanceof AST_Scope && node !== self)
|
if (node instanceof AST_Scope && node !== self)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -1336,6 +1362,79 @@ merge(Compressor.prototype, {
|
|||||||
if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self)
|
if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self)
|
||||||
last_branch.body.pop();
|
last_branch.body.pop();
|
||||||
}
|
}
|
||||||
|
var exp = self.expression.evaluate(compressor);
|
||||||
|
out: if (exp.length == 2) try {
|
||||||
|
// constant expression
|
||||||
|
self.expression = exp[0];
|
||||||
|
if (!compressor.option("dead_code")) break out;
|
||||||
|
var value = exp[1];
|
||||||
|
var in_if = false;
|
||||||
|
var in_block = false;
|
||||||
|
var started = false;
|
||||||
|
var stopped = false;
|
||||||
|
var ruined = false;
|
||||||
|
var tt = new TreeTransformer(function(node, descend, in_list){
|
||||||
|
if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) {
|
||||||
|
// no need to descend these node types
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
else if (node instanceof AST_Switch && node === self) {
|
||||||
|
node = node.clone();
|
||||||
|
descend(node, this);
|
||||||
|
return ruined ? node : make_node(AST_BlockStatement, node, {
|
||||||
|
body: node.body.reduce(function(a, branch){
|
||||||
|
return a.concat(branch.body);
|
||||||
|
}, [])
|
||||||
|
}).transform(compressor);
|
||||||
|
}
|
||||||
|
else if (node instanceof AST_If || node instanceof AST_Try) {
|
||||||
|
var save = in_if;
|
||||||
|
in_if = !in_block;
|
||||||
|
descend(node, this);
|
||||||
|
in_if = save;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
|
||||||
|
var save = in_block;
|
||||||
|
in_block = true;
|
||||||
|
descend(node, this);
|
||||||
|
in_block = save;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
|
||||||
|
if (in_if) {
|
||||||
|
ruined = true;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
if (in_block) return node;
|
||||||
|
stopped = true;
|
||||||
|
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
||||||
|
}
|
||||||
|
else if (node instanceof AST_SwitchBranch && this.parent() === self) {
|
||||||
|
if (stopped) return MAP.skip;
|
||||||
|
if (node instanceof AST_Case) {
|
||||||
|
var exp = node.expression.evaluate(compressor);
|
||||||
|
if (exp.length < 2) {
|
||||||
|
// got a case with non-constant expression, baling out
|
||||||
|
throw self;
|
||||||
|
}
|
||||||
|
if (exp[1] === value || started) {
|
||||||
|
started = true;
|
||||||
|
if (aborts(node)) stopped = true;
|
||||||
|
descend(node, this);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
return MAP.skip;
|
||||||
|
}
|
||||||
|
descend(node, this);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tt.stack = compressor.stack; // so that's able to see parent nodes
|
||||||
|
self = self.transform(tt);
|
||||||
|
} catch(ex) {
|
||||||
|
if (ex !== self) throw ex;
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1414,9 +1513,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
|
else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
|
||||||
return make_node(AST_Binary, self, {
|
return make_node(AST_Binary, self, {
|
||||||
left: exp.expression,
|
left: make_node(AST_String, self, { value: "" }),
|
||||||
operator: "+",
|
operator: "+",
|
||||||
right: make_node(AST_String, self, { value: "" })
|
right: exp.expression
|
||||||
}).transform(compressor);
|
}).transform(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1450,8 +1549,19 @@ merge(Compressor.prototype, {
|
|||||||
OPT(AST_Seq, function(self, compressor){
|
OPT(AST_Seq, function(self, compressor){
|
||||||
if (!compressor.option("side_effects"))
|
if (!compressor.option("side_effects"))
|
||||||
return self;
|
return self;
|
||||||
if (!self.car.has_side_effects())
|
if (!self.car.has_side_effects()) {
|
||||||
return self.cdr;
|
// we shouldn't compress (1,eval)(something) to
|
||||||
|
// eval(something) because that changes the meaning of
|
||||||
|
// eval (becomes lexical instead of global).
|
||||||
|
var p;
|
||||||
|
if (!(self.cdr instanceof AST_SymbolRef
|
||||||
|
&& self.cdr.name == "eval"
|
||||||
|
&& self.cdr.undeclared()
|
||||||
|
&& (p = compressor.parent()) instanceof AST_Call
|
||||||
|
&& p.expression === self)) {
|
||||||
|
return self.cdr;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (compressor.option("cascade")) {
|
if (compressor.option("cascade")) {
|
||||||
if (self.car instanceof AST_Assign
|
if (self.car instanceof AST_Assign
|
||||||
&& !self.car.left.has_side_effects()
|
&& !self.car.left.has_side_effects()
|
||||||
@@ -1537,10 +1647,12 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
OPT(AST_Binary, function(self, compressor){
|
OPT(AST_Binary, function(self, compressor){
|
||||||
function reverse(op) {
|
function reverse(op) {
|
||||||
if (op) self.operator = op;
|
if (!(self.left.has_side_effects() && self.right.has_side_effects())) {
|
||||||
var tmp = self.left;
|
if (op) self.operator = op;
|
||||||
self.left = self.right;
|
var tmp = self.left;
|
||||||
self.right = tmp;
|
self.left = self.right;
|
||||||
|
self.right = tmp;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (commutativeOperators(self.operator)) {
|
if (commutativeOperators(self.operator)) {
|
||||||
if (self.right instanceof AST_Constant
|
if (self.right instanceof AST_Constant
|
||||||
@@ -1552,7 +1664,7 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.option("comparisons")) switch (self.operator) {
|
if (compressor.option("comparisons")) switch (self.operator) {
|
||||||
case "===":
|
case "===":
|
||||||
case "!==":
|
case "!==":
|
||||||
if ((self.left.is_string() && self.right.is_string()) ||
|
if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
|
||||||
(self.left.is_boolean() && self.right.is_boolean())) {
|
(self.left.is_boolean() && self.right.is_boolean())) {
|
||||||
self.operator = self.operator.substr(0, 2);
|
self.operator = self.operator.substr(0, 2);
|
||||||
}
|
}
|
||||||
@@ -1630,6 +1742,11 @@ merge(Compressor.prototype, {
|
|||||||
case "<=": reverse(">="); break;
|
case "<=": reverse(">="); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (self.operator == "+" && self.right instanceof AST_String
|
||||||
|
&& self.right.getValue() === "" && self.left instanceof AST_Binary
|
||||||
|
&& self.left.operator == "+" && self.left.is_string()) {
|
||||||
|
return self.left;
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ function OutputStream(options) {
|
|||||||
source_map : null,
|
source_map : null,
|
||||||
bracketize : false,
|
bracketize : false,
|
||||||
semicolons : true,
|
semicolons : true,
|
||||||
comments : false
|
comments : false,
|
||||||
|
preserve_line : false
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
var indentation = 0;
|
var indentation = 0;
|
||||||
@@ -154,6 +155,18 @@ function OutputStream(options) {
|
|||||||
might_need_semicolon = false;
|
might_need_semicolon = false;
|
||||||
maybe_newline();
|
maybe_newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
|
||||||
|
var target_line = stack[stack.length - 1].start.line;
|
||||||
|
while (current_line < target_line) {
|
||||||
|
OUTPUT += "\n";
|
||||||
|
current_pos++;
|
||||||
|
current_line++;
|
||||||
|
current_col = 0;
|
||||||
|
might_need_space = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (might_need_space) {
|
if (might_need_space) {
|
||||||
var prev = last_char();
|
var prev = last_char();
|
||||||
if ((is_identifier_char(prev)
|
if ((is_identifier_char(prev)
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ TreeTransformer.prototype = new TreeWalker;
|
|||||||
x = this;
|
x = this;
|
||||||
descend(x, tw);
|
descend(x, tw);
|
||||||
} else {
|
} else {
|
||||||
tw.stack[tw.stack - 1] = x = this.clone();
|
tw.stack[tw.stack.length - 1] = x = this.clone();
|
||||||
descend(x, tw);
|
descend(x, tw);
|
||||||
y = tw.after(x, in_list);
|
y = tw.after(x, in_list);
|
||||||
if (y !== undefined) x = y;
|
if (y !== undefined) x = y;
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "uglify-js2",
|
"name": "uglify-js",
|
||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"homepage": "http://lisperator.net/uglifyjs",
|
"homepage": "http://lisperator.net/uglifyjs",
|
||||||
"main": "tools/node.js",
|
"main": "tools/node.js",
|
||||||
"version": "2.1.10",
|
"version": "2.2.0",
|
||||||
"engines": { "node" : ">=0.4.0" },
|
"engines": { "node" : ">=0.4.0" },
|
||||||
"maintainers": [{
|
"maintainers": [{
|
||||||
"name": "Mihai Bazon",
|
"name": "Mihai Bazon",
|
||||||
@@ -15,11 +15,11 @@
|
|||||||
"url": "https://github.com/mishoo/UglifyJS2.git"
|
"url": "https://github.com/mishoo/UglifyJS2.git"
|
||||||
}],
|
}],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"source-map" : "*",
|
"source-map" : "~0.1.7",
|
||||||
"optimist" : "*"
|
"optimist" : "~0.3.5"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"uglifyjs2" : "bin/uglifyjs2"
|
"uglifyjs" : "bin/uglifyjs"
|
||||||
},
|
},
|
||||||
"scripts": {"test": "node test/run-tests.js"}
|
"scripts": {"test": "node test/run-tests.js"}
|
||||||
}
|
}
|
||||||
|
|||||||
31
test/compress/issue-44.js
Normal file
31
test/compress/issue-44.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
issue_44_valid_ast_1: {
|
||||||
|
options = { unused: true };
|
||||||
|
input: {
|
||||||
|
function a(b) {
|
||||||
|
for (var i = 0, e = b.qoo(); ; i++) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a(b) {
|
||||||
|
var i = 0;
|
||||||
|
for (b.qoo(); ; i++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_44_valid_ast_2: {
|
||||||
|
options = { unused: true };
|
||||||
|
input: {
|
||||||
|
function a(b) {
|
||||||
|
if (foo) for (var i = 0, e = b.qoo(); ; i++) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function a(b) {
|
||||||
|
if (foo) {
|
||||||
|
var i = 0;
|
||||||
|
for (b.qoo(); ; i++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
210
test/compress/switch.js
Normal file
210
test/compress/switch.js
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
constant_switch_1: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
switch (1+1) {
|
||||||
|
case 1: foo(); break;
|
||||||
|
case 1+1: bar(); break;
|
||||||
|
case 1+1+1: baz(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_2: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
switch (1) {
|
||||||
|
case 1: foo();
|
||||||
|
case 1+1: bar(); break;
|
||||||
|
case 1+1+1: baz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_3: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
switch (10) {
|
||||||
|
case 1: foo();
|
||||||
|
case 1+1: bar(); break;
|
||||||
|
case 1+1+1: baz();
|
||||||
|
default:
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_4: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
switch (2) {
|
||||||
|
case 1:
|
||||||
|
x();
|
||||||
|
if (foo) break;
|
||||||
|
y();
|
||||||
|
break;
|
||||||
|
case 1+1:
|
||||||
|
bar();
|
||||||
|
default:
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
bar();
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_5: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
switch (1) {
|
||||||
|
case 1:
|
||||||
|
x();
|
||||||
|
if (foo) break;
|
||||||
|
y();
|
||||||
|
break;
|
||||||
|
case 1+1:
|
||||||
|
bar();
|
||||||
|
default:
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
// the break inside the if ruins our job
|
||||||
|
// we can still get rid of irrelevant cases.
|
||||||
|
switch (1) {
|
||||||
|
case 1:
|
||||||
|
x();
|
||||||
|
if (foo) break;
|
||||||
|
y();
|
||||||
|
}
|
||||||
|
// XXX: we could optimize this better by inventing an outer
|
||||||
|
// labeled block, but that's kinda tricky.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_6: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
OUT: {
|
||||||
|
foo();
|
||||||
|
switch (1) {
|
||||||
|
case 1:
|
||||||
|
x();
|
||||||
|
if (foo) break OUT;
|
||||||
|
y();
|
||||||
|
case 1+1:
|
||||||
|
bar();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
OUT: {
|
||||||
|
foo();
|
||||||
|
x();
|
||||||
|
if (foo) break OUT;
|
||||||
|
y();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_7: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
OUT: {
|
||||||
|
foo();
|
||||||
|
switch (1) {
|
||||||
|
case 1:
|
||||||
|
x();
|
||||||
|
if (foo) break OUT;
|
||||||
|
for (var x = 0; x < 10; x++) {
|
||||||
|
if (x > 5) break; // this break refers to the for, not to the switch; thus it
|
||||||
|
// shouldn't ruin our optimization
|
||||||
|
console.log(x);
|
||||||
|
}
|
||||||
|
y();
|
||||||
|
case 1+1:
|
||||||
|
bar();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
OUT: {
|
||||||
|
foo();
|
||||||
|
x();
|
||||||
|
if (foo) break OUT;
|
||||||
|
for (var x = 0; x < 10; x++) {
|
||||||
|
if (x > 5) break;
|
||||||
|
console.log(x);
|
||||||
|
}
|
||||||
|
y();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_8: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
OUT: switch (1) {
|
||||||
|
case 1:
|
||||||
|
x();
|
||||||
|
for (;;) break OUT;
|
||||||
|
y();
|
||||||
|
break;
|
||||||
|
case 1+1:
|
||||||
|
bar();
|
||||||
|
default:
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
OUT: {
|
||||||
|
x();
|
||||||
|
for (;;) break OUT;
|
||||||
|
y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constant_switch_9: {
|
||||||
|
options = { dead_code: true, evaluate: true };
|
||||||
|
input: {
|
||||||
|
OUT: switch (1) {
|
||||||
|
case 1:
|
||||||
|
x();
|
||||||
|
for (;;) if (foo) break OUT;
|
||||||
|
y();
|
||||||
|
case 1+1:
|
||||||
|
bar();
|
||||||
|
default:
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
OUT: {
|
||||||
|
x();
|
||||||
|
for (;;) if (foo) break OUT;
|
||||||
|
y();
|
||||||
|
bar();
|
||||||
|
def();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user