Merge branch 'master' into harmony
This commit is contained in:
32
test/compress/ascii.js
Normal file
32
test/compress/ascii.js
Normal file
@@ -0,0 +1,32 @@
|
||||
ascii_only_true: {
|
||||
options = {}
|
||||
beautify = {
|
||||
ascii_only : true,
|
||||
beautify : false,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\x0B\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
|
||||
}
|
||||
|
||||
ascii_only_false: {
|
||||
options = {}
|
||||
beautify = {
|
||||
ascii_only : false,
|
||||
beautify : false,
|
||||
}
|
||||
input: {
|
||||
function f() {
|
||||
return "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
||||
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f(){return"\\x00\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\x0B\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
|
||||
}
|
||||
|
||||
@@ -130,4 +130,3 @@ regression_block_scope_resolves: {
|
||||
}());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1155
test/compress/collapse_vars.js
Normal file
1155
test/compress/collapse_vars.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -407,8 +407,8 @@ cond_8: {
|
||||
a = !condition;
|
||||
a = !condition;
|
||||
|
||||
a = condition ? 1 : false;
|
||||
a = condition ? 0 : true;
|
||||
a = !!condition && 1;
|
||||
a = !condition || 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -490,8 +490,8 @@ cond_8b: {
|
||||
a = !condition;
|
||||
a = !condition;
|
||||
|
||||
a = condition ? 1 : !1;
|
||||
a = condition ? 0 : !0;
|
||||
a = !!condition && 1;
|
||||
a = !condition || 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -557,7 +557,7 @@ cond_8c: {
|
||||
|
||||
a = !!condition;
|
||||
a = !condition;
|
||||
a = condition() ? !0 : !-3.5;
|
||||
a = !!condition() || !-3.5;
|
||||
|
||||
a = !!condition;
|
||||
a = !!condition;
|
||||
@@ -573,12 +573,68 @@ cond_8c: {
|
||||
a = !condition;
|
||||
a = !condition;
|
||||
|
||||
a = condition ? 1 : false;
|
||||
a = condition ? 0 : true;
|
||||
a = !!condition && 1;
|
||||
a = !condition || 0;
|
||||
a = condition ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
ternary_boolean_consequent: {
|
||||
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 f1() { return a == b ? true : x; }
|
||||
function f2() { return a == b ? false : x; }
|
||||
function f3() { return a < b ? !0 : x; }
|
||||
function f4() { return a < b ? !1 : x; }
|
||||
function f5() { return c ? !0 : x; }
|
||||
function f6() { return c ? false : x; }
|
||||
function f7() { return !c ? true : x; }
|
||||
function f8() { return !c ? !1 : x; }
|
||||
}
|
||||
expect: {
|
||||
function f1() { return a == b || x; }
|
||||
function f2() { return a != b && x; }
|
||||
function f3() { return a < b || x; }
|
||||
function f4() { return !(a < b) && x; }
|
||||
function f5() { return !!c || x; }
|
||||
function f6() { return !c && x; }
|
||||
function f7() { return !c || x; }
|
||||
function f8() { return !!c && x; }
|
||||
}
|
||||
}
|
||||
|
||||
ternary_boolean_alternative: {
|
||||
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 f1() { return a == b ? x : true; }
|
||||
function f2() { return a == b ? x : false; }
|
||||
function f3() { return a < b ? x : !0; }
|
||||
function f4() { return a < b ? x : !1; }
|
||||
function f5() { return c ? x : true; }
|
||||
function f6() { return c ? x : !1; }
|
||||
function f7() { return !c ? x : !0; }
|
||||
function f8() { return !c ? x : false; }
|
||||
}
|
||||
expect: {
|
||||
function f1() { return a != b || x; }
|
||||
function f2() { return a == b && x; }
|
||||
function f3() { return !(a < b) || x; }
|
||||
function f4() { return a < b && x; }
|
||||
function f5() { return !c || x; }
|
||||
function f6() { return !!c && x; }
|
||||
function f7() { return !!c || x; }
|
||||
function f8() { return !c && x; }
|
||||
}
|
||||
}
|
||||
|
||||
conditional_and: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
@@ -738,3 +794,77 @@ conditional_or: {
|
||||
a = condition + 3 || null;
|
||||
}
|
||||
}
|
||||
|
||||
trivial_boolean_ternary_expressions : {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true,
|
||||
booleans : true
|
||||
};
|
||||
input: {
|
||||
f('foo' in m ? true : false);
|
||||
f('foo' in m ? false : true);
|
||||
|
||||
f(g ? true : false);
|
||||
f(foo() ? true : false);
|
||||
f("bar" ? true : false);
|
||||
f(5 ? true : false);
|
||||
f(5.7 ? true : false);
|
||||
f(x - y ? true : false);
|
||||
|
||||
f(x == y ? true : false);
|
||||
f(x === y ? !0 : !1);
|
||||
f(x < y ? !0 : false);
|
||||
f(x <= y ? true : false);
|
||||
f(x > y ? true : !1);
|
||||
f(x >= y ? !0 : !1);
|
||||
|
||||
f(g ? false : true);
|
||||
f(foo() ? false : true);
|
||||
f("bar" ? false : true);
|
||||
f(5 ? false : true);
|
||||
f(5.7 ? false : true);
|
||||
f(x - y ? false : true);
|
||||
|
||||
f(x == y ? !1 : !0);
|
||||
f(x === y ? false : true);
|
||||
|
||||
f(x < y ? false : true);
|
||||
f(x <= y ? false : !0);
|
||||
f(x > y ? !1 : true);
|
||||
f(x >= y ? !1 : !0);
|
||||
}
|
||||
expect: {
|
||||
f('foo' in m);
|
||||
f(!('foo' in m));
|
||||
|
||||
f(!!g);
|
||||
f(!!foo());
|
||||
f(!0);
|
||||
f(!0);
|
||||
f(!0);
|
||||
f(!!(x - y));
|
||||
|
||||
f(x == y);
|
||||
f(x === y);
|
||||
f(x < y);
|
||||
f(x <= y);
|
||||
f(x > y);
|
||||
f(x >= y);
|
||||
|
||||
f(!g);
|
||||
f(!foo());
|
||||
f(!1);
|
||||
f(!1);
|
||||
f(!1);
|
||||
f(!(x - y));
|
||||
|
||||
f(x != y);
|
||||
f(x !== y);
|
||||
|
||||
f(!(x < y));
|
||||
f(!(x <= y));
|
||||
f(!(x > y));
|
||||
f(!(x >= y));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,8 +87,8 @@ dead_code_constant_boolean_should_warn_more: {
|
||||
var moo;
|
||||
}
|
||||
}
|
||||
|
||||
dead_code_block_decls_die: {
|
||||
|
||||
dead_code_block_decls_die: {
|
||||
options = {
|
||||
dead_code : true,
|
||||
conditionals : true,
|
||||
@@ -109,3 +109,120 @@ dead_code_block_decls_die: {
|
||||
console.log(foo, bar, Baz);
|
||||
}
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
137
test/compress/issue-1034.js
Normal file
137
test/compress/issue-1034.js
Normal file
@@ -0,0 +1,137 @@
|
||||
non_hoisted_function_after_return: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar();
|
||||
not_called1();
|
||||
} else {
|
||||
return baz();
|
||||
not_called2();
|
||||
}
|
||||
function bar() { return 7; }
|
||||
return not_reached;
|
||||
function UnusedFunction() {}
|
||||
function baz() { return 8; }
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function foo(x) {
|
||||
return x ? bar() : baz();
|
||||
function bar() { return 7 }
|
||||
function baz() { return 8 }
|
||||
}
|
||||
}
|
||||
expect_warnings: [
|
||||
'WARN: Dropping unreachable code [test/compress/issue-1034.js:11,16]',
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]",
|
||||
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]"
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2a: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||
collapse_vars: false
|
||||
}
|
||||
input: {
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar(1);
|
||||
var a = not_called(1);
|
||||
} else {
|
||||
return bar(2);
|
||||
var b = not_called(2);
|
||||
}
|
||||
var c = bar(3);
|
||||
function bar(x) { return 7 - x; }
|
||||
function nope() {}
|
||||
return b || c;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
// NOTE: Output is correct, but suboptimal. Not a regression. Can be improved in future.
|
||||
// This output is run through non_hoisted_function_after_return_2b with same flags.
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar(1);
|
||||
} else {
|
||||
return bar(2);
|
||||
var b;
|
||||
}
|
||||
var c = bar(3);
|
||||
function bar(x) {
|
||||
return 7 - x;
|
||||
}
|
||||
return b || c;
|
||||
}
|
||||
}
|
||||
expect_warnings: [
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:48,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
|
||||
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
|
||||
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]"
|
||||
]
|
||||
}
|
||||
|
||||
non_hoisted_function_after_return_2b: {
|
||||
options = {
|
||||
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
|
||||
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
|
||||
if_return: true, join_vars: true, cascade: true, side_effects: true,
|
||||
collapse_vars: false
|
||||
}
|
||||
input: {
|
||||
// Note: output of test non_hoisted_function_after_return_2a run through compress again
|
||||
function foo(x) {
|
||||
if (x) {
|
||||
return bar(1);
|
||||
} else {
|
||||
return bar(2);
|
||||
var b;
|
||||
}
|
||||
var c = bar(3);
|
||||
function bar(x) {
|
||||
return 7 - x;
|
||||
}
|
||||
return b || c;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
// the output we would have liked to see from non_hoisted_function_after_return_2a
|
||||
function foo(x) {
|
||||
return bar(x ? 1 : 2);
|
||||
function bar(x) { return 7 - x; }
|
||||
}
|
||||
}
|
||||
expect_warnings: [
|
||||
// Notice that some warnings are repeated by multiple compress passes.
|
||||
// Not a regression. There is room for improvement here.
|
||||
// Warnings should be cached and only output if unique.
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:102,12]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:102,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:106,12]",
|
||||
"WARN: Dropping unreachable code [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:100,16]",
|
||||
"WARN: Dropping unused variable b [test/compress/issue-1034.js:100,20]",
|
||||
"WARN: Dropping unused variable c [test/compress/issue-1034.js:102,16]"
|
||||
]
|
||||
}
|
||||
|
||||
39
test/compress/issue-1041.js
Normal file
39
test/compress/issue-1041.js
Normal file
@@ -0,0 +1,39 @@
|
||||
const_declaration: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
|
||||
input: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
const goog = goog || {};
|
||||
}
|
||||
}
|
||||
|
||||
const_pragma: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
|
||||
input: {
|
||||
/** @const */ var goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
var goog = goog || {};
|
||||
}
|
||||
}
|
||||
|
||||
// for completeness' sake
|
||||
not_const: {
|
||||
options = {
|
||||
evaluate: true
|
||||
};
|
||||
|
||||
input: {
|
||||
var goog = goog || {};
|
||||
}
|
||||
expect: {
|
||||
var goog = goog || {};
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,50 @@ keep_name_of_setter: {
|
||||
input: { a = { set foo () {} } }
|
||||
expect: { a = { set foo () {} } }
|
||||
}
|
||||
|
||||
setter_with_operator_keys: {
|
||||
input: {
|
||||
var tokenCodes = {
|
||||
get instanceof(){
|
||||
return test0;
|
||||
},
|
||||
set instanceof(value){
|
||||
test0 = value;
|
||||
},
|
||||
set typeof(value){
|
||||
test1 = value;
|
||||
},
|
||||
get typeof(){
|
||||
return test1;
|
||||
},
|
||||
set else(value){
|
||||
test2 = value;
|
||||
},
|
||||
get else(){
|
||||
return test2;
|
||||
}
|
||||
};
|
||||
}
|
||||
expect: {
|
||||
var tokenCodes = {
|
||||
get instanceof(){
|
||||
return test0;
|
||||
},
|
||||
set instanceof(value){
|
||||
test0 = value;
|
||||
},
|
||||
set typeof(value){
|
||||
test1 = value;
|
||||
},
|
||||
get typeof(){
|
||||
return test1;
|
||||
},
|
||||
set else(value){
|
||||
test2 = value;
|
||||
},
|
||||
get else(){
|
||||
return test2;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,27 @@
|
||||
remove_redundant_sequence_items: {
|
||||
options = { side_effects: true };
|
||||
input: {
|
||||
(0, 1, eval)();
|
||||
(0, 1, logThis)();
|
||||
(0, 1, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
(0, logThis)();
|
||||
(0, eval)();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
}
|
||||
|
||||
dont_remove_lexical_binding_sequence: {
|
||||
dont_remove_this_binding_sequence: {
|
||||
options = { side_effects: true };
|
||||
input: {
|
||||
(0, eval)();
|
||||
(0, logThis)();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
expect: {
|
||||
(0, logThis)();
|
||||
(0, eval)();
|
||||
logThis();
|
||||
(0, _decorators.logThis)();
|
||||
}
|
||||
}
|
||||
|
||||
32
test/compress/issue-892.js
Normal file
32
test/compress/issue-892.js
Normal file
@@ -0,0 +1,32 @@
|
||||
dont_mangle_arguments: {
|
||||
mangle = {
|
||||
};
|
||||
options = {
|
||||
sequences : true,
|
||||
properties : true,
|
||||
dead_code : true,
|
||||
drop_debugger : true,
|
||||
conditionals : true,
|
||||
comparisons : true,
|
||||
evaluate : true,
|
||||
booleans : true,
|
||||
loops : true,
|
||||
unused : true,
|
||||
hoist_funs : true,
|
||||
keep_fargs : true,
|
||||
keep_fnames : false,
|
||||
hoist_vars : true,
|
||||
if_return : true,
|
||||
join_vars : true,
|
||||
cascade : true,
|
||||
side_effects : true,
|
||||
negate_iife : false
|
||||
};
|
||||
input: {
|
||||
(function(){
|
||||
var arguments = arguments, not_arguments = 9;
|
||||
console.log(not_arguments, arguments);
|
||||
})(5,6,7);
|
||||
}
|
||||
expect_exact: "(function(){var arguments=arguments,o=9;console.log(o,arguments)})(5,6,7);"
|
||||
}
|
||||
20
test/compress/issue-913.js
Normal file
20
test/compress/issue-913.js
Normal file
@@ -0,0 +1,20 @@
|
||||
keep_var_for_in: {
|
||||
options = {
|
||||
hoist_vars: true,
|
||||
unused: true
|
||||
};
|
||||
input: {
|
||||
(function(obj){
|
||||
var foo = 5;
|
||||
for (var i in obj)
|
||||
return foo;
|
||||
})();
|
||||
}
|
||||
expect: {
|
||||
(function(obj){
|
||||
var i, foo = 5;
|
||||
for (i in obj)
|
||||
return foo;
|
||||
})();
|
||||
}
|
||||
}
|
||||
96
test/compress/issue-973.js
Normal file
96
test/compress/issue-973.js
Normal file
@@ -0,0 +1,96 @@
|
||||
this_binding_conditionals: {
|
||||
options = {
|
||||
conditionals: true,
|
||||
evaluate : true
|
||||
};
|
||||
input: {
|
||||
(1 && a)();
|
||||
(0 || a)();
|
||||
(0 || 1 && a)();
|
||||
(1 ? a : 0)();
|
||||
|
||||
(1 && a.b)();
|
||||
(0 || a.b)();
|
||||
(0 || 1 && a.b)();
|
||||
(1 ? a.b : 0)();
|
||||
|
||||
(1 && a[b])();
|
||||
(0 || a[b])();
|
||||
(0 || 1 && a[b])();
|
||||
(1 ? a[b] : 0)();
|
||||
|
||||
(1 && eval)();
|
||||
(0 || eval)();
|
||||
(0 || 1 && eval)();
|
||||
(1 ? eval : 0)();
|
||||
}
|
||||
expect: {
|
||||
a();
|
||||
a();
|
||||
a();
|
||||
a();
|
||||
|
||||
(0, a.b)();
|
||||
(0, a.b)();
|
||||
(0, a.b)();
|
||||
(0, a.b)();
|
||||
|
||||
(0, a[b])();
|
||||
(0, a[b])();
|
||||
(0, a[b])();
|
||||
(0, a[b])();
|
||||
|
||||
(0, eval)();
|
||||
(0, eval)();
|
||||
(0, eval)();
|
||||
(0, eval)();
|
||||
}
|
||||
}
|
||||
|
||||
this_binding_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
};
|
||||
input: {
|
||||
var c = a; c();
|
||||
var d = a.b; d();
|
||||
var e = eval; e();
|
||||
}
|
||||
expect: {
|
||||
a();
|
||||
(0, a.b)();
|
||||
(0, eval)();
|
||||
}
|
||||
}
|
||||
|
||||
this_binding_side_effects: {
|
||||
options = {
|
||||
side_effects : true
|
||||
};
|
||||
input: {
|
||||
(function (foo) {
|
||||
(0, foo)();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
(function (foo) {
|
||||
var eval = console;
|
||||
(0, foo)();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
}
|
||||
expect: {
|
||||
(function (foo) {
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
(function (foo) {
|
||||
var eval = console;
|
||||
foo();
|
||||
(0, foo.bar)();
|
||||
(0, eval)('console.log(foo);');
|
||||
}());
|
||||
}
|
||||
}
|
||||
88
test/compress/issue-976.js
Normal file
88
test/compress/issue-976.js
Normal file
@@ -0,0 +1,88 @@
|
||||
eval_collapse_vars: {
|
||||
options = {
|
||||
collapse_vars:true, sequences:false, 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 f1() {
|
||||
var e = 7;
|
||||
var s = "abcdef";
|
||||
var i = 2;
|
||||
var eval = console.log.bind(console);
|
||||
var x = s.charAt(i++);
|
||||
var y = s.charAt(i++);
|
||||
var z = s.charAt(i++);
|
||||
eval(x, y, z, e);
|
||||
}
|
||||
function p1() { var a = foo(), b = bar(), eval = baz(); return a + b + eval; }
|
||||
function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }
|
||||
(function f2(eval) {
|
||||
var a = 2;
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
var e = 7,
|
||||
s = "abcdef",
|
||||
i = 2,
|
||||
eval = console.log.bind(console),
|
||||
x = s.charAt(i++),
|
||||
y = s.charAt(i++),
|
||||
z = s.charAt(i++);
|
||||
eval(x, y, z, e);
|
||||
}
|
||||
function p1() { return foo() + bar() + baz(); }
|
||||
function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }
|
||||
(function f2(eval) {
|
||||
var a = 2;
|
||||
console.log(a - 5);
|
||||
eval("console.log(a);");
|
||||
})(eval);
|
||||
}
|
||||
}
|
||||
|
||||
eval_unused: {
|
||||
options = { unused: true, keep_fargs: false };
|
||||
input: {
|
||||
function f1(a, eval, c, d, e) {
|
||||
return a('c') + eval;
|
||||
}
|
||||
function f2(a, b, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
function f3(a, eval, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1(a, eval) {
|
||||
return a('c') + eval;
|
||||
}
|
||||
function f2(a, b, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
function f3(a, eval, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eval_mangle: {
|
||||
mangle = {
|
||||
};
|
||||
input: {
|
||||
function f1(a, eval, c, d, e) {
|
||||
return a('c') + eval;
|
||||
}
|
||||
function f2(a, b, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
function f3(a, eval, c, d, e) {
|
||||
return a + eval('c');
|
||||
}
|
||||
}
|
||||
expect_exact: 'function f1(n,c,e,a,f){return n("c")+c}function f2(a,b,c,d,e){return a+eval("c")}function f3(a,eval,c,d,e){return a+eval("c")}'
|
||||
}
|
||||
89
test/compress/issue-979.js
Normal file
89
test/compress/issue-979.js
Normal file
@@ -0,0 +1,89 @@
|
||||
issue979_reported: {
|
||||
options = {
|
||||
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 f1() {
|
||||
if (a == 1 || b == 2) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f2() {
|
||||
if (!(a == 1 || b == 2)) {
|
||||
}
|
||||
else {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f1() {
|
||||
1!=a&&2!=b||foo();
|
||||
}
|
||||
function f2() {
|
||||
1!=a&&2!=b||foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
issue979_test_negated_is_best: {
|
||||
options = {
|
||||
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 f3() {
|
||||
if (a == 1 | b == 2) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f4() {
|
||||
if (!(a == 1 | b == 2)) {
|
||||
}
|
||||
else {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f5() {
|
||||
if (a == 1 && b == 2) {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f6() {
|
||||
if (!(a == 1 && b == 2)) {
|
||||
}
|
||||
else {
|
||||
foo();
|
||||
}
|
||||
}
|
||||
function f7() {
|
||||
if (a == 1 || b == 2) {
|
||||
foo();
|
||||
}
|
||||
else {
|
||||
return bar();
|
||||
}
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function f3() {
|
||||
1==a|2==b&&foo();
|
||||
}
|
||||
function f4() {
|
||||
1==a|2==b&&foo();
|
||||
}
|
||||
function f5() {
|
||||
1==a&&2==b&&foo();
|
||||
}
|
||||
function f6() {
|
||||
1!=a||2!=b||foo();
|
||||
}
|
||||
function f7() {
|
||||
return 1!=a&&2!=b?bar():void foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
test/compress/numbers.js
Normal file
19
test/compress/numbers.js
Normal file
@@ -0,0 +1,19 @@
|
||||
hex_numbers_in_parentheses_for_prototype_functions: {
|
||||
input: {
|
||||
(-2);
|
||||
(-2).toFixed(0);
|
||||
|
||||
(2);
|
||||
(2).toFixed(0);
|
||||
|
||||
(0.2);
|
||||
(0.2).toFixed(0);
|
||||
|
||||
(0.00000002);
|
||||
(0.00000002).toFixed(0);
|
||||
|
||||
(1000000000000000128);
|
||||
(1000000000000000128).toFixed(0);
|
||||
}
|
||||
expect_exact: "-2;(-2).toFixed(0);2;2..toFixed(0);.2;.2.toFixed(0);2e-8;2e-8.toFixed(0);0xde0b6b3a7640080;(0xde0b6b3a7640080).toFixed(0);"
|
||||
}
|
||||
29
test/mocha.js
Normal file
29
test/mocha.js
Normal file
@@ -0,0 +1,29 @@
|
||||
var Mocha = require('mocha'),
|
||||
fs = require('fs'),
|
||||
path = require('path');
|
||||
|
||||
// Instantiate a Mocha instance.
|
||||
var mocha = new Mocha({});
|
||||
|
||||
var testDir = __dirname + '/mocha/';
|
||||
|
||||
// Add each .js file to the mocha instance
|
||||
fs.readdirSync(testDir).filter(function(file){
|
||||
// Only keep the .js files
|
||||
return file.substr(-3) === '.js';
|
||||
|
||||
}).forEach(function(file){
|
||||
mocha.addFile(
|
||||
path.join(testDir, file)
|
||||
);
|
||||
});
|
||||
|
||||
module.exports = function() {
|
||||
mocha.run(function(failures) {
|
||||
if (failures !== 0) {
|
||||
process.on('exit', function () {
|
||||
process.exit(failures);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
22
test/mocha/arguments.js
Normal file
22
test/mocha/arguments.js
Normal file
@@ -0,0 +1,22 @@
|
||||
var UglifyJS = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("arguments", function() {
|
||||
it("Should known that arguments in functions are local scoped", function() {
|
||||
var ast = UglifyJS.parse("var arguments; var f = function() {arguments.length}");
|
||||
ast.figure_out_scope();
|
||||
|
||||
// Test scope of `var arguments`
|
||||
assert.strictEqual(ast.find_variable("arguments").global, true);
|
||||
|
||||
// Select arguments symbol in function
|
||||
var symbol = ast.body[1].definitions[0].value.find_variable("arguments");
|
||||
|
||||
assert.strictEqual(symbol.global, false);
|
||||
assert.strictEqual(symbol.scope, ast. // From ast
|
||||
body[1]. // Select 2nd statement (equals to `var f ...`)
|
||||
definitions[0]. // First definition of selected statement
|
||||
value // Select function as scope
|
||||
);
|
||||
});
|
||||
});
|
||||
45
test/mocha/comment-filter.js
Normal file
45
test/mocha/comment-filter.js
Normal file
@@ -0,0 +1,45 @@
|
||||
var UglifyJS = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("comment filters", function() {
|
||||
it("Should be able to filter comments by passing regex", function() {
|
||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
||||
assert.strictEqual(ast.print_to_string({comments: /^!/}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
|
||||
});
|
||||
|
||||
it("Should be able to filter comments by passing a function", function() {
|
||||
var ast = UglifyJS.parse("/*TEST 123*/\n//An other comment\n//8 chars.");
|
||||
var f = function(node, comment) {
|
||||
return comment.value.length === 8;
|
||||
};
|
||||
|
||||
assert.strictEqual(ast.print_to_string({comments: f}), "/*TEST 123*/\n//8 chars.\n");
|
||||
});
|
||||
|
||||
it("Should be able to get the comment and comment type when using a function", function() {
|
||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
||||
var f = function(node, comment) {
|
||||
return comment.type == "comment1" || comment.type == "comment3";
|
||||
};
|
||||
|
||||
assert.strictEqual(ast.print_to_string({comments: f}), "//!test3\n//test4\n//test5\n//!test6\n");
|
||||
});
|
||||
|
||||
it("Should be able to filter comments by passing a boolean", function() {
|
||||
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
|
||||
|
||||
assert.strictEqual(ast.print_to_string({comments: true}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
|
||||
assert.strictEqual(ast.print_to_string({comments: false}), "");
|
||||
});
|
||||
|
||||
it("Should never be able to filter comment5 (shebangs)", function() {
|
||||
var ast = UglifyJS.parse("#!Random comment\n//test1\n/*test2*/");
|
||||
var f = function(node, comment) {
|
||||
assert.strictEqual(comment.type === "comment5", false);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/\n");
|
||||
});
|
||||
});
|
||||
89
test/mocha/getter-setter.js
Normal file
89
test/mocha/getter-setter.js
Normal file
@@ -0,0 +1,89 @@
|
||||
var UglifyJS = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("Getters and setters", function() {
|
||||
it("Should not accept operator symbols as getter/setter name", function() {
|
||||
var illegalOperators = [
|
||||
"++",
|
||||
"--",
|
||||
"+",
|
||||
"-",
|
||||
"!",
|
||||
"~",
|
||||
"&",
|
||||
"|",
|
||||
"^",
|
||||
"*",
|
||||
"/",
|
||||
"%",
|
||||
">>",
|
||||
"<<",
|
||||
">>>",
|
||||
"<",
|
||||
">",
|
||||
"<=",
|
||||
">=",
|
||||
"==",
|
||||
"===",
|
||||
"!=",
|
||||
"!==",
|
||||
"?",
|
||||
"=",
|
||||
"+=",
|
||||
"-=",
|
||||
"/=",
|
||||
"*=",
|
||||
"%=",
|
||||
">>=",
|
||||
"<<=",
|
||||
">>>=",
|
||||
"|=",
|
||||
"^=",
|
||||
"&=",
|
||||
"&&",
|
||||
"||"
|
||||
];
|
||||
var generator = function() {
|
||||
var results = [];
|
||||
|
||||
for (var i in illegalOperators) {
|
||||
results.push({
|
||||
code: "var obj = { get " + illegalOperators[i] + "() { return test; }};",
|
||||
operator: illegalOperators[i],
|
||||
method: "get"
|
||||
});
|
||||
results.push({
|
||||
code: "var obj = { set " + illegalOperators[i] + "(value) { test = value}};",
|
||||
operator: illegalOperators[i],
|
||||
method: "set"
|
||||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
var testCase = function(data) {
|
||||
return function() {
|
||||
UglifyJS.parse(data.code);
|
||||
};
|
||||
};
|
||||
|
||||
var fail = function(data) {
|
||||
return function (e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
||||
e.message === "Invalid getter/setter name: " + data.operator;
|
||||
};
|
||||
};
|
||||
|
||||
var errorMessage = function(data) {
|
||||
return "Expected but didn't get a syntax error while parsing following line:\n" + data.code;
|
||||
};
|
||||
|
||||
var tests = generator();
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var test = tests[i];
|
||||
assert.throws(testCase(test), fail(test), errorMessage(test));
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
19
test/mocha/huge-number-of-comments.js
Normal file
19
test/mocha/huge-number-of-comments.js
Normal file
@@ -0,0 +1,19 @@
|
||||
var Uglify = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("Huge number of comments.", function() {
|
||||
it("Should parse and compress code with thousands of consecutive comments", function() {
|
||||
var js = 'function lots_of_comments(x) { return 7 -';
|
||||
var i;
|
||||
for (i = 1; i <= 5000; ++i) { js += "// " + i + "\n"; }
|
||||
for (; i <= 10000; ++i) { js += "/* " + i + " */ /**/"; }
|
||||
js += "x; }";
|
||||
var result = Uglify.minify(js, {
|
||||
fromString: true,
|
||||
mangle: false,
|
||||
compress: {}
|
||||
});
|
||||
assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
|
||||
});
|
||||
});
|
||||
|
||||
30
test/mocha/let.js
Normal file
30
test/mocha/let.js
Normal file
@@ -0,0 +1,30 @@
|
||||
var Uglify = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("let", function() {
|
||||
it("Should not produce `let` as a variable name in mangle", function(done) {
|
||||
this.timeout(10000);
|
||||
|
||||
// Produce a lot of variables in a function and run it through mangle.
|
||||
var s = '"use strict"; function foo() {';
|
||||
for (var i = 0; i < 21000; ++i) {
|
||||
s += "var v" + i + "=0;";
|
||||
}
|
||||
s += '}';
|
||||
var result = Uglify.minify(s, {fromString: true, compress: false});
|
||||
|
||||
// Verify that select keywords and reserved keywords not produced
|
||||
assert.strictEqual(result.code.indexOf("var let="), -1);
|
||||
assert.strictEqual(result.code.indexOf("var do="), -1);
|
||||
assert.strictEqual(result.code.indexOf("var var="), -1);
|
||||
|
||||
// Verify that the variable names that appeared immediately before
|
||||
// and after the erroneously generated `let` variable name still exist
|
||||
// to show the test generated enough symbols.
|
||||
assert(result.code.indexOf("var ket=") >= 0);
|
||||
assert(result.code.indexOf("var met=") >= 0);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
34
test/mocha/string-literal.js
Normal file
34
test/mocha/string-literal.js
Normal file
@@ -0,0 +1,34 @@
|
||||
var UglifyJS = require('../../');
|
||||
var assert = require("assert");
|
||||
|
||||
describe("String literals", function() {
|
||||
it("Should throw syntax error if a string literal contains a newline", function() {
|
||||
var inputs = [
|
||||
"'\n'",
|
||||
"'\r'",
|
||||
'"\r\n"',
|
||||
"'\u2028'",
|
||||
'"\u2029"'
|
||||
];
|
||||
|
||||
var test = function(input) {
|
||||
return function() {
|
||||
var ast = UglifyJS.parse(input);
|
||||
};
|
||||
};
|
||||
|
||||
var error = function(e) {
|
||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
||||
e.message === "Unterminated string constant";
|
||||
};
|
||||
|
||||
for (var input in inputs) {
|
||||
assert.throws(test(inputs[input]), error);
|
||||
}
|
||||
});
|
||||
|
||||
it("Should not throw syntax error if a string has a line continuation", function() {
|
||||
var output = UglifyJS.parse('var a = "a\\\nb";').print_to_string();
|
||||
assert.equal(output, 'var a="ab";');
|
||||
});
|
||||
});
|
||||
@@ -16,6 +16,9 @@ if (failures) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var mocha_tests = require("./mocha.js");
|
||||
mocha_tests();
|
||||
|
||||
var run_sourcemaps_tests = require('./sourcemaps');
|
||||
run_sourcemaps_tests();
|
||||
|
||||
@@ -86,9 +89,18 @@ function run_compress_tests() {
|
||||
log_start_file(file);
|
||||
function test_case(test) {
|
||||
log_test(test.name);
|
||||
U.base54.reset();
|
||||
var options = U.defaults(test.options, {
|
||||
warnings: false
|
||||
});
|
||||
var warnings_emitted = [];
|
||||
var original_warn_function = U.AST_Node.warn_function;
|
||||
if (test.expect_warnings) {
|
||||
U.AST_Node.warn_function = function(text) {
|
||||
warnings_emitted.push("WARN: " + text);
|
||||
};
|
||||
options.warnings = true;
|
||||
}
|
||||
var cmp = new U.Compressor(options, true);
|
||||
var output_options = test.beautify || {};
|
||||
var expect;
|
||||
@@ -105,6 +117,7 @@ function run_compress_tests() {
|
||||
var output = input.transform(cmp);
|
||||
output.figure_out_scope();
|
||||
if (test.mangle) {
|
||||
output.compute_char_frequency(test.mangle);
|
||||
output.mangle_names(test.mangle);
|
||||
}
|
||||
output = make_code(output, output_options);
|
||||
@@ -117,6 +130,24 @@ function run_compress_tests() {
|
||||
failures++;
|
||||
failed_files[file] = 1;
|
||||
}
|
||||
else if (test.expect_warnings) {
|
||||
U.AST_Node.warn_function = original_warn_function;
|
||||
var expected_warnings = make_code(test.expect_warnings, {
|
||||
beautify: false,
|
||||
quote_style: 2, // force double quote to match JSON
|
||||
});
|
||||
var actual_warnings = JSON.stringify(warnings_emitted);
|
||||
actual_warnings = actual_warnings.split(process.cwd() + "/").join("");
|
||||
if (expected_warnings != actual_warnings) {
|
||||
log("!!! failed\n---INPUT---\n{input}\n---EXPECTED WARNINGS---\n{expected_warnings}\n---ACTUAL WARNINGS---\n{actual_warnings}\n\n", {
|
||||
input: input_code,
|
||||
expected_warnings: expected_warnings,
|
||||
actual_warnings: actual_warnings,
|
||||
});
|
||||
failures++;
|
||||
failed_files[file] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var tests = parse_test(path.resolve(dir, file));
|
||||
for (var i in tests) if (tests.hasOwnProperty(i)) {
|
||||
@@ -168,7 +199,7 @@ function parse_test(file) {
|
||||
}
|
||||
if (node instanceof U.AST_LabeledStatement) {
|
||||
assert.ok(
|
||||
node.label.name == "input" || node.label.name == "expect" || node.label.name == "expect_exact",
|
||||
["input", "expect", "expect_exact", "expect_warnings"].indexOf(node.label.name) >= 0,
|
||||
tmpl("Unsupported label {name} [{line},{col}]", {
|
||||
name: node.label.name,
|
||||
line: node.label.start.line,
|
||||
|
||||
Reference in New Issue
Block a user