I find it weird to put `{}` together. So I figured I would change it to have an empty line and ask for feedback :)

Beware: most of the test cases are not representative of real code, you almost never define blocks with no content in practice.
987 lines
18 KiB
Plaintext
987 lines
18 KiB
Plaintext
exports[`test hoisted.js 1`] = `
|
|
"/**
|
|
* test initialization tracking in the presence of hoisting
|
|
* @flow
|
|
*/
|
|
|
|
function _if(b: () => boolean) {
|
|
if (b()) {
|
|
var f = function () {};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _while(b: () => boolean) {
|
|
while (b()) {
|
|
var f = function () {};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _do_while(b: () => boolean) {
|
|
do {
|
|
var f = function () {};
|
|
} while (b());
|
|
f(); // ok
|
|
}
|
|
|
|
function _for(n: number) {
|
|
for (var i = 0; i < n; i++) {
|
|
var f = function () {};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _for_in(obj: Object) {
|
|
for (var p in obj) {
|
|
var f = function () {};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _for_of(arr: Array<number>) {
|
|
for (var x of arr) {
|
|
var f = function () {};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
/**
|
|
* test initialization tracking in the presence of hoisting
|
|
* @flow
|
|
*/
|
|
|
|
function _if(b: () => boolean) {
|
|
if (b()) {
|
|
var f = function() {
|
|
};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _while(b: () => boolean) {
|
|
while (b()) {
|
|
var f = function() {
|
|
};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _do_while(b: () => boolean) {
|
|
do {
|
|
var f = function() {
|
|
};
|
|
} while (b());
|
|
f(); // ok
|
|
}
|
|
|
|
function _for(n: number) {
|
|
for (var i = 0; i < n; i++) {
|
|
var f = function() {
|
|
};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _for_in(obj: Object) {
|
|
for (var p in obj) {
|
|
var f = function() {
|
|
};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
|
|
function _for_of(arr: Array<number>) {
|
|
for (var x of arr) {
|
|
var f = function() {
|
|
};
|
|
}
|
|
f(); // error, possibly undefined
|
|
}
|
|
"
|
|
`;
|
|
|
|
exports[`test hoisted2.js 1`] = `
|
|
"/**
|
|
* test initialization tracking for vars
|
|
* note: for try/catch/finally, see tests/try/init.js
|
|
* @flow
|
|
*/
|
|
|
|
// deferred init on annotated vars is ok
|
|
function linear_deferred_init() {
|
|
var x:number;
|
|
x = 0;
|
|
var y:number = x;
|
|
}
|
|
|
|
// ...but use of var before init gives undefined
|
|
function linear_pre_init() {
|
|
var x:number;
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// local use of annotated vars in an if is ok
|
|
function if_scoped_init(b) {
|
|
if (b) {
|
|
var x:number = 0;
|
|
var y:number = x;
|
|
}
|
|
}
|
|
|
|
// but not across if/else
|
|
function if_else_partial_init(b) {
|
|
if (b) {
|
|
var x:number = 0;
|
|
} else {
|
|
var y:number = x; // error
|
|
}
|
|
}
|
|
|
|
// use of var before if gives undefined
|
|
function if_pre_init(b) {
|
|
var y:number = x; // error
|
|
if (b) {
|
|
var x:number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function if_partial_post_init(b) {
|
|
if (b) {
|
|
var x:number = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// ...unless both branches have initialized
|
|
function if_post_init(b) {
|
|
if (b) {
|
|
var x:number = 0;
|
|
} else {
|
|
var x:number = 1;
|
|
}
|
|
var y:number = x;
|
|
}
|
|
|
|
// use of var after partial init (non-exhaustive if) gives undefined
|
|
function if_partial_post_init(b) {
|
|
var x:number;
|
|
if (b) {
|
|
x = 0;
|
|
}
|
|
var y:number = x; // error, possibly uninitialized
|
|
}
|
|
|
|
// use of var after guaranteed init (exhaustive if) is ok
|
|
function if_post_init(b) {
|
|
var x:number;
|
|
if (b) {
|
|
x = 0;
|
|
} else {
|
|
x = 1;
|
|
}
|
|
var y:number = x;
|
|
}
|
|
|
|
// use of var after partial init (non-exhaustive switch) gives undefined
|
|
function switch_partial_post_init(i) {
|
|
var x:number;
|
|
switch (i) {
|
|
case 0:
|
|
x = 0;
|
|
break;
|
|
case 1:
|
|
x = 1;
|
|
break;
|
|
}
|
|
var y:number = x; // error, possibly uninitialized
|
|
}
|
|
|
|
// use of var after guaranteed init (exhaustive switch) is ok
|
|
function switch_post_init(i) {
|
|
var 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
|
|
}
|
|
|
|
// local use of annotated var in switch is ok
|
|
function switch_scoped_init_1(i) {
|
|
switch (i) {
|
|
case 0:
|
|
var x:number = 0;
|
|
var y:number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use of var before switch gives undefined
|
|
function switch_scoped_init_2(i) {
|
|
var y:number = x; // error
|
|
switch (i) {
|
|
case 0:
|
|
var x:number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function switch_scoped_init_3(i) {
|
|
switch (i) {
|
|
case 0:
|
|
var x:number = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// ...and in a fallthrough case without initialization
|
|
function switch_scoped_init_4(i) {
|
|
switch (i) {
|
|
case 0:
|
|
var x:number = 0;
|
|
case 1:
|
|
var y:number = x; // error
|
|
}
|
|
}
|
|
|
|
// local use of annotated var in while is ok
|
|
function while_scoped_init(b) {
|
|
while (b) {
|
|
var x:number = 0;
|
|
var y:number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use of var before while gives undefined
|
|
function while_pre_init(b) {
|
|
var y:number = x; // error
|
|
while (b) {
|
|
var x:number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function while_post_init(b) {
|
|
while (b) {
|
|
var x:number = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// local use of annotated var in do-while is ok
|
|
function do_while_scoped_init(b) {
|
|
do {
|
|
var x:number = 0;
|
|
var y:number = x;
|
|
} while (b);
|
|
}
|
|
|
|
// ...but use before do-while gives undefined
|
|
function do_while_pre_init(b) {
|
|
var y:number = x; // error
|
|
do {
|
|
var x:number = 0;
|
|
} while (b);
|
|
}
|
|
|
|
// after is ok, because loop is guaranteed to run
|
|
function do_while_post_init(b) {
|
|
do {
|
|
var x:number = 0;
|
|
} while (b);
|
|
var y:number = x;
|
|
}
|
|
|
|
// local use of annotated var in for is ok
|
|
function for_scoped_init(b) {
|
|
for (;b;) {
|
|
var x:number = 0;
|
|
var y:number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use before for gives undefined
|
|
function for_pre_init(b) {
|
|
var y:number = x; // error
|
|
for (;b;) {
|
|
var x:number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function for_post_init(b) {
|
|
for (;b;) {
|
|
var x:number = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// local use of annotated var in for-in is ok
|
|
function for_in_scoped_init() {
|
|
for (var p in { a:1, b: 2 }) {
|
|
var x:number = 0;
|
|
var y:number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use before while gives undefined
|
|
function for_in_pre_init() {
|
|
var y:number = x; // error
|
|
for (var p in { a:1, b: 2 }) {
|
|
var x:number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function for_in_post_init() {
|
|
for (var p in { a:1, b: 2 }) {
|
|
var x:number = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
|
|
// local use of annotated var in for-of is ok
|
|
function for_of_scoped_init() {
|
|
for (var x of [1, 2, 3]) {
|
|
var x:number = 0;
|
|
var y:number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use before while gives undefined
|
|
function for_in_pre_init() {
|
|
var y:number = x; // error
|
|
for (var x of [1, 2, 3]) {
|
|
var x:number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function for_in_post_init() {
|
|
for (var x of [1, 2, 3]) {
|
|
var x:number = 0;
|
|
}
|
|
var y:number = x; // error
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
/**
|
|
* test initialization tracking for vars
|
|
* note: for try/catch/finally, see tests/try/init.js
|
|
* @flow
|
|
*/
|
|
|
|
// deferred init on annotated vars is ok
|
|
function linear_deferred_init() {
|
|
var x: number;
|
|
x = 0;
|
|
var y: number = x;
|
|
}
|
|
|
|
// ...but use of var before init gives undefined
|
|
function linear_pre_init() {
|
|
var x: number;
|
|
var y: number = x; // error
|
|
}
|
|
|
|
// local use of annotated vars in an if is ok
|
|
function if_scoped_init(b) {
|
|
if (b) {
|
|
var x: number = 0;
|
|
var y: number = x;
|
|
}
|
|
}
|
|
|
|
// but not across if/else
|
|
function if_else_partial_init(b) {
|
|
if (b) {
|
|
var x: number = 0;
|
|
} else {
|
|
var y: number = x; // error
|
|
}
|
|
}
|
|
|
|
// use of var before if gives undefined
|
|
function if_pre_init(b) {
|
|
var y: number = x;
|
|
// error
|
|
if (b) {
|
|
var x: number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function if_partial_post_init(b) {
|
|
if (b) {
|
|
var x: number = 0;
|
|
}
|
|
var y: number = x; // error
|
|
}
|
|
|
|
// ...unless both branches have initialized
|
|
function if_post_init(b) {
|
|
if (b) {
|
|
var x: number = 0;
|
|
} else {
|
|
var x: number = 1;
|
|
}
|
|
var y: number = x;
|
|
}
|
|
|
|
// use of var after partial init (non-exhaustive if) gives undefined
|
|
function if_partial_post_init(b) {
|
|
var x: number;
|
|
if (b) {
|
|
x = 0;
|
|
}
|
|
var y: number = x; // error, possibly uninitialized
|
|
}
|
|
|
|
// use of var after guaranteed init (exhaustive if) is ok
|
|
function if_post_init(b) {
|
|
var x: number;
|
|
if (b) {
|
|
x = 0;
|
|
} else {
|
|
x = 1;
|
|
}
|
|
var y: number = x;
|
|
}
|
|
|
|
// use of var after partial init (non-exhaustive switch) gives undefined
|
|
function switch_partial_post_init(i) {
|
|
var x: number;
|
|
switch (i) {
|
|
case 0:
|
|
x = 0;
|
|
break;
|
|
case 1:
|
|
x = 1;
|
|
break;
|
|
}
|
|
var y: number = x; // error, possibly uninitialized
|
|
}
|
|
|
|
// use of var after guaranteed init (exhaustive switch) is ok
|
|
function switch_post_init(i) {
|
|
var 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
|
|
}
|
|
|
|
// local use of annotated var in switch is ok
|
|
function switch_scoped_init_1(i) {
|
|
switch (i) {
|
|
case 0:
|
|
var x: number = 0;
|
|
var y: number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use of var before switch gives undefined
|
|
function switch_scoped_init_2(i) {
|
|
var y: number = x;
|
|
// error
|
|
switch (i) {
|
|
case 0:
|
|
var x: number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function switch_scoped_init_3(i) {
|
|
switch (i) {
|
|
case 0:
|
|
var x: number = 0;
|
|
}
|
|
var y: number = x; // error
|
|
}
|
|
|
|
// ...and in a fallthrough case without initialization
|
|
function switch_scoped_init_4(i) {
|
|
switch (i) {
|
|
case 0:
|
|
var x: number = 0;
|
|
// error
|
|
case 1:
|
|
var y: number = x;
|
|
}
|
|
}
|
|
|
|
// local use of annotated var in while is ok
|
|
function while_scoped_init(b) {
|
|
while (b) {
|
|
var x: number = 0;
|
|
var y: number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use of var before while gives undefined
|
|
function while_pre_init(b) {
|
|
var y: number = x;
|
|
// error
|
|
while (b) {
|
|
var x: number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function while_post_init(b) {
|
|
while (b) {
|
|
var x: number = 0;
|
|
}
|
|
var y: number = x; // error
|
|
}
|
|
|
|
// local use of annotated var in do-while is ok
|
|
function do_while_scoped_init(b) {
|
|
do {
|
|
var x: number = 0;
|
|
var y: number = x;
|
|
} while (b);
|
|
}
|
|
|
|
// ...but use before do-while gives undefined
|
|
function do_while_pre_init(b) {
|
|
var y: number = x;
|
|
// error
|
|
do {
|
|
var x: number = 0;
|
|
} while (b);
|
|
}
|
|
|
|
// after is ok, because loop is guaranteed to run
|
|
function do_while_post_init(b) {
|
|
do {
|
|
var x: number = 0;
|
|
} while (b);
|
|
var y: number = x;
|
|
}
|
|
|
|
// local use of annotated var in for is ok
|
|
function for_scoped_init(b) {
|
|
for (; b; ) {
|
|
var x: number = 0;
|
|
var y: number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use before for gives undefined
|
|
function for_pre_init(b) {
|
|
var y: number = x;
|
|
// error
|
|
for (; b; ) {
|
|
var x: number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function for_post_init(b) {
|
|
for (; b; ) {
|
|
var x: number = 0;
|
|
}
|
|
var y: number = x; // error
|
|
}
|
|
|
|
// local use of annotated var in for-in is ok
|
|
function for_in_scoped_init() {
|
|
for (var p in { a: 1, b: 2 }) {
|
|
var x: number = 0;
|
|
var y: number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use before while gives undefined
|
|
function for_in_pre_init() {
|
|
var y: number = x;
|
|
// error
|
|
for (var p in { a: 1, b: 2 }) {
|
|
var x: number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function for_in_post_init() {
|
|
for (var p in { a: 1, b: 2 }) {
|
|
var x: number = 0;
|
|
}
|
|
var y: number = x; // error
|
|
}
|
|
|
|
// local use of annotated var in for-of is ok
|
|
function for_of_scoped_init() {
|
|
for (var x of [ 1, 2, 3 ]) {
|
|
var x: number = 0;
|
|
var y: number = x;
|
|
}
|
|
}
|
|
|
|
// ...but use before while gives undefined
|
|
function for_in_pre_init() {
|
|
var y: number = x;
|
|
// error
|
|
for (var x of [ 1, 2, 3 ]) {
|
|
var x: number = 0;
|
|
}
|
|
}
|
|
|
|
// ...and after
|
|
function for_in_post_init() {
|
|
for (var x of [ 1, 2, 3 ]) {
|
|
var x: number = 0;
|
|
}
|
|
var y: number = x; // error
|
|
}
|
|
"
|
|
`;
|
|
|
|
exports[`test let.js 1`] = `
|
|
"/**
|
|
* 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;
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
/**
|
|
* 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;
|
|
// error, skipped declaration
|
|
case 1:
|
|
let y: number = x;
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
"
|
|
`;
|
|
|
|
exports[`test nullable-init.js 1`] = `
|
|
"var o: {x: ?number} = { x: null };
|
|
var a: Array<?number> = [null,null];
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
var o: { x: ?number } = { x: null };
|
|
var a: Array<?number> = [ null, null ];
|
|
"
|
|
`;
|