- This brings in the flow test suite that contains a ton of JavaScript parsing edge cases - This creates snapshot tests using the pretty printer for all of them - If uncomment `RUN_AST_TESTS` line in `tests/run_specs.js`, it checks ast(pretty_print(x)) == ast(x). Right now, "178 failed, 197 passed, 375 of 377 total". So half of the tests are not passing, most of them are crashes and many of the rest are subtle issues.
158 lines
3.1 KiB
JavaScript
158 lines
3.1 KiB
JavaScript
/**
|
|
* test initialization tracking for lets
|
|
* @flow
|
|
*/
|
|
|
|
// deferred init on annotated lets is ok
|
|
function linear_deferred_init() {
|
|
let x:number;
|
|
x = 0;
|
|
let y:number = x;
|
|
}
|
|
|
|
// use of let before init gives undefined
|
|
function linear_pre_init() {
|
|
let x:number;
|
|
let y:?number = x; // ok
|
|
let z:number = x; // error
|
|
x = 0;
|
|
let w:number = x; // ok
|
|
}
|
|
|
|
// self-references in let bindings are not ok
|
|
function self_init() {
|
|
let x = x; // 'x' not initialized!
|
|
}
|
|
|
|
// use of let after partial init (non-exhaustive if) gives undefined
|
|
function if_partial_post_init(b) {
|
|
let x:number;
|
|
if (b) {
|
|
x = 0;
|
|
}
|
|
var y:number = x; // error, possibly uninitialized
|
|
}
|
|
|
|
// use of let after guaranteed init (exhaustive if) is ok
|
|
function if_post_init(b) {
|
|
let x:number;
|
|
if (b) {
|
|
x = 0;
|
|
} else {
|
|
x = 1;
|
|
}
|
|
var y:number = x;
|
|
}
|
|
|
|
// use of let after partial init (non-exhaustive switch) gives undefined
|
|
function switch_partial_post_init(i) {
|
|
let x:number;
|
|
switch (i) {
|
|
case 0:
|
|
x = 0;
|
|
break;
|
|
case 1:
|
|
x = 1;
|
|
break;
|
|
}
|
|
var y:number = x; // error, possibly uninitialized
|
|
}
|
|
|
|
// use of let after guaranteed init (exhaustive switch) is ok
|
|
function switch_post_init(i) {
|
|
let x:number;
|
|
switch (i) {
|
|
case 0:
|
|
x = 0;
|
|
break;
|
|
case 1:
|
|
x = 1;
|
|
break;
|
|
default:
|
|
x = 2;
|
|
}
|
|
var y:number = x; // no error, all cases covered
|
|
}
|
|
|
|
// use in a switch after a skipped decl is an error
|
|
function switch_scoped_init_2(i) {
|
|
switch (i) {
|
|
case 0:
|
|
let x:number;
|
|
case 1:
|
|
let y:number = x; // error, skipped declaration
|
|
}
|
|
}
|
|
|
|
// while leaves it possibly uninitialized
|
|
function while_post_init(b) {
|
|
let x:number;
|
|
while (b) {
|
|
x = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// do-while is ok, because loop is guaranteed to run at least once
|
|
function do_while_post_init(b) {
|
|
let x:number;
|
|
do {
|
|
x = 0;
|
|
} while (b);
|
|
var y:number = x; // ok
|
|
}
|
|
|
|
// for-in leaves it possibly uninitialized
|
|
function for_in_post_init() {
|
|
var x:number;
|
|
for (var p in {}) {
|
|
x = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// for-of leaves it possibly uninitialized
|
|
function for_of_post_init() {
|
|
var x:number;
|
|
for (var x of []) {
|
|
x = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// use of let after guaranteed init (exhaustive switch + throw) is ok
|
|
function switch_post_init2(i): number {
|
|
let bar;
|
|
switch (i) {
|
|
case 1:
|
|
bar = 3;
|
|
break;
|
|
default:
|
|
throw new Error('Invalid state');
|
|
}
|
|
return bar; // ok, definitely initialized
|
|
}
|
|
|
|
// use of let after guaranteed init (exhaustive switch + throw) is ok
|
|
function switch_post_init2(i): number {
|
|
let bar;
|
|
switch (i) {
|
|
case 1:
|
|
bar = 3;
|
|
break;
|
|
default:
|
|
throw new Error('Invalid state');
|
|
}
|
|
return bar; // ok, definitely initialized
|
|
}
|
|
|
|
// reference of a let-binding is permitted in a sub-closure within the init expr
|
|
function sub_closure_init_reference() {
|
|
let x = function() { return x; };
|
|
const y = function() { return y; };
|
|
|
|
// var-bindings can reference each other cyclically since they do not incur a
|
|
// TDZ (...even though this is weird...)
|
|
var z = z;
|
|
}
|