Merge branch 'master' into harmony-v2.8.22
This commit is contained in:
@@ -1672,6 +1672,7 @@ var_side_effects_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
pure_getters: true,
|
||||
unsafe: true,
|
||||
}
|
||||
input: {
|
||||
var print = console.log.bind(console);
|
||||
|
||||
@@ -962,3 +962,56 @@ condition_symbol_matches_consequent: {
|
||||
}
|
||||
expect_stdout: "3 7 true 4"
|
||||
}
|
||||
|
||||
delete_conditional_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1 ? undefined : x));
|
||||
console.log(delete (1 ? void 0 : x));
|
||||
console.log(delete (1 ? Infinity : x));
|
||||
console.log(delete (1 ? 1 / 0 : x));
|
||||
console.log(delete (1 ? NaN : x));
|
||||
console.log(delete (1 ? 0 / 0 : x));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((NaN, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_conditional_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
conditionals: true,
|
||||
evaluate: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (0 ? x : undefined));
|
||||
console.log(delete (0 ? x : void 0));
|
||||
console.log(delete (0 ? x : Infinity));
|
||||
console.log(delete (0 ? x : 1 / 0));
|
||||
console.log(delete (0 ? x : NaN));
|
||||
console.log(delete (0 ? x : 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((Infinity, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((NaN, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -1055,3 +1055,58 @@ issue_1715_4: {
|
||||
}
|
||||
expect_stdout: "1"
|
||||
}
|
||||
|
||||
delete_assign_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(delete (a = undefined));
|
||||
console.log(delete (a = void 0));
|
||||
console.log(delete (a = Infinity));
|
||||
console.log(delete (a = 1 / 0));
|
||||
console.log(delete (a = NaN));
|
||||
console.log(delete (a = 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_assign_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(delete (a = undefined));
|
||||
console.log(delete (a = void 0));
|
||||
console.log(delete (a = Infinity));
|
||||
console.log(delete (a = 1 / 0));
|
||||
console.log(delete (a = NaN));
|
||||
console.log(delete (a = 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((Infinity, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -951,3 +951,135 @@ issue_1760_2: {
|
||||
}
|
||||
expect_stdout: "Infinity"
|
||||
}
|
||||
|
||||
delete_expr_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete undefined);
|
||||
console.log(delete void 0);
|
||||
console.log(delete Infinity);
|
||||
console.log(delete (1 / 0));
|
||||
console.log(delete NaN);
|
||||
console.log(delete (0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(delete undefined);
|
||||
console.log((void 0, !0));
|
||||
console.log(delete Infinity);
|
||||
console.log((1 / 0, !0));
|
||||
console.log(delete NaN);
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_expr_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
keep_infinity: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete undefined);
|
||||
console.log(delete void 0);
|
||||
console.log(delete Infinity);
|
||||
console.log(delete (1 / 0));
|
||||
console.log(delete NaN);
|
||||
console.log(delete (0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log(delete undefined);
|
||||
console.log((void 0, !0));
|
||||
console.log(delete Infinity);
|
||||
console.log((1 / 0, !0));
|
||||
console.log(delete NaN);
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_binary_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (true && undefined));
|
||||
console.log(delete (true && void 0));
|
||||
console.log(delete (true && Infinity));
|
||||
console.log(delete (true && (1 / 0)));
|
||||
console.log(delete (true && NaN));
|
||||
console.log(delete (true && (0 / 0)));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((NaN, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_binary_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (false || undefined));
|
||||
console.log(delete (false || void 0));
|
||||
console.log(delete (false || Infinity));
|
||||
console.log(delete (false || (1 / 0)));
|
||||
console.log(delete (false || NaN));
|
||||
console.log(delete (false || (0 / 0)));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((Infinity, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((NaN, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
Infinity_NaN_undefined_LHS: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
Infinity = Infinity;
|
||||
++Infinity;
|
||||
Infinity--;
|
||||
NaN *= NaN;
|
||||
++NaN;
|
||||
NaN--;
|
||||
undefined |= undefined;
|
||||
++undefined;
|
||||
undefined--;
|
||||
}
|
||||
}
|
||||
expect_exact: [
|
||||
"function f() {",
|
||||
" Infinity = 1 / 0;",
|
||||
" ++Infinity;",
|
||||
" Infinity--;",
|
||||
" NaN *= NaN;",
|
||||
" ++NaN;",
|
||||
" NaN--;",
|
||||
" undefined |= void 0;",
|
||||
" ++undefined;",
|
||||
" undefined--;",
|
||||
"}",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -145,3 +145,18 @@ mixed: {
|
||||
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
|
||||
]
|
||||
}
|
||||
|
||||
issue_1801: {
|
||||
options = {
|
||||
booleans: true,
|
||||
global_defs: {
|
||||
"CONFIG.FOO.BAR": true,
|
||||
},
|
||||
}
|
||||
input: {
|
||||
console.log(CONFIG.FOO.BAR);
|
||||
}
|
||||
expect: {
|
||||
console.log(!0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,10 @@ chained_evaluation_2: {
|
||||
}
|
||||
expect: {
|
||||
(function() {
|
||||
var a = "long piece of string";
|
||||
(function() {
|
||||
var c;
|
||||
c = f(a);
|
||||
c.bar = a;
|
||||
var c, b = "long piece of string";
|
||||
c = f(b);
|
||||
c.bar = b;
|
||||
})();
|
||||
})();
|
||||
}
|
||||
|
||||
105
test/compress/issue-1770.js
Normal file
105
test/compress/issue-1770.js
Normal file
@@ -0,0 +1,105 @@
|
||||
mangle_props: {
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
undefined: 1,
|
||||
NaN: 2,
|
||||
Infinity: 3,
|
||||
"-Infinity": 4,
|
||||
null: 5,
|
||||
};
|
||||
console.log(
|
||||
obj[void 0],
|
||||
obj[undefined],
|
||||
obj["undefined"],
|
||||
obj[0/0],
|
||||
obj[NaN],
|
||||
obj["NaN"],
|
||||
obj[1/0],
|
||||
obj[Infinity],
|
||||
obj["Infinity"],
|
||||
obj[-1/0],
|
||||
obj[-Infinity],
|
||||
obj["-Infinity"],
|
||||
obj[null],
|
||||
obj["null"]
|
||||
);
|
||||
}
|
||||
expect: {
|
||||
var obj = {
|
||||
undefined: 1,
|
||||
NaN: 2,
|
||||
Infinity: 3,
|
||||
"-Infinity": 4,
|
||||
null: 5,
|
||||
};
|
||||
console.log(
|
||||
obj[void 0],
|
||||
obj[void 0],
|
||||
obj["undefined"],
|
||||
obj[0/0],
|
||||
obj[NaN],
|
||||
obj["NaN"],
|
||||
obj[1/0],
|
||||
obj[1/0],
|
||||
obj["Infinity"],
|
||||
obj[-1/0],
|
||||
obj[-1/0],
|
||||
obj["-Infinity"],
|
||||
obj[null],
|
||||
obj["null"]
|
||||
);
|
||||
}
|
||||
expect_stdout: "1 1 1 2 2 2 3 3 3 4 4 4 5 5"
|
||||
}
|
||||
|
||||
numeric_literal: {
|
||||
beautify = {
|
||||
beautify: true,
|
||||
}
|
||||
mangle_props = {}
|
||||
input: {
|
||||
var obj = {
|
||||
0: 0,
|
||||
"-0": 1,
|
||||
42: 2,
|
||||
"42": 3,
|
||||
0x25: 4,
|
||||
"0x25": 5,
|
||||
1E42: 6,
|
||||
"1E42": 7,
|
||||
"1e+42": 8,
|
||||
};
|
||||
console.log(obj[-0], obj[-""], obj["-0"]);
|
||||
console.log(obj[42], obj["42"]);
|
||||
console.log(obj[0x25], obj["0x25"], obj[37], obj["37"]);
|
||||
console.log(obj[1E42], obj["1E42"], obj["1e+42"]);
|
||||
}
|
||||
expect_exact: [
|
||||
'var obj = {',
|
||||
' 0: 0,',
|
||||
' "-0": 1,',
|
||||
' 42: 2,',
|
||||
' "42": 3,',
|
||||
' 37: 4,',
|
||||
' a: 5,',
|
||||
' 1e42: 6,',
|
||||
' b: 7,',
|
||||
' "1e+42": 8',
|
||||
'};',
|
||||
'',
|
||||
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||
'',
|
||||
'console.log(obj[42], obj["42"]);',
|
||||
'',
|
||||
'console.log(obj[37], obj["a"], obj[37], obj["37"]);',
|
||||
'',
|
||||
'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
|
||||
]
|
||||
expect_stdout: [
|
||||
"0 0 1",
|
||||
"3 3",
|
||||
"4 5 4 4",
|
||||
"8 7 8",
|
||||
]
|
||||
}
|
||||
19
test/compress/issue-1787.js
Normal file
19
test/compress/issue-1787.js
Normal file
@@ -0,0 +1,19 @@
|
||||
unary_prefix: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function() {
|
||||
var x = -(2 / 3);
|
||||
return x;
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
console.log(function() {
|
||||
return -2 / 3;
|
||||
}());
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
@@ -215,8 +215,7 @@ evaluate: {
|
||||
a();
|
||||
for(;;)
|
||||
c();
|
||||
// rule disabled due to issue_1532
|
||||
do d(); while (false);
|
||||
d();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,3 +457,26 @@ issue_1648: {
|
||||
}
|
||||
expect_exact: "function f(){for(x();1;);}"
|
||||
}
|
||||
|
||||
do_switch: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
loops: true,
|
||||
}
|
||||
input: {
|
||||
do {
|
||||
switch (a) {
|
||||
case b:
|
||||
continue;
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
expect: {
|
||||
do {
|
||||
switch (a) {
|
||||
case b:
|
||||
continue;
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
}
|
||||
|
||||
121
test/compress/pure_getters.js
Normal file
121
test/compress/pure_getters.js
Normal file
@@ -0,0 +1,121 @@
|
||||
strict: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
strict_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_vars: false,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
d;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe_reduce_vars: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a, b = null, c = {};
|
||||
a.prop;
|
||||
b.prop;
|
||||
c.prop;
|
||||
d.prop;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
undefined.prop;
|
||||
}
|
||||
expect: {
|
||||
var a, b = null, c = {};
|
||||
d;
|
||||
null.prop;
|
||||
(void 0).prop;
|
||||
(void 0).prop;
|
||||
}
|
||||
}
|
||||
|
||||
chained: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
a.b.c;
|
||||
}
|
||||
expect: {
|
||||
a.b.c;
|
||||
}
|
||||
}
|
||||
@@ -1866,3 +1866,132 @@ delay_def: {
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
booleans: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
if (a != 0);
|
||||
switch (a) {
|
||||
case 0:
|
||||
return "FAIL";
|
||||
case false:
|
||||
return "PASS";
|
||||
}
|
||||
}(false));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
if (!1);
|
||||
switch (!1) {
|
||||
case 0:
|
||||
return "FAIL";
|
||||
case !1:
|
||||
return "PASS";
|
||||
}
|
||||
}(!1));
|
||||
}
|
||||
expect_stdout: "PASS"
|
||||
}
|
||||
|
||||
side_effects_assign: {
|
||||
options = {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
var a = typeof void (a && a.in == 1, 0);
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
var a = typeof void (a && a.in);
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
pure_getters_1: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
toplevel: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
var a = (a.b, 2);
|
||||
} catch (e) {}
|
||||
console.log(a);
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
var a = (a.b, 2);
|
||||
} catch (e) {}
|
||||
console.log(a);
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
pure_getters_2: {
|
||||
options = {
|
||||
pure_getters: "strict",
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
var a = a && a.b;
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
var a = a && a.b;
|
||||
}
|
||||
}
|
||||
|
||||
pure_getters_3: {
|
||||
options = {
|
||||
pure_getters: true,
|
||||
reduce_vars: true,
|
||||
toplevel: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
var a = a && a.b;
|
||||
}
|
||||
expect: {
|
||||
}
|
||||
}
|
||||
|
||||
catch_var: {
|
||||
options = {
|
||||
booleans: true,
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
}
|
||||
input: {
|
||||
try {
|
||||
throw {};
|
||||
} catch (e) {
|
||||
var e;
|
||||
console.log(!!e);
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
try {
|
||||
throw {};
|
||||
} catch (e) {
|
||||
var e;
|
||||
console.log(!!e);
|
||||
}
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
@@ -466,3 +466,147 @@ issue_1758: {
|
||||
}
|
||||
expect_stdout: "undefined"
|
||||
}
|
||||
|
||||
delete_seq_1: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1, undefined));
|
||||
console.log(delete (1, void 0));
|
||||
console.log(delete (1, Infinity));
|
||||
console.log(delete (1, 1 / 0));
|
||||
console.log(delete (1, NaN));
|
||||
console.log(delete (1, 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_2: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1, 2, undefined));
|
||||
console.log(delete (1, 2, void 0));
|
||||
console.log(delete (1, 2, Infinity));
|
||||
console.log(delete (1, 2, 1 / 0));
|
||||
console.log(delete (1, 2, NaN));
|
||||
console.log(delete (1, 2, 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_3: {
|
||||
options = {
|
||||
booleans: true,
|
||||
keep_infinity: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
console.log(delete (1, 2, undefined));
|
||||
console.log(delete (1, 2, void 0));
|
||||
console.log(delete (1, 2, Infinity));
|
||||
console.log(delete (1, 2, 1 / 0));
|
||||
console.log(delete (1, 2, NaN));
|
||||
console.log(delete (1, 2, 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
console.log((void 0, !0));
|
||||
console.log((void 0, !0));
|
||||
console.log((Infinity, !0));
|
||||
console.log((1 / 0, !0));
|
||||
console.log((NaN, !0));
|
||||
console.log((0 / 0, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_4: {
|
||||
options = {
|
||||
booleans: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f() {}
|
||||
console.log(delete (f(), undefined));
|
||||
console.log(delete (f(), void 0));
|
||||
console.log(delete (f(), Infinity));
|
||||
console.log(delete (f(), 1 / 0));
|
||||
console.log(delete (f(), NaN));
|
||||
console.log(delete (f(), 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_5: {
|
||||
options = {
|
||||
booleans: true,
|
||||
keep_infinity: true,
|
||||
sequences: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
function f() {}
|
||||
console.log(delete (f(), undefined));
|
||||
console.log(delete (f(), void 0));
|
||||
console.log(delete (f(), Infinity));
|
||||
console.log(delete (f(), 1 / 0));
|
||||
console.log(delete (f(), NaN));
|
||||
console.log(delete (f(), 0 / 0));
|
||||
}
|
||||
expect: {
|
||||
function f() {}
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0)),
|
||||
console.log((f(), !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
delete_seq_6: {
|
||||
options = {
|
||||
booleans: true,
|
||||
side_effects: true,
|
||||
}
|
||||
input: {
|
||||
var a;
|
||||
console.log(delete (1, a));
|
||||
}
|
||||
expect: {
|
||||
var a;
|
||||
console.log((a, !0));
|
||||
}
|
||||
expect_stdout: true
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ var FUNC_TOSTRING = [
|
||||
' return "[Function: __func_" + i + "__]";',
|
||||
" }",
|
||||
"}();",
|
||||
""
|
||||
].join("\n");
|
||||
exports.run_code = function(code) {
|
||||
var stdout = "";
|
||||
@@ -21,15 +20,20 @@ exports.run_code = function(code) {
|
||||
stdout += chunk;
|
||||
};
|
||||
try {
|
||||
new vm.Script(FUNC_TOSTRING + code).runInNewContext({
|
||||
vm.runInNewContext([
|
||||
"!function() {",
|
||||
FUNC_TOSTRING,
|
||||
code,
|
||||
"}();",
|
||||
].join("\n"), {
|
||||
console: {
|
||||
log: function() {
|
||||
return console.log.apply(console, [].map.call(arguments, function(arg) {
|
||||
return typeof arg == "function" ? arg.toString() : arg;
|
||||
return typeof arg == "function" || arg && /Error$/.test(arg.name) ? arg.toString() : arg;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}, { timeout: 30000 });
|
||||
}, { timeout: 5000 });
|
||||
return stdout;
|
||||
} catch (ex) {
|
||||
return ex;
|
||||
|
||||
359
test/ufuzz.js
359
test/ufuzz.js
@@ -71,6 +71,7 @@ var STMT_COUNT_FROM_GLOBAL = true; // count statement depth from nearest functio
|
||||
var num_iterations = +process.argv[2] || 1/0;
|
||||
var verbose = false; // log every generated test
|
||||
var verbose_interval = false; // log every 100 generated tests
|
||||
var verbose_error = false;
|
||||
for (var i = 2; i < process.argv.length; ++i) {
|
||||
switch (process.argv[i]) {
|
||||
case '-v':
|
||||
@@ -79,6 +80,9 @@ for (var i = 2; i < process.argv.length; ++i) {
|
||||
case '-V':
|
||||
verbose_interval = true;
|
||||
break;
|
||||
case '-E':
|
||||
verbose_error = true;
|
||||
break;
|
||||
case '-t':
|
||||
MAX_GENERATED_TOPLEVELS_PER_RUN = +process.argv[++i];
|
||||
if (!MAX_GENERATED_TOPLEVELS_PER_RUN) throw new Error('Must generate at least one toplevel per run');
|
||||
@@ -118,6 +122,7 @@ for (var i = 2; i < process.argv.length; ++i) {
|
||||
console.log('<number>: generate this many cases (if used must be first arg)');
|
||||
console.log('-v: print every generated test case');
|
||||
console.log('-V: print every 100th generated test case');
|
||||
console.log('-E: print generated test case with runtime error');
|
||||
console.log('-t <int>: generate this many toplevels per run (more take longer)');
|
||||
console.log('-r <int>: maximum recursion depth for generator (higher takes longer)');
|
||||
console.log('-s1 <statement name>: force the first level statement to be this one (see list below)');
|
||||
@@ -135,6 +140,7 @@ for (var i = 2; i < process.argv.length; ++i) {
|
||||
}
|
||||
|
||||
var VALUES = [
|
||||
'""',
|
||||
'true',
|
||||
'false',
|
||||
' /[a2][^e]+$/ ',
|
||||
@@ -221,15 +227,19 @@ var ASSIGNMENTS = [
|
||||
'>>>=',
|
||||
'%=' ];
|
||||
|
||||
var UNARY_OPS = [
|
||||
'--',
|
||||
'++',
|
||||
var UNARY_SAFE = [
|
||||
'+',
|
||||
'-',
|
||||
'~',
|
||||
'!',
|
||||
'void ',
|
||||
'delete ', // should be safe, even `delete foo` and `delete f()` shouldn't crash
|
||||
' - ',
|
||||
' + ' ];
|
||||
'delete ',
|
||||
];
|
||||
var UNARY_POSTFIX = [
|
||||
'++',
|
||||
'--',
|
||||
];
|
||||
var UNARY_PREFIX = UNARY_POSTFIX.concat(UNARY_SAFE);
|
||||
|
||||
var NO_COMMA = true;
|
||||
var COMMA_OK = false;
|
||||
@@ -250,26 +260,26 @@ var NO_DECL = true;
|
||||
var DONT_STORE = true;
|
||||
|
||||
var VAR_NAMES = [
|
||||
'foo',
|
||||
'bar',
|
||||
'a',
|
||||
'a',
|
||||
'a',
|
||||
'a',
|
||||
'b',
|
||||
'b',
|
||||
'b',
|
||||
'b',
|
||||
'c', // prevent redeclaring this, avoid assigning to this
|
||||
'undefined', // fun!
|
||||
'eval', // mmmm, ok, also fun!
|
||||
'NaN', // mmmm, ok, also fun!
|
||||
'Infinity', // the fun never ends!
|
||||
'arguments', // this one is just creepy
|
||||
'Math', // since Math is assumed to be a non-constructor/function it may trip certain cases
|
||||
'foo',
|
||||
'foo',
|
||||
'bar',
|
||||
'bar',
|
||||
'undefined',
|
||||
'NaN',
|
||||
'Infinity',
|
||||
'arguments',
|
||||
'Math',
|
||||
'parseInt',
|
||||
'parseFloat',
|
||||
'isNaN',
|
||||
'isFinite',
|
||||
'decodeURI',
|
||||
'decodeURIComponent',
|
||||
'encodeURI',
|
||||
'encodeURIComponent',
|
||||
'Object'];
|
||||
];
|
||||
var INITIAL_NAMES_LEN = VAR_NAMES.length;
|
||||
|
||||
var TYPEOF_OUTCOMES = [
|
||||
@@ -306,6 +316,22 @@ function createFunctions(n, recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||
return s;
|
||||
}
|
||||
|
||||
function createParams() {
|
||||
var params = [];
|
||||
for (var n = rng(4); --n >= 0;) {
|
||||
params.push(createVarName(MANDATORY));
|
||||
}
|
||||
return params.join(', ');
|
||||
}
|
||||
|
||||
function createArgs() {
|
||||
var args = [];
|
||||
for (var n = rng(4); --n >= 0;) {
|
||||
args.push(createValue());
|
||||
}
|
||||
return args.join(', ');
|
||||
}
|
||||
|
||||
function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||
if (--recurmax < 0) { return ';'; }
|
||||
if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;
|
||||
@@ -316,17 +342,17 @@ function createFunction(recurmax, inGlobal, noDecl, canThrow, stmtDepth) {
|
||||
var s = '';
|
||||
if (rng(5) === 0) {
|
||||
// functions with functions. lower the recursion to prevent a mess.
|
||||
s = 'function ' + name + '(' + createVarName(MANDATORY) + '){' + createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth) + '}\n';
|
||||
s = 'function ' + name + '(' + createParams() + '){' + createFunctions(rng(5) + 1, Math.ceil(recurmax * 0.7), NOT_GLOBAL, ANY_TYPE, canThrow, stmtDepth) + '}\n';
|
||||
} else {
|
||||
// functions with statements
|
||||
s = 'function ' + name + '(' + createVarName(MANDATORY) + '){' + createStatements(3, recurmax, canThrow, CANNOT_THROW, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}\n';
|
||||
s = 'function ' + name + '(' + createParams() + '){' + createStatements(3, recurmax, canThrow, CANNOT_THROW, CANNOT_CONTINUE, CAN_RETURN, stmtDepth) + '}\n';
|
||||
}
|
||||
|
||||
VAR_NAMES.length = namesLenBefore;
|
||||
|
||||
if (noDecl) s = '!' + s + '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')';
|
||||
if (noDecl) s = 'var ' + createVarName(MANDATORY) + ' = ' + s + '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ');';
|
||||
// avoid "function statements" (decl inside statements)
|
||||
else if (inGlobal || rng(10) > 0) s += name + '();'
|
||||
else if (inGlobal || rng(10) > 0) s += 'var ' + createVarName(MANDATORY) + ' = ' + name + '(' + createArgs() + ');';
|
||||
|
||||
|
||||
return s;
|
||||
@@ -393,23 +419,27 @@ function createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn
|
||||
return 'var ' + n1 + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ', ' + n2 + ' = ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||
}
|
||||
case STMT_RETURN_ETC:
|
||||
switch (rng(3)) {
|
||||
switch (rng(8)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
if (canBreak && rng(5) === 0) return 'break;';
|
||||
if (canContinue && rng(5) === 0) return 'continue;';
|
||||
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||
return '/*3*/return;';
|
||||
case 2:
|
||||
// must wrap in curlies to prevent orphaned `else` statement
|
||||
if (canThrow && rng(5) === 0) return '{ throw ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + '}';
|
||||
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||
return '{ /*1*/ return ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + '}';
|
||||
default:
|
||||
if (rng(3) == 0) return '/*3*/return;';
|
||||
return 'return ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||
case 4:
|
||||
// this is actually more like a parser test, but perhaps it hits some dead code elimination traps
|
||||
// must wrap in curlies to prevent orphaned `else` statement
|
||||
// note: you can't `throw` without an expression so don't put a `throw` option in this case
|
||||
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||
return '{ /*2*/ return\n' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + '}';
|
||||
default:
|
||||
// must wrap in curlies to prevent orphaned `else` statement
|
||||
if (canThrow && rng(5) === 0) return '{ throw ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + '}';
|
||||
if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ';';
|
||||
return '{ return ' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + '}';
|
||||
}
|
||||
case STMT_FUNC_EXPR:
|
||||
// "In non-strict mode code, functions can only be declared at top level, inside a block, or ..."
|
||||
@@ -463,36 +493,44 @@ function createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotR
|
||||
|
||||
function createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
if (--recurmax < 0) {
|
||||
return '(c = 1 + c, ' + createNestedBinaryExpr(recurmax, noComma) + ')'; // note: should return a simple non-recursing expression value!
|
||||
return '(c = 1 + c, ' + createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')'; // note: should return a simple non-recursing expression value!
|
||||
}
|
||||
// since `a` and `b` are our canaries we want them more frequently than other expressions (1/3rd chance of a canary)
|
||||
var r = rng(6);
|
||||
if (r < 1) return 'a++ + ' + _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||
if (r < 2) return '(--b) + ' + _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||
if (r < 3) return '(c = c + 1) + ' + _createExpression(recurmax, noComma, stmtDepth, canThrow); // c only gets incremented
|
||||
|
||||
return _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||
switch (rng(6)) {
|
||||
case 0:
|
||||
return '(a++ + (' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + '))';
|
||||
case 1:
|
||||
return '((--b) + (' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + '))';
|
||||
case 2:
|
||||
return '((c = c + 1) + (' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + '))'; // c only gets incremented
|
||||
default:
|
||||
return '(' + _createExpression(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||
}
|
||||
}
|
||||
function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
switch (rng(15)) {
|
||||
case 0:
|
||||
return createUnaryOp() + (rng(2) === 1 ? 'a' : 'b');
|
||||
case 1:
|
||||
return 'a' + (rng(2) == 1 ? '++' : '--');
|
||||
case 2:
|
||||
var p = 0;
|
||||
switch (rng(_createExpression.N)) {
|
||||
case p++:
|
||||
case p++:
|
||||
return createUnaryPrefix() + (rng(2) === 1 ? 'a' : 'b');
|
||||
case p++:
|
||||
case p++:
|
||||
return (rng(2) === 1 ? 'a' : 'b') + createUnaryPostfix();
|
||||
case p++:
|
||||
case p++:
|
||||
// parens needed because assignments aren't valid unless they're the left-most op(s) in an expression
|
||||
return '(b ' + createAssignment() + ' a)';
|
||||
case 3:
|
||||
return 'b ' + createAssignment() + ' a';
|
||||
case p++:
|
||||
case p++:
|
||||
return rng(2) + ' === 1 ? a : b';
|
||||
case 4:
|
||||
return createNestedBinaryExpr(recurmax, noComma) + createBinaryOp(noComma) + createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||
case 5:
|
||||
case p++:
|
||||
case p++:
|
||||
return createValue();
|
||||
case 6:
|
||||
return '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')';
|
||||
case 7:
|
||||
case p++:
|
||||
return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||
case p++:
|
||||
return createExpression(recurmax, noComma, stmtDepth, canThrow) + '?' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':' + createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||
case 8:
|
||||
case p++:
|
||||
var nameLenBefore = VAR_NAMES.length;
|
||||
var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.
|
||||
if (name === 'c') name = 'a';
|
||||
@@ -513,17 +551,18 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
}
|
||||
VAR_NAMES.length = nameLenBefore;
|
||||
return s;
|
||||
case 9:
|
||||
case p++:
|
||||
case p++:
|
||||
return createTypeofExpr(recurmax, stmtDepth, canThrow);
|
||||
case 10:
|
||||
// you could statically infer that this is just `Math`, regardless of the other expression
|
||||
// I don't think Uglify does this at this time...
|
||||
return ''+
|
||||
'new function(){ \n' +
|
||||
(rng(2) === 1 ? createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + '\n' : '') +
|
||||
'return Math;\n' +
|
||||
'}';
|
||||
case 11:
|
||||
case p++:
|
||||
return [
|
||||
'new function() {',
|
||||
rng(2) ? '' : createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';',
|
||||
'return ' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ';',
|
||||
'}'
|
||||
].join('\n');
|
||||
case p++:
|
||||
case p++:
|
||||
// more like a parser test but perhaps comment nodes mess up the analysis?
|
||||
// note: parens not needed for post-fix (since that's the default when ambiguous)
|
||||
// for prefix ops we need parens to prevent accidental syntax errors.
|
||||
@@ -533,58 +572,151 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) {
|
||||
case 1:
|
||||
return 'b/* ignore */--';
|
||||
case 2:
|
||||
return '(++/* ignore */a)';
|
||||
return '++/* ignore */a';
|
||||
case 3:
|
||||
return '(--/* ignore */b)';
|
||||
return '--/* ignore */b';
|
||||
case 4:
|
||||
// only groups that wrap a single variable return a "Reference", so this is still valid.
|
||||
// may just be a parser edge case that is invisible to uglify...
|
||||
return '(--(b))';
|
||||
return '--(b)';
|
||||
case 5:
|
||||
// classic 0.3-0.1 case; 1-0.1-0.1-0.1 is not 0.7 :)
|
||||
return 'b + 1-0.1-0.1-0.1';
|
||||
default:
|
||||
return '(--/* ignore */b)';
|
||||
return '--/* ignore */b';
|
||||
}
|
||||
case 12:
|
||||
return createNestedBinaryExpr(recurmax, noComma);
|
||||
case 13:
|
||||
case p++:
|
||||
case p++:
|
||||
return createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow);
|
||||
case p++:
|
||||
case p++:
|
||||
return createUnarySafePrefix() + '(' + createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||
case p++:
|
||||
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || a || 3).toString() ";
|
||||
case 14:
|
||||
case p++:
|
||||
return " /[abc4]/.test(((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || b || 5).toString()) ";
|
||||
case p++:
|
||||
return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) +
|
||||
") || " + rng(10) + ").toString()[" +
|
||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "] ";
|
||||
case p++:
|
||||
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||
case p++:
|
||||
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow);
|
||||
case p++:
|
||||
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||
case p++:
|
||||
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' +
|
||||
createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||
case p++:
|
||||
return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + getDotKey();
|
||||
case p++:
|
||||
return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + getDotKey();
|
||||
case p++:
|
||||
var name = getVarName();
|
||||
return name + ' && ' + name + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ']';
|
||||
case p++:
|
||||
var name = getVarName();
|
||||
return name + ' && ' + name + '.' + getDotKey();
|
||||
}
|
||||
_createExpression.N = p;
|
||||
return _createExpression(recurmax, noComma, stmtDepth, canThrow);
|
||||
}
|
||||
|
||||
function createNestedBinaryExpr(recurmax, noComma) {
|
||||
recurmax = 3; // note that this generates 2^recurmax expression parts... make sure to cap it
|
||||
return _createSimpleBinaryExpr(recurmax, noComma);
|
||||
function createArrayLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
||||
recurmax--;
|
||||
var arr = "[";
|
||||
for (var i = rng(6); --i >= 0;) {
|
||||
// in rare cases produce an array hole element
|
||||
var element = rng(20) ? createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) : "";
|
||||
arr += element + ", ";
|
||||
}
|
||||
return arr + "]";
|
||||
}
|
||||
function _createSimpleBinaryExpr(recurmax, noComma) {
|
||||
|
||||
var SAFE_KEYS = [
|
||||
"length",
|
||||
"foo",
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"undefined",
|
||||
"null",
|
||||
"NaN",
|
||||
"Infinity",
|
||||
"in",
|
||||
"var",
|
||||
];
|
||||
var KEYS = [
|
||||
"''",
|
||||
'"\t"',
|
||||
'"-2"',
|
||||
"0",
|
||||
"1.5",
|
||||
"3",
|
||||
].concat(SAFE_KEYS);
|
||||
|
||||
function getDotKey() {
|
||||
return SAFE_KEYS[rng(SAFE_KEYS.length)];
|
||||
}
|
||||
|
||||
function createObjectLiteral(recurmax, noComma, stmtDepth, canThrow) {
|
||||
recurmax--;
|
||||
var obj = "({";
|
||||
for (var i = rng(6); --i >= 0;) {
|
||||
var key = KEYS[rng(KEYS.length)];
|
||||
obj += key + ":(" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "), ";
|
||||
}
|
||||
return obj + "})";
|
||||
}
|
||||
|
||||
function createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||
recurmax = 3; // note that this generates 2^recurmax expression parts... make sure to cap it
|
||||
return _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow);
|
||||
}
|
||||
function _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||
return '(' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)
|
||||
+ createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||
}
|
||||
function _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {
|
||||
// intentionally generate more hardcore ops
|
||||
if (--recurmax < 0) return createValue();
|
||||
var r = rng(30);
|
||||
if (r === 0) return '(c = c + 1, ' + _createSimpleBinaryExpr(recurmax, noComma) + ')';
|
||||
var s = _createSimpleBinaryExpr(recurmax, noComma) + createBinaryOp(noComma) + _createSimpleBinaryExpr(recurmax, noComma);
|
||||
if (r === 1) {
|
||||
// try to get a generated name reachable from current scope. default to just `a`
|
||||
var assignee = VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)] || 'a';
|
||||
return '( ' + assignee + createAssignment() + s + ')';
|
||||
switch (rng(30)) {
|
||||
case 0:
|
||||
return '(c = c + 1, ' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||
case 1:
|
||||
return '(' + createUnarySafePrefix() + '(' + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + '))';
|
||||
case 2:
|
||||
var assignee = getVarName();
|
||||
return '(' + assignee + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||
case 3:
|
||||
var assignee = getVarName();
|
||||
var expr = '(' + assignee + '[' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow)
|
||||
+ ']' + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||
case 4:
|
||||
var assignee = getVarName();
|
||||
var expr = '(' + assignee + '.' + getDotKey() + createAssignment()
|
||||
+ _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + ')';
|
||||
return canThrow && rng(10) == 0 ? expr : '(' + assignee + ' && ' + expr + ')';
|
||||
default:
|
||||
return _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function createTypeofExpr(recurmax, stmtDepth, canThrow) {
|
||||
switch (rng(8)) {
|
||||
case 0:
|
||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' === "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
||||
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' === "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 1:
|
||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' !== "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
||||
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' !== "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 2:
|
||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' == "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
||||
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' == "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 3:
|
||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE) + ' != "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '"';
|
||||
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ' != "' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '")';
|
||||
case 4:
|
||||
return 'typeof ' + createVarName(MANDATORY, DONT_STORE);
|
||||
return '(typeof ' + createVarName(MANDATORY, DONT_STORE) + ')';
|
||||
default:
|
||||
return '(typeof ' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')';
|
||||
}
|
||||
@@ -603,16 +735,31 @@ function createAssignment() {
|
||||
return ASSIGNMENTS[rng(ASSIGNMENTS.length)];
|
||||
}
|
||||
|
||||
function createUnaryOp() {
|
||||
return UNARY_OPS[rng(UNARY_OPS.length)];
|
||||
function createUnarySafePrefix() {
|
||||
return UNARY_SAFE[rng(UNARY_SAFE.length)];
|
||||
}
|
||||
|
||||
function createUnaryPrefix() {
|
||||
return UNARY_PREFIX[rng(UNARY_PREFIX.length)];
|
||||
}
|
||||
|
||||
function createUnaryPostfix() {
|
||||
return UNARY_POSTFIX[rng(UNARY_POSTFIX.length)];
|
||||
}
|
||||
|
||||
function getVarName() {
|
||||
// try to get a generated name reachable from current scope. default to just `a`
|
||||
return VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)] || 'a';
|
||||
}
|
||||
|
||||
function createVarName(maybe, dontStore) {
|
||||
if (!maybe || rng(2) === 1) {
|
||||
var r = rng(VAR_NAMES.length);
|
||||
var suffixed = rng(5) > 0;
|
||||
var name = VAR_NAMES[r] + (suffixed ? '_' + (++loops) : '');
|
||||
if (!dontStore && suffixed) VAR_NAMES.push(name);
|
||||
if (!maybe || rng(2)) {
|
||||
var name = VAR_NAMES[rng(VAR_NAMES.length)];
|
||||
var suffix = rng(3);
|
||||
if (suffix) {
|
||||
name += '_' + suffix;
|
||||
if (!dontStore) VAR_NAMES.push(name);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
return '';
|
||||
@@ -755,6 +902,20 @@ for (var round = 1; round <= num_iterations; round++) {
|
||||
ok = sandbox.same_stdout(original_result, uglify_result);
|
||||
}
|
||||
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
|
||||
if (!ok && isFinite(num_iterations)) process.exit(1);
|
||||
else if (verbose_error && typeof original_result != "string") {
|
||||
console.log("//=============================================================");
|
||||
console.log("// original code");
|
||||
try_beautify(original_code, original_result);
|
||||
console.log();
|
||||
console.log();
|
||||
console.log("original result:");
|
||||
console.log(original_result);
|
||||
console.log();
|
||||
}
|
||||
if (!ok && isFinite(num_iterations)) {
|
||||
console.log();
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log();
|
||||
|
||||
@@ -1,19 +1,4 @@
|
||||
[
|
||||
{
|
||||
"compress": {
|
||||
"warnings": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
"warnings": false
|
||||
},
|
||||
"mangle": false
|
||||
},
|
||||
{
|
||||
"compress": false,
|
||||
"mangle": true
|
||||
},
|
||||
{
|
||||
"compress": false,
|
||||
"mangle": false,
|
||||
@@ -22,11 +7,33 @@
|
||||
"bracketize": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"compress": false
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
"warnings": false
|
||||
},
|
||||
"mangle": false
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
"warnings": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
"toplevel": true,
|
||||
"warnings": false
|
||||
},
|
||||
"mangle": {
|
||||
"toplevel": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"compress": {
|
||||
"keep_fargs": false,
|
||||
"passes": 3,
|
||||
"pure_getters": true,
|
||||
"warnings": false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user