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;
|
|
}
|