aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/benchmark.js49
-rw-r--r--test/compress/arrays.js53
-rw-r--r--test/compress/collapse_vars.js114
-rw-r--r--test/compress/concat-strings.js140
-rw-r--r--test/compress/const.js165
-rw-r--r--test/compress/dead-code.js414
-rw-r--r--test/compress/drop-console.js48
-rw-r--r--test/compress/drop-unused.js502
-rw-r--r--test/compress/evaluate.js48
-rw-r--r--test/compress/global_defs.js147
-rw-r--r--test/compress/hoist_vars.js90
-rw-r--r--test/compress/if_return.js101
-rw-r--r--test/compress/issue-1041.js6
-rw-r--r--test/compress/issue-105.js25
-rw-r--r--test/compress/issue-1261.js118
-rw-r--r--test/compress/issue-1431.js29
-rw-r--r--test/compress/issue-1443.js69
-rw-r--r--test/compress/issue-1446.js71
-rw-r--r--test/compress/issue-1447.js45
-rw-r--r--test/compress/issue-208.js41
-rw-r--r--test/compress/issue-979.js2
-rw-r--r--test/compress/loops.js29
-rw-r--r--test/compress/max_line_len.js28
-rw-r--r--test/compress/negate-iife.js152
-rw-r--r--test/compress/properties.js16
-rw-r--r--test/compress/pure_funcs.js295
-rw-r--r--test/compress/reduce_vars.js124
-rw-r--r--test/compress/sequences.js82
-rw-r--r--test/input/global_defs/nested.js1
-rw-r--r--test/input/global_defs/simple.js1
-rw-r--r--test/input/issue-1482/bracketize.js73
-rw-r--r--test/input/issue-1482/default.js17
-rw-r--r--test/input/issue-1482/input.js12
-rw-r--r--test/jetstream.js87
-rw-r--r--test/mocha/accessorTokens-1492.js32
-rw-r--r--test/mocha/cli.js53
-rw-r--r--test/mocha/minify.js15
-rw-r--r--test/mocha/operator.js489
-rwxr-xr-xtest/run-tests.js3
39 files changed, 3517 insertions, 269 deletions
diff --git a/test/benchmark.js b/test/benchmark.js
new file mode 100644
index 00000000..dc176a88
--- /dev/null
+++ b/test/benchmark.js
@@ -0,0 +1,49 @@
+#! /usr/bin/env node
+// -*- js -*-
+
+"use strict";
+
+var createHash = require("crypto").createHash;
+var fork = require("child_process").fork;
+var args = process.argv.slice(2);
+if (!args.length) {
+ args.push("-mc", "warnings=false");
+}
+args.push("--stats");
+var urls = [
+ "https://code.jquery.com/jquery-3.1.1.js",
+ "https://code.angularjs.org/1.6.1/angular.js",
+ "https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
+ "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
+ "https://unpkg.com/react@15.3.2/dist/react.js",
+ "http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
+ "https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
+ "https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
+];
+var results = {};
+var remaining = 2 * urls.length;
+function done() {
+ if (!--remaining) {
+ urls.forEach(function(url) {
+ console.log();
+ console.log(url);
+ console.log(results[url].time);
+ console.log("SHA1:", results[url].sha1);
+ });
+ }
+}
+urls.forEach(function(url) {
+ results[url] = { time: "" };
+ require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
+ var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
+ res.pipe(uglifyjs.stdin);
+ uglifyjs.stdout.pipe(createHash("sha1")).on("data", function(data) {
+ results[url].sha1 = data.toString("hex");
+ done();
+ });
+ uglifyjs.stderr.setEncoding("utf8");
+ uglifyjs.stderr.on("data", function(data) {
+ results[url].time += data;
+ }).on("end", done)
+ });
+});
diff --git a/test/compress/arrays.js b/test/compress/arrays.js
index 77ef761a..f0ded06c 100644
--- a/test/compress/arrays.js
+++ b/test/compress/arrays.js
@@ -21,10 +21,19 @@ constant_join: {
input: {
var a = [ "foo", "bar", "baz" ].join("");
var a1 = [ "foo", "bar", "baz" ].join();
+ var a2 = [ "foo", "bar", "baz" ].join(null);
+ var a3 = [ "foo", "bar", "baz" ].join(void 0);
+ var a4 = [ "foo", , "baz" ].join();
+ var a5 = [ "foo", null, "baz" ].join();
+ var a6 = [ "foo", void 0, "baz" ].join();
var b = [ "foo", 1, 2, 3, "bar" ].join("");
var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join("");
var c1 = [ boo(), bar(), "foo", 1, 2, 3, "bar", bar() ].join("");
var c2 = [ 1, 2, "foo", "bar", baz() ].join("");
+ var c3 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join("");
+ var c4 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join("");
+ var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
+ var c6 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join();
var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-");
var e = [].join(foo + bar);
var f = [].join("");
@@ -33,10 +42,19 @@ constant_join: {
expect: {
var a = "foobarbaz";
var a1 = "foo,bar,baz";
+ var a2 = "foonullbarnullbaz";
+ var a3 = "foo,bar,baz";
+ var a4 = "foo,,baz";
+ var a5 = "foo,,baz";
+ var a6 = "foo,,baz";
var b = "foo123bar";
var c = boo() + "foo123bar" + bar();
var c1 = "" + boo() + bar() + "foo123bar" + bar();
var c2 = "12foobar" + baz();
+ var c3 = boo() + bar() + "foo123bar" + bar() + "foo";
+ var c4 = "12foobar" + baz();
+ var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join();
+ var c6 = [ "1,2,,,foo,bar", baz() ].join();
var d = "foo-3bar-baz";
var e = [].join(foo + bar);
var f = "";
@@ -73,6 +91,41 @@ constant_join_2: {
}
}
+constant_join_3: {
+ options = {
+ unsafe: true,
+ evaluate: true,
+ };
+ input: {
+ var a = [ null ].join();
+ var b = [ , ].join();
+ var c = [ , 1, , 3 ].join();
+ var d = [ foo ].join();
+ var e = [ foo, null, undefined, bar ].join("-");
+ var f = [ foo, bar ].join("");
+ var g = [ null, "foo", null, bar + "baz" ].join("");
+ var h = [ null, "foo", null, bar + "baz" ].join("-");
+ var i = [ "foo" + bar, null, baz + "moo" ].join("");
+ var j = [ foo + "bar", baz ].join("");
+ var k = [ foo, "bar" + baz ].join("");
+ var l = [ foo, bar + "baz" ].join("");
+ }
+ expect: {
+ var a = "";
+ var b = "";
+ var c = ",1,,3";
+ var d = "" + foo;
+ var e = [ foo, "-", bar ].join("-");
+ var f = "" + foo + bar;
+ var g = "foo" + bar + "baz";
+ var h = [ "-foo-", bar + "baz" ].join("-");
+ var i = "foo" + bar + baz + "moo";
+ var j = foo + "bar" + baz;
+ var k = foo + "bar" + baz;
+ var l = foo + (bar + "baz");
+ }
+}
+
for_loop: {
options = {
unsafe : true,
diff --git a/test/compress/collapse_vars.js b/test/compress/collapse_vars.js
index ef7af9ed..d7432f3f 100644
--- a/test/compress/collapse_vars.js
+++ b/test/compress/collapse_vars.js
@@ -338,8 +338,9 @@ collapse_vars_while: {
collapse_vars_do_while: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
- comparisons:true, evaluate:true, booleans:false, loops:false, unused:true, hoist_funs:true,
- keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
+ comparisons:true, evaluate:true, booleans:false, loops:false, unused:"keep_assign",
+ hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true, cascade:true,
+ side_effects:true
}
input: {
function f1(y) {
@@ -409,6 +410,79 @@ collapse_vars_do_while: {
}
}
+collapse_vars_do_while_drop_assign: {
+ options = {
+ collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
+ comparisons:true, evaluate:true, booleans:false, loops:false, unused:true, hoist_funs:true,
+ keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
+ }
+ input: {
+ function f1(y) {
+ // The constant do-while condition `c` will be replaced.
+ var c = 9;
+ do { } while (c === 77);
+ }
+ function f2(y) {
+ // The non-constant do-while condition `c` will not be replaced.
+ var c = 5 - y;
+ do { } while (c);
+ }
+ function f3(y) {
+ // The constant `x` will be replaced in the do loop body.
+ function fn(n) { console.log(n); }
+ var a = 2, x = 7;
+ do {
+ fn(a = x);
+ break;
+ } while (y);
+ }
+ function f4(y) {
+ // The non-constant `a` will not be replaced in the do loop body.
+ var a = y / 4;
+ do {
+ return a;
+ } while (y);
+ }
+ function f5(y) {
+ function p(x) { console.log(x); }
+ do {
+ // The non-constant `a` will be replaced in p(a)
+ // because it is declared in same block.
+ var a = y - 3;
+ p(a);
+ } while (--y);
+ }
+ }
+ expect: {
+ function f1(y) {
+ do ; while (false);
+ }
+ function f2(y) {
+ var c = 5 - y;
+ do ; while (c);
+ }
+ function f3(y) {
+ function fn(n) { console.log(n); }
+ do {
+ fn(7);
+ break;
+ } while (y);
+ }
+ function f4(y) {
+ var a = y / 4;
+ do
+ return a;
+ while (y);
+ }
+ function f5(y) {
+ function p(x) { console.log(x); }
+ do {
+ p(y - 3);
+ } while (--y);
+ }
+ }
+}
+
collapse_vars_seq: {
options = {
collapse_vars:true, sequences:true, properties:true, dead_code:true, conditionals:true,
@@ -567,8 +641,9 @@ collapse_vars_assignment: {
collapse_vars_lvalues: {
options = {
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,
- keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
+ comparisons:true, evaluate:true, booleans:true, loops:true, unused:"keep_assign",
+ hoist_funs:true, keep_fargs:true, if_return:true, join_vars:true, cascade:true,
+ side_effects:true
}
input: {
function f0(x) { var i = ++x; return x += i; }
@@ -593,7 +668,38 @@ collapse_vars_lvalues: {
function f7(x) { var w = e1(), v = e2(), c = v - x; return (w = x) - c; }
function f8(x) { var w = e1(), v = e2(); return (w = x) - (v - x); }
function f9(x) { var w = e1(); return e2() - x - (w = x); }
+ }
+}
+collapse_vars_lvalues_drop_assign: {
+ options = {
+ 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,
+ keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
+ }
+ input: {
+ function f0(x) { var i = ++x; return x += i; }
+ function f1(x) { var a = (x -= 3); return x += a; }
+ function f2(x) { var z = x, a = ++z; return z += a; }
+ function f3(x) { var a = (x -= 3), b = x + a; return b; }
+ function f4(x) { var a = (x -= 3); return x + a; }
+ function f5(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return b - c; }
+ function f6(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return c - b; }
+ function f7(x) { var w = e1(), v = e2(), c = v - x, b = w = x; return b - c; }
+ function f8(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return b - c; }
+ function f9(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return c - b; }
+ }
+ expect: {
+ function f0(x) { var i = ++x; return x += i; }
+ function f1(x) { var a = (x -= 3); return x += a; }
+ function f2(x) { var z = x, a = ++z; return z += a; }
+ function f3(x) { var a = (x -= 3); return x + a; }
+ function f4(x) { var a = (x -= 3); return x + a; }
+ function f5(x) { var v = (e1(), e2()), c = v = --x; return x - c; }
+ function f6(x) { e1(), e2(); return --x - x; }
+ function f7(x) { var v = (e1(), e2()), c = v - x; return x - c; }
+ function f8(x) { var v = (e1(), e2()); return x - (v - x); }
+ function f9(x) { e1(); return e2() - x - x; }
}
}
diff --git a/test/compress/concat-strings.js b/test/compress/concat-strings.js
index 50eef8b8..d2503c6d 100644
--- a/test/compress/concat-strings.js
+++ b/test/compress/concat-strings.js
@@ -24,3 +24,143 @@ concat_1: {
var f = "\x00360\08\0";
}
}
+
+concat_2: {
+ options = {};
+ input: {
+ console.log(
+ 1 + (2 + 3),
+ 1 + (2 + "3"),
+ 1 + ("2" + 3),
+ 1 + ("2" + "3"),
+ "1" + (2 + 3),
+ "1" + (2 + "3"),
+ "1" + ("2" + 3),
+ "1" + ("2" + "3")
+ );
+ }
+ expect: {
+ console.log(
+ 1 + (2 + 3),
+ 1 + (2 + "3"),
+ 1 + "2" + 3,
+ 1 + "2" + "3",
+ "1" + (2 + 3),
+ "1" + 2 + "3",
+ "1" + "2" + 3,
+ "1" + "2" + "3"
+ );
+ }
+}
+
+concat_3: {
+ options = {};
+ input: {
+ console.log(
+ 1 + 2 + (3 + 4 + 5),
+ 1 + 2 + (3 + 4 + "5"),
+ 1 + 2 + (3 + "4" + 5),
+ 1 + 2 + (3 + "4" + "5"),
+ 1 + 2 + ("3" + 4 + 5),
+ 1 + 2 + ("3" + 4 + "5"),
+ 1 + 2 + ("3" + "4" + 5),
+ 1 + 2 + ("3" + "4" + "5")
+ );
+ }
+ expect: {
+ console.log(
+ 1 + 2 + (3 + 4 + 5),
+ 1 + 2 + (3 + 4 + "5"),
+ 1 + 2 + (3 + "4") + 5,
+ 1 + 2 + (3 + "4") + "5",
+ 1 + 2 + "3" + 4 + 5,
+ 1 + 2 + "3" + 4 + "5",
+ 1 + 2 + "3" + "4" + 5,
+ 1 + 2 + "3" + "4" + "5"
+ );
+ }
+}
+
+concat_4: {
+ options = {};
+ input: {
+ console.log(
+ 1 + "2" + (3 + 4 + 5),
+ 1 + "2" + (3 + 4 + "5"),
+ 1 + "2" + (3 + "4" + 5),
+ 1 + "2" + (3 + "4" + "5"),
+ 1 + "2" + ("3" + 4 + 5),
+ 1 + "2" + ("3" + 4 + "5"),
+ 1 + "2" + ("3" + "4" + 5),
+ 1 + "2" + ("3" + "4" + "5")
+ );
+ }
+ expect: {
+ console.log(
+ 1 + "2" + (3 + 4 + 5),
+ 1 + "2" + (3 + 4) + "5",
+ 1 + "2" + 3 + "4" + 5,
+ 1 + "2" + 3 + "4" + "5",
+ 1 + "2" + "3" + 4 + 5,
+ 1 + "2" + "3" + 4 + "5",
+ 1 + "2" + "3" + "4" + 5,
+ 1 + "2" + "3" + "4" + "5"
+ );
+ }
+}
+
+concat_5: {
+ options = {};
+ input: {
+ console.log(
+ "1" + 2 + (3 + 4 + 5),
+ "1" + 2 + (3 + 4 + "5"),
+ "1" + 2 + (3 + "4" + 5),
+ "1" + 2 + (3 + "4" + "5"),
+ "1" + 2 + ("3" + 4 + 5),
+ "1" + 2 + ("3" + 4 + "5"),
+ "1" + 2 + ("3" + "4" + 5),
+ "1" + 2 + ("3" + "4" + "5")
+ );
+ }
+ expect: {
+ console.log(
+ "1" + 2 + (3 + 4 + 5),
+ "1" + 2 + (3 + 4) + "5",
+ "1" + 2 + 3 + "4" + 5,
+ "1" + 2 + 3 + "4" + "5",
+ "1" + 2 + "3" + 4 + 5,
+ "1" + 2 + "3" + 4 + "5",
+ "1" + 2 + "3" + "4" + 5,
+ "1" + 2 + "3" + "4" + "5"
+ );
+ }
+}
+
+concat_6: {
+ options = {};
+ input: {
+ console.log(
+ "1" + "2" + (3 + 4 + 5),
+ "1" + "2" + (3 + 4 + "5"),
+ "1" + "2" + (3 + "4" + 5),
+ "1" + "2" + (3 + "4" + "5"),
+ "1" + "2" + ("3" + 4 + 5),
+ "1" + "2" + ("3" + 4 + "5"),
+ "1" + "2" + ("3" + "4" + 5),
+ "1" + "2" + ("3" + "4" + "5")
+ );
+ }
+ expect: {
+ console.log(
+ "1" + "2" + (3 + 4 + 5),
+ "1" + "2" + (3 + 4) + "5",
+ "1" + "2" + 3 + "4" + 5,
+ "1" + "2" + 3 + "4" + "5",
+ "1" + "2" + "3" + 4 + 5,
+ "1" + "2" + "3" + 4 + "5",
+ "1" + "2" + "3" + "4" + 5,
+ "1" + "2" + "3" + "4" + "5"
+ );
+ }
+}
diff --git a/test/compress/const.js b/test/compress/const.js
new file mode 100644
index 00000000..f1f13f49
--- /dev/null
+++ b/test/compress/const.js
@@ -0,0 +1,165 @@
+issue_1191: {
+ options = {
+ evaluate : true,
+ booleans : true,
+ comparisons : true,
+ dead_code : true,
+ conditionals : true,
+ side_effects : true,
+ unused : true,
+ hoist_funs : true,
+ if_return : true,
+ join_vars : true,
+ sequences : false,
+ collapse_vars : false,
+ reduce_vars : true,
+ }
+ input: {
+ function foo(rot) {
+ const rotTol = 5;
+ if (rot < -rotTol || rot > rotTol)
+ bar();
+ baz();
+ }
+ }
+ expect: {
+ function foo(rot) {
+ (rot < -5 || rot > 5) && bar();
+ baz();
+ }
+ }
+}
+
+issue_1194: {
+ options = {
+ evaluate : true,
+ booleans : true,
+ comparisons : true,
+ dead_code : true,
+ conditionals : true,
+ side_effects : true,
+ unused : true,
+ hoist_funs : true,
+ if_return : true,
+ join_vars : true,
+ sequences : false,
+ collapse_vars : false,
+ reduce_vars : true,
+ }
+ input: {
+ function f1() {const a = "X"; return a + a;}
+ function f2() {const aa = "X"; return aa + aa;}
+ function f3() {const aaa = "X"; return aaa + aaa;}
+ }
+ expect: {
+ function f1(){return"XX"}
+ function f2(){return"XX"}
+ function f3(){return"XX"}
+ }
+}
+
+issue_1396: {
+ options = {
+ evaluate : true,
+ booleans : true,
+ comparisons : true,
+ dead_code : true,
+ conditionals : true,
+ side_effects : true,
+ unused : true,
+ hoist_funs : true,
+ if_return : true,
+ join_vars : true,
+ sequences : false,
+ collapse_vars : false,
+ reduce_vars : true,
+ }
+ input: {
+ function foo(a) {
+ const VALUE = 1;
+ console.log(2 | VALUE);
+ console.log(VALUE + 1);
+ console.log(VALUE);
+ console.log(a & VALUE);
+ }
+ function bar() {
+ const s = "01234567890123456789";
+ console.log(s + s + s + s + s);
+
+ const CONSTANT = "abc";
+ console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
+ }
+ }
+ expect: {
+ function foo(a) {
+ console.log(3);
+ console.log(2);
+ console.log(1);
+ console.log(1 & a);
+ }
+ function bar() {
+ const s = "01234567890123456789";
+ console.log(s + s + s + s + s);
+
+ console.log("abcabcabcabcabc");
+ }
+ }
+}
+
+unused_regexp_literal: {
+ options = {
+ evaluate : true,
+ booleans : true,
+ comparisons : true,
+ dead_code : true,
+ conditionals : true,
+ side_effects : true,
+ unused : true,
+ hoist_funs : true,
+ if_return : true,
+ join_vars : true,
+ sequences : false,
+ collapse_vars : false,
+ }
+ input: {
+ function f(){ var a = /b/; }
+ }
+ expect: {
+ function f(){}
+ }
+}
+
+regexp_literal_not_const: {
+ options = {
+ evaluate : true,
+ booleans : true,
+ comparisons : true,
+ dead_code : true,
+ conditionals : true,
+ side_effects : true,
+ unused : true,
+ hoist_funs : true,
+ if_return : true,
+ join_vars : true,
+ sequences : false,
+ collapse_vars : false,
+ reduce_vars : true,
+ }
+ input: {
+ (function(){
+ var result;
+ const s = 'acdabcdeabbb';
+ const REGEXP_LITERAL = /ab*/g;
+ while (result = REGEXP_LITERAL.exec(s)) {
+ console.log(result[0]);
+ }
+ })();
+ }
+ expect: {
+ (function() {
+ var result;
+ const REGEXP_LITERAL = /ab*/g;
+ while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
+ })();
+ }
+}
diff --git a/test/compress/dead-code.js b/test/compress/dead-code.js
index fa4b37d6..2596e80e 100644
--- a/test/compress/dead-code.js
+++ b/test/compress/dead-code.js
@@ -1,206 +1,208 @@
-dead_code_1: {
- options = {
- dead_code: true
- };
- input: {
- function f() {
- a();
- b();
- x = 10;
- return;
- if (x) {
- y();
- }
- }
- }
- expect: {
- function f() {
- a();
- b();
- x = 10;
- return;
- }
- }
-}
-
-dead_code_2_should_warn: {
- options = {
- dead_code: true
- };
- input: {
- function f() {
- g();
- x = 10;
- throw "foo";
- // completely discarding the `if` would introduce some
- // bugs. UglifyJS v1 doesn't deal with this issue; in v2
- // we copy any declarations to the upper scope.
- if (x) {
- y();
- var x;
- function g(){};
- // but nested declarations should not be kept.
- (function(){
- var q;
- function y(){};
- })();
- }
- }
- }
- expect: {
- function f() {
- g();
- x = 10;
- throw "foo";
- var x;
- function g(){};
- }
- }
-}
-
-dead_code_constant_boolean_should_warn_more: {
- options = {
- dead_code : true,
- loops : true,
- booleans : true,
- conditionals : true,
- evaluate : true
- };
- input: {
- while (!((foo && bar) || (x + "0"))) {
- console.log("unreachable");
- var foo;
- function bar() {}
- }
- for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
- asdf();
- foo();
- var moo;
- }
- }
- expect: {
- var foo;
- function bar() {}
- // nothing for the while
- // as for the for, it should keep:
- var x = 10, y;
- var moo;
- }
-}
-
-dead_code_const_declaration: {
- options = {
- dead_code : true,
- loops : true,
- booleans : true,
- conditionals : true,
- evaluate : true
- };
- input: {
- var unused;
- const CONST_FOO = false;
- if (CONST_FOO) {
- console.log("unreachable");
- var moo;
- function bar() {}
- }
- }
- expect: {
- var unused;
- const CONST_FOO = !1;
- var moo;
- function bar() {}
- }
-}
-
-dead_code_const_annotation: {
- options = {
- dead_code : true,
- loops : true,
- booleans : true,
- conditionals : true,
- evaluate : true
- };
- input: {
- var unused;
- /** @const */ var CONST_FOO_ANN = false;
- if (CONST_FOO_ANN) {
- console.log("unreachable");
- var moo;
- function bar() {}
- }
- }
- expect: {
- var unused;
- var CONST_FOO_ANN = !1;
- var moo;
- function bar() {}
- }
-}
-
-dead_code_const_annotation_regex: {
- options = {
- dead_code : true,
- loops : true,
- booleans : true,
- conditionals : true,
- evaluate : true
- };
- input: {
- var unused;
- // @constraint this shouldn't be a constant
- var CONST_FOO_ANN = false;
- if (CONST_FOO_ANN) {
- console.log("reachable");
- }
- }
- expect: {
- var unused;
- var CONST_FOO_ANN = !1;
- CONST_FOO_ANN && console.log('reachable');
- }
-}
-
-dead_code_const_annotation_complex_scope: {
- options = {
- dead_code : true,
- loops : true,
- booleans : true,
- conditionals : true,
- evaluate : true
- };
- input: {
- var unused_var;
- /** @const */ var test = 'test';
- // @const
- var CONST_FOO_ANN = false;
- var unused_var_2;
- if (CONST_FOO_ANN) {
- console.log("unreachable");
- var moo;
- function bar() {}
- }
- if (test === 'test') {
- var beef = 'good';
- /** @const */ var meat = 'beef';
- var pork = 'bad';
- if (meat === 'pork') {
- console.log('also unreachable');
- } else if (pork === 'good') {
- console.log('reached, not const');
- }
- }
- }
- expect: {
- var unused_var;
- var test = 'test';
- var CONST_FOO_ANN = !1;
- var unused_var_2;
- var moo;
- function bar() {}
- var beef = 'good';
- var meat = 'beef';
- var pork = 'bad';
- 'good' === pork && console.log('reached, not const');
- }
-}
+dead_code_1: {
+ options = {
+ dead_code: true
+ };
+ input: {
+ function f() {
+ a();
+ b();
+ x = 10;
+ return;
+ if (x) {
+ y();
+ }
+ }
+ }
+ expect: {
+ function f() {
+ a();
+ b();
+ x = 10;
+ return;
+ }
+ }
+}
+
+dead_code_2_should_warn: {
+ options = {
+ dead_code: true
+ };
+ input: {
+ function f() {
+ g();
+ x = 10;
+ throw "foo";
+ // completely discarding the `if` would introduce some
+ // bugs. UglifyJS v1 doesn't deal with this issue; in v2
+ // we copy any declarations to the upper scope.
+ if (x) {
+ y();
+ var x;
+ function g(){};
+ // but nested declarations should not be kept.
+ (function(){
+ var q;
+ function y(){};
+ })();
+ }
+ }
+ }
+ expect: {
+ function f() {
+ g();
+ x = 10;
+ throw "foo";
+ var x;
+ function g(){};
+ }
+ }
+}
+
+dead_code_constant_boolean_should_warn_more: {
+ options = {
+ dead_code : true,
+ loops : true,
+ booleans : true,
+ conditionals : true,
+ evaluate : true
+ };
+ input: {
+ while (!((foo && bar) || (x + "0"))) {
+ console.log("unreachable");
+ var foo;
+ function bar() {}
+ }
+ for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {
+ asdf();
+ foo();
+ var moo;
+ }
+ }
+ expect: {
+ var foo;
+ function bar() {}
+ // nothing for the while
+ // as for the for, it should keep:
+ var x = 10, y;
+ var moo;
+ }
+}
+
+dead_code_const_declaration: {
+ options = {
+ dead_code : true,
+ loops : true,
+ booleans : true,
+ conditionals : true,
+ evaluate : true,
+ reduce_vars : true,
+ };
+ input: {
+ var unused;
+ const CONST_FOO = false;
+ if (CONST_FOO) {
+ console.log("unreachable");
+ var moo;
+ function bar() {}
+ }
+ }
+ expect: {
+ var unused;
+ const CONST_FOO = !1;
+ var moo;
+ function bar() {}
+ }
+}
+
+dead_code_const_annotation: {
+ options = {
+ dead_code : true,
+ loops : true,
+ booleans : true,
+ conditionals : true,
+ evaluate : true,
+ reduce_vars : true,
+ };
+ input: {
+ var unused;
+ /** @const */ var CONST_FOO_ANN = false;
+ if (CONST_FOO_ANN) {
+ console.log("unreachable");
+ var moo;
+ function bar() {}
+ }
+ }
+ expect: {
+ var unused;
+ var CONST_FOO_ANN = !1;
+ var moo;
+ function bar() {}
+ }
+}
+
+dead_code_const_annotation_regex: {
+ options = {
+ dead_code : true,
+ loops : true,
+ booleans : true,
+ conditionals : true,
+ evaluate : true
+ };
+ input: {
+ var unused;
+ // @constraint this shouldn't be a constant
+ var CONST_FOO_ANN = false;
+ if (CONST_FOO_ANN) {
+ console.log("reachable");
+ }
+ }
+ expect: {
+ var unused;
+ var CONST_FOO_ANN = !1;
+ CONST_FOO_ANN && console.log('reachable');
+ }
+}
+
+dead_code_const_annotation_complex_scope: {
+ options = {
+ dead_code : true,
+ loops : true,
+ booleans : true,
+ conditionals : true,
+ evaluate : true,
+ reduce_vars : true,
+ };
+ input: {
+ var unused_var;
+ /** @const */ var test = 'test';
+ // @const
+ var CONST_FOO_ANN = false;
+ var unused_var_2;
+ if (CONST_FOO_ANN) {
+ console.log("unreachable");
+ var moo;
+ function bar() {}
+ }
+ if (test === 'test') {
+ var beef = 'good';
+ /** @const */ var meat = 'beef';
+ var pork = 'bad';
+ if (meat === 'pork') {
+ console.log('also unreachable');
+ } else if (pork === 'good') {
+ console.log('reached, not const');
+ }
+ }
+ }
+ expect: {
+ var unused_var;
+ var test = 'test';
+ var CONST_FOO_ANN = !1;
+ var unused_var_2;
+ var moo;
+ function bar() {}
+ var beef = 'good';
+ var meat = 'beef';
+ var pork = 'bad';
+ }
+}
diff --git a/test/compress/drop-console.js b/test/compress/drop-console.js
index 162b339c..7df6d9dc 100644
--- a/test/compress/drop-console.js
+++ b/test/compress/drop-console.js
@@ -1,24 +1,24 @@
-drop_console_1: {
- options = {};
- input: {
- console.log('foo');
- console.log.apply(console, arguments);
- }
- expect: {
- console.log('foo');
- console.log.apply(console, arguments);
- }
-}
-
-drop_console_1: {
- options = { drop_console: true };
- input: {
- console.log('foo');
- console.log.apply(console, arguments);
- }
- expect: {
- // with regular compression these will be stripped out as well
- void 0;
- void 0;
- }
-}
+drop_console_1: {
+ options = {};
+ input: {
+ console.log('foo');
+ console.log.apply(console, arguments);
+ }
+ expect: {
+ console.log('foo');
+ console.log.apply(console, arguments);
+ }
+}
+
+drop_console_2: {
+ options = { drop_console: true };
+ input: {
+ console.log('foo');
+ console.log.apply(console, arguments);
+ }
+ expect: {
+ // with regular compression these will be stripped out as well
+ void 0;
+ void 0;
+ }
+}
diff --git a/test/compress/drop-unused.js b/test/compress/drop-unused.js
index 035a428e..c1ca1b55 100644
--- a/test/compress/drop-unused.js
+++ b/test/compress/drop-unused.js
@@ -177,3 +177,505 @@ keep_fnames: {
}
}
}
+
+drop_assign: {
+ options = { unused: true };
+ input: {
+ function f1() {
+ var a;
+ a = 1;
+ }
+ function f2() {
+ var a = 1;
+ a = 2;
+ }
+ function f3(a) {
+ a = 1;
+ }
+ function f4() {
+ var a;
+ return a = 1;
+ }
+ function f5() {
+ var a;
+ return function() {
+ a = 1;
+ }
+ }
+ }
+ expect: {
+ function f1() {
+ 1;
+ }
+ function f2() {
+ 2;
+ }
+ function f3(a) {
+ 1;
+ }
+ function f4() {
+ return 1;
+ }
+ function f5() {
+ var a;
+ return function() {
+ a = 1;
+ }
+ }
+ }
+}
+
+keep_assign: {
+ options = { unused: "keep_assign" };
+ input: {
+ function f1() {
+ var a;
+ a = 1;
+ }
+ function f2() {
+ var a = 1;
+ a = 2;
+ }
+ function f3(a) {
+ a = 1;
+ }
+ function f4() {
+ var a;
+ return a = 1;
+ }
+ function f5() {
+ var a;
+ return function() {
+ a = 1;
+ }
+ }
+ }
+ expect: {
+ function f1() {
+ var a;
+ a = 1;
+ }
+ function f2() {
+ var a = 1;
+ a = 2;
+ }
+ function f3(a) {
+ a = 1;
+ }
+ function f4() {
+ var a;
+ return a = 1;
+ }
+ function f5() {
+ var a;
+ return function() {
+ a = 1;
+ }
+ }
+ }
+}
+
+drop_toplevel_funcs: {
+ options = { toplevel: "funcs", unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, b = 1, c = g;
+ a = 2;
+ function g() {}
+ console.log(b = 3);
+ }
+}
+
+drop_toplevel_vars: {
+ options = { toplevel: "vars", unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ 2;
+ function g() {}
+ function h() {}
+ console.log(3);
+ }
+}
+
+drop_toplevel_vars_fargs: {
+ options = { keep_fargs: false, toplevel: "vars", unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var c = g;
+ function f() {
+ return function() {
+ c = 2;
+ }
+ }
+ 2;
+ function g() {}
+ function h() {}
+ console.log(3);
+ }
+}
+
+drop_toplevel_all: {
+ options = { toplevel: true, unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ 2;
+ console.log(3);
+ }
+}
+
+drop_toplevel_retain: {
+ options = { top_retain: "f,a,o", unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ console.log(3);
+ }
+}
+
+drop_toplevel_retain_array: {
+ options = { top_retain: [ "f", "a", "o" ], unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ console.log(3);
+ }
+}
+
+drop_toplevel_retain_regex: {
+ options = { top_retain: /^[fao]$/, unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ console.log(3);
+ }
+}
+
+drop_toplevel_all_retain: {
+ options = { toplevel: true, top_retain: "f,a,o", unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ console.log(3);
+ }
+}
+
+drop_toplevel_funcs_retain: {
+ options = { toplevel: "funcs", top_retain: "f,a,o", unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ console.log(b = 3);
+ }
+}
+
+drop_toplevel_vars_retain: {
+ options = { toplevel: "vars", top_retain: "f,a,o", unused: true };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(3);
+ }
+}
+
+drop_toplevel_keep_assign: {
+ options = { toplevel: true, unused: "keep_assign" };
+ input: {
+ var a, b = 1, c = g;
+ function f(d) {
+ return function() {
+ c = 2;
+ }
+ }
+ a = 2;
+ function g() {}
+ function h() {}
+ console.log(b = 3);
+ }
+ expect: {
+ var a, b = 1;
+ a = 2;
+ console.log(b = 3);
+ }
+}
+
+drop_fargs: {
+ options = {
+ keep_fargs: false,
+ unused: true,
+ }
+ input: {
+ function f(a) {
+ var b = a;
+ }
+ }
+ expect: {
+ function f() {}
+ }
+}
+
+drop_fnames: {
+ options = {
+ keep_fnames: false,
+ unused: true,
+ }
+ input: {
+ function f() {
+ return function g() {
+ var a = g;
+ };
+ }
+ }
+ expect: {
+ function f() {
+ return function() {};
+ }
+ }
+}
+
+global_var: {
+ options = {
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ var a;
+ function foo(b) {
+ a;
+ b;
+ c;
+ typeof c === "undefined";
+ c + b + a;
+ b && b.ar();
+ return b;
+ }
+ }
+ expect: {
+ var a;
+ function foo(b) {
+ c;
+ c;
+ b && b.ar();
+ return b;
+ }
+ }
+}
+
+iife: {
+ options = {
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ function f() {
+ var a;
+ ~function() {}(b);
+ }
+ }
+ expect: {
+ function f() {
+ ~function() {}(b);
+ }
+ }
+}
+
+drop_value: {
+ options = {
+ side_effects: true,
+ }
+ input: {
+ (1, [2, foo()], 3, {a:1, b:bar()});
+ }
+ expect: {
+ foo(), bar();
+ }
+}
+
+const_assign: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ function f() {
+ const b = 2;
+ return 1 + b;
+ }
+
+ function g() {
+ const b = 2;
+ b = 3;
+ return 1 + b;
+ }
+ }
+ expect: {
+ function f() {
+ return 3;
+ }
+
+ function g() {
+ const b = 2;
+ b = 3;
+ return 1 + b;
+ }
+ }
+}
diff --git a/test/compress/evaluate.js b/test/compress/evaluate.js
index 0ff157dc..ae5e58d6 100644
--- a/test/compress/evaluate.js
+++ b/test/compress/evaluate.js
@@ -598,3 +598,51 @@ unsafe_prototype_function: {
var h = "" + ({toString: 0});
}
}
+
+call_args: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ }
+ input: {
+ const a = 1;
+ console.log(a);
+ +function(a) {
+ return a;
+ }(a);
+ }
+ expect: {
+ const a = 1;
+ console.log(1);
+ +function(a) {
+ return a;
+ }(1);
+ }
+}
+
+in_boolean_context: {
+ options = {
+ booleans: true,
+ evaluate: true,
+ }
+ input: {
+ !42;
+ !"foo";
+ ![1, 2];
+ !/foo/;
+ !b(42);
+ !b("foo");
+ !b([1, 2]);
+ !b(/foo/);
+ }
+ expect: {
+ !1;
+ !1;
+ !1;
+ !1;
+ !b(42);
+ !b("foo");
+ !b([1, 2]);
+ !b(/foo/);
+ }
+}
diff --git a/test/compress/global_defs.js b/test/compress/global_defs.js
new file mode 100644
index 00000000..a69d031e
--- /dev/null
+++ b/test/compress/global_defs.js
@@ -0,0 +1,147 @@
+must_replace: {
+ options = {
+ global_defs: {
+ D: "foo bar",
+ }
+ }
+ input: {
+ console.log(D);
+ }
+ expect: {
+ console.log("foo bar");
+ }
+}
+
+keyword: {
+ options = {
+ global_defs: {
+ undefined: 0,
+ NaN: 1,
+ Infinity: 2,
+ },
+ }
+ input: {
+ console.log(undefined, NaN, Infinity);
+ }
+ expect: {
+ console.log(0, 1, 2);
+ }
+}
+
+object: {
+ options = {
+ evaluate: true,
+ global_defs: {
+ CONFIG: {
+ DEBUG: [ 0 ],
+ VALUE: 42,
+ },
+ },
+ unsafe: true,
+ }
+ input: {
+ function f(CONFIG) {
+ // CONFIG not global - do not replace
+ return CONFIG.VALUE;
+ }
+ function g() {
+ var CONFIG = { VALUE: 1 };
+ // CONFIG not global - do not replace
+ return CONFIG.VALUE;
+ }
+ function h() {
+ return CONFIG.VALUE;
+ }
+ if (CONFIG.DEBUG[0])
+ console.debug("foo");
+ }
+ expect: {
+ function f(CONFIG) {
+ return CONFIG.VALUE;
+ }
+ function g() {
+ var CONFIG = { VALUE: 1 };
+ return CONFIG.VALUE;
+ }
+ function h() {
+ return 42;
+ }
+ if (0)
+ console.debug("foo");
+ }
+}
+
+expanded: {
+ options = {
+ global_defs: {
+ "CONFIG.DEBUG": [ 0 ],
+ "CONFIG.VALUE": 42,
+ },
+ }
+ input: {
+ function f(CONFIG) {
+ // CONFIG not global - do not replace
+ return CONFIG.VALUE;
+ }
+ function g() {
+ var CONFIG = { VALUE: 1 };
+ // CONFIG not global - do not replace
+ return CONFIG.VALUE;
+ }
+ function h() {
+ return CONFIG.VALUE;
+ }
+ if (CONFIG.DEBUG[0])
+ console.debug("foo");
+ }
+ expect: {
+ function f(CONFIG) {
+ return CONFIG.VALUE;
+ }
+ function g() {
+ var CONFIG = { VALUE: 1 };
+ return CONFIG.VALUE;
+ }
+ function h() {
+ return 42;
+ }
+ if ([0][0])
+ console.debug("foo");
+ }
+}
+
+mixed: {
+ options = {
+ evaluate: true,
+ global_defs: {
+ "CONFIG.VALUE": 42,
+ "FOO.BAR": "moo",
+ },
+ properties: true,
+ }
+ input: {
+ const FOO = { BAR: 0 };
+ console.log(FOO.BAR);
+ console.log(++CONFIG.DEBUG);
+ console.log(++CONFIG.VALUE);
+ console.log(++CONFIG["VAL" + "UE"]);
+ console.log(++DEBUG[CONFIG.VALUE]);
+ CONFIG.VALUE.FOO = "bar";
+ console.log(CONFIG);
+ }
+ expect: {
+ const FOO = { BAR: 0 };
+ console.log("moo");
+ console.log(++CONFIG.DEBUG);
+ console.log(++CONFIG.VALUE);
+ console.log(++CONFIG.VALUE);
+ console.log(++DEBUG[42]);
+ CONFIG.VALUE.FOO = "bar";
+ console.log(CONFIG);
+ }
+ expect_warnings: [
+ 'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
+ 'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
+ 'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
+ ]
+}
diff --git a/test/compress/hoist_vars.js b/test/compress/hoist_vars.js
new file mode 100644
index 00000000..6fe1c773
--- /dev/null
+++ b/test/compress/hoist_vars.js
@@ -0,0 +1,90 @@
+statements: {
+ options = {
+ hoist_funs: false,
+ hoist_vars: true,
+ }
+ input: {
+ function f() {
+ var a = 1;
+ var b = 2;
+ var c = 3;
+ function g() {}
+ return g(a, b, c);
+ }
+ }
+ expect: {
+ function f() {
+ var a = 1, b = 2, c = 3;
+ function g() {}
+ return g(a, b, c);
+ }
+ }
+}
+
+statements_funs: {
+ options = {
+ hoist_funs: true,
+ hoist_vars: true,
+ }
+ input: {
+ function f() {
+ var a = 1;
+ var b = 2;
+ var c = 3;
+ function g() {}
+ return g(a, b, c);
+ }
+ }
+ expect: {
+ function f() {
+ function g() {}
+ var a = 1, b = 2, c = 3;
+ return g(a, b, c);
+ }
+ }
+}
+
+sequences: {
+ options = {
+ hoist_funs: false,
+ hoist_vars: true,
+ }
+ input: {
+ function f() {
+ var a = 1, b = 2;
+ function g() {}
+ var c = 3;
+ return g(a, b, c);
+ }
+ }
+ expect: {
+ function f() {
+ var c, a = 1, b = 2;
+ function g() {}
+ c = 3;
+ return g(a, b, c);
+ }
+ }
+}
+
+sequences_funs: {
+ options = {
+ hoist_funs: true,
+ hoist_vars: true,
+ }
+ input: {
+ function f() {
+ var a = 1, b = 2;
+ function g() {}
+ var c = 3;
+ return g(a, b, c);
+ }
+ }
+ expect: {
+ function f() {
+ function g() {}
+ var a = 1, b = 2, c = 3;
+ return g(a, b, c);
+ }
+ }
+}
diff --git a/test/compress/if_return.js b/test/compress/if_return.js
index 78a6e818..0ac45c3c 100644
--- a/test/compress/if_return.js
+++ b/test/compress/if_return.js
@@ -170,8 +170,51 @@ if_return_7: {
}
}
expect: {
- // suboptimal
- function f(x){return!!x||(foo(),void bar())}
+ function f(x){if(x)return!0;foo(),bar()}
+ }
+}
+
+if_return_8: {
+ options = {
+ if_return: true,
+ sequences: true,
+ conditionals: true,
+ side_effects : true,
+ }
+ input: {
+ function f(e) {
+ if (2 == e) return foo();
+ if (3 == e) return bar();
+ if (4 == e) return baz();
+ fail(e);
+ }
+
+ function g(e) {
+ if (a(e)) return foo();
+ if (b(e)) return bar();
+ if (c(e)) return baz();
+ fail(e);
+ }
+
+ function h(e) {
+ if (a(e)) return foo();
+ else if (b(e)) return bar();
+ else if (c(e)) return baz();
+ else fail(e);
+ }
+
+ function i(e) {
+ if (a(e)) return foo();
+ else if (b(e)) return bar();
+ else if (c(e)) return baz();
+ fail(e);
+ }
+ }
+ expect: {
+ function f(e){return 2==e?foo():3==e?bar():4==e?baz():void fail(e)}
+ function g(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
+ function h(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
+ function i(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}
}
}
@@ -205,3 +248,57 @@ issue_1089: {
}
}
}
+
+issue_1437: {
+ options = {
+ if_return : true,
+ sequences : true,
+ conditionals : false
+ }
+ input: {
+ function x() {
+ if (a())
+ return b();
+ if (c())
+ return d();
+ else
+ e();
+ f();
+ }
+ }
+ expect: {
+ function x() {
+ if (a())
+ return b();
+ if (c())
+ return d();
+ else
+ e()
+ f();
+ }
+ }
+}
+
+issue_1437_conditionals: {
+ options = {
+ conditionals : true,
+ if_return : true,
+ sequences : true
+ }
+ input: {
+ function x() {
+ if (a())
+ return b();
+ if (c())
+ return d();
+ else
+ e();
+ f();
+ }
+ }
+ expect: {
+ function x() {
+ return a() ? b() : c() ? d() : (e(), f(), void 0);
+ }
+ }
+}
diff --git a/test/compress/issue-1041.js b/test/compress/issue-1041.js
index 9dd176fd..cdbc22cc 100644
--- a/test/compress/issue-1041.js
+++ b/test/compress/issue-1041.js
@@ -13,7 +13,8 @@ const_declaration: {
const_pragma: {
options = {
- evaluate: true
+ evaluate: true,
+ reduce_vars: true,
};
input: {
@@ -27,7 +28,8 @@ const_pragma: {
// for completeness' sake
not_const: {
options = {
- evaluate: true
+ evaluate: true,
+ reduce_vars: true,
};
input: {
diff --git a/test/compress/issue-105.js b/test/compress/issue-105.js
deleted file mode 100644
index ca17adbf..00000000
--- a/test/compress/issue-105.js
+++ /dev/null
@@ -1,25 +0,0 @@
-typeof_eq_undefined: {
- options = {
- comparisons: true
- };
- input: { a = typeof b.c != "undefined" }
- expect: { a = "undefined" != typeof b.c }
-}
-
-typeof_eq_undefined_unsafe: {
- options = {
- comparisons: true,
- unsafe: true
- };
- input: { a = typeof b.c != "undefined" }
- expect: { a = void 0 !== b.c }
-}
-
-typeof_eq_undefined_unsafe2: {
- options = {
- comparisons: true,
- unsafe: true
- };
- input: { a = "undefined" != typeof b.c }
- expect: { a = void 0 !== b.c }
-}
diff --git a/test/compress/issue-1261.js b/test/compress/issue-1261.js
new file mode 100644
index 00000000..dfbe2100
--- /dev/null
+++ b/test/compress/issue-1261.js
@@ -0,0 +1,118 @@
+pure_function_calls: {
+ options = {
+ evaluate : true,
+ conditionals : true,
+ comparisons : true,
+ side_effects : true,
+ booleans : true,
+ unused : true,
+ if_return : true,
+ join_vars : true,
+ cascade : true,
+ negate_iife : true,
+ }
+ input: {
+ // pure top-level IIFE will be dropped
+ // @__PURE__ - comment
+ (function() {
+ console.log("iife0");
+ })();
+
+ // pure top-level IIFE assigned to unreferenced var will not be dropped
+ var iife1 = /*@__PURE__*/(function() {
+ console.log("iife1");
+ function iife1() {}
+ return iife1;
+ })();
+
+ (function(){
+ // pure IIFE in function scope assigned to unreferenced var will be dropped
+ var iife2 = /*#__PURE__*/(function() {
+ console.log("iife2");
+ function iife2() {}
+ return iife2;
+ })();
+ })();
+
+ // comment #__PURE__ comment
+ bar(), baz(), quux();
+ a.b(), /* @__PURE__ */ c.d.e(), f.g();
+ }
+ expect: {
+ var iife1 = function() {
+ console.log("iife1");
+ function iife1() {}
+ return iife1;
+ }();
+
+ baz(), quux();
+ a.b(), f.g();
+ }
+ expect_warnings: [
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:17,8]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:17,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:30,37]",
+ "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:30,16]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:28,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:39,31]",
+ ]
+}
+
+pure_function_calls_toplevel: {
+ options = {
+ evaluate : true,
+ conditionals : true,
+ comparisons : true,
+ side_effects : true,
+ booleans : true,
+ unused : true,
+ if_return : true,
+ join_vars : true,
+ cascade : true,
+ negate_iife : true,
+ toplevel : true,
+ }
+ input: {
+ // pure top-level IIFE will be dropped
+ // @__PURE__ - comment
+ (function() {
+ console.log("iife0");
+ })();
+
+ // pure top-level IIFE assigned to unreferenced var will be dropped
+ var iife1 = /*@__PURE__*/(function() {
+ console.log("iife1");
+ function iife1() {}
+ return iife1;
+ })();
+
+ (function(){
+ // pure IIFE in function scope assigned to unreferenced var will be dropped
+ var iife2 = /*#__PURE__*/(function() {
+ console.log("iife2");
+ function iife2() {}
+ return iife2;
+ })();
+ })();
+
+ // comment #__PURE__ comment
+ bar(), baz(), quux();
+ a.b(), /* @__PURE__ */ c.d.e(), f.g();
+ }
+ expect: {
+ baz(), quux();
+ a.b(), f.g();
+ }
+ expect_warnings: [
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:79,8]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:79,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
+ "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
+ "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
+ "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
+ "WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
+ ]
+}
diff --git a/test/compress/issue-1431.js b/test/compress/issue-1431.js
index 731ebba8..9493fd37 100644
--- a/test/compress/issue-1431.js
+++ b/test/compress/issue-1431.js
@@ -1,3 +1,32 @@
+level_zero: {
+ options = {
+ keep_fnames: true
+ }
+ mangle = {
+ keep_fnames: true
+ }
+ input: {
+ function f(x) {
+ function n(a) {
+ return a * a;
+ }
+ return function() {
+ return x;
+ };
+ }
+ }
+ expect: {
+ function f(r) {
+ function n(n) {
+ return n * n;
+ }
+ return function() {
+ return r;
+ };
+ }
+ }
+}
+
level_one: {
options = {
keep_fnames: true
diff --git a/test/compress/issue-1443.js b/test/compress/issue-1443.js
new file mode 100644
index 00000000..a2565872
--- /dev/null
+++ b/test/compress/issue-1443.js
@@ -0,0 +1,69 @@
+// tests assume that variable `undefined` not redefined and has `void 0` as value
+
+unsafe_undefined: {
+ options = {
+ if_return: true,
+ unsafe: true
+ }
+ mangle = {}
+ input: {
+ function f(undefined) {
+ return function() {
+ if (a)
+ return b;
+ if (c)
+ return d;
+ };
+ }
+ }
+ expect: {
+ function f(n) {
+ return function() {
+ if (a)
+ return b;
+ if (c)
+ return d;
+ else
+ return n;
+ };
+ }
+ }
+}
+
+keep_fnames: {
+ options = {
+ if_return: true,
+ unsafe: true
+ }
+ mangle = {
+ keep_fnames: true
+ }
+ input: {
+ function f(undefined) {
+ return function() {
+ function n(a) {
+ return a * a;
+ }
+ if (a)
+ return b;
+ if (c)
+ return d;
+ };
+ }
+ }
+ expect: {
+ function f(r) {
+ return function() {
+ function n(n) {
+ return n * n;
+ }
+ if (a)
+ return b;
+ if (c)
+ return d;
+ else
+ return r;
+ };
+ }
+ }
+}
diff --git a/test/compress/issue-1446.js b/test/compress/issue-1446.js
new file mode 100644
index 00000000..3d69aa09
--- /dev/null
+++ b/test/compress/issue-1446.js
@@ -0,0 +1,71 @@
+typeof_eq_undefined: {
+ options = {
+ comparisons: true
+ }
+ input: {
+ var a = typeof b != "undefined";
+ b = typeof a != "undefined";
+ var c = typeof d.e !== "undefined";
+ var f = "undefined" === typeof g;
+ g = "undefined" === typeof f;
+ var h = "undefined" == typeof i.j;
+ }
+ expect: {
+ var a = "undefined" != typeof b;
+ b = void 0 !== a;
+ var c = void 0 !== d.e;
+ var f = "undefined" == typeof g;
+ g = void 0 === f;
+ var h = void 0 === i.j;
+ }
+}
+
+typeof_eq_undefined_ie8: {
+ options = {
+ comparisons: true,
+ screw_ie8: false
+ }
+ input: {
+ var a = typeof b != "undefined";
+ b = typeof a != "undefined";
+ var c = typeof d.e !== "undefined";
+ var f = "undefined" === typeof g;
+ g = "undefined" === typeof f;
+ var h = "undefined" == typeof i.j;
+ }
+ expect: {
+ var a = "undefined" != typeof b;
+ b = void 0 !== a;
+ var c = "undefined" != typeof d.e;
+ var f = "undefined" == typeof g;
+ g = void 0 === f;
+ var h = "undefined" == typeof i.j;
+ }
+}
+
+undefined_redefined: {
+ options = {
+ comparisons: true
+ }
+ input: {
+ function f(undefined) {
+ var n = 1;
+ return typeof n == "undefined";
+ }
+ }
+ expect_exact: "function f(undefined){var n=1;return void 0===n}"
+}
+
+undefined_redefined_mangle: {
+ options = {
+ comparisons: true
+ }
+ mangle = {}
+ input: {
+ function f(undefined) {
+ var n = 1;
+ return typeof n == "undefined";
+ }
+ }
+ expect_exact: "function f(n){var r=1;return void 0===r}"
+}
diff --git a/test/compress/issue-1447.js b/test/compress/issue-1447.js
new file mode 100644
index 00000000..163acbc2
--- /dev/null
+++ b/test/compress/issue-1447.js
@@ -0,0 +1,45 @@
+else_with_empty_block: {
+ options = {}
+ input: {
+ if (x)
+ yes();
+ else {
+ }
+ }
+ expect_exact: "if(x)yes();"
+}
+
+else_with_empty_statement: {
+ options = {}
+ input: {
+ if (x)
+ yes();
+ else
+ ;
+ }
+ expect_exact: "if(x)yes();"
+}
+
+conditional_false_stray_else_in_loop: {
+ options = {
+ evaluate : true,
+ comparisons : true,
+ booleans : true,
+ unused : true,
+ loops : true,
+ side_effects : true,
+ dead_code : true,
+ hoist_vars : true,
+ join_vars : true,
+ if_return : true,
+ cascade : true,
+ conditionals : false,
+ }
+ input: {
+ for (var i = 1; i <= 4; ++i) {
+ if (i <= 2) continue;
+ console.log(i);
+ }
+ }
+ expect_exact: "for(var i=1;i<=4;++i)if(!(i<=2))console.log(i);"
+}
diff --git a/test/compress/issue-208.js b/test/compress/issue-208.js
index 2f103786..fb9861f6 100644
--- a/test/compress/issue-208.js
+++ b/test/compress/issue-208.js
@@ -27,3 +27,44 @@ do_update_rhs: {
MY_DEBUG += 0;
}
}
+
+mixed: {
+ options = {
+ evaluate: true,
+ global_defs: {
+ DEBUG: 0,
+ ENV: 1,
+ FOO: 2,
+ }
+ }
+ input: {
+ const ENV = 3;
+ var FOO = 4;
+ f(ENV * 10);
+ --FOO;
+ DEBUG = 1;
+ DEBUG++;
+ DEBUG += 1;
+ f(DEBUG);
+ x = DEBUG;
+ }
+ expect: {
+ const ENV = 3;
+ var FOO = 4;
+ f(10);
+ --FOO;
+ DEBUG = 1;
+ DEBUG++;
+ DEBUG += 1;
+ f(0);
+ x = 0;
+ }
+ expect_warnings: [
+ 'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
+ 'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
+ 'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
+ 'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
+ 'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]',
+ 'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]',
+ ]
+}
diff --git a/test/compress/issue-979.js b/test/compress/issue-979.js
index bae15db8..7ed5801d 100644
--- a/test/compress/issue-979.js
+++ b/test/compress/issue-979.js
@@ -82,7 +82,7 @@ issue979_test_negated_is_best: {
1!=a||2!=b||foo();
}
function f7() {
- return 1!=a&&2!=b?bar():void foo();
+ if(1!=a&&2!=b)return bar();foo()
}
}
}
diff --git a/test/compress/loops.js b/test/compress/loops.js
index 78f618aa..ca05461c 100644
--- a/test/compress/loops.js
+++ b/test/compress/loops.js
@@ -187,3 +187,32 @@ keep_collapse_const_in_own_block_scope_2: {
console.log(c);
}
}
+
+evaluate: {
+ options = {
+ loops: true,
+ dead_code: true,
+ evaluate: true,
+ };
+ input: {
+ while (true) {
+ a();
+ }
+ while (false) {
+ b();
+ }
+ do {
+ c();
+ } while (true);
+ do {
+ d();
+ } while (false);
+ }
+ expect: {
+ for(;;)
+ a();
+ for(;;)
+ c();
+ d();
+ }
+}
diff --git a/test/compress/max_line_len.js b/test/compress/max_line_len.js
new file mode 100644
index 00000000..b9e09178
--- /dev/null
+++ b/test/compress/max_line_len.js
@@ -0,0 +1,28 @@
+too_short: {
+ beautify = {
+ max_line_len: 10,
+ }
+ input: {
+ function f(a) {
+ return { c: 42, d: a(), e: "foo"};
+ }
+ }
+ expect_exact: 'function f(a){\nreturn{\nc:42,\nd:a(),\ne:"foo"}}'
+ expect_warnings: [
+ "WARN: Output exceeds 10 characters"
+ ]
+}
+
+just_enough: {
+ beautify = {
+ max_line_len: 14,
+ }
+ input: {
+ function f(a) {
+ return { c: 42, d: a(), e: "foo"};
+ }
+ }
+ expect_exact: 'function f(a){\nreturn{c:42,\nd:a(),e:"foo"}\n}'
+ expect_warnings: [
+ ]
+}
diff --git a/test/compress/negate-iife.js b/test/compress/negate-iife.js
index 0c111604..001795c5 100644
--- a/test/compress/negate-iife.js
+++ b/test/compress/negate-iife.js
@@ -10,6 +10,16 @@ negate_iife_1: {
}
}
+negate_iife_1_off: {
+ options = {
+ negate_iife: false,
+ };
+ input: {
+ (function(){ stuff() })();
+ }
+ expect_exact: '(function(){stuff()})();'
+}
+
negate_iife_2: {
options = {
negate_iife: true
@@ -25,6 +35,7 @@ negate_iife_2: {
negate_iife_3: {
options = {
negate_iife: true,
+ conditionals: true
};
input: {
(function(){ return true })() ? console.log(true) : console.log(false);
@@ -34,9 +45,23 @@ negate_iife_3: {
}
}
-negate_iife_3: {
+negate_iife_3_off: {
+ options = {
+ negate_iife: false,
+ conditionals: true,
+ };
+ input: {
+ (function(){ return true })() ? console.log(true) : console.log(false);
+ }
+ expect: {
+ !function(){ return true }() ? console.log(false) : console.log(true);
+ }
+}
+
+negate_iife_4: {
options = {
negate_iife: true,
+ conditionals: true,
sequences: true
};
input: {
@@ -52,7 +77,42 @@ negate_iife_3: {
}
}
-negate_iife_4: {
+sequence_off: {
+ options = {
+ negate_iife: false,
+ conditionals: true,
+ sequences: true,
+ passes: 2,
+ };
+ input: {
+ function f() {
+ (function(){ return true })() ? console.log(true) : console.log(false);
+ (function(){
+ console.log("something");
+ })();
+ }
+ function g() {
+ (function(){
+ console.log("something");
+ })();
+ (function(){ return true })() ? console.log(true) : console.log(false);
+ }
+ }
+ expect: {
+ function f() {
+ !function(){ return true }() ? console.log(false) : console.log(true), function(){
+ console.log("something");
+ }();
+ }
+ function g() {
+ (function(){
+ console.log("something");
+ })(), function(){ return true }() ? console.log(true) : console.log(false);
+ }
+ }
+}
+
+negate_iife_5: {
options = {
negate_iife: true,
sequences: true,
@@ -75,6 +135,29 @@ negate_iife_4: {
}
}
+negate_iife_5_off: {
+ options = {
+ negate_iife: false,
+ sequences: true,
+ conditionals: true,
+ };
+ input: {
+ if ((function(){ return true })()) {
+ foo(true);
+ } else {
+ bar(false);
+ }
+ (function(){
+ console.log("something");
+ })();
+ }
+ expect: {
+ !function(){ return true }() ? bar(false) : foo(true), function(){
+ console.log("something");
+ }();
+ }
+}
+
negate_iife_nested: {
options = {
negate_iife: true,
@@ -107,6 +190,38 @@ negate_iife_nested: {
}
}
+negate_iife_nested_off: {
+ options = {
+ negate_iife: false,
+ sequences: true,
+ conditionals: true,
+ };
+ input: {
+ function Foo(f) {
+ this.f = f;
+ }
+ new Foo(function() {
+ (function(x) {
+ (function(y) {
+ console.log(y);
+ })(x);
+ })(7);
+ }).f();
+ }
+ expect: {
+ function Foo(f) {
+ this.f = f;
+ }
+ new Foo(function() {
+ (function(x) {
+ (function(y) {
+ console.log(y);
+ })(x);
+ })(7);
+ }).f();
+ }
+}
+
negate_iife_issue_1073: {
options = {
negate_iife: true,
@@ -172,3 +287,36 @@ issue_1254_negate_iife_nested: {
}
expect_exact: '!function(){return function(){console.log("test")}}()()()()();'
}
+
+issue_1288: {
+ options = {
+ negate_iife: true,
+ conditionals: true,
+ };
+ input: {
+ if (w) ;
+ else {
+ (function f() {})();
+ }
+ if (!x) {
+ (function() {
+ x = {};
+ })();
+ }
+ if (y)
+ (function() {})();
+ else
+ (function(z) {
+ return z;
+ })(0);
+ }
+ expect: {
+ w || function f() {}();
+ x || function() {
+ x = {};
+ }();
+ y ? function() {}() : function(z) {
+ return z;
+ }(0);
+ }
+}
diff --git a/test/compress/properties.js b/test/compress/properties.js
index 7ad54ebe..29bdfe2a 100644
--- a/test/compress/properties.js
+++ b/test/compress/properties.js
@@ -539,3 +539,19 @@ first_256_hex_chars_as_properties: {
};
}
}
+
+native_prototype: {
+ options = {
+ unsafe_proto: true,
+ }
+ input: {
+ Array.prototype.splice.apply(a, [1, 2, b, c]);
+ Object.prototype.hasOwnProperty.call(d, "foo");
+ String.prototype.indexOf.call(e, "bar");
+ }
+ expect: {
+ [].splice.apply(a, [1, 2, b, c]);
+ ({}).hasOwnProperty.call(d, "foo");
+ "".indexOf.call(e, "bar");
+ }
+}
diff --git a/test/compress/pure_funcs.js b/test/compress/pure_funcs.js
new file mode 100644
index 00000000..3cc529a8
--- /dev/null
+++ b/test/compress/pure_funcs.js
@@ -0,0 +1,295 @@
+array: {
+ options = {
+ pure_funcs: [ "Math.floor" ],
+ side_effects: true,
+ }
+ input: {
+ var a;
+ function f(b) {
+ Math.floor(a / b);
+ Math.floor(c / b);
+ }
+ }
+ expect: {
+ var a;
+ function f(b) {
+ c;
+ }
+ }
+}
+
+func: {
+ options = {
+ pure_funcs: function(node) {
+ return !~node.args[0].print_to_string().indexOf("a");
+ },
+ side_effects: true,
+ }
+ input: {
+ function f(a, b) {
+ Math.floor(a / b);
+ Math.floor(c / b);
+ }
+ }
+ expect: {
+ function f(a, b) {
+ Math.floor(c / b);
+ }
+ }
+}
+
+side_effects: {
+ options = {
+ pure_funcs: [ "console.log" ],
+ side_effects: true,
+ }
+ input: {
+ function f(a, b) {
+ console.log(a());
+ console.log(b);
+ }
+ }
+ expect: {
+ function f(a, b) {
+ a();
+ }
+ }
+}
+
+unused: {
+ options = {
+ pure_funcs: [ "pure" ],
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ function foo() {
+ var u = pure(1);
+ var x = pure(2);
+ var y = pure(x);
+ var z = pure(pure(side_effects()));
+ return pure(3);
+ }
+ }
+ expect: {
+ function foo() {
+ side_effects();
+ return pure(3);
+ }
+ }
+}
+
+babel: {
+ options = {
+ pure_funcs: [ "_classCallCheck" ],
+ side_effects: true,
+ unused: true,
+ }
+ input: {
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor))
+ throw new TypeError("Cannot call a class as a function");
+ }
+ var Foo = function Foo() {
+ _classCallCheck(this, Foo);
+ };
+ }
+ expect: {
+ function _classCallCheck(instance, Constructor) {
+ if (!(instance instanceof Constructor))
+ throw new TypeError("Cannot call a class as a function");
+ }
+ var Foo = function() {
+ };
+ }
+}
+
+conditional: {
+ options = {
+ pure_funcs: [ "pure" ],
+ side_effects: true,
+ }
+ input: {
+ pure(1 | a() ? 2 & b() : 7 ^ c());
+ pure(1 | a() ? 2 & b() : 5);
+ pure(1 | a() ? 4 : 7 ^ c());
+ pure(1 | a() ? 4 : 5);
+ pure(3 ? 2 & b() : 7 ^ c());
+ pure(3 ? 2 & b() : 5);
+ pure(3 ? 4 : 7 ^ c());
+ pure(3 ? 4 : 5);
+ }
+ expect: {
+ 1 | a() ? b() : c();
+ 1 | a() && b();
+ 1 | a() || c();
+ a();
+ 3 ? b() : c();
+ 3 && b();
+ 3 || c();
+ }
+}
+
+relational: {
+ options = {
+ pure_funcs: [ "foo" ],
+ side_effects :true,
+ }
+ input: {
+ foo() in foo();
+ foo() instanceof bar();
+ foo() < "bar";
+ bar() > foo();
+ bar() != bar();
+ bar() !== "bar";
+ "bar" == foo();
+ "bar" === bar();
+ "bar" >= "bar";
+ }
+ expect: {
+ bar();
+ bar();
+ bar(), bar();
+ bar();
+ bar();
+ }
+}
+
+arithmetic: {
+ options = {
+ pure_funcs: [ "foo" ],
+ side_effects :true,
+ }
+ input: {
+ foo() + foo();
+ foo() - bar();
+ foo() * "bar";
+ bar() / foo();
+ bar() & bar();
+ bar() | "bar";
+ "bar" >> foo();
+ "bar" << bar();
+ "bar" >>> "bar";
+ }
+ expect: {
+ bar();
+ bar();
+ bar(), bar();
+ bar();
+ bar();
+ }
+}
+
+boolean_and: {
+ options = {
+ pure_funcs: [ "foo" ],
+ side_effects :true,
+ }
+ input: {
+ foo() && foo();
+ foo() && bar();
+ foo() && "bar";
+ bar() && foo();
+ bar() && bar();
+ bar() && "bar";
+ "bar" && foo();
+ "bar" && bar();
+ "bar" && "bar";
+ }
+ expect: {
+ foo() && bar();
+ bar();
+ bar() && bar();
+ bar();
+ "bar" && bar();
+ }
+}
+
+boolean_or: {
+ options = {
+ pure_funcs: [ "foo" ],
+ side_effects :true,
+ }
+ input: {
+ foo() || foo();
+ foo() || bar();
+ foo() || "bar";
+ bar() || foo();
+ bar() || bar();
+ bar() || "bar";
+ "bar" || foo();
+ "bar" || bar();
+ "bar" || "bar";
+ }
+ expect: {
+ foo() || bar();
+ bar();
+ bar() || bar();
+ bar();
+ "bar" || bar();
+ }
+}
+
+assign: {
+ options = {
+ pure_funcs: [ "foo" ],
+ side_effects :true,
+ }
+ input: {
+ var a;
+ function f(b) {
+ a = foo();
+ b *= 4 + foo();
+ c >>= 0 | foo();
+ }
+ }
+ expect: {
+ var a;
+ function f(b) {
+ a = foo();
+ b *= 4 + foo();
+ c >>= 0 | foo();
+ }
+ }
+}
+
+unary: {
+ options = {
+ pure_funcs: [ "foo" ],
+ side_effects :true,
+ }
+ input: {
+ typeof foo();
+ typeof bar();
+ typeof "bar";
+ void foo();
+ void bar();
+ void "bar";
+ delete a[foo()];
+ delete a[bar()];
+ delete a["bar"];
+ a[foo()]++;
+ a[bar()]++;
+ a["bar"]++;
+ --a[foo()];
+ --a[bar()];
+ --a["bar"];
+ ~foo();
+ ~bar();
+ ~"bar";
+ }
+ expect: {
+ bar();
+ bar();
+ delete a[foo()];
+ delete a[bar()];
+ delete a["bar"];
+ a[foo()]++;
+ a[bar()]++;
+ a["bar"]++;
+ --a[foo()];
+ --a[bar()];
+ --a["bar"];
+ bar();
+ }
+}
diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js
index 2301a92a..d9d02efa 100644
--- a/test/compress/reduce_vars.js
+++ b/test/compress/reduce_vars.js
@@ -108,8 +108,6 @@ modified: {
}
console.log(a + b);
console.log(b + c);
- // TODO: as "modified" is determined in "figure_out_scope",
- // even "passes" wouldn't improve this any further
console.log(a + c);
console.log(a + b + c);
}
@@ -350,3 +348,125 @@ unsafe_evaluate_equality: {
}
}
}
+
+passes: {
+ options = {
+ conditionals: true,
+ evaluate: true,
+ passes: 2,
+ reduce_vars: true,
+ unused: true,
+ }
+ input: {
+ function f() {
+ var a = 1, b = 2, c = 3;
+ if (a) {
+ b = c;
+ } else {
+ c = b;
+ }
+ console.log(a + b);
+ console.log(b + c);
+ console.log(a + c);
+ console.log(a + b + c);
+ }
+ }
+ expect: {
+ function f() {
+ var b = 2, c = 3;
+ b = c;
+ console.log(1 + b);
+ console.log(b + 3);
+ console.log(4);
+ console.log(1 + b + 3);
+ }
+ }
+}
+
+iife: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ }
+ input: {
+ !function(a, b, c) {
+ b++;
+ console.log(a - 1, b * 1, c + 2);
+ }(1, 2, 3);
+ }
+ expect: {
+ !function(a, b, c) {
+ b++;
+ console.log(0, 1 * b, 5);
+ }(1, 2, 3);
+ }
+}
+
+iife_new: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ }
+ input: {
+ var A = new function(a, b, c) {
+ b++;
+ console.log(a - 1, b * 1, c + 2);
+ }(1, 2, 3);
+ }
+ expect: {
+ var A = new function(a, b, c) {
+ b++;
+ console.log(0, 1 * b, 5);
+ }(1, 2, 3);
+ }
+}
+
+multi_def: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ }
+ input: {
+ function f(a) {
+ if (a)
+ var b = 1;
+ else
+ var b = 2
+ console.log(b + 1);
+ }
+ }
+ expect: {
+ function f(a) {
+ if (a)
+ var b = 1;
+ else
+ var b = 2
+ console.log(b + 1);
+ }
+ }
+}
+
+multi_def_2: {
+ options = {
+ evaluate: true,
+ reduce_vars: true,
+ }
+ input: {
+ if (code == 16)
+ var bitsLength = 2, bitsOffset = 3, what = len;
+ else if (code == 17)
+ var bitsLength = 3, bitsOffset = 3, what = (len = 0);
+ else if (code == 18)
+ var bitsLength = 7, bitsOffset = 11, what = (len = 0);
+ var repeatLength = this.getBits(bitsLength) + bitsOffset;
+ }
+ expect: {
+ if (16 == code)
+ var bitsLength = 2, bitsOffset = 3, what = len;
+ else if (17 == code)
+ var bitsLength = 3, bitsOffset = 3, what = (len = 0);
+ else if (18 == code)
+ var bitsLength = 7, bitsOffset = 11, what = (len = 0);
+ var repeatLength = this.getBits(bitsLength) + bitsOffset;
+ }
+}
diff --git a/test/compress/sequences.js b/test/compress/sequences.js
index 0e3319ab..d93f5237 100644
--- a/test/compress/sequences.js
+++ b/test/compress/sequences.js
@@ -169,3 +169,85 @@ for_sequences: {
for (y = 5; false;);
}
}
+
+limit_1: {
+ options = {
+ sequences: 3,
+ };
+ input: {
+ a;
+ b;
+ c;
+ d;
+ e;
+ f;
+ g;
+ h;
+ i;
+ j;
+ k;
+ }
+ expect: {
+ a, b, c;
+ d, e, f;
+ g, h, i;
+ j, k;
+ }
+}
+
+limit_2: {
+ options = {
+ sequences: 3,
+ };
+ input: {
+ a, b;
+ c, d;
+ e, f;
+ g, h;
+ i, j;
+ k;
+ }
+ expect: {
+ a, b, c, d;
+ e, f, g, h;
+ i, j, k;
+ }
+}
+
+negate_iife_for: {
+ options = {
+ sequences: true,
+ negate_iife: true,
+ };
+ input: {
+ (function() {})();
+ for (i = 0; i < 5; i++) console.log(i);
+
+ (function() {})();
+ for (; i < 5; i++) console.log(i);
+ }
+ expect: {
+ for (!function() {}(), i = 0; i < 5; i++) console.log(i);
+ for (function() {}(); i < 5; i++) console.log(i);
+ }
+}
+
+iife: {
+ options = {
+ sequences: true,
+ };
+ input: {
+ x = 42;
+ (function a() {})();
+ !function b() {}();
+ ~function c() {}();
+ +function d() {}();
+ -function e() {}();
+ void function f() {}();
+ typeof function g() {}();
+ }
+ expect: {
+ x = 42, function a() {}(), function b() {}(), function c() {}(),
+ function d() {}(), function e() {}(), function f() {}(), function g() {}()
+ }
+}
diff --git a/test/input/global_defs/nested.js b/test/input/global_defs/nested.js
new file mode 100644
index 00000000..dbf57909
--- /dev/null
+++ b/test/input/global_defs/nested.js
@@ -0,0 +1 @@
+console.log(C.V, C.D);
diff --git a/test/input/global_defs/simple.js b/test/input/global_defs/simple.js
new file mode 100644
index 00000000..44d515e3
--- /dev/null
+++ b/test/input/global_defs/simple.js
@@ -0,0 +1 @@
+console.log(D);
diff --git a/test/input/issue-1482/bracketize.js b/test/input/issue-1482/bracketize.js
new file mode 100644
index 00000000..2c2b103c
--- /dev/null
+++ b/test/input/issue-1482/bracketize.js
@@ -0,0 +1,73 @@
+if (x) {
+ foo();
+}
+
+if (x) {
+ foo();
+} else {
+ baz();
+}
+
+if (x) {
+ foo();
+} else if (y) {
+ bar();
+} else {
+ baz();
+}
+
+if (x) {
+ if (y) {
+ foo();
+ } else {
+ bar();
+ }
+} else {
+ baz();
+}
+
+if (x) {
+ foo();
+} else if (y) {
+ bar();
+} else if (z) {
+ baz();
+} else {
+ moo();
+}
+
+function f() {
+ if (x) {
+ foo();
+ }
+ if (x) {
+ foo();
+ } else {
+ baz();
+ }
+ if (x) {
+ foo();
+ } else if (y) {
+ bar();
+ } else {
+ baz();
+ }
+ if (x) {
+ if (y) {
+ foo();
+ } else {
+ bar();
+ }
+ } else {
+ baz();
+ }
+ if (x) {
+ foo();
+ } else if (y) {
+ bar();
+ } else if (z) {
+ baz();
+ } else {
+ moo();
+ }
+}
diff --git a/test/input/issue-1482/default.js b/test/input/issue-1482/default.js
new file mode 100644
index 00000000..14054e98
--- /dev/null
+++ b/test/input/issue-1482/default.js
@@ -0,0 +1,17 @@
+if (x) foo();
+
+if (x) foo(); else baz();
+
+if (x) foo(); else if (y) bar(); else baz();
+
+if (x) if (y) foo(); else bar(); else baz();
+
+if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
+
+function f() {
+ if (x) foo();
+ if (x) foo(); else baz();
+ if (x) foo(); else if (y) bar(); else baz();
+ if (x) if (y) foo(); else bar(); else baz();
+ if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
+}
diff --git a/test/input/issue-1482/input.js b/test/input/issue-1482/input.js
new file mode 100644
index 00000000..0186e82c
--- /dev/null
+++ b/test/input/issue-1482/input.js
@@ -0,0 +1,12 @@
+if (x) foo();
+if (x) foo(); else baz();
+if (x) foo(); else if (y) bar(); else baz();
+if (x) if (y) foo(); else bar(); else baz();
+if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
+function f() {
+if (x) foo();
+if (x) foo(); else baz();
+if (x) foo(); else if (y) bar(); else baz();
+if (x) if (y) foo(); else bar(); else baz();
+if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();
+}
diff --git a/test/jetstream.js b/test/jetstream.js
new file mode 100644
index 00000000..a8195389
--- /dev/null
+++ b/test/jetstream.js
@@ -0,0 +1,87 @@
+#! /usr/bin/env node
+// -*- js -*-
+
+"use strict";
+
+var site = "http://browserbench.org/JetStream/";
+if (typeof phantom == "undefined") {
+ // workaround for tty output truncation upon process.exit()
+ [process.stdout, process.stderr].forEach(function(stream){
+ if (stream._handle && stream._handle.setBlocking)
+ stream._handle.setBlocking(true);
+ });
+ var args = process.argv.slice(2);
+ if (!args.length) {
+ args.push("-mc", "warnings=false");
+ }
+ args.push("--stats");
+ var child_process = require("child_process");
+ try {
+ require("phantomjs-prebuilt");
+ } catch(e) {
+ child_process.execSync("npm install phantomjs-prebuilt@2.1.14");
+ }
+ var http = require("http");
+ var server = http.createServer(function(request, response) {
+ request.resume();
+ var url = decodeURIComponent(request.url.slice(1));
+ var stderr = "";
+ var uglifyjs = child_process.fork("bin/uglifyjs", args, {
+ silent: true
+ }).on("exit", function(code) {
+ console.log("uglifyjs", url.indexOf(site) == 0 ? url.slice(site.length) : url, args.join(" "));
+ console.log(stderr);
+ if (code) throw new Error("uglifyjs failed with code " + code);
+ });
+ uglifyjs.stderr.on("data", function(data) {
+ stderr += data;
+ }).setEncoding("utf8");
+ uglifyjs.stdout.pipe(response);
+ http.get(url, function(res) {
+ res.pipe(uglifyjs.stdin);
+ });
+ }).listen().on("listening", function() {
+ var phantomjs = require("phantomjs-prebuilt");
+ var program = phantomjs.exec(process.argv[1], server.address().port);
+ program.stdout.pipe(process.stdout);
+ program.stderr.pipe(process.stderr);
+ program.on("exit", function(code) {
+ server.close();
+ if (code) throw new Error("JetStream failed!");
+ console.log("JetStream completed successfully.");
+ });
+ });
+ server.timeout = 0;
+} else {
+ var page = require("webpage").create();
+ page.onError = function(msg, trace) {
+ var body = [ msg ];
+ if (trace) trace.forEach(function(t) {
+ body.push(" " + (t.function || "Anonymous function") + " (" + t.file + ":" + t.line + ")");
+ });
+ console.error(body.join("\n"));
+ phantom.exit(1);
+ };
+ var url = "http://localhost:" + require("system").args[1] + "/";
+ page.onResourceRequested = function(requestData, networkRequest) {
+ if (/\.js$/.test(requestData.url))
+ networkRequest.changeUrl(url + encodeURIComponent(requestData.url));
+ }
+ page.onConsoleMessage = function(msg) {
+ if (/Error:/i.test(msg)) {
+ console.error(msg);
+ phantom.exit(1);
+ }
+ console.log(msg);
+ if (~msg.indexOf("Raw results:")) {
+ phantom.exit();
+ }
+ };
+ page.open(site, function(status) {
+ if (status != "success") phantomjs.exit(1);
+ page.evaluate(function() {
+ JetStream.switchToQuick();
+ JetStream.start();
+ });
+ });
+}
diff --git a/test/mocha/accessorTokens-1492.js b/test/mocha/accessorTokens-1492.js
new file mode 100644
index 00000000..861414ee
--- /dev/null
+++ b/test/mocha/accessorTokens-1492.js
@@ -0,0 +1,32 @@
+var UglifyJS = require('../../');
+var assert = require("assert");
+
+describe("Accessor tokens", function() {
+ it("Should fill the token information for accessors (issue #1492)", function() {
+ // location 0 1 2 3 4
+ // 01234567890123456789012345678901234567890123456789
+ var ast = UglifyJS.parse("var obj = { get latest() { return undefined; } }");
+
+ // test all AST_ObjectProperty tokens are set as expected
+ var checkedAST_ObjectProperty = false;
+ var checkWalker = new UglifyJS.TreeWalker(function(node, descend) {
+ if (node instanceof UglifyJS.AST_ObjectProperty) {
+ checkedAST_ObjectProperty = true;
+
+ assert.equal(node.start.pos, 12);
+ assert.equal(node.end.endpos, 46);
+
+ assert(node.key instanceof UglifyJS.AST_SymbolRef);
+ assert.equal(node.key.start.pos, 16);
+ assert.equal(node.key.end.endpos, 22);
+
+ assert(node.value instanceof UglifyJS.AST_Accessor);
+ assert.equal(node.value.start.pos, 22);
+ assert.equal(node.value.end.endpos, 46);
+
+ }
+ });
+ ast.walk(checkWalker);
+ assert(checkedAST_ObjectProperty, "AST_ObjectProperty not found");
+ });
+}); \ No newline at end of file
diff --git a/test/mocha/cli.js b/test/mocha/cli.js
index a8de05c5..450df1fd 100644
--- a/test/mocha/cli.js
+++ b/test/mocha/cli.js
@@ -1,10 +1,11 @@
var assert = require("assert");
var exec = require("child_process").exec;
+var readFileSync = require("fs").readFileSync;
describe("bin/uglifyjs", function () {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("should produce a functional build when using --self", function (done) {
- this.timeout(5000);
+ this.timeout(15000);
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
@@ -100,4 +101,54 @@ describe("bin/uglifyjs", function () {
done();
});
});
+ it("Should work with --define (simple)", function (done) {
+ var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "console.log(5);\n");
+ done();
+ });
+ });
+ it("Should work with --define (nested)", function (done) {
+ var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "console.log(3,5);\n");
+ done();
+ });
+ });
+ it("Should work with --define (AST_Node)", function (done) {
+ var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, "stdout.println(D);\n");
+ done();
+ });
+ });
+ it("Should work with `--beautify`", function (done) {
+ var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, readFileSync("test/input/issue-1482/default.js", "utf8"));
+ done();
+ });
+ });
+ it("Should work with `--beautify bracketize`", function (done) {
+ var command = uglifyjscmd + ' test/input/issue-1482/input.js -b bracketize';
+
+ exec(command, function (err, stdout) {
+ if (err) throw err;
+
+ assert.strictEqual(stdout, readFileSync("test/input/issue-1482/bracketize.js", "utf8"));
+ done();
+ });
+ });
});
diff --git a/test/mocha/minify.js b/test/mocha/minify.js
index 70cf73ae..8fe1565f 100644
--- a/test/mocha/minify.js
+++ b/test/mocha/minify.js
@@ -95,4 +95,19 @@ describe("minify", function() {
assert.strictEqual(code, "var a=function(n){return n};");
});
});
+
+ describe("#__PURE__", function() {
+ it("should drop #__PURE__ hint after use", function() {
+ var result = Uglify.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
+ fromString: true,
+ output: {
+ comments: "all",
+ beautify: false,
+ }
+ });
+ var code = result.code;
+ assert.strictEqual(code, "// comment1 comment2\nbar();");
+ });
+ });
+
});
diff --git a/test/mocha/operator.js b/test/mocha/operator.js
new file mode 100644
index 00000000..adef3abd
--- /dev/null
+++ b/test/mocha/operator.js
@@ -0,0 +1,489 @@
+var UglifyJS = require("../../");
+var assert = require("assert");
+
+describe("operator", function() {
+ it("Should handle mixing of ++/+/--/- correctly", function() {
+ function evaluate(exp) {
+ return new Function("var a=1,b=2,c=" + exp + ";return{a:a,b:b,c:c}")();
+ }
+
+ [ "", "+", "-" ].forEach(function(p) {
+ [ "++a", "--a", "a", "a--", "a++" ].forEach(function(a) {
+ [ "+", "-" ].forEach(function(o) {
+ [ "", "+", "-" ].forEach(function(q) {
+ [ "++b", "--b", "b", "b--", "b++" ].forEach(function(b) {
+ var exp = [p, a, o, q, b].join(" ");
+ var orig = evaluate(exp);
+ var uglify = evaluate(UglifyJS.parse(exp).print_to_string());
+ assert.strictEqual(orig.a, uglify.a);
+ assert.strictEqual(orig.b, uglify.b);
+ assert.strictEqual(orig.c, uglify.c);
+ var beautify = evaluate(UglifyJS.parse(exp).print_to_string({
+ beautify: true
+ }));
+ assert.strictEqual(orig.a, beautify.a);
+ assert.strictEqual(orig.b, beautify.b);
+ assert.strictEqual(orig.c, beautify.c);
+ });
+ });
+ });
+ });
+ });
+ });
+ it("Should remove extraneous spaces", function() {
+ [
+ [ "++a + ++b", "++a+ ++b" ],
+ [ "++a + --b", "++a+--b" ],
+ [ "++a + b", "++a+b" ],
+ [ "++a + b--", "++a+b--" ],
+ [ "++a + b++", "++a+b++" ],
+ [ "++a + + ++b", "++a+ + ++b" ],
+ [ "++a + + --b", "++a+ +--b" ],
+ [ "++a + + b", "++a+ +b" ],
+ [ "++a + + b--", "++a+ +b--" ],
+ [ "++a + + b++", "++a+ +b++" ],
+ [ "++a + - ++b", "++a+-++b" ],
+ [ "++a + - --b", "++a+- --b" ],
+ [ "++a + - b", "++a+-b" ],
+ [ "++a + - b--", "++a+-b--" ],
+ [ "++a + - b++", "++a+-b++" ],
+ [ "++a - ++b", "++a-++b" ],
+ [ "++a - --b", "++a- --b" ],
+ [ "++a - b", "++a-b" ],
+ [ "++a - b--", "++a-b--" ],
+ [ "++a - b++", "++a-b++" ],
+ [ "++a - + ++b", "++a-+ ++b" ],
+ [ "++a - + --b", "++a-+--b" ],
+ [ "++a - + b", "++a-+b" ],
+ [ "++a - + b--", "++a-+b--" ],
+ [ "++a - + b++", "++a-+b++" ],
+ [ "++a - - ++b", "++a- -++b" ],
+ [ "++a - - --b", "++a- - --b" ],
+ [ "++a - - b", "++a- -b" ],
+ [ "++a - - b--", "++a- -b--" ],
+ [ "++a - - b++", "++a- -b++" ],
+ [ "--a + ++b", "--a+ ++b" ],
+ [ "--a + --b", "--a+--b" ],
+ [ "--a + b", "--a+b" ],
+ [ "--a + b--", "--a+b--" ],
+ [ "--a + b++", "--a+b++" ],
+ [ "--a + + ++b", "--a+ + ++b" ],
+ [ "--a + + --b", "--a+ +--b" ],
+ [ "--a + + b", "--a+ +b" ],
+ [ "--a + + b--", "--a+ +b--" ],
+ [ "--a + + b++", "--a+ +b++" ],
+ [ "--a + - ++b", "--a+-++b" ],
+ [ "--a + - --b", "--a+- --b" ],
+ [ "--a + - b", "--a+-b" ],
+ [ "--a + - b--", "--a+-b--" ],
+ [ "--a + - b++", "--a+-b++" ],
+ [ "--a - ++b", "--a-++b" ],
+ [ "--a - --b", "--a- --b" ],
+ [ "--a - b", "--a-b" ],
+ [ "--a - b--", "--a-b--" ],
+ [ "--a - b++", "--a-b++" ],
+ [ "--a - + ++b", "--a-+ ++b" ],
+ [ "--a - + --b", "--a-+--b" ],
+ [ "--a - + b", "--a-+b" ],
+ [ "--a - + b--", "--a-+b--" ],
+ [ "--a - + b++", "--a-+b++" ],
+ [ "--a - - ++b", "--a- -++b" ],
+ [ "--a - - --b", "--a- - --b" ],
+ [ "--a - - b", "--a- -b" ],
+ [ "--a - - b--", "--a- -b--" ],
+ [ "--a - - b++", "--a- -b++" ],
+ [ "a + ++b", "a+ ++b" ],
+ [ "a + --b", "a+--b" ],
+ [ "a + b", "a+b" ],
+ [ "a + b--", "a+b--" ],
+ [ "a + b++", "a+b++" ],
+ [ "a + + ++b", "a+ + ++b" ],
+ [ "a + + --b", "a+ +--b" ],
+ [ "a + + b", "a+ +b" ],
+ [ "a + + b--", "a+ +b--" ],
+ [ "a + + b++", "a+ +b++" ],
+ [ "a + - ++b", "a+-++b" ],
+ [ "a + - --b", "a+- --b" ],
+ [ "a + - b", "a+-b" ],
+ [ "a + - b--", "a+-b--" ],
+ [ "a + - b++", "a+-b++" ],
+ [ "a - ++b", "a-++b" ],
+ [ "a - --b", "a- --b" ],
+ [ "a - b", "a-b" ],
+ [ "a - b--", "a-b--" ],
+ [ "a - b++", "a-b++" ],
+ [ "a - + ++b", "a-+ ++b" ],
+ [ "a - + --b", "a-+--b" ],
+ [ "a - + b", "a-+b" ],
+ [ "a - + b--", "a-+b--" ],
+ [ "a - + b++", "a-+b++" ],
+ [ "a - - ++b", "a- -++b" ],
+ [ "a - - --b", "a- - --b" ],
+ [ "a - - b", "a- -b" ],
+ [ "a - - b--", "a- -b--" ],
+ [ "a - - b++", "a- -b++" ],
+ [ "a-- + ++b", "a--+ ++b" ],
+ [ "a-- + --b", "a--+--b" ],
+ [ "a-- + b", "a--+b" ],
+ [ "a-- + b--", "a--+b--" ],
+ [ "a-- + b++", "a--+b++" ],
+ [ "a-- + + ++b", "a--+ + ++b" ],
+ [ "a-- + + --b", "a--+ +--b" ],
+ [ "a-- + + b", "a--+ +b" ],
+ [ "a-- + + b--", "a--+ +b--" ],
+ [ "a-- + + b++", "a--+ +b++" ],
+ [ "a-- + - ++b", "a--+-++b" ],
+ [ "a-- + - --b", "a--+- --b" ],
+ [ "a-- + - b", "a--+-b" ],
+ [ "a-- + - b--", "a--+-b--" ],
+ [ "a-- + - b++", "a--+-b++" ],
+ [ "a-- - ++b", "a---++b" ],
+ [ "a-- - --b", "a--- --b" ],
+ [ "a-- - b", "a---b" ],
+ [ "a-- - b--", "a---b--" ],
+ [ "a-- - b++", "a---b++" ],
+ [ "a-- - + ++b", "a---+ ++b" ],
+ [ "a-- - + --b", "a---+--b" ],
+ [ "a-- - + b", "a---+b" ],
+ [ "a-- - + b--", "a---+b--" ],
+ [ "a-- - + b++", "a---+b++" ],
+ [ "a-- - - ++b", "a--- -++b" ],
+ [ "a-- - - --b", "a--- - --b" ],
+ [ "a-- - - b", "a--- -b" ],
+ [ "a-- - - b--", "a--- -b--" ],
+ [ "a-- - - b++", "a--- -b++" ],
+ [ "a++ + ++b", "a+++ ++b" ],
+ [ "a++ + --b", "a+++--b" ],
+ [ "a++ + b", "a+++b" ],
+ [ "a++ + b--", "a+++b--" ],
+ [ "a++ + b++", "a+++b++" ],
+ [ "a++ + + ++b", "a+++ + ++b" ],
+ [ "a++ + + --b", "a+++ +--b" ],
+ [ "a++ + + b", "a+++ +b" ],
+ [ "a++ + + b--", "a+++ +b--" ],
+ [ "a++ + + b++", "a+++ +b++" ],
+ [ "a++ + - ++b", "a+++-++b" ],
+ [ "a++ + - --b", "a+++- --b" ],
+ [ "a++ + - b", "a+++-b" ],
+ [ "a++ + - b--", "a+++-b--" ],
+ [ "a++ + - b++", "a+++-b++" ],
+ [ "a++ - ++b", "a++-++b" ],
+ [ "a++ - --b", "a++- --b" ],
+ [ "a++ - b", "a++-b" ],
+ [ "a++ - b--", "a++-b--" ],
+ [ "a++ - b++", "a++-b++" ],
+ [ "a++ - + ++b", "a++-+ ++b" ],
+ [ "a++ - + --b", "a++-+--b" ],
+ [ "a++ - + b", "a++-+b" ],
+ [ "a++ - + b--", "a++-+b--" ],
+ [ "a++ - + b++", "a++-+b++" ],
+ [ "a++ - - ++b", "a++- -++b" ],
+ [ "a++ - - --b", "a++- - --b" ],
+ [ "a++ - - b", "a++- -b" ],
+ [ "a++ - - b--", "a++- -b--" ],
+ [ "a++ - - b++", "a++- -b++" ],
+ [ "+ ++a + ++b", "+ ++a+ ++b" ],
+ [ "+ ++a + --b", "+ ++a+--b" ],
+ [ "+ ++a + b", "+ ++a+b" ],
+ [ "+ ++a + b--", "+ ++a+b--" ],
+ [ "+ ++a + b++", "+ ++a+b++" ],
+ [ "+ ++a + + ++b", "+ ++a+ + ++b" ],
+ [ "+ ++a + + --b", "+ ++a+ +--b" ],
+ [ "+ ++a + + b", "+ ++a+ +b" ],
+ [ "+ ++a + + b--", "+ ++a+ +b--" ],
+ [ "+ ++a + + b++", "+ ++a+ +b++" ],
+ [ "+ ++a + - ++b", "+ ++a+-++b" ],
+ [ "+ ++a + - --b", "+ ++a+- --b" ],
+ [ "+ ++a + - b", "+ ++a+-b" ],
+ [ "+ ++a + - b--", "+ ++a+-b--" ],
+ [ "+ ++a + - b++", "+ ++a+-b++" ],
+ [ "+ ++a - ++b", "+ ++a-++b" ],
+ [ "+ ++a - --b", "+ ++a- --b" ],
+ [ "+ ++a - b", "+ ++a-b" ],
+ [ "+ ++a - b--", "+ ++a-b--" ],
+ [ "+ ++a - b++", "+ ++a-b++" ],
+ [ "+ ++a - + ++b", "+ ++a-+ ++b" ],
+ [ "+ ++a - + --b", "+ ++a-+--b" ],
+ [ "+ ++a - + b", "+ ++a-+b" ],
+ [ "+ ++a - + b--", "+ ++a-+b--" ],
+ [ "+ ++a - + b++", "+ ++a-+b++" ],
+ [ "+ ++a - - ++b", "+ ++a- -++b" ],
+ [ "+ ++a - - --b", "+ ++a- - --b" ],
+ [ "+ ++a - - b", "+ ++a- -b" ],
+ [ "+ ++a - - b--", "+ ++a- -b--" ],
+ [ "+ ++a - - b++", "+ ++a- -b++" ],
+ [ "+ --a + ++b", "+--a+ ++b" ],
+ [ "+ --a + --b", "+--a+--b" ],
+ [ "+ --a + b", "+--a+b" ],
+ [ "+ --a + b--", "+--a+b--" ],
+ [ "+ --a + b++", "+--a+b++" ],
+ [ "+ --a + + ++b", "+--a+ + ++b" ],
+ [ "+ --a + + --b", "+--a+ +--b" ],
+ [ "+ --a + + b", "+--a+ +b" ],
+ [ "+ --a + + b--", "+--a+ +b--" ],
+ [ "+ --a + + b++", "+--a+ +b++" ],
+ [ "+ --a + - ++b", "+--a+-++b" ],
+ [ "+ --a + - --b", "+--a+- --b" ],
+ [ "+ --a + - b", "+--a+-b" ],
+ [ "+ --a + - b--", "+--a+-b--" ],
+ [ "+ --a + - b++", "+--a+-b++" ],
+ [ "+ --a - ++b", "+--a-++b" ],
+ [ "+ --a - --b", "+--a- --b" ],
+ [ "+ --a - b", "+--a-b" ],
+ [ "+ --a - b--", "+--a-b--" ],
+ [ "+ --a - b++", "+--a-b++" ],
+ [ "+ --a - + ++b", "+--a-+ ++b" ],
+ [ "+ --a - + --b", "+--a-+--b" ],
+ [ "+ --a - + b", "+--a-+b" ],
+ [ "+ --a - + b--", "+--a-+b--" ],
+ [ "+ --a - + b++", "+--a-+b++" ],
+ [ "+ --a - - ++b", "+--a- -++b" ],
+ [ "+ --a - - --b", "+--a- - --b" ],
+ [ "+ --a - - b", "+--a- -b" ],
+ [ "+ --a - - b--", "+--a- -b--" ],
+ [ "+ --a - - b++", "+--a- -b++" ],
+ [ "+ a + ++b", "+a+ ++b" ],
+ [ "+ a + --b", "+a+--b" ],
+ [ "+ a + b", "+a+b" ],
+ [ "+ a + b--", "+a+b--" ],
+ [ "+ a + b++", "+a+b++" ],
+ [ "+ a + + ++b", "+a+ + ++b" ],
+ [ "+ a + + --b", "+a+ +--b" ],
+ [ "+ a + + b", "+a+ +b" ],
+ [ "+ a + + b--", "+a+ +b--" ],
+ [ "+ a + + b++", "+a+ +b++" ],
+ [ "+ a + - ++b", "+a+-++b" ],
+ [ "+ a + - --b", "+a+- --b" ],
+ [ "+ a + - b", "+a+-b" ],
+ [ "+ a + - b--", "+a+-b--" ],
+ [ "+ a + - b++", "+a+-b++" ],
+ [ "+ a - ++b", "+a-++b" ],
+ [ "+ a - --b", "+a- --b" ],
+ [ "+ a - b", "+a-b" ],
+ [ "+ a - b--", "+a-b--" ],
+ [ "+ a - b++", "+a-b++" ],
+ [ "+ a - + ++b", "+a-+ ++b" ],
+ [ "+ a - + --b", "+a-+--b" ],
+ [ "+ a - + b", "+a-+b" ],
+ [ "+ a - + b--", "+a-+b--" ],
+ [ "+ a - + b++", "+a-+b++" ],
+ [ "+ a - - ++b", "+a- -++b" ],
+ [ "+ a - - --b", "+a- - --b" ],
+ [ "+ a - - b", "+a- -b" ],
+ [ "+ a - - b--", "+a- -b--" ],
+ [ "+ a - - b++", "+a- -b++" ],
+ [ "+ a-- + ++b", "+a--+ ++b" ],
+ [ "+ a-- + --b", "+a--+--b" ],
+ [ "+ a-- + b", "+a--+b" ],
+ [ "+ a-- + b--", "+a--+b--" ],
+ [ "+ a-- + b++", "+a--+b++" ],
+ [ "+ a-- + + ++b", "+a--+ + ++b" ],
+ [ "+ a-- + + --b", "+a--+ +--b" ],
+ [ "+ a-- + + b", "+a--+ +b" ],
+ [ "+ a-- + + b--", "+a--+ +b--" ],
+ [ "+ a-- + + b++", "+a--+ +b++" ],
+ [ "+ a-- + - ++b", "+a--+-++b" ],
+ [ "+ a-- + - --b", "+a--+- --b" ],
+ [ "+ a-- + - b", "+a--+-b" ],
+ [ "+ a-- + - b--", "+a--+-b--" ],
+ [ "+ a-- + - b++", "+a--+-b++" ],
+ [ "+ a-- - ++b", "+a---++b" ],
+ [ "+ a-- - --b", "+a--- --b" ],
+ [ "+ a-- - b", "+a---b" ],
+ [ "+ a-- - b--", "+a---b--" ],
+ [ "+ a-- - b++", "+a---b++" ],
+ [ "+ a-- - + ++b", "+a---+ ++b" ],
+ [ "+ a-- - + --b", "+a---+--b" ],
+ [ "+ a-- - + b", "+a---+b" ],
+ [ "+ a-- - + b--", "+a---+b--" ],
+ [ "+ a-- - + b++", "+a---+b++" ],
+ [ "+ a-- - - ++b", "+a--- -++b" ],
+ [ "+ a-- - - --b", "+a--- - --b" ],
+ [ "+ a-- - - b", "+a--- -b" ],
+ [ "+ a-- - - b--", "+a--- -b--" ],
+ [ "+ a-- - - b++", "+a--- -b++" ],
+ [ "+ a++ + ++b", "+a+++ ++b" ],
+ [ "+ a++ + --b", "+a+++--b" ],
+ [ "+ a++ + b", "+a+++b" ],
+ [ "+ a++ + b--", "+a+++b--" ],
+ [ "+ a++ + b++", "+a+++b++" ],
+ [ "+ a++ + + ++b", "+a+++ + ++b" ],
+ [ "+ a++ + + --b", "+a+++ +--b" ],
+ [ "+ a++ + + b", "+a+++ +b" ],
+ [ "+ a++ + + b--", "+a+++ +b--" ],
+ [ "+ a++ + + b++", "+a+++ +b++" ],
+ [ "+ a++ + - ++b", "+a+++-++b" ],
+ [ "+ a++ + - --b", "+a+++- --b" ],
+ [ "+ a++ + - b", "+a+++-b" ],
+ [ "+ a++ + - b--", "+a+++-b--" ],
+ [ "+ a++ + - b++", "+a+++-b++" ],
+ [ "+ a++ - ++b", "+a++-++b" ],
+ [ "+ a++ - --b", "+a++- --b" ],
+ [ "+ a++ - b", "+a++-b" ],
+ [ "+ a++ - b--", "+a++-b--" ],
+ [ "+ a++ - b++", "+a++-b++" ],
+ [ "+ a++ - + ++b", "+a++-+ ++b" ],
+ [ "+ a++ - + --b", "+a++-+--b" ],
+ [ "+ a++ - + b", "+a++-+b" ],
+ [ "+ a++ - + b--", "+a++-+b--" ],
+ [ "+ a++ - + b++", "+a++-+b++" ],
+ [ "+ a++ - - ++b", "+a++- -++b" ],
+ [ "+ a++ - - --b", "+a++- - --b" ],
+ [ "+ a++ - - b", "+a++- -b" ],
+ [ "+ a++ - - b--", "+a++- -b--" ],
+ [ "+ a++ - - b++", "+a++- -b++" ],
+ [ "- ++a + ++b", "-++a+ ++b" ],
+ [ "- ++a + --b", "-++a+--b" ],
+ [ "- ++a + b", "-++a+b" ],
+ [ "- ++a + b--", "-++a+b--" ],
+ [ "- ++a + b++", "-++a+b++" ],
+ [ "- ++a + + ++b", "-++a+ + ++b" ],
+ [ "- ++a + + --b", "-++a+ +--b" ],
+ [ "- ++a + + b", "-++a+ +b" ],
+ [ "- ++a + + b--", "-++a+ +b--" ],
+ [ "- ++a + + b++", "-++a+ +b++" ],
+ [ "- ++a + - ++b", "-++a+-++b" ],
+ [ "- ++a + - --b", "-++a+- --b" ],
+ [ "- ++a + - b", "-++a+-b" ],
+ [ "- ++a + - b--", "-++a+-b--" ],
+ [ "- ++a + - b++", "-++a+-b++" ],
+ [ "- ++a - ++b", "-++a-++b" ],
+ [ "- ++a - --b", "-++a- --b" ],
+ [ "- ++a - b", "-++a-b" ],
+ [ "- ++a - b--", "-++a-b--" ],
+ [ "- ++a - b++", "-++a-b++" ],
+ [ "- ++a - + ++b", "-++a-+ ++b" ],
+ [ "- ++a - + --b", "-++a-+--b" ],
+ [ "- ++a - + b", "-++a-+b" ],
+ [ "- ++a - + b--", "-++a-+b--" ],
+ [ "- ++a - + b++", "-++a-+b++" ],
+ [ "- ++a - - ++b", "-++a- -++b" ],
+ [ "- ++a - - --b", "-++a- - --b" ],
+ [ "- ++a - - b", "-++a- -b" ],
+ [ "- ++a - - b--", "-++a- -b--" ],
+ [ "- ++a - - b++", "-++a- -b++" ],
+ [ "- --a + ++b", "- --a+ ++b" ],
+ [ "- --a + --b", "- --a+--b" ],
+ [ "- --a + b", "- --a+b" ],
+ [ "- --a + b--", "- --a+b--" ],
+ [ "- --a + b++", "- --a+b++" ],
+ [ "- --a + + ++b", "- --a+ + ++b" ],
+ [ "- --a + + --b", "- --a+ +--b" ],
+ [ "- --a + + b", "- --a+ +b" ],
+ [ "- --a + + b--", "- --a+ +b--" ],
+ [ "- --a + + b++", "- --a+ +b++" ],
+ [ "- --a + - ++b", "- --a+-++b" ],
+ [ "- --a + - --b", "- --a+- --b" ],
+ [ "- --a + - b", "- --a+-b" ],
+ [ "- --a + - b--", "- --a+-b--" ],
+ [ "- --a + - b++", "- --a+-b++" ],
+ [ "- --a - ++b", "- --a-++b" ],
+ [ "- --a - --b", "- --a- --b" ],
+ [ "- --a - b", "- --a-b" ],
+ [ "- --a - b--", "- --a-b--" ],
+ [ "- --a - b++", "- --a-b++" ],
+ [ "- --a - + ++b", "- --a-+ ++b" ],
+ [ "- --a - + --b", "- --a-+--b" ],
+ [ "- --a - + b", "- --a-+b" ],
+ [ "- --a - + b--", "- --a-+b--" ],
+ [ "- --a - + b++", "- --a-+b++" ],
+ [ "- --a - - ++b", "- --a- -++b" ],
+ [ "- --a - - --b", "- --a- - --b" ],
+ [ "- --a - - b", "- --a- -b" ],
+ [ "- --a - - b--", "- --a- -b--" ],
+ [ "- --a - - b++", "- --a- -b++" ],
+ [ "- a + ++b", "-a+ ++b" ],
+ [ "- a + --b", "-a+--b" ],
+ [ "- a + b", "-a+b" ],
+ [ "- a + b--", "-a+b--" ],
+ [ "- a + b++", "-a+b++" ],
+ [ "- a + + ++b", "-a+ + ++b" ],
+ [ "- a + + --b", "-a+ +--b" ],
+ [ "- a + + b", "-a+ +b" ],
+ [ "- a + + b--", "-a+ +b--" ],
+ [ "- a + + b++", "-a+ +b++" ],
+ [ "- a + - ++b", "-a+-++b" ],
+ [ "- a + - --b", "-a+- --b" ],
+ [ "- a + - b", "-a+-b" ],
+ [ "- a + - b--", "-a+-b--" ],
+ [ "- a + - b++", "-a+-b++" ],
+ [ "- a - ++b", "-a-++b" ],
+ [ "- a - --b", "-a- --b" ],
+ [ "- a - b", "-a-b" ],
+ [ "- a - b--", "-a-b--" ],
+ [ "- a - b++", "-a-b++" ],
+ [ "- a - + ++b", "-a-+ ++b" ],
+ [ "- a - + --b", "-a-+--b" ],
+ [ "- a - + b", "-a-+b" ],
+ [ "- a - + b--", "-a-+b--" ],
+ [ "- a - + b++", "-a-+b++" ],
+ [ "- a - - ++b", "-a- -++b" ],
+ [ "- a - - --b", "-a- - --b" ],
+ [ "- a - - b", "-a- -b" ],
+ [ "- a - - b--", "-a- -b--" ],
+ [ "- a - - b++", "-a- -b++" ],
+ [ "- a-- + ++b", "-a--+ ++b" ],
+ [ "- a-- + --b", "-a--+--b" ],
+ [ "- a-- + b", "-a--+b" ],
+ [ "- a-- + b--", "-a--+b--" ],
+ [ "- a-- + b++", "-a--+b++" ],
+ [ "- a-- + + ++b", "-a--+ + ++b" ],
+ [ "- a-- + + --b", "-a--+ +--b" ],
+ [ "- a-- + + b", "-a--+ +b" ],
+ [ "- a-- + + b--", "-a--+ +b--" ],
+ [ "- a-- + + b++", "-a--+ +b++" ],
+ [ "- a-- + - ++b", "-a--+-++b" ],
+ [ "- a-- + - --b", "-a--+- --b" ],
+ [ "- a-- + - b", "-a--+-b" ],
+ [ "- a-- + - b--", "-a--+-b--" ],
+ [ "- a-- + - b++", "-a--+-b++" ],
+ [ "- a-- - ++b", "-a---++b" ],
+ [ "- a-- - --b", "-a--- --b" ],
+ [ "- a-- - b", "-a---b" ],
+ [ "- a-- - b--", "-a---b--" ],
+ [ "- a-- - b++", "-a---b++" ],
+ [ "- a-- - + ++b", "-a---+ ++b" ],
+ [ "- a-- - + --b", "-a---+--b" ],
+ [ "- a-- - + b", "-a---+b" ],
+ [ "- a-- - + b--", "-a---+b--" ],
+ [ "- a-- - + b++", "-a---+b++" ],
+ [ "- a-- - - ++b", "-a--- -++b" ],
+ [ "- a-- - - --b", "-a--- - --b" ],
+ [ "- a-- - - b", "-a--- -b" ],
+ [ "- a-- - - b--", "-a--- -b--" ],
+ [ "- a-- - - b++", "-a--- -b++" ],
+ [ "- a++ + ++b", "-a+++ ++b" ],
+ [ "- a++ + --b", "-a+++--b" ],
+ [ "- a++ + b", "-a+++b" ],
+ [ "- a++ + b--", "-a+++b--" ],
+ [ "- a++ + b++", "-a+++b++" ],
+ [ "- a++ + + ++b", "-a+++ + ++b" ],
+ [ "- a++ + + --b", "-a+++ +--b" ],
+ [ "- a++ + + b", "-a+++ +b" ],
+ [ "- a++ + + b--", "-a+++ +b--" ],
+ [ "- a++ + + b++", "-a+++ +b++" ],
+ [ "- a++ + - ++b", "-a+++-++b" ],
+ [ "- a++ + - --b", "-a+++- --b" ],
+ [ "- a++ + - b", "-a+++-b" ],
+ [ "- a++ + - b--", "-a+++-b--" ],
+ [ "- a++ + - b++", "-a+++-b++" ],
+ [ "- a++ - ++b", "-a++-++b" ],
+ [ "- a++ - --b", "-a++- --b" ],
+ [ "- a++ - b", "-a++-b" ],
+ [ "- a++ - b--", "-a++-b--" ],
+ [ "- a++ - b++", "-a++-b++" ],
+ [ "- a++ - + ++b", "-a++-+ ++b" ],
+ [ "- a++ - + --b", "-a++-+--b" ],
+ [ "- a++ - + b", "-a++-+b" ],
+ [ "- a++ - + b--", "-a++-+b--" ],
+ [ "- a++ - + b++", "-a++-+b++" ],
+ [ "- a++ - - ++b", "-a++- -++b" ],
+ [ "- a++ - - --b", "-a++- - --b" ],
+ [ "- a++ - - b", "-a++- -b" ],
+ [ "- a++ - - b--", "-a++- -b--" ],
+ [ "- a++ - - b++", "-a++- -b++" ],
+ ].forEach(function(exp) {
+ assert.strictEqual(UglifyJS.parse(exp[0]).print_to_string(), exp[1] + ";");
+ });
+ });
+});
diff --git a/test/run-tests.js b/test/run-tests.js
index a4721399..15a12c6b 100755
--- a/test/run-tests.js
+++ b/test/run-tests.js
@@ -194,6 +194,9 @@ function parse_test(file) {
if (node instanceof U.AST_LabeledStatement
&& tw.parent() instanceof U.AST_Toplevel) {
var name = node.label.name;
+ if (name in tests) {
+ throw new Error('Duplicated test name "' + name + '" in ' + file);
+ }
tests[name] = get_one_test(name, node.body);
return true;
}