Add special case for comment at top of file; regenerate snapshots

master
James Long 2017-01-09 21:49:06 -05:00
parent 74fc539e1a
commit a4643f1bae
365 changed files with 7437 additions and 6418 deletions

View File

@ -79,7 +79,8 @@ function decorateComment(node, comment, text) {
if (locStart(child) - locStart(comment) <= 0 &&
locEnd(comment) - locEnd(child) <= 0) {
// The comment is completely contained by this child node.
decorateComment(comment.enclosingNode = child, comment, text);
comment.enclosingNode = child;
decorateComment(child, comment, text);
return; // Abandon the binary search at this level.
}
@ -163,7 +164,7 @@ exports.attach = function(comments, ast, text) {
addDanglingComment(en, comment);
} else {
throw new Error("AST contains no nodes at all?");
// throw new Error("AST contains no nodes at all?");
}
});
@ -271,9 +272,12 @@ function printTrailingComment(commentPath, print, options) {
exports.printComments = function(path, print, options) {
var value = path.getValue();
var parent = path.getParentNode();
var printed = print(path);
var comments = n.Node.check(value) &&
types.getFieldValue(value, "comments");
var isFirstInProgram = n.Program.check(parent) &&
parent.body[0] === value;
if (!comments || comments.length === 0) {
return printed;
@ -291,6 +295,15 @@ exports.printComments = function(path, print, options) {
comment.type === "Block" ||
comment.type === "CommentBlock"))) {
leadingParts.push(printLeadingComment(commentPath, print));
// Support a special case where a comment exists at the very top
// of the file. Allow the user to add spacing between that file
// and any code beneath it.
if(isFirstInProgram &&
util.newlineExistsAfter(options.originalText, util.locEnd(comment))) {
leadingParts.push(hardline);
}
} else if (trailing) {
trailingParts.push(printTrailingComment(commentPath, print, options));
}

View File

@ -1551,8 +1551,6 @@ function genericPrintNoParens(path, options, print) {
}
function printStatementSequence(path, options, print) {
let inClassBody = namedTypes.ClassBody &&
namedTypes.ClassBody.check(path.getParentNode());
let printed = [];
path.map(function(stmtPath, i) {
@ -1571,11 +1569,13 @@ function printStatementSequence(path, options, print) {
}
const stmtPrinted = print(stmtPath);
const text = options.originalText;
const parts = [];
parts.push(stmtPrinted);
if (shouldAddSpacing(stmt, options) && !isLastStatement(stmtPath)) {
if (util.newlineExistsAfter(text, util.locEnd(stmt)) &&
!isLastStatement(stmtPath)) {
parts.push(hardline);
}
@ -2008,11 +2008,6 @@ function nodeStr(str, options) {
}
}
function shouldAddSpacing(node, options) {
const text = options.originalText;
return util.newlineExistsAfter(text, util.locEnd(node));
}
function isFirstStatement(path) {
const parent = path.getParentNode();
const node = path.getValue();

View File

@ -12,13 +12,13 @@ function foo() {
break;
}
}
function bar() {
L:
do {
continue L;
} while (false);
}
"
}"
`;
exports[`test return.js 1`] = `
@ -35,6 +35,5 @@ function foo() {
if (x == null)
return;
bar(x);
}
"
}"
`;

View File

@ -60,45 +60,54 @@ var zer : null = null;
function foobar(n : ?number) : number | null | void { return n; }
function barfoo(n : number | null | void) : ?number { return n; }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// array sugar
// param type annos are strict UBs like var type annos
// error
// another error on param UB, more typical of www (mis)use-cases
// this one cribbed from API.atlas.js
// error below, since we\'re assigning elements to batchRequests
// which lack a path property.
// just assign result to new var instead of reassigning to param.
// Transform the requests to the format the Graph API expects.
// ...
function foo(str: string, i: number): string {
return str;
}
var bar: (str: number, i: number) => string = foo;
var qux = function(str: string, i: number): number {
return foo(str, i);
};
var obj: { str: string, i: number, j: boolean } = {
str: \"...\",
i: \"...\",
k: false
};
var arr: Array<number> = [ 1, 2, \"...\" ];
// array sugar
var array: number[] = [ 1, 2, \"...\" ];
var matrix: number[][] = [ [ 1, 2 ], [ 3, 4 ] ];
var matrix_parens: number[][] = matrix;
var nullable_array: ?(number[]) = null;
var nullable_array_parens: ?(number[]) = nullable_array;
var array_of_nullable: (?number)[] = [ null, 3 ];
var array_of_tuple: [number, string][] = [ [ 0, \"foo\" ], [ 1, \"bar\" ] ];
var array_of_tuple_parens: [number, string][] = array_of_tuple;
type ObjType = { \"bar-foo\": string, \"foo-bar\": number };
var test_obj: ObjType = { \"bar-foo\": \"23\" };
// param type annos are strict UBs like var type annos
function param_anno(n: number): void {
n = \"hey\";
n = \"hey\"; // error
}
// another error on param UB, more typical of www (mis)use-cases
// this one cribbed from API.atlas.js
function param_anno2(
batchRequests: Array<{ method: string, path: string, params: ?Object }>
): void {
// error below, since we\'re assigning elements to batchRequests
// which lack a path property.
// just assign result to new var instead of reassigning to param.
// Transform the requests to the format the Graph API expects.
batchRequests = batchRequests.map(request => {
return {
method: request.method,
@ -106,16 +115,19 @@ function param_anno2(
relative_url: request.path
};
});
// ...
}
var toz: null = 3;
var zer: null = null;
function foobar(n: ?number): number | null | void {
return n;
}
function barfoo(n: number | null | void): ?number {
return n;
}
"
}"
`;
exports[`test forward_ref.js 1`] = `
@ -134,24 +146,23 @@ function foo() {
class MyClass { } // looked up above
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// forward ref ok, null ~> class error
// forward ref ok, null ~> class error
// looked up above
// ok (no confusion across scopes)
// looked up above
let myClassInstance: MyClass = null;
// forward ref ok, null ~> class error
function bar(): MyClass {
return null;
return null; // forward ref ok, null ~> class error
}
class MyClass {}
// looked up above
function foo() {
let myClassInstance: MyClass = mk();
// ok (no confusion across scopes)
function mk() {
return new MyClass();
}
class MyClass {}
}
"
class MyClass {} // looked up above
}"
`;
exports[`test issue-530.js 1`] = `
@ -160,8 +171,8 @@ exports[`test issue-530.js 1`] = `
module.exports = foo;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function foo(...args: any) {}
module.exports = foo;
"
module.exports = foo;"
`;
exports[`test leak.js 1`] = `
@ -189,6 +200,7 @@ function bar(y: MyObj): string {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** @flow */
/* This test documents an example we ran into of a type annotation leaking.
*
* When foo() calls bar(), we should make sure the type of x matches the type
@ -199,14 +211,16 @@ function bar(y: MyObj): string {
* and type checking the body of bar() using the stricter dictionary type,
* leading to an error.
*/
type MyObj = Object;
function foo(x: { [key: string]: mixed }) {
bar(x);
}
function bar(y: MyObj): string {
return y.foo;
}
"
}"
`;
exports[`test other.js 1`] = `
@ -214,8 +228,7 @@ exports[`test other.js 1`] = `
module.exports = (C: any);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class C {}
module.exports = (C: any);
"
module.exports = (C: any);"
`;
exports[`test scope.js 1`] = `
@ -244,13 +257,16 @@ class Foo<A> {
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// hypothetical immutable map
type Merge<T> = (a: T, b: T) => T;
// hypothetical immutable map
declare class Map<K, V> {
(): Map<K, V>,
insertWith(fn: Merge<V>, k: K, v: V): Map<K, V>
}
declare function foldr<A, B>(fn: (a: A, b: B) => B, b: B, as: A[]): B;
function insertMany<K, V>(
merge: Merge<V>,
vs: [K, V][],
@ -261,14 +277,14 @@ function insertMany<K, V>(
}
return foldr(f, m, vs);
}
class Foo<A> {
bar<B>() {
return function<C>(a: A, b: B, c: C): void {
([ a, b, c ]: [A, B, C]);
};
}
}
"
}"
`;
exports[`test test.js 1`] = `
@ -276,6 +292,5 @@ exports[`test test.js 1`] = `
((0: C): string);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var C = require(\"./other\");
((0: C): string);
"
((0: C): string);"
`;

View File

@ -10,13 +10,14 @@ export default class {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type T = any;
export default class {
p: T;
constructor() {
this.p = 0;
}
}
"
}"
`;
exports[`test B.js 1`] = `
@ -26,10 +27,9 @@ class B extends A {
p: string; // OK, string ~> any
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OK, string ~> any
import A from \"./A\";
class B extends A {
p: string;
}
"
p: string; // OK, string ~> any
}"
`;

View File

@ -18,14 +18,16 @@ export default class {
* @providesModule A
* @flow
*/
import type T from \"T\";
export default class {
p: T;
constructor() {
this.p = 0;
}
}
"
}"
`;
exports[`test B.js 1`] = `
@ -42,12 +44,12 @@ class B extends A {
/**
* @flow
*/
// OK, string ~> any
import A from \"A\";
class B extends A {
p: string;
}
"
p: string; // OK, string ~> any
}"
`;
exports[`test T.js 1`] = `
@ -55,9 +57,5 @@ exports[`test T.js 1`] = `
* @providesModule T
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @providesModule T
*/
"
`;

View File

@ -10,6 +10,7 @@ var y:string = bar(0);
var z:string = qux(0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
function foo(x: any): any {
return x;
}
@ -19,10 +20,10 @@ function bar(x: any): mixed {
function qux(x: mixed): any {
return x;
}
var x: string = foo(0);
var y: string = bar(0);
var z: string = qux(0);
"
var z: string = qux(0);"
`;
exports[`test anyexportflowfile.js 1`] = `
@ -31,8 +32,8 @@ exports[`test anyexportflowfile.js 1`] = `
module.exports = ((x: any) => x: any);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
module.exports = ((x: any) => x: any);
"
module.exports = ((x: any) => x: any);"
`;
exports[`test flowfixme.js 1`] = `
@ -62,26 +63,27 @@ var w:string = baz(0);
@flow
*/
// no param
// param (info only)
// ...params are still checked. unknown type
function foo(x: $FlowFixMe): $FlowFixMe {
return x;
}
function bar(x: $FlowFixMe): mixed {
return x;
}
// param (info only)
function qux(x: $FlowFixMe<number>): $FlowFixMe<number> {
return x;
}
// ...params are still checked. unknown type
function baz(x: $FlowFixMe<nnumber>): $FlowFixMe<number> {
return x;
}
var x: string = foo(0);
var y: string = bar(0);
var z: string = qux(0);
var w: string = baz(0);
"
var w: string = baz(0);"
`;
exports[`test flowissue.js 1`] = `
@ -111,26 +113,27 @@ var w:string = baz(0);
@flow
*/
// no param
// param (info only)
// ...params are still checked. unknown type
function foo(x: $FlowIssue): $FlowIssue {
return x;
}
function bar(x: $FlowIssue): mixed {
return x;
}
// param (info only)
function qux(x: $FlowIssue<number>): $FlowIssue<number> {
return x;
}
// ...params are still checked. unknown type
function baz(x: $FlowIssue<nnumber>): $FlowIssue<number> {
return x;
}
var x: string = foo(0);
var y: string = bar(0);
var z: string = qux(0);
var w: string = baz(0);
"
var w: string = baz(0);"
`;
exports[`test nonflowfile.js 1`] = `
@ -139,8 +142,8 @@ exports[`test nonflowfile.js 1`] = `
module.exports = (x) => x;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow
module.exports = x => x;
"
module.exports = x => x;"
`;
exports[`test propagate.js 1`] = `
@ -171,28 +174,30 @@ function bar2(x: mixed) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// should be able to select first case and error
declare class C {
bar(n1: number, n2: number): number,
bar(s1: string, s2: string): string
}
function foo(c: C, x: any): string {
let y = x.y;
return c.bar(0, y);
return c.bar(0, y); // should be able to select first case and error
}
var any_fun1 = require(\"./nonflowfile\");
function bar1(x: mixed) {
if (any_fun1(x)) {
(x: boolean);
}
}
var any_fun2 = require(\"./anyexportflowfile\");
function bar2(x: mixed) {
if (any_fun2(x)) {
(x: boolean);
}
}
"
}"
`;
exports[`test reach.js 1`] = `
@ -215,11 +220,12 @@ function foo(o: ?AsyncRequest) {
* type annotations. Here we test propagation of any through the
* annotation - without it, the body of the if will be unreachable
*/
type AsyncRequest = any;
function foo(o: ?AsyncRequest) {
if (o) {
var n: number = o;
}
}
"
}"
`;

View File

@ -92,116 +92,118 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @providesModule Arith */
// error
// error
// error
// test MaybeT(NumT)
// test OptionalT(NumT)
// test OptionalT(MaybeT(NumT))
// === 0
// === NaN
// === 1
// === 1
// === NaN
// === NaN
// === 1
// === 1
// === NaN
// === NaN
// error
// error
// error
// error
// error
// error
// error
// error
// error
// error
// error
// error
// error
// when one side is a string or number and the other is invalid, we
// assume you are expecting a string or number (respectively), rather than
// erroring twice saying number !~> string and obj !~> string.
// error: object !~> number
// error: object !~> number
// error: object !~> string
// error: object !~> string
// ok
// ok
// error, string ~> empty
// error, string ~> empty
function num(x: number) {}
function str(x: string) {}
function foo() {
var x = 0;
var y = \"...\";
var z = {};
num(x + x);
num(x + y);
// error
str(x + y);
str(x + x);
str(z + y);
// error
str(z + y); // error
}
// test MaybeT(NumT)
function bar0(x: ?number, y: number) {
num(x + y);
}
function bar1(x: number, y: ?number) {
num(x + y);
}
// test OptionalT(NumT)
function bar2(x?: number, y: number) {
num(x + y);
}
function bar3(x: number, y?: number) {
num(x + y);
}
// test OptionalT(MaybeT(NumT))
function bar4(x?: ?number, y: number) {
num(x + y);
}
function bar5(x: number, y?: ?number) {
num(x + y);
}
num(null + null);
// === 0
num(undefined + undefined);
// === NaN
num(null + 1);
// === 1
num(1 + null);
// === 1
num(undefined + 1);
// === NaN
num(1 + undefined);
// === NaN
num(null + true);
// === 1
num(true + null);
// === 1
num(undefined + true);
// === NaN
num(true + undefined);
// === NaN
str(\"foo\" + true);
// error
str(true + \"foo\");
// error
str(\"foo\" + null);
// error
str(null + \"foo\");
// error
str(\"foo\" + undefined);
// error
str(undefined + \"foo\");
// error
let tests = [
function(x: mixed, y: mixed) {
x + y;
// error
x + 0;
// error
0 + x;
// error
x + \"\";
// error
\"\" + x;
// error
x + {};
({}) + x;
// error
({}) + x; // error
},
// when one side is a string or number and the other is invalid, we
// assume you are expecting a string or number (respectively), rather than
// erroring twice saying number !~> string and obj !~> string.
function() {
(1 + {}: number);
// error: object !~> number
({} + 1: number);
// error: object !~> number
(\"1\" + {}: string);
({} + \"1\": string);
// error: object !~> string
({} + \"1\": string); // error: object !~> string
},
function(x: any, y: number, z: string) {
(x + y: string);
// ok
(y + x: string);
// ok
(x + z: empty);
(z + x: empty);
// error, string ~> empty
(z + x: empty); // error, string ~> empty
}
];
"
];"
`;
exports[`test exponent.js 1`] = `
@ -218,15 +220,16 @@ y **= 2; // error
(-2) ** 2;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error
let x: number = 2 ** 3;
x **= 4;
let y: string = \"123\";
y **= 2;
// error
1 + 2 ** 3 + 4;
2 ** 2;
(-2) ** 2;
"
(-2) ** 2;"
`;
exports[`test generic.js 1`] = `
@ -239,27 +242,26 @@ function f<A,B>(a: A, b: B): B {return a + b; } // error
function f<A,B>(a: A, b: B): B {return b + a; } // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error
// error
// error
// error
// error
function f<A>(a: A): A {
return a + a;
}
// error
function f<A, B>(a: A, b: B): A {
return a + b;
}
// error
function f<A, B>(a: A, b: B): A {
return b + a;
}
// error
function f<A, B>(a: A, b: B): B {
return a + b;
}
// error
function f<A, B>(a: A, b: B): B {
return b + a;
}
"
} // error"
`;
exports[`test mult.js 1`] = `
@ -277,15 +279,17 @@ let y: string = \"123\";
y *= 2; // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error
function num(x: number) {}
num(null * 1);
num(1 * null);
let x: number = 2 * 3;
x *= 4;
let y: string = \"123\";
y *= 2;
"
y *= 2; // error"
`;
exports[`test relational.js 1`] = `
@ -321,43 +325,44 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error
// error
// error
// error
// error
// error
// error
// 2 errors: null !~> number; undefined !~> number
// 2 errors: null !~> number; undefined !~> number
// error
// error
// error
// error
1 < 2;
1 < \"foo\";
// error
\"foo\" < 1;
// error
\"foo\" < \"bar\";
1 < { foo: 1 };
// error
({ foo: 1 }) < 1;
// error
({ foo: 1 }) < { foo: 1 };
// error
\"foo\" < { foo: 1 };
// error
({ foo: 1 }) < \"foo\";
// error
var x = (null: ?number);
1 < x;
// 2 errors: null !~> number; undefined !~> number
x < 1;
// 2 errors: null !~> number; undefined !~> number
null < null;
// error
undefined < null;
// error
null < undefined;
// error
undefined < undefined;
// error
NaN < 1;
1 < NaN;
NaN < NaN;
let tests = [
function(x: any, y: number, z: string) {
x > y;
x > z;
}
];
"
];"
`;

View File

@ -10,13 +10,14 @@ function filterOutSmall (arr: Array<?number>): Array<?number> {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
function filterOutVoids<T>(arr: Array<?T>): Array<T> {
return arr.filter(Boolean);
}
function filterOutSmall(arr: Array<?number>): Array<?number> {
return arr.filter(num => num && num > 10);
}
"
}"
`;
exports[`test test2.js 1`] = `
@ -37,6 +38,7 @@ const filteredItems = filterItems([\'foo\', \'b\', 1, 2]);
console.log(filteredItems);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
function filterItems(items: Array<string | number>): Array<string | number> {
return items.map(item => {
if (typeof item === \"string\") {
@ -46,7 +48,8 @@ function filterItems(items: Array<string | number>): Array<string | number> {
}
}).filter(Boolean);
}
const filteredItems = filterItems([ \"foo\", \"b\", 1, 2 ]);
console.log(filteredItems);
"
console.log(filteredItems);"
`;

View File

@ -13,7 +13,7 @@ var B = [ ...A ];
var C = [ 1, 2, 3 ];
B.sort((a, b) => a - b);
C.sort((a, b) => a - b);
var x: Array<string> = [ \"1\", \"2\" ];
var y: Array<string> = [ \"3\", ...x ];
"
var y: Array<string> = [ \"3\", ...x ];"
`;

View File

@ -58,27 +58,24 @@ function from_test() {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// Error
/* Adapted from the following source:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
*/
/* Added later, because the above is insufficient */
// acc is element type of array when no init is provided
// error, string ~> number
// error, string ~> number
function foo(x: string) {}
var a = [ 0 ];
var b = a.map(function(x) {
foo(x);
return \"\" + x;
});
var c: number = a[0];
var d: number = b[0];
var e: Array<string> = a.reverse();
var f = [ \"\" ];
var g: number = f.map(function() {
return 0;
})[0];
var h: Array<number> = [ 1, 2, 3 ];
var i: Array<string> = [ \"a\", \"b\", \"c\" ];
var j: Array<number | string> = h.concat(i);
@ -86,25 +83,37 @@ var k: Array<number> = h.concat(h);
var l: Array<number> = h.concat(1, 2, 3);
var m: Array<number | string> = h.concat(\"a\", \"b\", \"c\");
var n: Array<number> = h.concat(\"a\", \"b\", \"c\");
// Error
function reduce_test() {
/* Adapted from the following source:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
*/
[ 0, 1, 2, 3, 4 ].reduce(function(previousValue, currentValue, index, array) {
return previousValue + currentValue + array[index];
});
[ 0, 1, 2, 3, 4 ].reduce(
function(previousValue, currentValue, index, array) {
return previousValue + currentValue + array[index];
},
10
);
var total = [ 0, 1, 2, 3 ].reduce(function(a, b) {
return a + b;
});
var flattened = [ [ 0, 1 ], [ 2, 3 ], [ 4, 5 ] ].reduce(function(a, b) {
return a.concat(b);
});
/* Added later, because the above is insufficient */
// acc is element type of array when no init is provided
[ \"\" ].reduce((acc, str) => acc * str.length);
[ \"\" ].reduceRight((acc, str) => acc * str.length);
// error, string ~> number
[ \"\" ].reduceRight((acc, str) => acc * str.length); // error, string ~> number
}
function from_test() {
var a: Array<string> = Array.from([ 1, 2, 3 ], function(val, index) {
return index % 2 ? \"foo\" : String(val);
@ -112,6 +121,5 @@ function from_test() {
var b: Array<string> = Array.from([ 1, 2, 3 ], function(val) {
return String(val);
});
}
"
}"
`;

View File

@ -40,17 +40,22 @@ var abig2: Array<{x:number; y:number}> = [
module.exports = \"arrays\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @providesModule Arrays */
// for literals, composite element type is union of individuals
// note: test both tuple and non-tuple inferred literals
function foo(x: string) {}
var a = [];
a[0] = 1;
a[1] = \"...\";
foo(a[1]);
var y;
a.forEach(x => y = x);
// for literals, composite element type is union of individuals
// note: test both tuple and non-tuple inferred literals
var alittle: Array<?number> = [ 0, 1, 2, 3, null ];
var abig: Array<?number> = [ 0, 1, 2, 3, 4, 5, 6, 8, null ];
var abig2: Array<{ x: number, y: number }> = [
{ x: 0, y: 0 },
{ x: 0, y: 0 },
@ -70,8 +75,8 @@ var abig2: Array<{ x: number, y: number }> = [
{ x: 0, y: 0, c: 1 },
{ x: 0, y: 0, c: \"hey\" }
];
module.exports = \"arrays\";
"
module.exports = \"arrays\";"
`;
exports[`test numeric_elem.js 1`] = `
@ -83,12 +88,11 @@ var day = new Date;
arr[day] = 0;
(arr[day]: string); // error: number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Date instances are numeric (see Flow_js.numeric) and thus can index into
// arrays.
// error: number ~> string
var arr = [];
var day = new Date();
// Date instances are numeric (see Flow_js.numeric) and thus can index into
// arrays.
arr[day] = 0;
(arr[day]: string);
"
(arr[day]: string); // error: number ~> string"
`;

View File

@ -14,14 +14,14 @@ var ident = <T>(x: T): T => x;
/**
* @flow
*/
// Error!
// Error
var add = (x: number, y: number): number => x + y;
var bad = (x: number): string => x;
// Error!
var ident = <T>(x: T): T => x;
(ident(1): number);
(ident(\"hi\"): number);
"
(ident(\"hi\"): number); // Error"
`;
exports[`test arrows.js 1`] = `
@ -36,15 +36,14 @@ exports[`test arrows.js 1`] = `
images[images.length - 1];
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//images = images.sort(function (a, b) { return a.width - b.width });
function selectBestEffortImageForWidth(
maxWidth: number,
images: Array<Image>
): Image {
var maxPixelWidth = maxWidth;
//images = images.sort(function (a, b) { return a.width - b.width });
images = images.sort((a, b) => a.width - b.width + \"\");
return images.find(image => image.width >= maxPixelWidth) ||
images[images.length - 1];
}
"
}"
`;

View File

@ -53,39 +53,43 @@ var obj = { f: async () => await 1 };
var objf : () => Promise<number> = obj.f;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// \"For async functions, a Promise<T> is returned,
// and the type of return expressions must be T.\"
//
// error, number != bool
// await: (p: Promise<T> | T) => T
//
// TODO: this is one of those bad generic errors, currently:
// \"inconsistent use of library definitions\" with two core.js locs
// error, number != bool
// async arrow functions
//
// async methods
//
// error, void != Promise<void>
// async function props
async function f0(): Promise<number> {
return 1;
}
async function f1(): Promise<boolean> {
return 1;
return 1; // error, number != bool
}
// await: (p: Promise<T> | T) => T
//
async function f2(p: Promise<number>): Promise<number> {
var x: number = await p;
var y: number = await 1;
return x + y;
}
async function f3(p: Promise<number>): Promise<number> {
return await p;
}
// TODO: this is one of those bad generic errors, currently:
// \"inconsistent use of library definitions\" with two core.js locs
async function f4(p: Promise<number>): Promise<boolean> {
return await p;
return await p; // error, number != bool
}
// async arrow functions
//
var f5: () => Promise<number> = async () => await 1;
// async methods
//
class C {
async m() {
return 1;
@ -96,13 +100,15 @@ class C {
static async m(a): void {
await a;
}
// error, void != Promise<void>
static async mt<T>(a: T): Promise<T> {
return a;
}
}
// async function props
var obj = { f: async () => await 1 };
var objf: () => Promise<number> = obj.f;
"
var objf: () => Promise<number> = obj.f;"
`;
exports[`test async_base_class.js 1`] = `
@ -126,14 +132,15 @@ async function foo() {
// am not clear on whether it should. In any case it\'s a strange corner case
// that is probably not important to support.
class C {}
var P: Promise<Class<C>> = new Promise(function(resolve, reject) {
resolve(C);
});
async function foo() {
class Bar extends (await P) {}
return Bar;
}
"
}"
`;
exports[`test async_parse.js 1`] = `
@ -164,23 +171,28 @@ var y = { async };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
async function f() {}
async function ft<T>(a: T) {}
class C {
async m() {}
async mt<T>(a: T) {}
static async m(a) {}
static async mt<T>(a: T) {}
}
var e = async function() {};
var et = async function<T>(a: T) {};
var n = new async function() {}();
var o = { async m() {} };
var ot = { async m<T>(a: T) {} };
var oz = { async async() {} };
var x = { async: 5 };
console.log(x.async);
var async = 3;
var y = { async };
"
var y = { async };"
`;
exports[`test async_promise.js 1`] = `
@ -190,8 +202,7 @@ exports[`test async_promise.js 1`] = `
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
async function f(): Promise<number> {
return Promise.resolve(1);
}
"
}"
`;
exports[`test async_return_void.js 1`] = `
@ -211,17 +222,19 @@ async function foo3(): Promise<string> {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
async function foo1(): Promise<string> {
return;
}
async function foo2(): Promise<string> {
return undefined;
}
async function foo3(): Promise<string> {
function bar() {}
return bar();
}
"
}"
`;
exports[`test async2.js 1`] = `
@ -287,59 +300,64 @@ function test5() {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// misc basic
// valid
// Error: number ~> string
function test1() {
async function foo() {
return 42;
}
async function bar() {
var a = await foo();
var b: number = a;
// valid
var c: string = a; // Error: number ~> string
}
}
//
// void returns:
//
// inference should produce return type Promise<void>
// in the absence of an explicit return
//
// ok
// error, void != Promise<void>
// annotated return type of Promise<void> should work
//
// ok
// other annotated return types should fail
// (note: misannotated return types with explicit
// return statements are covered in async.js)
//
// error, void != Promise<void>
// error, number != void
function test1() {
async function foo() {
return 42;
}
async function bar() {
var a = await foo();
var b: number = a;
var c: string = a;
}
}
function test2() {
async function voidoid1() {
console.log(\"HEY\");
}
var voidoid2: () => Promise<void> = voidoid1;
var voidoid3: () => void = voidoid1;
// ok
var voidoid3: () => void = voidoid1; // error, void != Promise<void>
}
// annotated return type of Promise<void> should work
//
function test3() {
async function voidoid4(): Promise<void> {
// ok
console.log(\"HEY\");
}
}
// other annotated return types should fail
// (note: misannotated return types with explicit
// return statements are covered in async.js)
//
function test4() {
async function voidoid5(): void {
// error, void != Promise<void>
console.log(\"HEY\");
}
}
function test5() {
async function voidoid6(): Promise<number> {
// error, number != void
console.log(\"HEY\");
}
}
"
}"
`;
exports[`test async3.js 1`] = `
@ -377,6 +395,7 @@ async function baz() {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
/**
* test nested-promise unwrapping.
* Note: currently we don\'t do this properly in the underlying
@ -384,24 +403,28 @@ async function baz() {
* be raised here. Once that\'s fixed, the errors here will go
* away.
*/
// a should now be typed as number, but is in fact
// Promise<number> until nested-promise unwrap is fixed
// TODO this is valid code, but currently gives Promise ~> number error
// due to lack of transitive Promise unwrap.
// should be number ~> string error, but currently gives
// Promise ~> string error for the same reason
async function foo() {
return 42;
}
async function bar() {
return foo();
}
async function baz() {
// a should now be typed as number, but is in fact
// Promise<number> until nested-promise unwrap is fixed
var a = await bar();
// TODO this is valid code, but currently gives Promise ~> number error
// due to lack of transitive Promise unwrap.
var b: number = a;
// should be number ~> string error, but currently gives
// Promise ~> string error for the same reason
var c: string = a;
}
"
}"
`;
exports[`test await_parse.js 1`] = `
@ -436,6 +459,7 @@ async function f() {
async function ft<T>(a: T) {
await 1;
}
class C {
async m() {
await 1;
@ -450,15 +474,18 @@ class C {
await 1;
}
}
var e = async function() {
await 1;
};
var et = async function<T>(a: T) {
await 1;
};
var n = new async function() {
await 1;
}();
var o = {
async m() {
await 1;
@ -474,9 +501,10 @@ var oz = {
await async;
}
};
var x = { await: 5 };
console.log(x.await);
var await = 3;
var y = { await };
"
var y = { await };"
`;

View File

@ -26,16 +26,14 @@ async function *delegate_return() {
var x: void = yield *inner(); // error: number ~> void
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: number ~> void
// error: number ~> void
// error: number ~> void
async function* delegate_next() {
async function* inner() {
var x: void = yield;
var x: void = yield; // error: number ~> void
}
yield* inner();
}
delegate_next().next(0);
async function* delegate_yield() {
async function* inner() {
yield 0;
@ -44,16 +42,16 @@ async function* delegate_yield() {
}
async () => {
for await (const x of delegate_yield()) {
(x: void);
(x: void); // error: number ~> void
}
};
async function* delegate_return() {
async function* inner() {
return 0;
}
var x: void = yield* inner();
}
"
var x: void = yield* inner(); // error: number ~> void
}"
`;
exports[`test generator.js 1`] = `
@ -83,11 +81,13 @@ async function f() {
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: string ~> void
interface File { readLine(): Promise<string>, close(): void, EOF: boolean }
declare function fileOpen(path: string): Promise<File>;
async function* readLines(path) {
let file: File = await fileOpen(path);
try {
while (!file.EOF) {
yield await file.readLine();
@ -96,12 +96,12 @@ async function* readLines(path) {
file.close();
}
}
async function f() {
for await (const line of readLines(\"/path/to/file\")) {
(line: void);
(line: void); // error: string ~> void
}
}
"
}"
`;
exports[`test return.js 1`] = `
@ -128,16 +128,16 @@ refuse_return().return(\"string\").then(result => {
}
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare var gen: AsyncGenerator<void, string, void>;
// You can pass whatever you like to return, it doesn\'t need to be related to
// the AsyncGenerator\'s return type
// error: string | number ~> void
gen.return(0).then(result => {
(result.value: void); // error: string | number ~> void
});
// However, a generator can \"refuse\" the return by catching an exception and
// yielding or returning internally.
// error: number | void ~> string
declare var gen: AsyncGenerator<void, string, void>;
gen.return(0).then(result => {
(result.value: void);
});
async function* refuse_return() {
try {
yield 1;
@ -147,10 +147,9 @@ async function* refuse_return() {
}
refuse_return().return(\"string\").then(result => {
if (result.done) {
(result.value: string);
(result.value: string); // error: number | void ~> string
}
});
"
});"
`;
exports[`test throw.js 1`] = `
@ -187,8 +186,6 @@ async function *yield_return() {
});
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: number ~> void
// error: number ~> void
async function* catch_return() {
try {
yield 0;
@ -196,13 +193,15 @@ async function* catch_return() {
return e;
}
}
async () => {
catch_return().throw(\"\").then(({ value }) => {
if (value !== undefined) {
(value: void);
(value: void); // error: number ~> void
}
});
};
async function* yield_return() {
try {
yield 0;
@ -211,12 +210,12 @@ async function* yield_return() {
yield e;
}
}
async () => {
yield_return().throw(\"\").then(({ value }) => {
if (value !== undefined) {
(value: void);
(value: void); // error: number ~> void
}
});
};
"
};"
`;

View File

@ -12,6 +12,7 @@ declare var objectAssign: Object$Assign
m
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
declare var idx: $Facebookism$Idx;
declare var merge: $Facebookism$Merge;
declare var mergeDeepInto: $Facebookism$MergeDeepInto;
@ -19,8 +20,8 @@ declare var mergeInto: $Facebookism$MergeInto;
declare var mixin: $Facebookism$Mixin;
declare var objectGetPrototypeOf: Object$GetPrototypeOf;
declare var objectAssign: Object$Assign;
m;
"
m;"
`;
exports[`test unknown.js 1`] = `
@ -28,6 +29,5 @@ exports[`test unknown.js 1`] = `
module.exports = { x: { y: \"\" } };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @noflow
module.exports = { x: { y: \"\" } };
"
module.exports = { x: { y: \"\" } };"
`;

View File

@ -1,6 +1,5 @@
exports[`test client.js 1`] = `
"var y:number = x;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var y: number = x;
"
var y: number = x;"
`;

View File

@ -1,6 +1,5 @@
exports[`test lib.js 1`] = `
"declare var x: string;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare var x: string;
"
declare var x: string;"
`;

View File

@ -55,64 +55,61 @@ let tests = [
]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// objects on RHS
// arrays on RHS
// primitive classes on RHS
// primitives on RHS
// error
// error
// error
// error
// bogus stuff on LHS
// error
// error
// error
// error
// error
// in predicates
// error
// error, !\'foo\' is a boolean
// annotations on RHS
// ok
// error
let tests = [
// objects on RHS
function() {
\"foo\" in {};
\"foo\" in { foo: null };
0 in {};
0 in { \"0\": null };
},
// arrays on RHS
function() {
\"foo\" in [];
0 in [];
\"length\" in [];
},
// primitive classes on RHS
function() {
\"foo\" in new String(\"bar\");
\"foo\" in new Number(123);
},
// primitives on RHS
function() {
\"foo\" in 123;
// error
\"foo\" in \"bar\";
// error
\"foo\" in void 0;
\"foo\" in null;
// error
\"foo\" in null; // error
},
// bogus stuff on LHS
function() {
null in {};
// error
void 0 in {};
// error
({}) in {};
// error
[] in {};
false in [];
// error
false in []; // error
},
// in predicates
function() {
if (\"foo\" in 123) {}
// error
if (!\"foo\" in {}) {}
// error, !\'foo\' is a boolean
if (!(\"foo\" in {})) {}
},
// annotations on RHS
function(x: Object, y: mixed) {
\"foo\" in x;
\"foo\" in y;
// ok
\"foo\" in y; // error
}
];
"
];"
`;

View File

@ -27,12 +27,9 @@ for (const { baz } of bazzes) {
(baz: number); // error: string ~> number
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// errors: const cannot be reassigned
// regression tests -- OK to assign consts like this:
// error: string ~> number
// error: string ~> number
// error: string ~> number
const x = 0;
// errors: const cannot be reassigned
x++;
x--;
x += 0;
@ -45,15 +42,18 @@ x >>>= 0;
x |= 0;
x ^= 0;
x &= 0;
// regression tests -- OK to assign consts like this:
const { foo } = { foo: \"foo\" };
const [ bar ] = [ \"bar\" ];
(foo: number);
// error: string ~> number
(bar: number);
// error: string ~> number
declare var bazzes: { baz: string }[];
for (const { baz } of bazzes) {
(baz: number);
}
"
(baz: number); // error: string ~> number
}"
`;
exports[`test rebinding.js 1`] = `
@ -265,188 +265,189 @@ function fn_params_clash_fn_binding(x,y) {
* const x x x x x x
* var x x x x
*/
// type x *
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// error: type alias ref\'d from value pos
// class x *
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// let x *
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// const x *
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// error: cannot be reassigned
// var x *
// error: name already bound
// error: name already bound
// error: name already bound
// error: name already bound
// OK
// function x *
// OK
// error: name already bound
// corner cases
// error: name already bound
// error: name already bound
// fn params name clash
/* error: x already bound */
// error: x already bound
// OK
function type_type() {
type A = number;
type A = number;
type A = number; // error: name already bound
}
function type_class() {
type A = number;
class A {}
class A {} // error: name already bound
}
function type_let() {
type A = number;
let A = 0;
let A = 0; // error: name already bound
}
function type_const() {
type A = number;
const A = 0;
const A = 0; // error: name already bound
}
function type_var() {
type A = number;
var A = 0;
var A = 0; // error: name already bound
}
function type_reassign() {
type A = number;
A = 42;
A = 42; // error: type alias ref\'d from value pos
}
// class x *
function class_type() {
class A {}
type A = number;
type A = number; // error: name already bound
}
function class_class() {
class A {}
class A {}
class A {} // error: name already bound
}
function class_let() {
class A {}
let A = 0;
let A = 0; // error: name already bound
}
function class_const() {
class A {}
const A = 0;
const A = 0; // error: name already bound
}
function class_var() {
class A {}
var A = 0;
var A = 0; // error: name already bound
}
// let x *
function let_type() {
let A = 0;
type A = number;
type A = number; // error: name already bound
}
function let_class() {
let A = 0;
class A {}
class A {} // error: name already bound
}
function let_let() {
let A = 0;
let A = 0;
let A = 0; // error: name already bound
}
function let_const() {
let A = 0;
const A = 0;
const A = 0; // error: name already bound
}
function let_var() {
let A = 0;
var A = 0;
var A = 0; // error: name already bound
}
// const x *
function const_type() {
const A = 0;
type A = number;
type A = number; // error: name already bound
}
function const_class() {
const A = 0;
class A {}
class A {} // error: name already bound
}
function const_let() {
const A = 0;
let A = 0;
let A = 0; // error: name already bound
}
function const_const() {
const A = 0;
const A = 0;
const A = 0; // error: name already bound
}
function const_var() {
const A = 0;
var A = 0;
var A = 0; // error: name already bound
}
function const_reassign() {
const A = 0;
A = 42;
A = 42; // error: cannot be reassigned
}
// var x *
function var_type() {
var A = 0;
type A = number;
type A = number; // error: name already bound
}
function var_class() {
var A = 0;
class A {}
class A {} // error: name already bound
}
function var_let() {
var A = 0;
let A = 0;
let A = 0; // error: name already bound
}
function var_const() {
var A = 0;
const A = 0;
const A = 0; // error: name already bound
}
function var_var() {
var A = 0;
var A = 0;
var A = 0; // OK
}
// function x *
function function_toplevel() {
function a() {}
function a() {}
}
function function_block() {
{
function a() {}
function a() {}
}
}
// corner cases
function var_shadow_nested_scope() {
{
let x = 0;
{
var x = 0;
var x = 0; // error: name already bound
}
}
}
function type_shadow_nested_scope() {
{
let x = 0;
{
type x = string;
type x = string; // error: name already bound
}
}
}
function fn_params_name_clash(x, x) {}
// fn params name clash
function fn_params_name_clash(x, x /* error: x already bound */) {}
function fn_params_clash_fn_binding(x, y) {
let x = 0;
var y = 0;
}
"
// error: x already bound
var y = 0; // OK
}"
`;
exports[`test scope.js 1`] = `
@ -560,125 +561,124 @@ function default_param_2() {
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ok: local to block
// error: string ~> number
// ok: local to switch
// error: string ~> number
// error: a already bound in switch
// a switch is a single lexical scope, so lets and non-disjoint
// cases can mix in odd ways. our support for edge cases is not
// yet perfect.
// error: assign before declaration
// error: use before declaration
// error: skipped initializer
// error: skipped initializer
// error: a no longer in scope
// ok
// ok
// ok
/* ok: local to init */
/* error: string ~> number */
/* ok: local to init */
/* error: string ~> number */
/* ok: local to init */
/* error: string ~> number */
// function binding in scope in default expr
// error: number ~> string
// fn body bindings not visible from param scope
// error: string ~> number
/* error: cannot resolve b */
function block_scope() {
let a: number = 0;
var b: number = 0;
{
let a = \"\";
var b = \"\";
// ok: local to block
var b = \"\"; // error: string ~> number
}
}
function switch_scope(x: string) {
let a: number = 0;
var b: number = 0;
switch (x) {
case \"foo\":
let a = \"\";
// ok: local to switch
var b = \"\";
// error: string ~> number
break;
case \"bar\":
let a = \"\";
// error: a already bound in switch
break;
}
}
// a switch is a single lexical scope, so lets and non-disjoint
// cases can mix in odd ways. our support for edge cases is not
// yet perfect.
function switch_scope2(x: number) {
switch (x) {
case 0:
a = \"\";
// error: assign before declaration
break;
case 1:
var b = a;
// error: use before declaration
break;
case 2:
let a = \"\";
break;
case 3:
a = \"\";
// error: skipped initializer
break;
case 4:
var c: string = a;
// error: skipped initializer
break;
}
a = \"\";
a = \"\"; // error: a no longer in scope
}
function try_scope() {
let a: number = 0;
try {
let a = \"\";
let a = \"\"; // ok
} catch (e) {
let a = \"\";
let a = \"\"; // ok
} finally {
let a = \"\";
let a = \"\"; // ok
}
}
function for_scope_let() {
let a: number = 0;
for (let a = \"\"; ; ) {}
for (let a = \"\" /* ok: local to init */; ; ) {}
}
function for_scope_var() {
var a: number = 0;
for (var a = \"\"; ; ) {}
for (var a = \"\" /* error: string ~> number */; ; ) {}
}
function for_in_scope_let(o: Object) {
let a: number = 0;
for (let a in o) {}
for (let a /* ok: local to init */ in o) {}
}
function for_in_scope_var(o: Object) {
var a: number = 0;
for (var a in o) {}
for (var a /* error: string ~> number */ in o) {}
}
function for_of_scope_let(xs: string[]) {
let a: number = 0;
for (let a of xs) {}
for (let a /* ok: local to init */ of xs) {}
}
function for_of_scope_var(xs: string[]) {
var a: number = 0;
for (var a of xs) {}
for (var a /* error: string ~> number */ of xs) {}
}
function default_param_1() {
function f(x: () => string = f): number {
// function binding in scope in default expr
function f(
// error: number ~> string
x: () => string = f
): number {
return 0;
}
}
function default_param_2() {
// fn body bindings not visible from param scope
let a = \"\";
function f0(x = () => a): number {
let a = 0;
return x();
return x(); // error: string ~> number
}
function f1(x = b): number {
function f1(x = b /* error: cannot resolve b */): number {
let b = 0;
return x;
}
}
"
}"
`;
exports[`test tdz.js 1`] = `
@ -784,9 +784,15 @@ a = 10;
f(a); // ok, a: number (not ?number)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** @flow */
// -- types ---
// type aliases are hoisted and always available
type T1 = T2;
// ok
type T2 = number;
// --- lets ---
// to be correct, we would
// - not allow forward refs to lets from value positions,
@ -799,92 +805,96 @@ f(a); // ok, a: number (not ?number)
// a lambda runs. But a simple conservative approach would prohibit
// forward references to let/consts from within lambdas entirely,
// which would be annoying. TODO
// errors, let + const referenced before decl
// error, attempt to write to let before decl
// error, attempt to write to let before decl
// errors, let + const referenced before decl
// functions are let-scoped and hoisted
// ok, finds hoisted outer
// ok, finds hoisted inner
// ok, hoisted outer not clobbered
// out-of-scope TDZ not enforced. sometimes right...
// ok, g doesn\'t run in TDZ
// ...sometimes wrong
// should error, but doesn\'t currently
// - from type positions, we currently error on forward refs to any
// value (i.e., class or function). this is a basic flaw in our
// phasing of AST traversal, and will be fixed.
//
// ok
// error: let ref before decl from value position
// ok
// --- vars ---
// it\'s possible to annotate a var with a non-maybe type,
// but leave it uninitialized until later (as long as it\'s
// initialized before use)
// not an error per se - only if used before init
// error: undefined ~/> number
// ok, a: number (not ?number)
type T1 = T2;
type T2 = number;
function f0() {
var v = x * c;
// errors, let + const referenced before decl
let x = 0;
const c = 0;
}
function f1(b) {
x = 10;
// error, attempt to write to let before decl
let x = 0;
if (b) {
y = 10;
// error, attempt to write to let before decl
let y = 0;
}
}
function f2() {
{
var v = x * c;
var v = x * c; // errors, let + const referenced before decl
}
let x = 0;
const c = 0;
}
// functions are let-scoped and hoisted
function f3() {
var s: string = foo();
// ok, finds hoisted outer
{
var n: number = foo();
// ok, finds hoisted inner
function foo() {
return 0;
}
}
var s2: string = foo();
// ok, hoisted outer not clobbered
function foo() {
return \"\";
}
}
// out-of-scope TDZ not enforced. sometimes right...
function f4() {
function g() {
return x + c;
}
// ok, g doesn\'t run in TDZ
let x = 0;
const c = 0;
}
// ...sometimes wrong
function f5() {
function g() {
return x;
}
g();
// should error, but doesn\'t currently
let x = 0;
const c = 0;
}
// - from type positions, we currently error on forward refs to any
// value (i.e., class or function). this is a basic flaw in our
// phasing of AST traversal, and will be fixed.
//
var x: C;
// ok
var y = new C();
// error: let ref before decl from value position
class C {}
var z: C = new C();
// ok
// --- vars ---
// it\'s possible to annotate a var with a non-maybe type,
// but leave it uninitialized until later (as long as it\'s
// initialized before use)
var a: number;
// not an error per se - only if used before init
function f(n: number) {
return n;
}
f(a);
// error: undefined ~/> number
a = 10;
f(a);
"
f(a); // ok, a: number (not ?number)"
`;

View File

@ -68,109 +68,108 @@ for (let [x, y]: [string, number] of a.entries()) {} // incorrect
for (let [x, y]: [number, number] of a.entries()) {} // incorrect
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// constructor
const a: FormData = new FormData();
// correct
new FormData(\"\");
// incorrect
new FormData(document.createElement(\"input\"));
// incorrect
new FormData(document.createElement(\"form\"));
// correct
// has
const b: boolean = a.has(\"foo\");
// correct
// get
const c: ?(string | File) = a.get(\"foo\");
// correct
const d: string = a.get(\"foo\");
// incorrect
const e: Blob = a.get(\"foo\");
// incorrect
const f: ?(string | File | Blob) = a.get(\"foo\");
// incorrect
a.get(2);
// incorrect
// getAll
const a1: Array<string | File> = a.getAll(\"foo\");
// correct
const a2: Array<string | File | number> = a.getAll(\"foo\");
// incorrect
const a3: Array<string | Blob | File> = a.getAll(\"foo\");
// incorrect
a.getAll(23);
// incorrect
// set
a.set(\"foo\", \"bar\");
// correct
a.set(\"foo\", {});
// incorrect
a.set(2, \"bar\");
// incorrect
a.set(\"foo\", \"bar\", \"baz\");
// incorrect
a.set(\"bar\", new File([], \"q\"));
// correct
a.set(\"bar\", new File([], \"q\"), \"x\");
// correct
a.set(\"bar\", new File([], \"q\"), 2);
// incorrect
a.set(\"bar\", new Blob());
// correct
a.set(\"bar\", new Blob(), \"x\");
// correct
a.set(\"bar\", new Blob(), 2);
// incorrect
// append
a.append(\"foo\", \"bar\");
// correct
a.append(\"foo\", {});
// incorrect
a.append(2, \"bar\");
// incorrect
a.append(\"foo\", \"bar\", \"baz\");
// incorrect
a.append(\"foo\", \"bar\");
// incorrect
a.append(\"bar\", new File([], \"q\"));
// correct
a.append(\"bar\", new File([], \"q\"), \"x\");
// correct
a.append(\"bar\", new File([], \"q\"), 2);
// incorrect
a.append(\"bar\", new Blob());
// correct
a.append(\"bar\", new Blob(), \"x\");
// correct
a.append(\"bar\", new Blob(), 2);
// incorrect
// delete
a.delete(\"xx\");
// correct
a.delete(3);
// incorrect
// keys
for (let x: string of a.keys()) {}
// correct
for (let x: number of a.keys()) {}
// incorrect
// values
for (let x: string | File of a.values()) {}
// correct
for (let x: string | File | Blob of a.values()) {}
// incorrect
// entries
// correct
// incorrect
// incorrect
// incorrect
// incorrect
const a: FormData = new FormData();
new FormData(\"\");
new FormData(document.createElement(\"input\"));
new FormData(document.createElement(\"form\"));
const b: boolean = a.has(\"foo\");
const c: ?(string | File) = a.get(\"foo\");
const d: string = a.get(\"foo\");
const e: Blob = a.get(\"foo\");
const f: ?(string | File | Blob) = a.get(\"foo\");
a.get(2);
const a1: Array<string | File> = a.getAll(\"foo\");
const a2: Array<string | File | number> = a.getAll(\"foo\");
const a3: Array<string | Blob | File> = a.getAll(\"foo\");
a.getAll(23);
a.set(\"foo\", \"bar\");
a.set(\"foo\", {});
a.set(2, \"bar\");
a.set(\"foo\", \"bar\", \"baz\");
a.set(\"bar\", new File([], \"q\"));
a.set(\"bar\", new File([], \"q\"), \"x\");
a.set(\"bar\", new File([], \"q\"), 2);
a.set(\"bar\", new Blob());
a.set(\"bar\", new Blob(), \"x\");
a.set(\"bar\", new Blob(), 2);
a.append(\"foo\", \"bar\");
a.append(\"foo\", {});
a.append(2, \"bar\");
a.append(\"foo\", \"bar\", \"baz\");
a.append(\"foo\", \"bar\");
a.append(\"bar\", new File([], \"q\"));
a.append(\"bar\", new File([], \"q\"), \"x\");
a.append(\"bar\", new File([], \"q\"), 2);
a.append(\"bar\", new Blob());
a.append(\"bar\", new Blob(), \"x\");
a.append(\"bar\", new Blob(), 2);
a.delete(\"xx\");
a.delete(3);
for (let x: string of a.keys()) {}
for (let x: number of a.keys()) {}
for (let x: string | File of a.values()) {}
for (let x: string | File | Blob of a.values()) {}
for (let [ x, y ]: [string, string | File] of a.entries()) {}
// correct
for (let [ x, y ]: [string, string | File | Blob] of a.entries()) {}
// incorrect
for (let [ x, y ]: [number, string] of a.entries()) {}
// incorrect
for (let [ x, y ]: [string, number] of a.entries()) {}
for (let [ x, y ]: [number, number] of a.entries()) {}
"
// incorrect
for (let [ x, y ]: [number, number] of a.entries()) {} // incorrect"
`;
exports[`test MutationObserver.js 1`] = `
@ -205,26 +204,8 @@ o.takeRecords(); // correct
o.disconnect(); // correct
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// constructor
// correct
// correct
// correct
// incorrect
// incorrect
// incorrect
// observe
// correct
// correct
// incorrect
// incorrect
// incorrect
// incorrect
// incorrect
// incorrect
// takeRecords
// correct
// disconnect
// correct
function callback(
arr: Array<MutationRecord>,
observer: MutationObserver
@ -232,21 +213,38 @@ function callback(
return;
}
const o: MutationObserver = new MutationObserver(callback);
// correct
new MutationObserver((arr: Array<MutationRecord>) => true);
// correct
new MutationObserver(() => {});
// correct
new MutationObserver();
// incorrect
new MutationObserver(42);
// incorrect
new MutationObserver((n: number) => {});
// incorrect
// observe
const div = document.createElement(\"div\");
o.observe(div, { attributes: true, attributeFilter: [ \"style\" ] });
// correct
o.observe(div, { characterData: true, invalid: true });
// correct
o.observe();
// incorrect
o.observe(\"invalid\");
// incorrect
o.observe(div);
// incorrect
o.observe(div, {});
// incorrect
o.observe(div, { subtree: true });
// incorrect
o.observe(div, { attributes: true, attributeFilter: true });
// incorrect
// takeRecords
o.takeRecords();
o.disconnect();
"
// correct
// disconnect
o.disconnect(); // correct"
`;

View File

@ -6,10 +6,10 @@ function bar<X:number, Y:X>(x:X, y:Y): number { return y*0; }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function foo<X, Y: X>(x: X, y: Y): void {}
foo(0, \"\");
function bar<X: number, Y: X>(x: X, y: Y): number {
return y * 0;
}
"
}"
`;
exports[`test test.js 1`] = `
@ -39,38 +39,37 @@ var q: number = c.qux(0);
/* 2 more errors, since argument U = number is incompatible with T = string, and
* result T = string is incompatible with number */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OK
// error
// OK
// error, since T: number and U: number does not imply U: T
// OK, since T: number and U: T implies U: number
// error
// OK, since U: T
// error, since T = string is incompatible with number
/* 2 more errors, since argument U = number is incompatible with T = string, and
* result T = string is incompatible with number */
function foo<T: number>(x: T): T {
var _ = x * 1;
// OK
var y: string = x;
return x;
// error
return x; // OK
}
class C<T: number> {
bar<U: number>(x: U): T {
return x;
return x; // error, since T: number and U: number does not imply U: T
}
qux<U: T>(x: U): T {
var _ = x * 1;
// OK, since T: number and U: T implies U: number
var y: string = x;
return x;
// error
return x; // OK, since U: T
}
}
function example<T: { x: number }>(o: T): T {
o.x = 0;
return o;
}
var obj1: { x: number, y: string } = example({ x: 0, y: \"\" });
var obj2: { x: number } = example({ x: 0 });
var c: C<string> = new C();
// error, since T = string is incompatible with number
var q: number = c.qux(0);
"
/* 2 more errors, since argument U = number is incompatible with T = string, and
* result T = string is incompatible with number */"
`;

View File

@ -68,19 +68,6 @@ function test_const() {
return st;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: boolean !~> number
// 2 errors: ?string !~> number
// error: boolean !~> number
// 2 errors: (boolean | string) !~> number
// 2 errors: (boolean | string) !~> number
// error: boolean !~> number
// 2 errors: (boolean | string) !~> number
// 2 errors: (boolean | string) !~> number
// error: string !~> number
// error: string !~> number
// same basic test as foo(), but with const. probes the
// logic that still uses havoc to do env resets.
// no error
function foo(b) {
var x = b ? null : false;
var z;
@ -89,10 +76,11 @@ function foo(b) {
z = \"\";
break;
}
var y: number = x;
var y: number = x; // error: boolean !~> number
}
var w: number = z;
var w: number = z; // 2 errors: ?string !~> number
}
function bar(b) {
var x = b ? null : false;
if (x == null)
@ -100,14 +88,17 @@ function bar(b) {
switch (\"\") {
case 0:
var y: number = x;
// error: boolean !~> number
x = \"\";
case 1:
var z: number = x;
// 2 errors: (boolean | string) !~> number
break;
case 2:
}
var w: number = x;
var w: number = x; // 2 errors: (boolean | string) !~> number
}
function bar2(b) {
var x = b ? null : false;
if (x == null)
@ -115,16 +106,19 @@ function bar2(b) {
switch (\"\") {
case 0: {
let y: number = x;
// error: boolean !~> number
x = \"\";
}
case 1: {
let z: number = x;
// 2 errors: (boolean | string) !~> number
break;
}
case 2:
}
var w: number = x;
var w: number = x; // 2 errors: (boolean | string) !~> number
}
function qux(b) {
var z = 0;
while (b) {
@ -133,20 +127,26 @@ function qux(b) {
z = \"\";
continue;
}
// error: string !~> number
z = 0;
}
var w: number = z;
var w: number = z; // error: string !~> number
}
// same basic test as foo(), but with const. probes the
// logic that still uses havoc to do env resets.
function test_const() {
let st: string = \"abc\";
for (let i = 1; i < 100; i++) {
const fooRes: ?string = \"HEY\";
if (!fooRes) {
break;
}
st = fooRes;
st = fooRes; // no error
}
return st;
}
"
}"
`;

View File

@ -5,8 +5,7 @@ module.exports = o;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var o = Object.freeze({ foo: 0 });
(o.foo: string);
module.exports = o;
"
module.exports = o;"
`;
exports[`test test2.js 1`] = `
@ -14,6 +13,5 @@ exports[`test test2.js 1`] = `
(o.foo: string);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var o = require(\"./test\");
(o.foo: string);
"
(o.foo: string);"
`;

View File

@ -17,21 +17,20 @@ function g() {
foo = foo1;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: number !~> string
// error: string !~> number
// error: string !~> number
var a = [ \"...\" ];
var b = a.map(function(x) {
return 0;
});
var c: string = b[0];
// error: number !~> string
var array = [];
function f() {
array = array.map(function() {
return \"...\";
});
var x: number = array[0];
var x: number = array[0]; // error: string !~> number
}
var Foo = require(\"./genericfoo\");
var foo = new Foo();
function g() {
@ -39,9 +38,9 @@ function g() {
return \"...\";
});
var x: number = foo1.get();
// error: string !~> number
foo = foo1;
}
"
}"
`;
exports[`test genericfoo.js 1`] = `
@ -68,6 +67,6 @@ class Foo<T> {
return this.x;
}
}
module.exports = Foo;
"
module.exports = Foo;"
`;

View File

@ -31,31 +31,35 @@ function f(): number {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// You should be able to call objects with call properties
// ...and get an error if the return type is wrong
// ...or if the param type is wrong
// ...or if the arity is wrong
// ...or if there is no call property
// Make sure we complain even if the object literal is unsealed.
function a(f: { (): string }, g: { (x: number): string }): string {
return f() + g(123);
}
// ...and get an error if the return type is wrong
function b(f: { (): string }): number {
return f();
}
// ...or if the param type is wrong
function c(f: { (x: number): number }): number {
return f(\"hello\");
}
// ...or if the arity is wrong
function d(f: { (x: number): number }): number {
return f();
}
// ...or if there is no call property
function e(f: {}): number {
return f();
}
// Make sure we complain even if the object literal is unsealed.
function f(): number {
var x = {};
return x();
}
"
}"
`;
exports[`test B.js 1`] = `
@ -81,38 +85,41 @@ var y : {} = function (x: number): string { return \"hi\"; };
var z : Object = function (x: number): string { return \"hi\"; };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// You should be able to use a function as an object with a call property
// ...and it should notice when the return type is wrong
// ...or if the param type is wrong
// ...or if the arity is wrong
// ...but subtyping rules still apply
// arity
// return type
// param type
// A function can be an object
var a: { (x: number): string } = function(x: number): string {
return \"hi\";
};
// ...and it should notice when the return type is wrong
var b: { (x: number): number } = function(x: number): string {
return \"hi\";
};
// ...or if the param type is wrong
var c: { (x: string): string } = function(x: number): string {
return \"hi\";
};
// ...or if the arity is wrong
var d: { (): string } = function(x: number): string {
return \"hi\";
};
// ...but subtyping rules still apply
var e: { (x: any): void } = function() {};
// arity
var f: { (): mixed } = function(): string {
return \"hi\";
};
// return type
var g: { (x: string): void } = function(x: mixed) {};
// param type
// A function can be an object
var y: {} = function(x: number): string {
return \"hi\";
};
var z: Object = function(x: number): string {
return \"hi\";
};
"
};"
`;
exports[`test C.js 1`] = `
@ -152,35 +159,39 @@ function g(x: {}): Function {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// You should be able to use an object as a function
// ...and it should notice when the return type is wrong
// ...or if the param type is wrong
// ...or if the arity is wrong
// ...or if it doesn\'t have a call property
// AnyFunT should also be allowed
// ... but only if the object is callable
// error
function a(x: { (z: number): string }): (z: number) => string {
return x;
}
// ...and it should notice when the return type is wrong
function b(x: { (z: number): string }): (z: number) => number {
return x;
}
// ...or if the param type is wrong
function c(x: { (z: number): string }): (z: string) => string {
return x;
}
// ...or if the arity is wrong
function d(x: { (z: number): string }): () => string {
return x;
}
// ...or if it doesn\'t have a call property
function e(x: {}): () => string {
return x;
}
// AnyFunT should also be allowed
function f(x: { (z: number): string }): Function {
return x;
}
// ... but only if the object is callable
function g(x: {}): Function {
return x;
}
"
return x; // error
}"
`;
exports[`test D.js 1`] = `
@ -208,26 +219,29 @@ function e(x: { (): string; (x: number): string }): () => number {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Multiple call properties should also be supported
// It should be fine when a function satisfies them all
// ...but should notice when a function doesn\'t satisfy them all
// Only one call property needs to match the function
// ...but you need at least one
function a(f: { (): string, (x: number): string }): string {
return f() + f(123);
}
// It should be fine when a function satisfies them all
var b: { (): string, (x: number): string } = function(x?: number): string {
return \"hi\";
};
// ...but should notice when a function doesn\'t satisfy them all
var c: { (): string, (x: number): string } = function(x: number): string {
return \"hi\";
};
// Only one call property needs to match the function
function d(x: { (): string, (x: number): string }): () => string {
return x;
}
// ...but you need at least one
function e(x: { (): string, (x: number): string }): () => number {
return x;
}
"
}"
`;
exports[`test E.js 1`] = `
@ -243,14 +257,15 @@ f.myProp = 123;
var c : { myProp: number } = f;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Expecting properties that don\'t exist should be an error
// Expecting properties that do exist should be fine
// Expecting properties in the functions statics should be fine
var a: { someProp: number } = function() {};
// Expecting properties that do exist should be fine
var b: { apply: Function } = function() {};
// Expecting properties in the functions statics should be fine
var f = function() {};
f.myProp = 123;
var c: { myProp: number } = f;
"
var c: { myProp: number } = f;"
`;
exports[`test F.js 1`] = `
@ -277,24 +292,28 @@ var y : {} = (x) => \"hi\"
var z : Object = (x) => \"hi\"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// You should be able to use an arrow function as an object with a call property
// ...and it should notice when the return type is wrong
// ...or if the param type is wrong
// ...or if the arity is wrong
// ...but subtyping rules still apply
// arity
// return type
// param type (date < number)
// A function can be an object
var a: { (x: number): string } = x => x.toString();
// ...and it should notice when the return type is wrong
var b: { (x: number): number } = x => \"hi\";
// ...or if the param type is wrong
var c: { (x: string): string } = x => x.toFixed();
// ...or if the arity is wrong
var d: { (): string } = x => \"hi\";
// ...but subtyping rules still apply
var e: { (x: any): void } = () => {};
// arity
var f: { (): mixed } = () => \"hi\";
// return type
var g: { (x: Date): void } = x => {
x * 2;
};
// param type (date < number)
// A function can be an object
var y: {} = x => \"hi\";
var z: Object = x => \"hi\";
"
var z: Object = x => \"hi\";"
`;

View File

@ -11,11 +11,12 @@ function f(x) {
(f: F);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type F = { (x: string): number, p?: string };
function f(x) {
return x.length;
}
(f: F);
"
(f: F);"
`;
exports[`test primitives.js 1`] = `
@ -41,23 +42,23 @@ declare var callable: Callable;
callable(0); // error, number ~> string
callable.call(null, 0); // error, number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, callable signature not found
// error, number ~> string
// error, number ~> string
// error, number ~> string
// error, number ~> string
var x = Boolean(4);
function foo(fn: (value: any) => boolean) {}
foo(Boolean);
var dict: { [k: string]: any } = {};
dict();
// error, callable signature not found
interface ICall { (x: string): void }
declare var icall: ICall;
icall(0);
// error, number ~> string
icall.call(null, 0);
// error, number ~> string
type Callable = { (x: string): void };
declare var callable: Callable;
callable(0);
callable.call(null, 0);
"
// error, number ~> string
callable.call(null, 0); // error, number ~> string"
`;

View File

@ -1,6 +1,5 @@
exports[`test not_flow.js 1`] = `
"1 * \'foo\';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 * \"foo\";
"
1 * \"foo\";"
`;

View File

@ -18,18 +18,18 @@ class Bar extends Foo {
/**
* @flow
*/
// error
class Foo {
_method(): string {
return \"this is private\";
}
}
class Bar extends Foo {
test() {
(this._method(): string);
(this._method(): string); // error
}
}
"
}"
`;
exports[`test without_munging.js 1`] = `
@ -54,16 +54,16 @@ class Bar extends Foo {
* @flow
* @preventMunge
*/
// ok
class Foo {
_method(): string {
return \"this is not private\";
}
}
class Bar extends Foo {
test() {
(this._method(): string);
(this._method(): string); // ok
}
}
"
}"
`;

View File

@ -61,19 +61,6 @@ module.exports = {
A: A, B: B, C: C, D: D, E: E
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error?
// error?
// error?
// error
// error
// error
// error
// error
// error B ~> number
// error?
// error
// error
// note: above classdefs are sufficiently annotated to export
class A {
static x: number;
static y: string;
@ -81,25 +68,34 @@ class A {
static bar(y: string) {}
}
A.qux = function(x: string) {};
// error?
class B extends A {
static x: string;
// error?
static foo(x: string) {}
// error?
static main() {
B.x = 0;
// error
B.x = \"\";
B.foo(0);
// error
B.foo(\"\");
B.y = 0;
// error
B.bar(0);
B.qux(0);
// error
B.qux(0); // error
}
static create(): A {
return new this();
}
static badCreate(): number {
return new this();
return new this(); // error B ~> number
}
}
class C<X> {
static x: X;
static bar(x: X) {}
@ -107,22 +103,28 @@ class C<X> {
return new this();
}
}
class D extends C<string> {
static main() {
D.foo(0);
// error?
D.bar(0);
}
}
var d: C<*> = D.create();
(new A(): typeof A);
(B: typeof A);
class E {
static x: number;
static foo(): string {
this.bar();
return this.x;
// error
return this.x; // error
}
}
module.exports = { A: A, B: B, C: C, D: D, E: E };
"
// note: above classdefs are sufficiently annotated to export
module.exports = { A: A, B: B, C: C, D: D, E: E };"
`;

View File

@ -8,8 +8,8 @@ module.exports = { A, B };
/* @flow */
class A {}
class B {}
module.exports = { A, B };
"
module.exports = { A, B };"
`;
exports[`test test2.js 1`] = `
@ -23,10 +23,11 @@ var y: I.B = new C();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
var I = require(\"./test.js\");
class C extends I.A {}
var x: I.A = new C();
var y: I.B = new C();
"
var y: I.B = new C();"
`;
exports[`test test3.js 1`] = `
@ -37,14 +38,13 @@ class C<X, Y, Z> extends B {}
var c: C<number, string, Array<bool>> = new C; // none of the type args matter
var a: A<string, number, Array<bool>> = c; // the third type arg is incorrect
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// none of the type args matter
// the third type arg is incorrect
class A<X, Y, Z> {}
class B extends A<string, number, boolean> {}
class C<X, Y, Z> extends B {}
var c: C<number, string, Array<boolean>> = new C();
var a: A<string, number, Array<boolean>> = c;
"
// none of the type args matter
var a: A<string, number, Array<boolean>> = c; // the third type arg is incorrect"
`;
exports[`test test4.js 1`] = `
@ -65,14 +65,18 @@ foo(new D, { f_: 0 });
class C<X> {
x: X;
}
function foo<X>(c: C<X>, x: X) {}
type O = { f: number };
foo((new C(): C<O>), { f_: 0 });
class D extends C<O> {
bar() {
this.x;
}
}
foo(new D(), { f_: 0 });
"
foo(new D(), { f_: 0 });"
`;

View File

@ -11,19 +11,17 @@ function bar(x: Class<B>): B {
return new x(); // error (too few args)
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OK
// error (too few args)
class A {}
function foo(x: Class<A>): A {
return new x();
return new x(); // OK
}
class B {
constructor(_: any) {}
}
function bar(x: Class<B>): B {
return new x();
}
"
return new x(); // error (too few args)
}"
`;
exports[`test test2.js 1`] = `
@ -46,13 +44,14 @@ check(B, new C);
// makes it useless in such a function (when limited to classes and instances),
// since everything can be trivially satisfied by going to \`mixed\`.
declare function check<X>(cls: $Type<X>, inst: X): void;
class A {}
class B extends A {}
class C {}
check(B, new A());
check(A, new B());
check(C, new A());
check(C, new B());
check(B, new C());
"
check(B, new C());"
`;

View File

@ -8,8 +8,8 @@ module.exports = A;
class A {
foo(x: number): void {}
}
module.exports = A;
"
module.exports = A;"
`;
exports[`test B.js 1`] = `
@ -22,13 +22,14 @@ let b = new B();
module.exports = B;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, number !~> function
var A = require(\"./A\");
class B extends A {}
let b = new B();
(b.foo: number);
module.exports = B;
"
// error, number !~> function
module.exports = B;"
`;
exports[`test C.js 1`] = `
@ -43,15 +44,16 @@ let c = new C();
module.exports = C;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, number !~> function
var B = require(\"./B\");
class C extends B {
foo(x: string): void {}
}
let c = new C();
(c.foo: number);
module.exports = C;
"
// error, number !~> function
module.exports = C;"
`;
exports[`test D.js 1`] = `
@ -61,8 +63,7 @@ new E().x
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class D {}
class E {}
new E().x;
"
new E().x;"
`;
exports[`test class_shapes.js 1`] = `
@ -103,42 +104,48 @@ var z = new Test2Class();
var w : Foo = z;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// exists in TestClass
// doesn\'t exist
// exists in TestClass, optional
/* doesn\'t exist*/
// ok
// error, TestClass has no b
// ok
// error, TestClass has no d
// error, doesn\'t exist in TestClass
// ok, it\'s optional
// conflicts with cast to Foo
// conflicts with cast to Foo
// conflicts with cast to Foo
type Foo = { a: string, b: string, c?: ?string, d?: number };
type Foo = {
a: string,
// exists in TestClass
b: string,
// doesn\'t exist
c?: ?string,
// exists in TestClass, optional
d?: number /* doesn\'t exist*/
};
class TestClass {
a: string;
c: ?string;
}
var x = new TestClass();
x.a;
// ok
x.b;
// error, TestClass has no b
x.c;
// ok
x.d;
// error, TestClass has no d
var y: Foo = x;
y.b;
// error, doesn\'t exist in TestClass
y.d;
// ok, it\'s optional
class Test2Superclass {
a: number;
c: ?number;
// conflicts with cast to Foo
c: ?number; // conflicts with cast to Foo
}
class Test2Class extends Test2Superclass {
b: number;
b: number; // conflicts with cast to Foo
}
var z = new Test2Class();
var w: Foo = z;
"
var w: Foo = z;"
`;
exports[`test expr.js 1`] = `
@ -173,30 +180,29 @@ var _Alias = class Alias {
var alias1: Alias = new _Alias(); // error: bad pun
var alias2: Alias = _Alias.factory(); // error: bad pun
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OK: Foo is a type in this scope
// OK: Foo is a runtime binding in this scope
var Bar = class Foo {
static factory(): Foo {
// OK: Foo is a type in this scope
return new Foo(); // OK: Foo is a runtime binding in this scope
}
};
var bar1: Bar = new Bar();
// OK
var bar2: Bar = Bar.factory();
// OK
// NB: Don\'t write expected errors using Foo to avoid error collapse hiding an
// unexpected failure in the above code.
// error: Baz is not a runtime binding in this scope
// error: Qux is not a type in this scope
// OK: anon classes create no binding, but can be bound manually
// error: bad pun
// error: bad pun
var Bar = class Foo {
static factory(): Foo {
return new Foo();
}
};
var bar1: Bar = new Bar();
var bar2: Bar = Bar.factory();
var B = class Baz {};
var b = new Baz();
// error: Baz is not a runtime binding in this scope
var C = class Qux {};
var c: Qux = new C();
// error: Qux is not a type in this scope
// OK: anon classes create no binding, but can be bound manually
var Anon = class {};
var anon: Anon = new Anon();
class Alias {}
var _Alias = class Alias {
static factory(): Alias {
@ -204,8 +210,8 @@ var _Alias = class Alias {
}
};
var alias1: Alias = new _Alias();
var alias2: Alias = _Alias.factory();
"
// error: bad pun
var alias2: Alias = _Alias.factory(); // error: bad pun"
`;
exports[`test loc.js 1`] = `
@ -216,10 +222,10 @@ type Foo = number
class Foo {} // error, shadows type Foo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error, shadows type Foo
type Foo = number;
class Foo {}
"
class Foo {} // error, shadows type Foo"
`;
exports[`test statics.js 1`] = `
@ -238,17 +244,17 @@ declare var o: {p:number};
(o: Class<C>); // error, object type incompatible with class type
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// Class static fields are compatible with object types
// ok
// errors, string ~> number & vice versa (unify)
// error, object type incompatible with class type
class C {
static p: string;
}
C.p = \"hi\";
// Class static fields are compatible with object types
(C: { p: string });
// ok
(C: { p: number });
// errors, string ~> number & vice versa (unify)
declare var o: { p: number };
(o: Class<C>);
"
(o: Class<C>); // error, object type incompatible with class type"
`;

View File

@ -84,76 +84,84 @@ function local_meth() {
* Test tracking of variable types across closure calls.
* @flow
*/
function takes_string(_: string) {}
// global write from function
//
// ok
// error
// shouldn\'t pollute linear refinement
// local write from function
//
// ok
// error
// shouldn\'t pollute linear refinement
// global write from method
//
// ok
// error
// shouldn\'t pollute linear refinement
// local write from method
//
// ok
// error
// shouldn\'t pollute linear refinement
function takes_string(_: string) {}
var global_x = \"hello\";
function global_f() {}
function global_g() {
global_x = 42;
}
global_f();
takes_string(global_x);
// ok
global_g();
takes_string(global_x);
// error
global_x = 42;
// shouldn\'t pollute linear refinement
// local write from function
//
function local_func() {
var local_x = \"hello\";
function local_f() {}
function local_g() {
local_x = 42;
}
local_f();
takes_string(local_x);
// ok
local_g();
takes_string(local_x);
local_x = 42;
// error
local_x = 42; // shouldn\'t pollute linear refinement
}
// global write from method
//
var global_y = \"hello\";
var global_o = {
f: function() {},
g: function() {
global_y = 42;
}
};
global_o.f();
takes_string(global_y);
// ok
global_o.g();
takes_string(global_y);
// error
global_y = 42;
// shouldn\'t pollute linear refinement
// local write from method
//
function local_meth() {
var local_y = \"hello\";
var local_o = {
f: function() {},
g: function() {
local_y = 42;
}
};
local_o.f();
takes_string(local_y);
// ok
local_o.g();
takes_string(local_y);
local_y = 42;
}
"
// error
local_y = 42; // shouldn\'t pollute linear refinement
}"
`;
exports[`test cond_havoc.js 1`] = `
@ -172,10 +180,10 @@ function example(b: bool): number {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// from sam, https://github.com/facebook/flow/issues/780
// call to f() within if should properly havoc x.
//
// error, string ~/~> number (return type anno) TODO
function example(b: boolean): number {
var x = 0;
function f() {
@ -184,9 +192,8 @@ function example(b: boolean): number {
if (b) {
f();
}
return x;
}
"
return x; // error, string ~/~> number (return type anno) TODO
}"
`;
exports[`test const.js 1`] = `
@ -242,63 +249,61 @@ call_me();
* consts retain refinements
* @flow
*/
// global, anybody can call it at any time
// ok: if const_x is truthy here, it\'s truthy everywhere
// error: var_x might no longer be truthy when call_me is called
// error
// ok
// ok
// ok
// error
// error
// error
// in a galaxy far far away
var call_me: () => void = () => {};
function g(x: ?number) {
const const_x = x;
if (const_x) {
// ok: if const_x is truthy here, it\'s truthy everywhere
call_me = () => {
var y: number = const_x;
};
}
var var_x = x;
if (var_x) {
// error: var_x might no longer be truthy when call_me is called
call_me = () => {
var y: number = var_x;
};
}; // error
}
var_x = null;
}
function h(x: number | string | boolean) {
const const_x = x;
if (typeof const_x == \"number\") {
call_me = () => {
var y: number = const_x;
};
}; // ok
} else if (typeof const_x == \"string\") {
call_me = () => {
var y: string = const_x;
};
}; // ok
} else if (typeof const_x == \"boolean\") {
call_me = () => {
var y: boolean = const_x;
};
}; // ok
}
var var_x = x;
if (typeof var_x == \"number\") {
call_me = () => {
var y: number = var_x;
};
}; // error
} else if (typeof var_x == \"string\") {
call_me = () => {
var y: string = var_x;
};
}; // error
} else if (typeof var_x == \"boolean\") {
call_me = () => {
var y: boolean = var_x;
};
}; // error
}
}
call_me();
"
// in a galaxy far far away
call_me();"
`;

View File

@ -5,8 +5,8 @@ function f(x:string) { }
module.exports = f;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function f(x: string) {}
module.exports = f;
"
module.exports = f;"
`;
exports[`test Rel.js 1`] = `
@ -16,6 +16,6 @@ var f = require(\'./Abs\');
f(0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var f = require(\"./Abs\");
f(0);
"
f(0);"
`;

View File

@ -23,19 +23,21 @@ ColorIdToNumber.XXX; // oops
module.exports = { ColorId, ColorNumber };
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// oops
// oops
var ColorId = { RED: \"R\", GREEN: \"G\", BLUE: \"B\" };
var ColorNumber = { RED: \"ff0000\", GREEN: \"00ff00\", BLUE: \"0000ff\" };
var ColorIdToNumber = {
[ColorId.RED]: ColorNumber.RED,
[ColorId.GREEN]: ColorNumber.GREEN,
[ColorId.BLUE]: ColorNumber.BLUE
};
(ColorIdToNumber[ColorId.RED]: \"ffffff\");
// oops
ColorIdToNumber.XXX;
module.exports = { ColorId, ColorNumber };
"
// oops
module.exports = { ColorId, ColorNumber };"
`;
exports[`test test2.js 1`] = `
@ -50,16 +52,16 @@ var ColorIdToNumber = {
module.exports = ColorIdToNumber;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// oops
var { ColorId, ColorNumber } = require(\"./test\");
var ColorIdToNumber = {
[ColorId.RED]: ColorNumber.RED,
[ColorId.GREEN]: ColorNumber.GREEN,
[ColorId.BLUE]: ColorNumber.BLUE
};
(ColorIdToNumber[ColorId.GREEN]: \"ffffff\");
module.exports = ColorIdToNumber;
"
// oops
module.exports = ColorIdToNumber;"
`;
exports[`test test3.js 1`] = `
@ -68,18 +70,16 @@ var ColorIdToNumber = require(\'./test2\');
(ColorIdToNumber[ColorId.BLUE]: \'ffffff\'); // oops
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// oops
var { ColorId } = require(\"./test\");
var ColorIdToNumber = require(\"./test2\");
(ColorIdToNumber[ColorId.BLUE]: \"ffffff\");
"
(ColorIdToNumber[ColorId.BLUE]: \"ffffff\"); // oops"
`;
exports[`test test4.js 1`] = `
"module.exports = \'hello\';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
module.exports = \"hello\";
"
module.exports = \"hello\";"
`;
exports[`test test5.js 1`] = `
@ -93,18 +93,15 @@ module.exports = {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var hello = require(\"./test4\");
var dummy = require(\"./test\");
module.exports = { ...dummy, [hello]: \"world\", ...dummy };
"
module.exports = { ...dummy, [hello]: \"world\", ...dummy };"
`;
exports[`test test6.js 1`] = `
"var o = require(\'./test5\');
(o.hello: \'nothing\'); // oops
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// oops
var o = require(\"./test5\");
(o.hello: \"nothing\");
"
(o.hello: \"nothing\"); // oops"
`;
exports[`test test7.js 1`] = `
@ -114,8 +111,6 @@ var x: string = obj[\'m\'](); // error, number ~> string
var arr = [function() { return this.length }];
var y: string = arr[0](); // error: number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, number ~> string
// error: number ~> string
var obj = {
x: 0,
m() {
@ -123,11 +118,11 @@ var obj = {
}
};
var x: string = obj[\"m\"]();
// error, number ~> string
var arr = [
function() {
return this.length;
}
];
var y: string = arr[0]();
"
var y: string = arr[0](); // error: number ~> string"
`;

View File

@ -25,25 +25,28 @@ function d(): string { // expected \`: number | boolean\`
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// equivalent to \`return (x && 1) || 0\`
// expected \`: number | boolean\`
// equivalent to \`return x != null && x\`
function a(): number {
var x: ?string = null;
return x ? 1 : 0;
}
function b(): number {
var x: ?number = null;
return x != null ? x : 0;
}
function c(): number {
// equivalent to \`return (x && 1) || 0\`
var x = false;
var temp = x ? 1 : x;
return temp ? temp : 0;
}
function d(): string {
// expected \`: number | boolean\`
// equivalent to \`return x != null && x\`
var x: ?number = null;
return x != null ? x : x != null;
}
"
}"
`;

View File

@ -1,7 +1,5 @@
exports[`test no_at_flow.js 1`] = `
"var x: number = \"not a number\"; // Error: string ~> number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Error: string ~> number
var x: number = \"not a number\";
"
var x: number = \"not a number\"; // Error: string ~> number"
`;

View File

@ -1,7 +1,5 @@
exports[`test no_at_flow.js 1`] = `
"var x: number = \"not a number\"; // No error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// No error
var x: number = \"not a number\";
"
var x: number = \"not a number\"; // No error"
`;

View File

@ -4,6 +4,6 @@ exports[`test no_at_flow.js 1`] = `
x.length;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var x;
x.length;
"
x.length;"
`;

View File

@ -14,11 +14,12 @@ foo(\'Hello, world!\');
/*
* @flow
*/
// This file should be ignored, so this should not result in an error
function foo(x) {
var a: number = \"asdf\";
return x * 10;
}
foo(\"Hello, world!\");
"
// This file should be ignored, so this should not result in an error
foo(\"Hello, world!\");"
`;

View File

@ -5,7 +5,7 @@ exports[`test foo.js 1`] = `
var x: number = \"string\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// No error, this file is ignored
var x: number = \"string\";
"
var x: number = \"string\";"
`;

View File

@ -4,7 +4,6 @@ exports[`test foo.js 1`] = `
var x: number = \"string\"; // Error string ~> number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// Error string ~> number
var x: number = \"string\";
"
var x: number = \"string\"; // Error string ~> number"
`;

View File

@ -7,9 +7,9 @@ var a: number = test;
var b: string = test; // Error: number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Error: number ~> string
import {test} from \"testmodule\";
var a: number = test;
var b: string = test;
"
var b: string = test; // Error: number ~> string"
`;

View File

@ -4,6 +4,6 @@ exports[`test testmodule.js 1`] = `
export let test = 42;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
export let test = 42;
"
export let test = 42;"
`;

View File

@ -5,8 +5,7 @@ import {className} from \"./SomeCSSFile.css\";
import {doesntExist} from \"./SomeCSSFile.css\"; // Error: \`doestExist\` isn\'t an export
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Error: \`doestExist\` isn\'t an export
import {className} from \"./SomeCSSFile.css\";
import {doesntExist} from \"./SomeCSSFile.css\";
"
import {doesntExist} from \"./SomeCSSFile.css\"; // Error: \`doestExist\` isn\'t an export"
`;

View File

@ -14,19 +14,19 @@ var m2 = require(\'2DoesntExist\'); // Error
import {numVal as numVal2} from \'3DoesntExist\'; // Error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// Error: \'Exists2\' is not a valid module name
//
// This tests that, for haste, the first name_mapper regexp that happens to
// match the given module name string is picked.
// Error
// Error
var m1 = require(\"1DoesntExist\");
import {numVal as numVal1} from \"1DoesntExist\";
var a_1: number = m1.numVal;
var a_2: number = numVal1;
// Error: \'Exists2\' is not a valid module name
//
// This tests that, for haste, the first name_mapper regexp that happens to
// match the given module name string is picked.
var m2 = require(\"2DoesntExist\");
import {numVal as numVal2} from \"3DoesntExist\";
"
// Error
import {numVal as numVal2} from \"3DoesntExist\"; // Error"
`;
exports[`test Exists.js 1`] = `
@ -43,6 +43,6 @@ module.exports = {
* @providesModule Exists
* @flow
*/
module.exports = { numVal: 42 };
"
module.exports = { numVal: 42 };"
`;

View File

@ -26,34 +26,33 @@ var c_3: number = numVal3;
var c_4: string = numVal3; // Error: number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// Error: number ~> string
// Error: number ~> string
// This tests that, for node, the first name mapping that both matches *and*
// results in a valid module filename is picked.
// Error: number ~> string
// Error: number ~> string
// node_modules/Exists/index.js
// Error: number ~> string
// Error: number ~> string
var m1 = require(\"./1DoesntExist\");
var a_1: number = m1.numVal;
var a_2: string = m1.numVal;
// Error: number ~> string
import {numVal} from \"./1DoesntExist\";
var a_3: number = numVal;
var a_4: string = numVal;
// Error: number ~> string
// This tests that, for node, the first name mapping that both matches *and*
// results in a valid module filename is picked.
var m2 = require(\"./2DoesntExist\");
var b_1: number = m2.numVal;
var b_2: string = m2.numVal;
// Error: number ~> string
import {numVal as numVal2} from \"./3DoesntExist\";
var b_3: number = numVal2;
var b_4: string = numVal2;
// Error: number ~> string
// node_modules/Exists/index.js
var m3 = require(\"4DoesntExist\");
var c_1: number = m3.numVal;
var c_2: string = m3.numVal;
// Error: number ~> string
import {numVal as numVal3} from \"5DoesntExist\";
var c_3: number = numVal3;
var c_4: string = numVal3;
"
var c_4: string = numVal3; // Error: number ~> string"
`;
exports[`test Exists.js 1`] = `
@ -64,6 +63,6 @@ module.exports = {
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
module.exports = { numVal: 42 };
"
module.exports = { numVal: 42 };"
`;

View File

@ -7,9 +7,9 @@ import {name} from \"testproj\";
(name: \"custom_resolve_dir/testproj\"); // Error: Resolve from node_modules first!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Error: Resolve from node_modules first!
import {name} from \"testproj\";
(name: \"node_modules/testproj\");
(name: \"custom_resolve_dir/testproj\");
"
(name: \"custom_resolve_dir/testproj\"); // Error: Resolve from node_modules first!"
`;

View File

@ -4,6 +4,6 @@ exports[`test index.js 1`] = `
export var name: \"otherdir/testproj\" = \"otherdir/testproj\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
export var name: \"otherdir/testproj\" = \"otherdir/testproj\";
"
export var name: \"otherdir/testproj\" = \"otherdir/testproj\";"
`;

View File

@ -4,6 +4,6 @@ exports[`test index.js 1`] = `
export var name: \"otherdir/testproj2\" = \"otherdir/testproj2\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
export var name: \"otherdir/testproj2\" = \"otherdir/testproj2\";
"
export var name: \"otherdir/testproj2\" = \"otherdir/testproj2\";"
`;

View File

@ -7,9 +7,10 @@ import {name} from \"testproj2\";
(name: \"subdir/custom_resolve_dir/testproj2\");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Error: Resolve from sibling \'custom_resolve_dir\' first!
import {name} from \"testproj2\";
(name: \"node_modules/testproj2\");
(name: \"subdir/custom_resolve_dir/testproj2\");
"
// Error: Resolve from sibling \'custom_resolve_dir\' first!
(name: \"subdir/custom_resolve_dir/testproj2\");"
`;

View File

@ -4,6 +4,6 @@ exports[`test index.js 1`] = `
export var name: \"subdir/custom_resolve_dir/testproj2\" = \"subdir/custom_resolve_dir/testproj2\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
export var name: \"subdir/custom_resolve_dir/testproj2\" = \"subdir/custom_resolve_dir/testproj2\";
"
export var name: \"subdir/custom_resolve_dir/testproj2\" = \"subdir/custom_resolve_dir/testproj2\";"
`;

View File

@ -35,9 +35,11 @@ class B extends A {
B._sProperty = \"B._sProperty string\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
class A {
_property1: number;
static _sProperty: number;
constructor() {
this._property1 = 5;
}
@ -49,9 +51,11 @@ class A {
}
}
A._sProperty = 48;
class B extends A {
_property1: string;
static _sProperty: string;
constructor() {
super();
this._property1 = \"another string\";
@ -63,8 +67,7 @@ class B extends A {
return 23;
}
}
B._sProperty = \"B._sProperty string\";
"
B._sProperty = \"B._sProperty string\";"
`;
exports[`test commonjs_export.js 1`] = `
@ -77,11 +80,12 @@ class C {
module.exports = new C;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
class C {
_p: string;
}
module.exports = new C();
"
module.exports = new C();"
`;
exports[`test commonjs_import.js 1`] = `
@ -90,6 +94,6 @@ exports[`test commonjs_import.js 1`] = `
import {_p} from \"./commonjs_export\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
import {_p} from \"./commonjs_export\";
"
import {_p} from \"./commonjs_export\";"
`;

View File

@ -35,9 +35,11 @@ class B extends A {
B._sProperty = \"B._sProperty string\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
class A {
_property1: number;
static _sProperty: number;
constructor() {
this._property1 = 5;
}
@ -49,9 +51,11 @@ class A {
}
}
A._sProperty = 48;
class B extends A {
_property1: string;
static _sProperty: string;
constructor() {
super();
this._property1 = \"another string\";
@ -63,6 +67,5 @@ class B extends A {
return 23;
}
}
B._sProperty = \"B._sProperty string\";
"
B._sProperty = \"B._sProperty string\";"
`;

View File

@ -43,21 +43,21 @@ function durable_refi(x: ?number) {
*
* @flow
*/
// error, const param cannot be reassigned
function cannot_reassign(x: string) {
x = \"hey\"; // error, const param cannot be reassigned
}
// Note: const params use the same machinery as explicit
// const bindings, which are tested more extensively elsewhere.
// Here we\'re just making sure the machinery is hooked up.
//
// ok: if x is truthy here, it\'s truthy everywhere
function cannot_reassign(x: string) {
x = \"hey\";
}
function durable_refi(x: ?number) {
if (x) {
// ok: if x is truthy here, it\'s truthy everywhere
return () => {
var y: number = x;
};
}
}
"
}"
`;

View File

@ -12,9 +12,10 @@ module.exports = C;
class C {
constructor() {}
}
class D {
constructor(): number {}
}
module.exports = C;
"
module.exports = C;"
`;

View File

@ -22,31 +22,30 @@ interface IFoo extends IFooPrototype {
exports.Foo2 = (Foo: Class<IFoo>);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Foo is a class-like function
// constructs objects with property x
// has static property y
// exporting Foo directly doesn\'t work
// Foo\'s instance and static props are not picked up
// so you want to type Foo, by declaring it as a class
/* error, should have declared x: number instead*/
/* error, should have declared static y: number instead*/
function Foo() {
this.x = 0;
this.x = 0; // constructs objects with property x
}
Foo.y = 0;
// has static property y
Foo.prototype = {
m() {
return 0;
}
};
// exporting Foo directly doesn\'t work
// Foo\'s instance and static props are not picked up
exports.Foo = Foo;
// so you want to type Foo, by declaring it as a class
interface IFooPrototype { m(): number }
interface IFoo extends IFooPrototype {
/* error, should have declared x: number instead*/
static (): void,
x: boolean,
static y: boolean
static y: boolean /* error, should have declared static y: number instead*/
}
exports.Foo2 = (Foo: Class<IFoo>);
"
exports.Foo2 = (Foo: Class<IFoo>);"
`;
exports[`test test.js 1`] = `
@ -60,17 +59,17 @@ var x2: string = new Foo2().x; // error, found boolean instead of string
var y2: string = Foo2.y; // error, found boolean instead of string
var z2: string = new Foo2().m();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, found number instead of string
// error, found number instead of string
// error, found boolean instead of string
// error, found boolean instead of string
var Foo = require(\"./constructors\").Foo;
var x: string = new Foo().x;
// error, found number instead of string
var y: string = Foo.y;
// error, found number instead of string
var z: string = new Foo().m();
var Foo2 = require(\"./constructors\").Foo2;
var x2: string = new Foo2().x;
// error, found boolean instead of string
var y2: string = Foo2.y;
var z2: string = new Foo2().m();
"
// error, found boolean instead of string
var z2: string = new Foo2().m();"
`;

View File

@ -1,6 +1,5 @@
exports[`test dummy.js 1`] = `
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"
`;
@ -11,6 +10,5 @@ xxx
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./dummy\");
var xxx = 0;
xxx;
"
xxx;"
`;

View File

@ -1,6 +1,5 @@
exports[`test dummy.js 1`] = `
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"
`;
@ -11,6 +10,5 @@ xxx
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./dummy\");
var xxx = 0;
xxx;
"
xxx;"
`;

View File

@ -43,12 +43,11 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Boolean (the class) tests. booleans (the literals) are not part of core.js
// constructor
// toString
// valueOf
// casting
let tests = [
// constructor
function() {
new Boolean();
new Boolean(0);
@ -59,15 +58,18 @@ let tests = [
new Boolean(undefined);
new Boolean(\"\");
},
// toString
function() {
true.toString();
let x: boolean = false;
x.toString();
new Boolean(true).toString();
},
// valueOf
function() {
(new Boolean(0).valueOf(): boolean);
},
// casting
function() {
Boolean();
Boolean(0);
@ -78,8 +80,7 @@ let tests = [
Boolean(undefined);
Boolean(\"\");
}
];
"
];"
`;
exports[`test map.js 1`] = `
@ -117,19 +118,15 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// good constructors
// bad constructors
// error
// error
// get()
// error, string | void
// error, wrong key type
function* generator(): Iterable<[string, number]> {
while (true) {
yield [ \"foo\", 123 ];
}
}
let tests = [
// good constructors
function() {
let w = new Map();
let x = new Map(null);
@ -139,16 +136,19 @@ let tests = [
let b: Map<string, number> = new Map([ [ \"foo\", 123 ] ]);
let c: Map<string, number> = new Map(generator());
},
// bad constructors
function() {
let x = new Map([ \"foo\", 123 ]);
let y: Map<number, string> = new Map([ [ \"foo\", 123 ] ]);
// error
let y: Map<number, string> = new Map([ [ \"foo\", 123 ] ]); // error
},
// get()
function(x: Map<string, number>) {
(x.get(\"foo\"): boolean);
x.get(123);
// error, string | void
x.get(123); // error, wrong key type
}
];
"
];"
`;
exports[`test regexp.js 1`] = `
@ -183,38 +183,35 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// constructor
// invalid in ES5, valid in ES6
// invalid in ES5, valid in ES6
// called as a function (equivalent to the constructor per ES6 21.2.3)
// invalid in ES5, valid in ES6
// invalid in ES5, valid in ES6
// invalid flags
// error
// error
let tests = [
// constructor
function() {
new RegExp(\"foo\");
new RegExp(/foo/);
new RegExp(\"foo\", \"i\");
new RegExp(\"foo\", \"ig\");
new RegExp(/foo/, \"i\");
new RegExp(/foo/g, \"i\");
// invalid in ES5, valid in ES6
new RegExp(/foo/g, \"i\"); // invalid in ES5, valid in ES6
},
// called as a function (equivalent to the constructor per ES6 21.2.3)
function() {
RegExp(\"foo\");
RegExp(/foo/);
RegExp(\"foo\", \"i\");
RegExp(\"foo\", \"ig\");
RegExp(/foo/, \"i\");
RegExp(/foo/g, \"i\");
// invalid in ES5, valid in ES6
RegExp(/foo/g, \"i\"); // invalid in ES5, valid in ES6
},
// invalid flags
function() {
RegExp(\"foo\", \"z\");
new RegExp(\"foo\", \"z\");
// error
new RegExp(\"foo\", \"z\"); // error
}
];
"
];"
`;
exports[`test weakset.js 1`] = `
@ -256,11 +253,11 @@ function* numbers(): Iterable<number> {
let ws5 = new WeakSet(numbers()); // error, must be objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// error, must be objects
// error, must be objects
let ws = new WeakSet();
let obj: Object = {};
let dict: { foo: string } = { foo: \"bar\" };
ws.add(window);
ws.add(obj);
ws.add(dict);
@ -270,20 +267,25 @@ ws.has(dict);
ws.delete(window);
ws.delete(obj);
ws.delete(dict);
let ws2 = new WeakSet([ obj, dict ]);
let ws3 = new WeakSet([ 1, 2, 3 ]);
// error, must be objects
function* generator(): Iterable<{ foo: string }> {
while (true) {
yield { foo: \"bar\" };
}
}
let ws4 = new WeakSet(generator());
function* numbers(): Iterable<number> {
let i = 0;
while (true) {
yield i++;
}
}
let ws5 = new WeakSet(numbers());
"
let ws5 = new WeakSet(numbers()); // error, must be objects"
`;

View File

@ -49,9 +49,23 @@ n.x = [0];
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type CovArrayVerbose<X, Y: X> = Array<Y>;
var b: CovArrayVerbose<number, *> = [];
var y: CovArrayVerbose<mixed, *> = b;
y[0] = \"\";
// error
class NVerbose<E, I: E> {
x: CovArrayVerbose<E, I>;
foo(): CovArrayVerbose<mixed, I> {
return this.x;
}
}
var nv: NVerbose<number, *> = new NVerbose();
nv.x = [ 0 ];
(nv.x[0]: string);
// error
// error
(nv.foo()[0]: string); // error
/* TODO: use existentials for non-verbose covariance?
type CovArray<X> = Array<*:X>;
@ -85,20 +99,5 @@ n.x = [0];
(n.x[0]: string); // error
(n.foo()[0]: string); // not an error!
*/
type CovArrayVerbose<X, Y: X> = Array<Y>;
var b: CovArrayVerbose<number, *> = [];
var y: CovArrayVerbose<mixed, *> = b;
y[0] = \"\";
class NVerbose<E, I: E> {
x: CovArrayVerbose<E, I>;
foo(): CovArrayVerbose<mixed, I> {
return this.x;
}
}
var nv: NVerbose<number, *> = new NVerbose();
nv.x = [ 0 ];
(nv.x[0]: string);
(nv.foo()[0]: string);
"
*/"
`;

View File

@ -11,13 +11,12 @@ declare module bar {
// TODO
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare module foo {}
// TODO
// This file triggers a violation of the \"disjoint-or-nested ranges invariant\"
// that we implicitly assume in type-at-pos and coverage implementations. In
// particular, when unchecked it causes a crash with coverage --color.
// TODO
declare module foo {}
declare module bar {}
"
declare module bar {}"
`;
exports[`test declare_module.js 1`] = `
@ -27,8 +26,8 @@ declare module foo {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// check coverage of declare module
declare module foo {}
"
declare module foo {}"
`;
exports[`test no_pragma.js 1`] = `
@ -36,8 +35,7 @@ exports[`test no_pragma.js 1`] = `
(x: string);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
let x = 0;
(x: string);
"
(x: string);"
`;
exports[`test non-termination.js 1`] = `
@ -56,12 +54,11 @@ declare module bar {
declare class qux {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare module foo {}
// This file triggers a violation of the \"disjoint-or-nested ranges invariant\"
// that we implicitly assume in type-at-pos and coverage implementations. In
// particular, when unchecked it causes non-termination with coverage --color.
// TODO
declare module foo {}
declare module bar {}
declare class qux {}
"
// TODO
declare class qux {}"
`;

View File

@ -6,9 +6,10 @@ class A extends B { }
module.exports = A;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var B = require(\"./B\");
class A extends B {}
module.exports = A;
"
module.exports = A;"
`;
exports[`test B.js 1`] = `
@ -18,8 +19,8 @@ exports[`test B.js 1`] = `
module.exports = B;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//class B extends A { }
var A = require(\"./A\");
module.exports = B;
"
//class B extends A { }
module.exports = B;"
`;

View File

@ -28,12 +28,12 @@ new Date(2015, 6, 18, 11, 55, 42, \'999\');
new Date(\'2015\', 6);
new Date(2015, 6, 18, 11, 55, 42, 999, \'hahaha\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// valid constructors
// invalid constructors
// invalid constructors that we incorrectly consider valid
var d = new Date(0);
var x: string = d.getTime();
var y: number = d;
// valid constructors
new Date();
new Date(1234567890);
new Date(\"2015/06/18\");
@ -43,6 +43,8 @@ new Date(2015, 6, 18, 11);
new Date(2015, 6, 18, 11, 55);
new Date(2015, 6, 18, 11, 55, 42);
new Date(2015, 6, 18, 11, 55, 42, 999);
// invalid constructors
new Date({});
new Date(2015, \"6\");
new Date(2015, 6, \"18\");
@ -50,7 +52,8 @@ new Date(2015, 6, 18, \"11\");
new Date(2015, 6, 18, 11, \"55\");
new Date(2015, 6, 18, 11, 55, \"42\");
new Date(2015, 6, 18, 11, 55, 42, \"999\");
// invalid constructors that we incorrectly consider valid
new Date(\"2015\", 6);
new Date(2015, 6, 18, 11, 55, 42, 999, \"hahaha\");
"
new Date(2015, 6, 18, 11, 55, 42, 999, \"hahaha\");"
`;

View File

@ -10,8 +10,8 @@ module.exports.fun = (): string => \"hello there\";
* @providesModule ExplicitProvidesModuleDifferentName
* @flow
*/
module.exports.fun = (): string => \"hello there\";
"
module.exports.fun = (): string => \"hello there\";"
`;
exports[`test ExplicitProvidesModuleSameName.js 1`] = `
@ -26,8 +26,8 @@ module.exports.fun = (): string => \"hello there\";
* @providesModule ExplicitProvidesModuleSameName
* @flow
*/
module.exports.fun = (): string => \"hello there\";
"
module.exports.fun = (): string => \"hello there\";"
`;
exports[`test ImplicitProvidesModule.js 1`] = `
@ -42,15 +42,13 @@ module.exports.fun = (): string => \"hello there\";
* @providesModule ImplicitProvidesModule
* @flow
*/
module.exports.fun = (): string => \"hello there\";
"
module.exports.fun = (): string => \"hello there\";"
`;
exports[`test md5.js 1`] = `
"/* @providesModule md5 */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @providesModule md5 */
"
`;
@ -67,11 +65,13 @@ var ExplicitDifferentName = require(\'ExplicitProvidesModuleDifferentName\');
(ExplicitDifferentName.fun(): string);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
var Implicit = require(\"ImplicitProvidesModule\");
(Implicit.fun(): string);
var ExplicitSameName = require(\"ExplicitProvidesModuleSameName\");
(ExplicitSameName.fun(): string);
var ExplicitDifferentName = require(\"ExplicitProvidesModuleDifferentName\");
(ExplicitDifferentName.fun(): string);
"
(ExplicitDifferentName.fun(): string);"
`;

View File

@ -1,6 +1,5 @@
exports[`test min.js 1`] = `
"module.exports.fun = (): string => \"hello there\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
module.exports.fun = (): string => \"hello there\";
"
module.exports.fun = (): string => \"hello there\";"
`;

View File

@ -14,14 +14,16 @@ var unreachable = require(\'annotation\');
(corge.fun(): string);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// make sure we don\'t pick up non-header @providesModule
// annotations - see node_modules/qux/docblock.js
var docblock = require(\"qux/docblock\");
var min = require(\"d3/min.js\");
var corge = require(\"qux/corge\");
// make sure we don\'t pick up non-header @providesModule
// annotations - see node_modules/qux/docblock.js
var unreachable = require(\"annotation\");
(docblock.fun(): string);
(min.fun(): string);
(corge.fun(): string);
"
(corge.fun(): string);"
`;

View File

@ -1,5 +1,4 @@
exports[`test index.js 1`] = `
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"
`;

View File

@ -1,6 +1,5 @@
exports[`test client.js 1`] = `
"var ws = require(\'../\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var ws = require(\"../\");
"
var ws = require(\"../\");"
`;

View File

@ -7,8 +7,7 @@ export function foo(): Implementation { return new Implementation; }
class Implementation {}
export function foo(): Implementation {
return new Implementation();
}
"
}"
`;
exports[`test ExplicitProvidesModuleDifferentName.js 1`] = `
@ -24,9 +23,9 @@ module.exports.fun = (): Implementation => new Implementation;
* @providesModule ExplicitProvidesModuleDifferentName
* @flow
*/
class Implementation {}
module.exports.fun = (): Implementation => new Implementation();
"
module.exports.fun = (): Implementation => new Implementation();"
`;
exports[`test ExplicitProvidesModuleSameName.js 1`] = `
@ -42,9 +41,9 @@ module.exports.fun = (): Implementation => new Implementation;
* @providesModule ExplicitProvidesModuleSameName
* @flow
*/
class Implementation {}
module.exports.fun = (): Implementation => new Implementation();
"
module.exports.fun = (): Implementation => new Implementation();"
`;
exports[`test ImplicitProvidesModule.js 1`] = `
@ -60,16 +59,14 @@ module.exports.fun = (): Implementation => new Implementation;
* @providesModule ImplicitProvidesModule
* @flow
*/
class Implementation {}
module.exports.fun = (): Implementation => new Implementation();
"
module.exports.fun = (): Implementation => new Implementation();"
`;
exports[`test md5.js 1`] = `
"/* @providesModule md5 */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @providesModule md5 */
"
`;
@ -86,14 +83,13 @@ var ExplicitDifferentName = require(\'ExplicitProvidesModuleDifferentName\');
(ExplicitDifferentName.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// Error: Either Implementation ~> boolean or Declaration ~> boolean
// Error: Either Implementation ~> boolean or Declaration ~> boolean
// Error: Either Implementation ~> boolean or Declaration ~> boolean
var Implicit = require(\"ImplicitProvidesModule\");
(Implicit.fun(): boolean);
// Error: Either Implementation ~> boolean or Declaration ~> boolean
var ExplicitSameName = require(\"ExplicitProvidesModuleSameName\");
(ExplicitSameName.fun(): boolean);
// Error: Either Implementation ~> boolean or Declaration ~> boolean
var ExplicitDifferentName = require(\"ExplicitProvidesModuleDifferentName\");
(ExplicitDifferentName.fun(): boolean);
"
(ExplicitDifferentName.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean"
`;

View File

@ -3,6 +3,5 @@ exports[`test min.js 1`] = `
module.exports.fun = (): Implementation => new Implementation;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Implementation {}
module.exports.fun = (): Implementation => new Implementation();
"
module.exports.fun = (): Implementation => new Implementation();"
`;

View File

@ -10,14 +10,14 @@ var corge = require(\'qux/corge\');
(corge.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// Error: Either Implementation ~> boolean or Declaration ~> boolean
// Error: Either Implementation ~> boolean or Declaration ~> boolean
// Error: Either Implementation ~> boolean or Declaration ~> boolean
var docblock = require(\"qux/docblock\");
var min = require(\"d3/min.js\");
var corge = require(\"qux/corge\");
(docblock.fun(): boolean);
// Error: Either Implementation ~> boolean or Declaration ~> boolean
(min.fun(): boolean);
(corge.fun(): boolean);
"
// Error: Either Implementation ~> boolean or Declaration ~> boolean
(corge.fun(): boolean); // Error: Either Implementation ~> boolean or Declaration ~> boolean"
`;

View File

@ -1,5 +1,4 @@
exports[`test index.js 1`] = `
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"
`;

View File

@ -1,6 +1,5 @@
exports[`test client.js 1`] = `
"var ws = require(\'../\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var ws = require(\"../\");
"
var ws = require(\"../\");"
`;

View File

@ -5,8 +5,7 @@ export function foo(): Implementation { return new Implementation; }
class Implementation {}
export function foo(): Implementation {
return new Implementation();
}
"
}"
`;
exports[`test test_absolute.js 1`] = `
@ -53,47 +52,46 @@ var F = require(\'package_with_dir_main\');
(F.fun(): boolean); // Error either Implementation ~> boolean or Declaration ~> boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// This will require ./node_modules/B.js.flow
// Error either Implementation ~> boolean or Declaration ~> boolean
// This will require ./node_modules/B.js.flow
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
// This will require ./node_modules/B.js.flow
// Error either Implementation ~> boolean or Declaration ~> boolean
// This will require ./node_modules/B.js.flow
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
// Error either Implementation ~> boolean or Declaration ~> boolean
var B1 = require(\"B\");
(B1.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
// This will require ./node_modules/B.js.flow
var B2 = require(\"B.js\");
(B2.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var C = require(\"package_with_full_main\");
(C.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var D = require(\"package_with_partial_main\");
(D.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var E = require(\"package_with_no_package_json\");
(E.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var F = require(\"package_with_dir_main\");
(F.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
// This will require ./node_modules/B.js.flow
var B1 = require(\"B\");
(B1.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
// This will require ./node_modules/B.js.flow
var B2 = require(\"B.js\");
(B2.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var C = require(\"package_with_full_main\");
(C.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var D = require(\"package_with_partial_main\");
(D.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var E = require(\"package_with_no_package_json\");
(E.fun(): boolean);
// Error either Implementation ~> boolean or Declaration ~> boolean
var F = require(\"package_with_dir_main\");
(F.fun(): boolean);
"
(F.fun(): boolean); // Error either Implementation ~> boolean or Declaration ~> boolean"
`;
exports[`test test_relative.js 1`] = `
@ -101,8 +99,7 @@ exports[`test test_relative.js 1`] = `
(foo(): boolean); // Error: either Implementation ~> boolean or Definition ~> boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Error: either Implementation ~> boolean or Definition ~> boolean
import {foo} from \"./A\";
(foo(): boolean);
"
(foo(): boolean); // Error: either Implementation ~> boolean or Definition ~> boolean"
`;

View File

@ -4,8 +4,8 @@ exports[`test A.js 1`] = `
module.exports.fun = (): string => \'hello there!\';
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
module.exports.fun = (): string => \"hello there!\";
"
module.exports.fun = (): string => \"hello there!\";"
`;
exports[`test CJS.js 1`] = `
@ -13,8 +13,7 @@ exports[`test CJS.js 1`] = `
module.exports = 42;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
module.exports = 42;
"
module.exports = 42;"
`;
exports[`test test_absolute.js 1`] = `
@ -41,27 +40,26 @@ var F = require(\'package_with_dir_main\');
(F.fun(): string); // Error number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// This will require ./node_modules/B.js.flow
// Error number ~> string
// This will require ./node_modules/B.js.flow
// Error number ~> string
// Error number ~> string
// Error number ~> string
// Error number ~> string
// Error number ~> string
var B1 = require(\"B\");
(B1.fun(): string);
// Error number ~> string
// This will require ./node_modules/B.js.flow
var B2 = require(\"B.js\");
(B2.fun(): string);
// Error number ~> string
var C = require(\"package_with_full_main\");
(C.fun(): string);
// Error number ~> string
var D = require(\"package_with_partial_main\");
(D.fun(): string);
// Error number ~> string
var E = require(\"package_with_no_package_json\");
(E.fun(): string);
// Error number ~> string
var F = require(\"package_with_dir_main\");
(F.fun(): string);
"
(F.fun(): string); // Error number ~> string"
`;
exports[`test test_relative.js 1`] = `
@ -80,17 +78,16 @@ var CJS = require(\'./CJS.js\');
(CJS: number); // Error: string ~> number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// This will require ./A.js.flow
// Error number ~> string
// This will require ./A.js.flow
// Error number ~> string
// Error: string ~> number
var A1 = require(\"./A\");
(A1.fun(): string);
// Error number ~> string
// This will require ./A.js.flow
var A2 = require(\"./A.js\");
(A2.fun(): string);
// Error number ~> string
var CJS = require(\"./CJS.js\");
(CJS: string);
(CJS: number);
"
(CJS: number); // Error: string ~> number"
`;

View File

@ -10,11 +10,11 @@ C.foo(\"\");
(C.name: string);
(C.name: number); // error, it\'s a string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, it\'s a string
declare class C { static x: number, static foo(x: number): void }
C.x = \"\";
C.foo(\"\");
(C.name: string);
(C.name: number);
"
(C.name: number); // error, it\'s a string"
`;

View File

@ -11,6 +11,5 @@ declare class D extends _module.C {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare class _C { foo(): number }
declare var _module: { C: Class<_C> };
declare class D extends _module.C { foo(): string }
"
declare class D extends _module.C { foo(): string }"
`;

View File

@ -4,15 +4,13 @@ exports[`test B.js 1`] = `
exports.numberValue = 42;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
exports.numberValue = 42;
"
exports.numberValue = 42;"
`;
exports[`test C.js 1`] = `
"/* @flow */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
"
`;
@ -43,11 +41,14 @@ module.exports = Test;
* @providesModule CommonJS_Clobbering_Class
* @flow
*/
class Base {
static baseProp: number;
}
class Test extends Base {
static childProp: number;
static staticNumber1(): number {
return 1;
}
@ -57,6 +58,7 @@ class Test extends Base {
static staticNumber3(): number {
return 3;
}
instNumber1(): number {
return 1;
}
@ -64,8 +66,8 @@ class Test extends Base {
return 2;
}
}
module.exports = Test;
"
module.exports = Test;"
`;
exports[`test CommonJS_Clobbering_Lit.js 1`] = `
@ -86,14 +88,14 @@ module.exports = {
* @providesModule CommonJS_Clobbering_Lit
* @flow
*/
module.exports = {
numberValue1: 1,
numberValue2: 2,
numberValue3: 3,
numberValue4: 4,
numberValue5: 5
};
"
};"
`;
exports[`test CommonJS_Named.js 1`] = `
@ -112,12 +114,12 @@ exports.numberValue5 = 5;
* @providesModule CommonJS_Named
* @flow
*/
exports.numberValue1 = 1;
exports.numberValue2 = 2;
exports.numberValue3 = 3;
exports.numberValue4 = 4;
exports.numberValue5 = 5;
"
exports.numberValue5 = 5;"
`;
exports[`test ES6_Default_AnonFunction1.js 1`] = `
@ -132,8 +134,8 @@ declare export default () => number;
* @providesModule ES6_Default_AnonFunction1
* @flow
*/
declare export default () => number
"
declare export default () => number"
`;
exports[`test ES6_Default_AnonFunction2.js 1`] = `
@ -148,8 +150,8 @@ declare export default () =>number;
* @providesModule ES6_Default_AnonFunction2
* @flow
*/
declare export default () => number
"
declare export default () => number"
`;
exports[`test ES6_Default_NamedClass1.js 1`] = `
@ -170,13 +172,14 @@ declare export function getAFoo(): FooImpl;
* @providesModule ES6_Default_NamedClass1
* @flow
*/
declare export default class FooImpl { givesANum(): number }
// Regression test for https://github.com/facebook/flow/issues/511
//
// Default-exported class should also be available in local scope
declare export default class FooImpl { givesANum(): number }
declare export {FooImpl as Foo}
declare export function getAFoo(): FooImpl;
"
declare export function getAFoo(): FooImpl;"
`;
exports[`test ES6_Default_NamedClass2.js 1`] = `
@ -191,6 +194,7 @@ declare export default class Foo { givesANum(): number; };
* @providesModule ES6_Default_NamedClass2
* @flow
*/
declare export default class Foo { givesANum(): number }
"
`;
@ -207,8 +211,8 @@ declare export default function foo():number;
* @providesModule ES6_Default_NamedFunction1
* @flow
*/
declare export default function foo(): number;
"
declare export default function foo(): number;"
`;
exports[`test ES6_Default_NamedFunction2.js 1`] = `
@ -223,8 +227,8 @@ declare export default function foo():number;
* @providesModule ES6_Default_NamedFunction2
* @flow
*/
declare export default function foo(): number;
"
declare export default function foo(): number;"
`;
exports[`test ES6_DefaultAndNamed.js 1`] = `
@ -234,9 +238,9 @@ declare export default number;
declare export var str: string;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
declare export default number
declare export var str: string;
"
declare export var str: string;"
`;
exports[`test ES6_ExportAllFrom_Intermediary1.js 1`] = `
@ -251,8 +255,8 @@ declare export * from \"ES6_ExportAllFrom_Source1\";
* @providesModule ES6_ExportAllFrom_Intermediary1
* @flow
*/
declare export * from \"ES6_ExportAllFrom_Source1\"
"
declare export * from \"ES6_ExportAllFrom_Source1\""
`;
exports[`test ES6_ExportAllFrom_Intermediary2.js 1`] = `
@ -267,8 +271,8 @@ declare export * from \"ES6_ExportAllFrom_Source2\";
* @providesModule ES6_ExportAllFrom_Intermediary2
* @flow
*/
declare export * from \"ES6_ExportAllFrom_Source2\"
"
declare export * from \"ES6_ExportAllFrom_Source2\""
`;
exports[`test ES6_ExportAllFrom_Source1.js 1`] = `
@ -283,8 +287,8 @@ declare export var numberValue1: number;
* @providesModule ES6_ExportAllFrom_Source1
* @flow
*/
declare export var numberValue1: number;
"
declare export var numberValue1: number;"
`;
exports[`test ES6_ExportAllFrom_Source2.js 1`] = `
@ -299,8 +303,8 @@ declare export var numberValue2: number;
* @providesModule ES6_ExportAllFrom_Source2
* @flow
*/
declare export var numberValue2: number;
"
declare export var numberValue2: number;"
`;
exports[`test ES6_ExportAllFromMulti.js 1`] = `
@ -310,9 +314,9 @@ declare export * from \"./ES6_ExportAllFrom_Source1\";
declare export * from \"./ES6_ExportAllFrom_Source2\";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
declare export * from \"./ES6_ExportAllFrom_Source1\"
declare export * from \"./ES6_ExportAllFrom_Source2\"
"
declare export * from \"./ES6_ExportAllFrom_Source2\""
`;
exports[`test ES6_ExportFrom_Intermediary1.js 1`] = `
@ -330,8 +334,8 @@ declare export {
* @providesModule ES6_ExportFrom_Intermediary1
* @flow
*/
declare export {numberValue1, numberValue2 as numberValue2_renamed} from \"ES6_ExportFrom_Source1\"
"
declare export {numberValue1, numberValue2 as numberValue2_renamed} from \"ES6_ExportFrom_Source1\""
`;
exports[`test ES6_ExportFrom_Intermediary2.js 1`] = `
@ -349,8 +353,8 @@ declare export {
* @providesModule ES6_ExportFrom_Intermediary2
* @flow
*/
declare export {numberValue1, numberValue2 as numberValue2_renamed2} from \"ES6_ExportFrom_Source2\"
"
declare export {numberValue1, numberValue2 as numberValue2_renamed2} from \"ES6_ExportFrom_Source2\""
`;
exports[`test ES6_ExportFrom_Source1.js 1`] = `
@ -366,9 +370,9 @@ declare export var numberValue2: number;
* @providesModule ES6_ExportFrom_Source1
* @flow
*/
declare export var numberValue1: number;
declare export var numberValue2: number;
"
declare export var numberValue2: number;"
`;
exports[`test ES6_ExportFrom_Source2.js 1`] = `
@ -384,9 +388,9 @@ declare export var numberValue2: number;
* @providesModule ES6_ExportFrom_Source2
* @flow
*/
declare export var numberValue1: number;
declare export var numberValue2: number;
"
declare export var numberValue2: number;"
`;
exports[`test ES6_Named1.js 1`] = `
@ -416,20 +420,23 @@ declare export var varDeclNumber2: number;
* @providesModule ES6_Named1
* @flow
*/
var specifierNumber1 = 1;
var specifierNumber2 = 2;
var specifierNumber3 = 3;
var groupedSpecifierNumber1 = 1;
var groupedSpecifierNumber2 = 2;
declare export {specifierNumber1}
declare export {specifierNumber2 as specifierNumber2Renamed}
declare export {specifierNumber3}
declare export {groupedSpecifierNumber1, groupedSpecifierNumber2}
declare export function givesANumber(): number;
declare export class NumberGenerator { givesANumber(): number }
declare export var varDeclNumber1: number;
declare export var varDeclNumber2: number;
"
declare export var varDeclNumber2: number;"
`;
exports[`test ES6_Named2.js 1`] = `
@ -457,18 +464,21 @@ declare export var varDeclNumber4: number;
* @providesModule ES6_Named2
* @flow
*/
var specifierNumber4 = 1;
var specifierNumber5 = 2;
var groupedSpecifierNumber3 = 1;
var groupedSpecifierNumber4 = 2;
declare export {specifierNumber4}
declare export {specifierNumber5 as specifierNumber5Renamed}
declare export {groupedSpecifierNumber3, groupedSpecifierNumber4}
declare export function givesANumber2(): number;
declare export class NumberGenerator2 { givesANumber(): number }
declare export var varDeclNumber3: number;
declare export var varDeclNumber4: number;
"
declare export var varDeclNumber4: number;"
`;
exports[`test ProvidesModuleA.js 1`] = `
@ -487,12 +497,12 @@ exports.stringValue = \"str\";
* @providesModule A
* @flow
*/
exports.numberValue1 = 42;
exports.numberValue2 = 42;
exports.numberValue3 = 42;
exports.numberValue4 = 42;
exports.stringValue = \"str\";
"
exports.stringValue = \"str\";"
`;
exports[`test ProvidesModuleCJSDefault.js 1`] = `
@ -509,8 +519,8 @@ module.exports = {
* @providesModule CJSDefault
* @flow
*/
module.exports = { numberValue: 42 };
"
module.exports = { numberValue: 42 };"
`;
exports[`test ProvidesModuleD.js 1`] = `
@ -519,11 +529,6 @@ exports[`test ProvidesModuleD.js 1`] = `
* @flow
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @providesModule D
* @flow
*/
"
`;
@ -539,24 +544,12 @@ export default {
};
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @providesModule ES6Default
* @flow
*/
/*
export default {
numberValue: 42,
};
*/
"
`;
exports[`test SideEffects.js 1`] = `
"/* @flow */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
"
`;
@ -854,271 +847,274 @@ var at3: number = numberValue9;
var at4: string = numberValue9; // Error: number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// ===================== //
// == Path Resolution == //
// ===================== //
// @providesModule
import * as DefaultA from \"A\";
var a1: number = DefaultA.numberValue1;
var a2: string = DefaultA.numberValue1;
// Error: number ~> string
// File path
import * as DefaultB from \"./B\";
var b1: number = DefaultB.numberValue;
var b2: string = DefaultB.numberValue;
// Error: number ~> string
// C.js exists, but not as a providesModule
import DefaultC from \"C\";
// Error: No such module
// @providesModule D exists, but not as a filename
import DefaultD from \"./D\";
// Error: No such module
// ================================================ //
// == CommonJS Clobbering Literal Exports -> ES6 == //
// ================================================ //
import {doesntExist1} from \"CommonJS_Clobbering_Lit\";
// Error: Not an exported binding
import {numberValue1} from \"CommonJS_Clobbering_Lit\";
var c1: number = numberValue1;
var c2: string = numberValue1;
// Error: number ~> string
import {numberValue2 as numVal1} from \"CommonJS_Clobbering_Lit\";
var d1: number = numVal1;
var d2: string = numVal1;
// Error: number ~> string
import CJS_Clobb_Lit from \"CommonJS_Clobbering_Lit\";
var e1: number = CJS_Clobb_Lit.numberValue3;
var e2: string = CJS_Clobb_Lit.numberValue3;
// Error: number ~> string
CJS_Clobb_Lit.doesntExist;
// Error: doesntExist isn\'t a property
import * as CJS_Clobb_Lit_NS from \"CommonJS_Clobbering_Lit\";
var f1: number = CJS_Clobb_Lit_NS.numberValue4;
var f2: number = CJS_Clobb_Lit_NS.default.numberValue4;
CJS_Clobb_Lit_NS.default.default;
// Error: No \'default\' property on the exported obj
var f3: string = CJS_Clobb_Lit_NS.numberValue4;
// Error: number ~> string
var f4: string = CJS_Clobb_Lit_NS.default.numberValue5;
// Error: number ~> string
// ============================================== //
// == CommonJS Clobbering Class Exports -> ES6 == //
// ============================================== //
import {doesntExist2} from \"CommonJS_Clobbering_Class\";
// Error: Not an exported binding
// The following import should error because class statics are not turned into
// named exports for now. This avoids complexities with polymorphic static
// members (where the polymophism is defined on the class itself rather than the
// method).
import {staticNumber1, baseProp, childProp} from \"CommonJS_Clobbering_Class\";
// Error
import CJS_Clobb_Class from \"CommonJS_Clobbering_Class\";
new CJS_Clobb_Class();
new CJS_Clobb_Class().doesntExist;
// Error: Class has no \`doesntExist\` property
var h1: number = CJS_Clobb_Class.staticNumber2();
var h2: string = CJS_Clobb_Class.staticNumber2();
// Error: number ~> string
var h3: number = new CJS_Clobb_Class().instNumber1();
var h4: string = new CJS_Clobb_Class().instNumber1();
// Error: number ~> string
import * as CJS_Clobb_Class_NS from \"CommonJS_Clobbering_Class\";
new CJS_Clobb_Class_NS();
// Error: Namespace object isn\'t constructable
var i1: number = CJS_Clobb_Class_NS.staticNumber3();
// Error: Class statics not copied to Namespace object
var i2: number = new CJS_Clobb_Class_NS.default().instNumber2();
var i3: string = new CJS_Clobb_Class_NS.default().instNumber2();
// Error: number ~> string
// =================================== //
// == CommonJS Named Exports -> ES6 == //
// =================================== //
import {doesntExist3} from \"CommonJS_Named\";
// Error: Not an exported binding
import {numberValue2} from \"CommonJS_Named\";
var j1: number = numberValue2;
var j2: string = numberValue2;
// Error: number ~> string
import {numberValue3 as numVal3} from \"CommonJS_Named\";
var k1: number = numVal3;
var k2: string = numVal3;
// Error: number ~> string
import * as CJS_Named from \"CommonJS_Named\";
var l1: number = CJS_Named.numberValue1;
var l2: string = CJS_Named.numberValue1;
// Error: number ~> string
CJS_Named.doesntExist;
// Error: doesntExist isn\'t a property
import * as CJS_Named_NS from \"CommonJS_Named\";
var m1: number = CJS_Named_NS.numberValue4;
var m2: string = CJS_Named_NS.default.numberValue4;
// Error: CommonJS_Named has no default export
var m3: string = CJS_Named_NS.numberValue4;
// Error: number ~> string
//////////////////////////////
// == ES6 Default -> ES6 == //
//////////////////////////////
import {doesntExist4} from \"ES6_Default_AnonFunction1\";
// Error: Not an exported binding
import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\";
var n1: number = ES6_Def_AnonFunc1();
var n2: string = ES6_Def_AnonFunc1();
// Error: number ~> string
import ES6_Def_NamedFunc1 from \"ES6_Default_NamedFunction1\";
var o1: number = ES6_Def_NamedFunc1();
var o2: string = ES6_Def_NamedFunc1();
// Error: number ~> string
import ES6_Def_NamedClass1 from \"ES6_Default_NamedClass1\";
var q1: number = new ES6_Def_NamedClass1().givesANum();
var q2: string = new ES6_Def_NamedClass1().givesANum();
// Error: number ~> string
////////////////////////////
// == ES6 Named -> ES6 == //
////////////////////////////
// Error: Not an exported binding
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
///////////////////////////////////
// == ES6 Default -> CommonJS == //
///////////////////////////////////
// Error: \'doesntExist\' isn\'t an export
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
/////////////////////////////////
// == ES6 Named -> CommonJS == //
/////////////////////////////////
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
////////////////////////////////////////////////////////
// == ES6 Default+Named -> ES6 import Default+Named== //
////////////////////////////////////////////////////////
// Error: number ~> string
// Error: string ~> number
////////////////////////////////////////
// == Side-effect only ES6 imports == //
////////////////////////////////////////
//////////////////////////////////////////////
// == Suggest export name on likely typo == //
//////////////////////////////////////////////
// Error: Did you mean \`import {specifierNumber1} from ...\`?
// Error: Did you mean \`specifierNumber1\`?
///////////////////////////////////////////////////
// == Multi \`export *\` should combine exports == //
///////////////////////////////////////////////////
// Error: number ~> string
// Error: number ~> string
import * as DefaultA from \"A\";
var a1: number = DefaultA.numberValue1;
var a2: string = DefaultA.numberValue1;
import * as DefaultB from \"./B\";
var b1: number = DefaultB.numberValue;
var b2: string = DefaultB.numberValue;
import DefaultC from \"C\";
import DefaultD from \"./D\";
import {doesntExist1} from \"CommonJS_Clobbering_Lit\";
import {numberValue1} from \"CommonJS_Clobbering_Lit\";
var c1: number = numberValue1;
var c2: string = numberValue1;
import {numberValue2 as numVal1} from \"CommonJS_Clobbering_Lit\";
var d1: number = numVal1;
var d2: string = numVal1;
import CJS_Clobb_Lit from \"CommonJS_Clobbering_Lit\";
var e1: number = CJS_Clobb_Lit.numberValue3;
var e2: string = CJS_Clobb_Lit.numberValue3;
CJS_Clobb_Lit.doesntExist;
import * as CJS_Clobb_Lit_NS from \"CommonJS_Clobbering_Lit\";
var f1: number = CJS_Clobb_Lit_NS.numberValue4;
var f2: number = CJS_Clobb_Lit_NS.default.numberValue4;
CJS_Clobb_Lit_NS.default.default;
var f3: string = CJS_Clobb_Lit_NS.numberValue4;
var f4: string = CJS_Clobb_Lit_NS.default.numberValue5;
import {doesntExist2} from \"CommonJS_Clobbering_Class\";
import {staticNumber1, baseProp, childProp} from \"CommonJS_Clobbering_Class\";
import CJS_Clobb_Class from \"CommonJS_Clobbering_Class\";
new CJS_Clobb_Class();
new CJS_Clobb_Class().doesntExist;
var h1: number = CJS_Clobb_Class.staticNumber2();
var h2: string = CJS_Clobb_Class.staticNumber2();
var h3: number = new CJS_Clobb_Class().instNumber1();
var h4: string = new CJS_Clobb_Class().instNumber1();
import * as CJS_Clobb_Class_NS from \"CommonJS_Clobbering_Class\";
new CJS_Clobb_Class_NS();
var i1: number = CJS_Clobb_Class_NS.staticNumber3();
var i2: number = new CJS_Clobb_Class_NS.default().instNumber2();
var i3: string = new CJS_Clobb_Class_NS.default().instNumber2();
import {doesntExist3} from \"CommonJS_Named\";
import {numberValue2} from \"CommonJS_Named\";
var j1: number = numberValue2;
var j2: string = numberValue2;
import {numberValue3 as numVal3} from \"CommonJS_Named\";
var k1: number = numVal3;
var k2: string = numVal3;
import * as CJS_Named from \"CommonJS_Named\";
var l1: number = CJS_Named.numberValue1;
var l2: string = CJS_Named.numberValue1;
CJS_Named.doesntExist;
import * as CJS_Named_NS from \"CommonJS_Named\";
var m1: number = CJS_Named_NS.numberValue4;
var m2: string = CJS_Named_NS.default.numberValue4;
var m3: string = CJS_Named_NS.numberValue4;
import {doesntExist4} from \"ES6_Default_AnonFunction1\";
import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\";
var n1: number = ES6_Def_AnonFunc1();
var n2: string = ES6_Def_AnonFunc1();
import ES6_Def_NamedFunc1 from \"ES6_Default_NamedFunction1\";
var o1: number = ES6_Def_NamedFunc1();
var o2: string = ES6_Def_NamedFunc1();
import ES6_Def_NamedClass1 from \"ES6_Default_NamedClass1\";
var q1: number = new ES6_Def_NamedClass1().givesANum();
var q2: string = new ES6_Def_NamedClass1().givesANum();
import doesntExist5 from \"ES6_Named1\";
// Error: Not an exported binding
import {specifierNumber1 as specifierNumber1_1} from \"ES6_Named1\";
var r1: number = specifierNumber1_1;
var r2: string = specifierNumber1_1;
// Error: number ~> string
import {specifierNumber2Renamed} from \"ES6_Named1\";
var s1: number = specifierNumber2Renamed;
var s2: string = specifierNumber2Renamed;
// Error: number ~> string
import {specifierNumber3 as specifierNumber3Renamed} from \"ES6_Named1\";
var t1: number = specifierNumber3Renamed;
var t2: string = specifierNumber3Renamed;
// Error: number ~> string
import {groupedSpecifierNumber1, groupedSpecifierNumber2} from \"ES6_Named1\";
var u1: number = groupedSpecifierNumber1;
var u2: number = groupedSpecifierNumber2;
var u3: string = groupedSpecifierNumber1;
// Error: number ~> string
var u4: string = groupedSpecifierNumber2;
// Error: number ~> string
import {givesANumber} from \"ES6_Named1\";
var v1: number = givesANumber();
var v2: string = givesANumber();
// Error: number ~> string
import {NumberGenerator} from \"ES6_Named1\";
var w1: number = new NumberGenerator().givesANumber();
var w2: string = new NumberGenerator().givesANumber();
// Error: number ~> string
import {varDeclNumber1, varDeclNumber2} from \"ES6_Named1\";
var x1: number = varDeclNumber1;
var x2: number = varDeclNumber2;
var x3: string = varDeclNumber1;
// Error: number ~> string
var x4: string = varDeclNumber2;
// Error: number ~> string
import {numberValue1 as numberValue4} from \"ES6_ExportFrom_Intermediary1\";
var aa1: number = numberValue4;
var aa2: string = numberValue4;
// Error: number ~> string
import {numberValue2_renamed} from \"ES6_ExportFrom_Intermediary1\";
var ab1: number = numberValue2_renamed;
var ab2: string = numberValue2_renamed;
// Error: number ~> string
import {numberValue1 as numberValue5} from \"ES6_ExportAllFrom_Intermediary1\";
var ac1: number = numberValue5;
var ac2: string = numberValue5;
// Error: number ~> string
///////////////////////////////////
// == ES6 Default -> CommonJS == //
///////////////////////////////////
require(\"ES6_Default_AnonFunction2\").doesntExist;
// Error: \'doesntExist\' isn\'t an export
var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default;
var ad1: number = ES6_Def_AnonFunc2();
var ad2: string = ES6_Def_AnonFunc2();
// Error: number ~> string
var ES6_Def_NamedFunc2 = require(\"ES6_Default_NamedFunction2\").default;
var ae1: number = ES6_Def_NamedFunc2();
var ae2: string = ES6_Def_NamedFunc2();
// Error: number ~> string
var ES6_Def_NamedClass2 = require(\"ES6_Default_NamedClass2\").default;
var ag1: number = new ES6_Def_NamedClass2().givesANum();
var ag2: string = new ES6_Def_NamedClass2().givesANum();
// Error: number ~> string
/////////////////////////////////
// == ES6 Named -> CommonJS == //
/////////////////////////////////
var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4;
var ah1: number = specifierNumber4;
var ah2: string = specifierNumber4;
// Error: number ~> string
var specifierNumber5Renamed = require(\"ES6_Named2\").specifierNumber5Renamed;
var ai1: number = specifierNumber5Renamed;
var ai2: string = specifierNumber5Renamed;
// Error: number ~> string
var groupedSpecifierNumber3 = require(\"ES6_Named2\").groupedSpecifierNumber3;
var groupedSpecifierNumber4 = require(\"ES6_Named2\").groupedSpecifierNumber4;
var aj1: number = groupedSpecifierNumber3;
var aj2: number = groupedSpecifierNumber4;
var aj3: string = groupedSpecifierNumber3;
// Error: number ~> string
var aj4: string = groupedSpecifierNumber4;
// Error: number ~> string
var givesANumber2 = require(\"ES6_Named2\").givesANumber2;
var ak1: number = givesANumber2();
var ak2: string = givesANumber2();
// Error: number ~> string
var NumberGenerator2 = require(\"ES6_Named2\").NumberGenerator2;
var al1: number = new NumberGenerator2().givesANumber();
var al2: string = new NumberGenerator2().givesANumber();
// Error: number ~> string
var varDeclNumber3 = require(\"ES6_Named2\").varDeclNumber3;
var varDeclNumber4 = require(\"ES6_Named2\").varDeclNumber4;
var am1: number = varDeclNumber3;
var am2: number = varDeclNumber4;
var am3: string = varDeclNumber3;
// Error: number ~> string
var am4: string = varDeclNumber4;
// Error: number ~> string
var numberValue6 = require(\"ES6_ExportFrom_Intermediary2\").numberValue1;
var ap1: number = numberValue6;
var ap2: string = numberValue6;
// Error: number ~> string
var numberValue2_renamed2 = require(
\"ES6_ExportFrom_Intermediary2\"
).numberValue2_renamed2;
var aq1: number = numberValue2_renamed2;
var aq2: string = numberValue2_renamed2;
// Error: number ~> string
var numberValue7 = require(\"ES6_ExportAllFrom_Intermediary2\").numberValue2;
var ar1: number = numberValue7;
var ar2: string = numberValue7;
// Error: number ~> string
////////////////////////////////////////////////////////
// == ES6 Default+Named -> ES6 import Default+Named== //
////////////////////////////////////////////////////////
import defaultNum, {str as namedStr} from \"./ES6_DefaultAndNamed\";
var as1: number = defaultNum;
var as2: string = defaultNum;
// Error: number ~> string
var as3: string = namedStr;
var as4: number = namedStr;
// Error: string ~> number
////////////////////////////////////////
// == Side-effect only ES6 imports == //
////////////////////////////////////////
import \"./SideEffects\";
//////////////////////////////////////////////
// == Suggest export name on likely typo == //
//////////////////////////////////////////////
import specifierNumber1 from \"ES6_Named1\";
// Error: Did you mean \`import {specifierNumber1} from ...\`?
import {specifierNumber} from \"ES6_Named1\";
// Error: Did you mean \`specifierNumber1\`?
///////////////////////////////////////////////////
// == Multi \`export *\` should combine exports == //
///////////////////////////////////////////////////
import {numberValue1 as numberValue8, numberValue2 as numberValue9} from \"./ES6_ExportAllFromMulti\";
var at1: number = numberValue8;
var at2: string = numberValue8;
// Error: number ~> string
var at3: number = numberValue9;
var at4: string = numberValue9;
"
var at4: string = numberValue9; // Error: number ~> string"
`;

View File

@ -7,14 +7,13 @@ declare function foo<X>(x: X): X;
(foo(\"hello\"): number); // OK
(foo(false): void); // error, boolean ~/~ undefined
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// OK
// OK
// error, boolean ~/~ undefined
declare function foo(x: number): string;
declare function foo(x: string): number;
declare function foo<X>(x: X): X;
(foo(0): string);
// OK
(foo(\"hello\"): number);
(foo(false): void);
"
// OK
(foo(false): void); // error, boolean ~/~ undefined"
`;

View File

@ -26,27 +26,27 @@ import declare_m_e_with_declare_var_e from \"declare_m_e_with_declare_var_e\";
(declare_m_e_with_declare_var_e: string); // Error: number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
import declare_module_exports from \"declare_module_exports\";
(declare_module_exports: number);
(declare_module_exports: string);
// Error: number ~> string
// Error: Has no named export \"str\"!
import {str} from \"declare_m_e_with_other_value_declares\";
import type {str2} from \"declare_m_e_with_other_type_declares\";
(\"asdf\": str2);
(42: str2);
// Error: number ~> string
/**
* \`declare var exports\` is deprecated, so we have a grace period where both
* syntaxes will work.
*/
// Error: number ~> string
// Error: number ~> string
import declare_module_exports from \"declare_module_exports\";
(declare_module_exports: number);
(declare_module_exports: string);
import {str} from \"declare_m_e_with_other_value_declares\";
import type {str2} from \"declare_m_e_with_other_type_declares\";
(\"asdf\": str2);
(42: str2);
import DEPRECATED__declare_var_exports from \"DEPRECATED__declare_var_exports\";
(DEPRECATED__declare_var_exports: number);
(DEPRECATED__declare_var_exports: string);
// Error: number ~> string
import declare_m_e_with_declare_var_e from \"declare_m_e_with_declare_var_e\";
(declare_m_e_with_declare_var_e: number);
(declare_m_e_with_declare_var_e: string);
"
(declare_m_e_with_declare_var_e: string); // Error: number ~> string"
`;

View File

@ -30,13 +30,6 @@ declare module \"declare_m_e_with_declare_var_e\" {
declare var exports: string;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* \`declare var exports\` is deprecated, so we have a grace period where both
* syntaxes will work.
*/
/**
* Ensure that, if both are present, \`declare module.exports\` wins
*/
declare module \"declare_module_exports\" {
declare module.exports: number;
}
@ -48,12 +41,18 @@ declare module \"declare_m_e_with_other_type_declares\" {
declare module.exports: number;
declare type str2 = string;
}
/**
* \`declare var exports\` is deprecated, so we have a grace period where both
* syntaxes will work.
*/
declare module \"DEPRECATED__declare_var_exports\" {
declare var exports: number;
/**
* Ensure that, if both are present, \`declare module.exports\` wins
*/
}
declare module \"declare_m_e_with_declare_var_e\" {
declare module.exports: number;
declare var exports: string;
}
"
}"
`;

View File

@ -33,30 +33,31 @@ blah(0, 0);
/**
* @flow
*/
////////////////////////////////////////////////////////////
// == Import Declared Type Alias From Declared Module == //
//////////////////////////////////////////////////////////
// Error: string to int
// works
// works
//////////////////////////////////////////////////////////
// == Declared Module with exports prop (issue 880) == //
////////////////////////////////////////////////////////
// error : {toz : number} ~> string
// error : number ~> A
// error : string ~> number
import type {baz} from \"ModuleAliasFoo\";
import {foo} from \"ModuleAliasFoo\";
var k1: baz = 42;
var k2: baz = \"shab\";
// Error: string to int
var k3: toz = foo(k1);
// works
import type {toz} from \"ModuleAliasFoo\";
var k4: toz = foo(k1);
// works
//////////////////////////////////////////////////////////
// == Declared Module with exports prop (issue 880) == //
////////////////////////////////////////////////////////
import blah from \"foo\";
import type {Foo, Bar, Id} from \"foo\";
blah(0, 0);
({ toz: 3 }: Foo);
// error : {toz : number} ~> string
(3: Bar);
(\"lol\": Id<number>);
"
// error : number ~> A
(\"lol\": Id<number>); // error : string ~> number"
`;

View File

@ -12,12 +12,12 @@ declare module ModuleAliasFoo {
/**
* @flow
*/
declare module ModuleAliasFoo {
declare type baz = number;
declare type toz = string;
declare function foo(bar: baz): toz;
}
"
}"
`;
exports[`test declare_type_exports.js 1`] = `
@ -40,13 +40,16 @@ declare module \'foo\' {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
declare module \"foo\" {
declare class A { toz: number }
declare var n: string;
declare type Foo = typeof n;
declare type Bar = A;
declare type Id<T> = T;
declare var exports: { (a: number, b: number): number };
}
"
}"
`;

View File

@ -31,20 +31,6 @@ class PropVariance<+Out,-In> {
con_dict2: {-[k:string]: In}; // ok
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error on both targs (A ~/~> B)
// OK for both targs (B ~> A)
// error
// error
// error
// ok
// ok
// error
// error
// error
// ok
// error
// error
// ok
class Variance<+Out, -In> {
foo(x: Out): Out {
return x;
@ -53,25 +39,39 @@ class Variance<+Out, -In> {
return y;
}
}
class A {}
class B extends A {}
function subtyping(v1: Variance<A, B>, v2: Variance<B, A>) {
(v1: Variance<B, A>);
(v2: Variance<A, B>);
// error on both targs (A ~/~> B)
(v2: Variance<A, B>); // OK for both targs (B ~> A)
}
class PropVariance<+Out, -In> {
inv1: Out;
// error
inv2: In;
// error
-co1: Out;
// error
-co2: In;
// ok
+con1: Out;
// ok
+con2: In;
// error
inv_dict1: { [k: string]: Out };
// error
inv_dict2: { [k: string]: In };
// error
co_dict1: { +[k: string]: Out };
// ok
co_dict2: { +[k: string]: In };
// error
con_dict1: { -[k: string]: Out };
con_dict2: { -[k: string]: In };
}
"
// error
con_dict2: { -[k: string]: In }; // ok
}"
`;

View File

@ -9,11 +9,12 @@ var x = null;
f(x);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* demo */
//...
function f(x) {
return 42 / x;
}
var x = null;
f(x);
"
//...
f(x);"
`;

View File

@ -20,26 +20,31 @@ a.onLoad(callback);
module.exports = A;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @providesModule Demo */
// instance field declaration
class A {
x: number;
// instance field declaration
constructor(x) {
this.x = x;
}
getX() {
return this.x;
}
onLoad(callback) {
return callback(this.getX());
}
}
function callback(x: string) {
return x.length;
}
var a = new A(42);
a.onLoad(callback);
module.exports = A;
"
module.exports = A;"
`;
exports[`test B.js 1`] = `
@ -48,6 +53,6 @@ exports[`test B.js 1`] = `
var z = new A(\"42\").getX();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var A = require(\"Demo\");
var z = new A(\"42\").getX();
"
var z = new A(\"42\").getX();"
`;

View File

@ -1,15 +1,13 @@
exports[`test A.js 1`] = `
"require(\'./C\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./C\");
"
require(\"./C\");"
`;
exports[`test B.js 1`] = `
"require(\'./C\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./C\");
"
require(\"./C\");"
`;
exports[`test C.js 1`] = `
@ -21,50 +19,41 @@ require(\'./G\');
require(\"./D\");
require(\"./E\");
require(\"./F\");
require(\"./G\");
"
require(\"./G\");"
`;
exports[`test D.js 1`] = `
"require(\'./I\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./I\");
"
require(\"./I\");"
`;
exports[`test E.js 1`] = `
"require(\'./I\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./I\");
"
require(\"./I\");"
`;
exports[`test F.js 1`] = `
"// empty
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// empty
"
`;
exports[`test G.js 1`] = `
"require(\'./H\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./H\");
"
require(\"./H\");"
`;
exports[`test H.js 1`] = `
"// empty
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// empty
"
`;
exports[`test I.js 1`] = `
"require(\'./A\');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(\"./A\");
"
require(\"./A\");"
`;

View File

@ -12,23 +12,22 @@ let d = zs[1]; // run off the end
let [...e] = 0;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// retain tuple info
// run off the end
// error: number ~> void
// error: string ~> void
// error: boolean ~> void
// error: number|string|boolean ~> void
let xs = [ 0, \"\", true ];
let [ a, ...ys ] = xs;
let [ b, ...zs ] = ys;
let c = zs[0];
// retain tuple info
let d = zs[1];
// run off the end
(a: void);
// error: number ~> void
(b: void);
// error: string ~> void
(c: void);
// error: boolean ~> void
(d: void);
let [ ...e ] = 0;
"
// error: number|string|boolean ~> void
let [ ...e ] = 0;"
`;
exports[`test computed.js 1`] = `
@ -42,17 +41,15 @@ var { [key]: val2 } = { key: \"val\" };
var { [\"key\"]: val3, ...spread } = { key: \"val\" };
(spread.key: void); // error (gasp!) in general we don\'t know if a computed prop should be excluded from spread
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: string ~> void
// ok (gasp!) by existing StrT -> ElemT rule
// error (gasp!) in general we don\'t know if a computed prop should be excluded from spread
var { [\"key\"]: val1 } = { key: \"val\" };
(val1: void);
// error: string ~> void
var key: string = \"key\";
var { [key]: val2 } = { key: \"val\" };
(val2: void);
// ok (gasp!) by existing StrT -> ElemT rule
var { [\"key\"]: val3, ...spread } = { key: \"val\" };
(spread.key: void);
"
(spread.key: void); // error (gasp!) in general we don\'t know if a computed prop should be excluded from spread"
`;
exports[`test defaults.js 1`] = `
@ -140,90 +137,104 @@ function obj_prop_union2({p}:{p:number}|{p:string}={p:true}) {}
function default_expr_scope({a, b = a}) {}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// errors:
// * number ~> void, from default on _.p.q
// * boolean ~> void, from default on _.p
// * string ~> void, from default on _
// * null ~> void, from call below
// ok
// ok
// ok
// ok, provides add\'l lower bound
// errors:
// * number ~> void, from default on o.p.q
// * boolean ~> void, from default on o.p
// * string ~> void, from default on o
// * null ~> void, from call below
// ok
// ok
// ok
// ok, provides add\'l lower bound
// errors:
// * number ~> void, from default on _.p
// * string ~> void, from default on _
// * null ~> void, from call below
// ok
// ok
// ok
// error: boolean ~> string
// error: number ~> string
// error: string ~> void
// error: boolean ~> string
// error: number ~> string
// error: string ~> void
// error: property \`x\` cannot be accessed on null
// error: expected object instead of number
// error: element 0 cannot be accessed on null
// error: expected array instead of null
// Default values in destructuring unwrap optional types
// ok
// ok
// union-like upper bounds preserved through destructuring
// TODO: union-of-objects upper bounds preserved through destructuring
function obj_prop_fun({ p: { q = 0 } = { q: true } } = { p: { q: \"\" } }) {
// errors:
// * number ~> void, from default on _.p.q
// * boolean ~> void, from default on _.p
// * string ~> void, from default on _
// * null ~> void, from call below
(q: void);
}
obj_prop_fun();
// ok
obj_prop_fun({});
// ok
obj_prop_fun({ p: {} });
// ok
obj_prop_fun({ p: { q: null } });
// ok, provides add\'l lower bound
function obj_prop_var(o = { p: { q: \"\" } }) {
var { p: { q = 0 } = { q: true } } = o;
// errors:
// * number ~> void, from default on o.p.q
// * boolean ~> void, from default on o.p
// * string ~> void, from default on o
// * null ~> void, from call below
(q: void);
}
obj_prop_var();
// ok
obj_prop_var({});
// ok
obj_prop_var({ p: {} });
// ok
obj_prop_var({ p: { q: null } });
// ok, provides add\'l lower bound
function obj_rest(
{ p: { q, ...o } = { q: 0, r: 0 } } = { p: { q: 0, r: \"\" } }
) {
// errors:
// * number ~> void, from default on _.p
// * string ~> void, from default on _
// * null ~> void, from call below
(o.r: void);
}
obj_rest();
// ok
obj_rest({});
// ok
obj_rest({ p: {} });
// ok
obj_rest({ p: { q: 0, r: null } });
function obj_prop_annot({ p = true }: { p: string } = { p: 0 }) {
(p: void);
function obj_prop_annot(
{
// error: boolean ~> string
p = true
}: { p: string } = {
// error: number ~> string
p: 0
}
) {
(p: void); // error: string ~> void
}
var { p = true }: { p: string } = { p: 0 };
var {
// error: boolean ~> string
p = true
}: { p: string } = {
// error: number ~> string
p: 0
};
(p: void);
// error: string ~> void
function obj_prop_err({ x: { y } } = null) {}
// error: property \`x\` cannot be accessed on null
function obj_rest_err({ ...o } = 0) {}
// error: expected object instead of number
function arr_elem_err([ x ] = null) {}
// error: element 0 cannot be accessed on null
function arr_rest_err([ ...a ] = null) {}
// error: expected array instead of null
function gen<T>(x: T, { p = x }: { p: T }): T {
return p;
}
// Default values in destructuring unwrap optional types
obj_prop_fun(({}: { p?: { q?: null } }));
// ok
obj_prop_var(({}: { p?: { q?: null } }));
// ok
// union-like upper bounds preserved through destructuring
function obj_prop_opt({ p }: { p?: string } = { p: 0 }) {}
function obj_prop_maybe({ p }: { p: ?string } = { p: 0 }) {}
function obj_prop_union({ p }: { p: number | string } = { p: true }) {}
// TODO: union-of-objects upper bounds preserved through destructuring
function obj_prop_union2({ p }: { p: number } | { p: string } = { p: true }) {}
function default_expr_scope({ a, b = a }) {}
"
function default_expr_scope({ a, b = a }) {}"
`;
exports[`test destructuring.js 1`] = `
@ -299,70 +310,81 @@ var cp1_err: string = childprop1; // Error: number ~> string
var cp2: number = others.childprop1;
var cp2_err: string = others.childprop2; // Error: number ~> string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error on foo
// error on baz
// error, baz doesn\'t exist
// no error, rest is unsealed
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
// Error: number ~> string
declare var a: string;
declare var b: string;
declare var c: string;
[ { a1: a, b }, c ] = [ { a1: 0, b: 1 }, 2 ];
var { m } = { m: 0 };
({ m } = { m: m });
var obj;
({ n: obj.x } = { n: 3 });
[ obj.x ] = [ \"foo\" ];
function foo({ p, z: [ r ] }) {
a = p;
b = z;
c = r;
}
foo({ p: 0, z: [ 1, 2 ] });
[ a, , b, ...c ] = [ 0, 1, true, 3 ];
function bar({ x, ...z }) {
var o: { x: string, y: number } = z;
}
bar({ x: \"\", y: 0 });
var spread = { y: \"\" };
var extend: { x: number, y: string, z: boolean } = { x: 0, ...spread };
function qux(_: { a: number }) {}
qux({ a: \"\" });
function corge({ b }: { b: string }) {}
corge({ b: 0 });
var { n }: { n: number } = { n: \"\" };
function test() {
var { foo } = { bar: 123 };
var { bar, baz } = { bar: 123 };
// error on foo
var { bar, baz } = { bar: 123 }; // error on baz
}
function test() {
var x = { foo: \"abc\", bar: 123 };
var { foo, ...rest } = x;
(x.baz: string);
(rest.baz: string);
// error, baz doesn\'t exist
(rest.baz: string); // no error, rest is unsealed
}
module.exports = corge;
class Base {
baseprop1: number;
baseprop2: number;
}
class Child extends Base {
childprop1: number;
childprop2: number;
}
var { baseprop1, childprop1, ...others } = new Child();
var bp1: number = baseprop1;
var bp1_err: string = baseprop1;
// Error: number ~> string
var bp2: number = others.baseprop2;
var bp2_err: string = others.baseprop2;
// Error: number ~> string
var cp1: number = childprop1;
var cp1_err: string = childprop1;
// Error: number ~> string
var cp2: number = others.childprop1;
var cp2_err: string = others.childprop2;
"
var cp2_err: string = others.childprop2; // Error: number ~> string"
`;
exports[`test destructuring_param.js 1`] = `
@ -379,27 +401,24 @@ exports[`test destructuring_param.js 1`] = `
// return a + b + c + d;
// }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function f(a, { b }) {
return a + b;
}
// TODO: These throw errors when parsing.
// function g(a, { a }) {
// return a;
// }
// function h({ a, { b } }, { c }, { { d } }) {
// return a + b + c + d;
// }
function f(a, { b }) {
return a + b;
}
"
// }"
`;
exports[`test eager.js 1`] = `
"var x;
({x} = null); // error, property \`x\` can not be accessed on \`null\`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, property \`x\` can not be accessed on \`null\`
var x;
({ x } = null);
"
({ x } = null); // error, property \`x\` can not be accessed on \`null\`"
`;
exports[`test poly.js 1`] = `
@ -437,44 +456,45 @@ function arr_rest_pattern<X>([ _, ...a ] : ArrRest<X>) { // a: [X]
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// prop: X
// prop: X
// elem: X
// elem: X
// proj: X
// proj: X
// nonsense
// r: X[]
// o: { x: X }
// o: { x: X }
// a: [X]
// a: [X]
function obj_pattern<X>({ prop }: { prop: X }) {}
// prop: X
type Prop<X> = { prop: X };
function obj_pattern2<X>({ prop }: Prop<X>) {}
// prop: X
function arr_pattern<X>([ elem ]: X[]) {}
// elem: X
type Elem<X> = X[];
function arr_pattern2<X>([ elem ]: Elem<X>) {}
// elem: X
function tup_pattern<X>([ proj ]: [X]) {}
// proj: X
type Proj<X> = [X];
function tup_pattern2<X>([ proj ]: Proj<X>) {}
// proj: X
function rest_antipattern<T>(...t: T) {}
// nonsense
function rest_pattern<X>(...r: X[]) {}
// r: X[]
function obj_rest_pattern<X>({ _, ...o }: { _: any, x: X }) {
// o: { x: X }
o.x;
}
type ObjRest<X> = { _: any, x: X };
function obj_rest_pattern<X>({ _, ...o }: ObjRest<X>) {
// o: { x: X }
o.x;
}
function arr_rest_pattern<X>([ _, ...a ]: [any, X]) {
// a: [X]
a[0];
}
type ArrRest<X> = [any, X];
function arr_rest_pattern<X>([ _, ...a ]: ArrRest<X>) {
// a: [X]
a[0];
}
"
}"
`;
exports[`test rec.js 1`] = `
@ -500,20 +520,24 @@ declare var o;
var { x: o } = o;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Make sure that destructuring doesn\'t cause infinite loops when combined with
// funny doses of repositioning
// Also make sure that the following doesn\'t loop
let foo = (i: number) => [ i ];
const bar = (i: number) => {
[ i ] = foo(i);
return [ i ];
};
foo = (i: number) => {
return bar(i);
};
// Also make sure that the following doesn\'t loop
declare var o;
var { x: o } = o;
"
var { x: o } = o;"
`;
exports[`test string_lit.js 1`] = `
@ -523,13 +547,11 @@ exports[`test string_lit.js 1`] = `
var { \"with-dash\": with_dash } = { \"with-dash\": \"motivating example\" };
(with_dash: \"motivating example\"); // ok
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: string ~> void
// ok
var { \"key\": val } = { key: \"val\" };
(val: void);
// error: string ~> void
var { \"with-dash\": with_dash } = { \"with-dash\": \"motivating example\" };
(with_dash: \"motivating example\");
"
(with_dash: \"motivating example\"); // ok"
`;
exports[`test unannotated.js 1`] = `
@ -544,9 +566,10 @@ function bar() {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
var { x } = { x: { foo: \"foo\" } };
function bar() {
x.bar;
}
"
}"
`;

View File

@ -6,11 +6,10 @@ const k: any = \'foo\'
const val: string = dict[k] // error: number incompatible with string
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error: number incompatible with string
const dict: { [key: string]: number } = {};
const k: any = \"foo\";
const val: string = dict[k];
"
const val: string = dict[k]; // error: number incompatible with string"
`;
exports[`test compatible.js 1`] = `
@ -31,21 +30,22 @@ function foo2(
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// this adds a fooBar property to the param type, which should NOT cause
// an error in the return type because it is a dictionary.
// x\'s prototype has a toString method
function foo0(
x: Array<{ [key: string]: mixed }>
): Array<{ [key: string]: mixed }> {
// this adds a fooBar property to the param type, which should NOT cause
// an error in the return type because it is a dictionary.
x[0].fooBar = \"foobar\";
return x;
}
function foo2(
x: { [key: string]: number }
): { [key: string]: number, +toString: () => string } {
// x\'s prototype has a toString method
return x;
}
"
}"
`;
exports[`test dictionary.js 1`] = `
@ -385,288 +385,310 @@ function subtype_optional_c_to_dict(
*
* @flow
*/
// Some logic is variance-sensitive.
class A {}
class B extends A {}
class C extends B {}
// Just a couple of short type names. Compare to string/number.
class X {}
class Y {}
// Any property can be set on a dict with string keys.
function set_prop_to_string_key(o: { [k: string]: any }) {
o.prop = \"ok\";
}
// **UNSOUND**
// This is allowed by design. We don\'t track get/set and we don\'t wrap the
// return type in a maybe.
// ok
// ok
function unsound_dict_has_every_key(o: { [k: string]: X }) {
(o.p: X);
// ok
(o[\"p\"]: X); // ok
}
// As with any object type, we can assign subtypes to properties.
// error, A ~> B
// ok
// ok
function set_prop_covariant(o: { [k: string]: B }) {
o.p = new A();
// error, A ~> B
o.p = new B();
// ok
o.p = new C(); // ok
}
// This isn\'t specific behavior to dictionaries, but for completeness...
// ok
// ok
// error, C ~> B
function get_prop_contravariant(o: { [k: string]: B }) {
(o.p: A);
// ok
(o.p: B);
// ok
(o.p: C); // error, C ~> B
}
// Dot-notation can not be used to add properties to dictionaries with
// non-string keys, because keys are strings.
// error: string ~> number
function add_prop_to_nonstring_key_dot(o: { [k: number]: any }) {
o.prop = \"err\"; // error: string ~> number
}
// Bracket notation can be used to add properties to dictionaries with
// non-string keys, even though all keys are strings. This is a convenient
// affordance.
function add_prop_to_nonstring_key_bracket(o: { [k: number]: any }) {
o[0] = \"ok\";
}
// Objects can be part dict, part not by mixing an indexer with declared props.
// ok
// ok
// ok
// ok
function mix_with_declared_props(o: { [k: number]: X, p: Y }, x: X, y: Y) {
(o[0]: X);
// ok
(o.p: Y);
// ok
o[0] = x;
// ok
o.p = y; // ok
}
// Indeed, dict types are still Objects and have Object.prototype stuff
// error: string ~> boolean
// ok
function object_prototype(
o: { [k: string]: number }
): { [k: string]: number, +toString: () => string } {
(o.toString(): boolean);
// error: string ~> boolean
return o; // ok
}
// **UNSOUND**
// Because we support non-string props w/ bracket notation, it\'s possible to
// write into a declared prop unsoundly.
// a[\"0\"] no longer X
// error
// in[0].p no longer B
// ok
// error
// not true
// error
// x[0].p no longer B
// ok
// error
// not true
// ok, A == A
// ok, B <: A
// ok, C <: A
// error, A not <: B
// ok, B == B
// ok, C <: A
// error, A not <: C
// error, A not <: C
// ok, C == C
function unsound_string_conversion_alias_declared_prop(
o: { [k: number]: any, \"0\": X }
) {
o[0] = \"not-x\"; // a[\"0\"] no longer X
}
function unification_dict_values_invariant(x: Array<{ [k: string]: B }>) {
let a: Array<{ [k: string]: A }> = x;
// error
a[0].p = new A();
// in[0].p no longer B
let b: Array<{ [k: string]: B }> = x;
// ok
let c: Array<{ [k: string]: C }> = x;
// error
(x[0].p: C); // not true
}
function subtype_dict_values_invariant(x: { [k: string]: B }) {
let a: { [k: string]: A } = x;
// error
a.p = new A();
// x[0].p no longer B
let b: { [k: string]: B } = x;
// ok
let c: { [k: string]: C } = x;
// error
(x.p: C); // not true
}
function subtype_dict_values_fresh_exception() {
let a: { [k: string]: A } = {
a: new A(),
// ok, A == A
b: new B(),
// ok, B <: A
// ok, C <: A
c: new C()
};
let b: { [k: string]: B } = {
a: new A(),
// error, A not <: B
b: new B(),
// ok, B == B
// ok, C <: A
c: new C()
};
let c: { [k: string]: C } = {
a: new A(),
// error, A not <: C
b: new B(),
// error, A not <: C
// ok, C == C
c: new C()
};
}
// Actually, unsound_string_conversion_alias_declared_prop behavior makes an
// argument that we shouldn\'t really care about this, since we ignore the fact
// that coercing values to string keys can cause unintended aliasing in general.
// Barring some compelling use case for that in this context, though, we choose
// to be strict.
// error
// ok
// error
// error
// ok
// error
// error: A ~> B
// x[0].p no longer B
// ok
// error
// not true
// error
// xa[0].p no longer B
// ok
// error
// not true
// error: A ~> B
// x.p no longer B
// ok
// error
// not true
// error
// xa.p no longer B
// ok
// error
// not true
// error: if allowed, could write {p:X,q:Y} into \`x\`
// error: if allowed, could write {p:X,q:Y} into returned array
// error
// x.p no longer B
// ok
// error
// not true
// error
// x.p no longer B
// error
// not true
// Only props in l which are not in u must match indexer, but must do so
// exactly.
// error (as above), but exclusive of x
// ok,
// error (as above), but exclusive of x
// error
// ok
// error
// error
// ok
// error
// error
// ok
// error
// error: A ~> B
// ok
// error: C ~> B
class A {}
class B extends A {}
class C extends B {}
class X {}
class Y {}
function set_prop_to_string_key(o: { [k: string]: any }) {
o.prop = \"ok\";
}
function unsound_dict_has_every_key(o: { [k: string]: X }) {
(o.p: X);
(o[\"p\"]: X);
}
function set_prop_covariant(o: { [k: string]: B }) {
o.p = new A();
o.p = new B();
o.p = new C();
}
function get_prop_contravariant(o: { [k: string]: B }) {
(o.p: A);
(o.p: B);
(o.p: C);
}
function add_prop_to_nonstring_key_dot(o: { [k: number]: any }) {
o.prop = \"err\";
}
function add_prop_to_nonstring_key_bracket(o: { [k: number]: any }) {
o[0] = \"ok\";
}
function mix_with_declared_props(o: { [k: number]: X, p: Y }, x: X, y: Y) {
(o[0]: X);
(o.p: Y);
o[0] = x;
o.p = y;
}
function object_prototype(
o: { [k: string]: number }
): { [k: string]: number, +toString: () => string } {
(o.toString(): boolean);
return o;
}
function unsound_string_conversion_alias_declared_prop(
o: { [k: number]: any, \"0\": X }
) {
o[0] = \"not-x\";
}
function unification_dict_values_invariant(x: Array<{ [k: string]: B }>) {
let a: Array<{ [k: string]: A }> = x;
a[0].p = new A();
let b: Array<{ [k: string]: B }> = x;
let c: Array<{ [k: string]: C }> = x;
(x[0].p: C);
}
function subtype_dict_values_invariant(x: { [k: string]: B }) {
let a: { [k: string]: A } = x;
a.p = new A();
let b: { [k: string]: B } = x;
let c: { [k: string]: C } = x;
(x.p: C);
}
function subtype_dict_values_fresh_exception() {
let a: { [k: string]: A } = { a: new A(), b: new B(), c: new C() };
let b: { [k: string]: B } = { a: new A(), b: new B(), c: new C() };
let c: { [k: string]: C } = { a: new A(), b: new B(), c: new C() };
}
function unification_dict_keys_invariant(x: Array<{ [k: B]: any }>) {
let a: Array<{ [k: A]: any }> = x;
// error
let b: Array<{ [k: B]: any }> = x;
let c: Array<{ [k: C]: any }> = x;
// ok
let c: Array<{ [k: C]: any }> = x; // error
}
function subtype_dict_keys_invariant(x: { [k: B]: any }) {
let a: { [k: A]: any } = x;
// error
let b: { [k: B]: any } = x;
let c: { [k: C]: any } = x;
// ok
let c: { [k: C]: any } = x; // error
}
function unification_mix_with_declared_props_invariant_l(
x: Array<{ [k: string]: B }>
) {
let a: Array<{ [k: string]: B, p: A }> = x;
// error: A ~> B
a[0].p = new A();
// x[0].p no longer B
let b: Array<{ [k: string]: B, p: B }> = x;
// ok
let c: Array<{ [k: string]: B, p: C }> = x;
(x[0].p: C);
// error
(x[0].p: C); // not true
}
function unification_mix_with_declared_props_invariant_r(
xa: Array<{ [k: string]: A, p: B }>,
xb: Array<{ [k: string]: B, p: B }>,
xc: Array<{ [k: string]: C, p: B }>
) {
let a: Array<{ [k: string]: A }> = xa;
// error
a[0].p = new A();
// xa[0].p no longer B
let b: Array<{ [k: string]: B }> = xb;
// ok
let c: Array<{ [k: string]: C }> = xc;
(xc[0].p: C);
// error
(xc[0].p: C); // not true
}
function subtype_mix_with_declared_props_invariant_l(x: { [k: string]: B }) {
let a: { [k: string]: B, p: A } = x;
// error: A ~> B
a.p = new A();
// x.p no longer B
let b: { [k: string]: B, p: B } = x;
// ok
let c: { [k: string]: B, p: C } = x;
(x.p: C);
// error
(x.p: C); // not true
}
function subtype_mix_with_declared_props_invariant_r(
xa: { [k: string]: A, p: B },
xb: { [k: string]: B, p: B },
xc: { [k: string]: C, p: B }
) {
let a: { [k: string]: A } = xa;
// error
a.p = new A();
// xa.p no longer B
let b: { [k: string]: B } = xb;
// ok
let c: { [k: string]: C } = xc;
(xc.p: C);
// error
(xc.p: C); // not true
}
function unification_dict_to_obj(
x: Array<{ [k: string]: X }>
): Array<{ p: X }> {
return x;
return x; // error: if allowed, could write {p:X,q:Y} into \`x\`
}
function unification_obj_to_dict(
x: Array<{ p: X }>
): Array<{ [k: string]: X }> {
return x;
return x; // error: if allowed, could write {p:X,q:Y} into returned array
}
function subtype_dict_to_obj(x: { [k: string]: B }) {
let a: { p: A } = x;
// error
a.p = new A();
// x.p no longer B
let b: { p: B } = x;
// ok
let c: { p: C } = x;
(x.p: C);
// error
(x.p: C); // not true
}
function subtype_obj_to_dict(x: { p: B }) {
let a: { [k: string]: A } = x;
// error
a.p = new A();
// x.p no longer B
let b: { [k: string]: B } = x;
let c: { [k: string]: C } = x;
(x.p: C);
// error
(x.p: C); // not true
}
// Only props in l which are not in u must match indexer, but must do so
// exactly.
function subtype_obj_to_mixed(x: { p: B, x: X }) {
let a: { [k: string]: A, x: X } = x;
// error (as above), but exclusive of x
let b: { [k: string]: B, x: X } = x;
let c: { [k: string]: C, x: X } = x;
// ok,
let c: { [k: string]: C, x: X } = x; // error (as above), but exclusive of x
}
function unification_dict_to_mixed(x: Array<{ [k: string]: B }>) {
let a: Array<{ [k: string]: B, p: A }> = x;
// error
let b: Array<{ [k: string]: B, p: B }> = x;
let c: Array<{ [k: string]: B, p: C }> = x;
// ok
let c: Array<{ [k: string]: B, p: C }> = x; // error
}
function subtype_dict_to_mixed(x: { [k: string]: B }) {
let a: { [k: string]: B, p: A } = x;
// error
let b: { [k: string]: B, p: B } = x;
let c: { [k: string]: B, p: C } = x;
// ok
let c: { [k: string]: B, p: C } = x; // error
}
function subtype_dict_to_optional_a(x: { [k: string]: B }) {
let a: { p?: A } = x;
let a: { p?: A } = x; // error
}
function subtype_dict_to_optional_b(x: { [k: string]: B }) {
let b: { p?: B } = x;
let b: { p?: B } = x; // ok
}
function subtype_dict_to_optional_c(x: { [k: string]: B }) {
let c: { p?: C } = x;
let c: { p?: C } = x; // error
}
function subtype_optional_a_to_dict(x: { p?: A }): { [k: string]: B } {
// error: A ~> B
return x;
}
function subtype_optional_b_to_dict(x: { p?: B }): { [k: string]: B } {
// ok
return x;
}
function subtype_optional_c_to_dict(x: { p?: C }): { [k: string]: B } {
// error: C ~> B
return x;
}
"
}"
`;
exports[`test incompatible.js 1`] = `
@ -729,63 +751,70 @@ function foo8(x: {[key: string]: number}) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// 2 errors, number !~> string & vice versa
// 2 errors, string !~> number & vice versa
// 2 errors (null & undefined)
// 2 errors, since c[\'x\'] = null updates b
// 2 errors (number !~> string, string !~> number)
// error, fooBar:string !~> number (x\'s dictionary)
// OK, since number ~> mixed (x elem\'s dictionary)
// error: mixed ~> string
// OK, since we assume dictionaries have every key
// error: foo can\'t exist in x
// error, some prop in x could be incompatible (covariance)
// error, some prop in return could be incompatible
// error
var x: { [key: string]: string } = {};
var y: { [key: string]: number } = x;
// 2 errors, number !~> string & vice versa
var z: { [key: number]: string } = x;
// 2 errors, string !~> number & vice versa
var a: { [key: string]: ?string } = {};
var b: { [key: string]: string } = a;
// 2 errors (null & undefined)
var c: { [key: string]: ?string } = b;
// 2 errors, since c[\'x\'] = null updates b
// 2 errors (number !~> string, string !~> number)
function foo0(
x: Array<{ [key: string]: number }>
): Array<{ [key: string]: string }> {
return x;
}
// error, fooBar:string !~> number (x\'s dictionary)
function foo1(
x: Array<{ [key: string]: number }>
): Array<{ [key: string]: number, fooBar: string }> {
return x;
}
function foo2(
x: Array<{ [key: string]: mixed }>
): Array<{ [key: string]: mixed, fooBar: string }> {
x[0].fooBar = 123;
return x;
// OK, since number ~> mixed (x elem\'s dictionary)
return x; // error: mixed ~> string
}
// OK, since we assume dictionaries have every key
function foo3(x: { [key: string]: number }): { foo: number } {
return x;
}
// error: foo can\'t exist in x
function foo4(
x: { [key: string]: number }
): { [key: string]: number, foo: string } {
return x;
}
// error, some prop in x could be incompatible (covariance)
function foo5(x: Array<{ [key: string]: number }>): Array<{ foo: number }> {
return x;
}
// error, some prop in return could be incompatible
function foo6(x: Array<{ foo: number }>): Array<{ [key: string]: number }> {
return x;
}
function foo7(x: { [key: string]: number, bar: string }) {
(x.bar: string);
}
function foo8(x: { [key: string]: number }) {
(x.foo: string);
// error
(x.foo: number);
}
"
}"
`;
exports[`test issue-1745.js 1`] = `
@ -816,29 +845,30 @@ class B {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// no error
// no error
// no error
// no error
class A {
x: { [k: string]: number };
m1() {
this.x = { bar: 0 };
this.x = { bar: 0 }; // no error
}
m2() {
this.x.foo = 0;
this.x.foo = 0; // no error
}
}
class B {
x: { [k: string]: number };
m2() {
this.x.foo = 0;
this.x.foo = 0; // no error
}
m1() {
this.x = { bar: 0 };
this.x = { bar: 0 }; // no error
}
}
"
}"
`;
exports[`test test.js 1`] = `
@ -853,16 +883,16 @@ var o: { foo: QueryFunction } = {
module.exports = o;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, number ~/~ string
type Params = { [name: string]: string, count: number };
type QueryFunction = (params: Params) => string;
var o: { foo: QueryFunction } = {
foo(params) {
return params.count;
return params.count; // error, number ~/~ string
}
};
module.exports = o;
"
module.exports = o;"
`;
exports[`test test_client.js 1`] = `
@ -872,10 +902,9 @@ o.foo = function (params) {
return params.count; // error, number ~/~ string
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error, number ~/~ string
var o = require(\"./test\");
o.foo = function(params) {
return params.count;
};
"
return params.count; // error, number ~/~ string
};"
`;

View File

@ -83,6 +83,7 @@ export type TypedNode =
/**
* @flow
*/
export type InferredType = \"unknown\" |
\"gender\" |
\"enum\" |
@ -90,12 +91,14 @@ export type InferredType = \"unknown\" |
\"number\" |
\"string\" |
\"error\";
export type Pos = {
firstLine: number,
firstColumn: number,
lastLine: number,
lastColumn: number
};
export type TypedBinaryOpNode = {
exprNodeType: \"binary_op\",
binaryOp: \"plus\" | \"multiply\" | \"divide\" | \"minus\",
@ -105,6 +108,7 @@ export type TypedBinaryOpNode = {
exprType: InferredType,
typed: true
};
export type TypedUnaryMinusNode = {
exprNodeType: \"unary_minus\",
op: TypedNode,
@ -112,6 +116,7 @@ export type TypedUnaryMinusNode = {
exprType: InferredType,
typed: true
};
export type TypedNumberNode = {
exprNodeType: \"number\",
value: number,
@ -119,6 +124,7 @@ export type TypedNumberNode = {
exprType: \"number\",
typed: true
};
export type TypedStringLiteralNode = {
exprNodeType: \"string_literal\",
value: string,
@ -126,6 +132,7 @@ export type TypedStringLiteralNode = {
exprType: \"string\",
typed: true
};
export type TypedVariableNode = {
exprNodeType: \"variable\",
name: string,
@ -133,6 +140,7 @@ export type TypedVariableNode = {
exprType: InferredType,
typed: true
};
export type TypedFunctionInvocationNode = {
exprNodeType: \"function_invocation\",
name: string,
@ -141,13 +149,13 @@ export type TypedFunctionInvocationNode = {
exprType: \"error\" | \"string\",
typed: true
};
export type TypedNode = TypedBinaryOpNode |
TypedUnaryMinusNode |
TypedNumberNode |
TypedStringLiteralNode |
TypedVariableNode |
TypedFunctionInvocationNode;
"
TypedFunctionInvocationNode;"
`;
exports[`test emit.js 1`] = `
@ -220,10 +228,12 @@ export function emitExpression(node: TypedNode) : t.Expression {
/**
* @flow
*/
// FALLTHROUGH
import * as t from \"./jsAst\";
const b = t.builders;
import type {TypedNode} from \"./ast\";
function getBinaryOp(
op: \"plus\" | \"minus\" | \"divide\" | \"multiply\"
): \"+\" | \"-\" | \"*\" | \"/\" {
@ -240,9 +250,11 @@ function getBinaryOp(
throw new Error(\"Invalid binary operator: \" + op);
}
}
export function emitExpression(node: TypedNode): t.Expression {
switch (node.exprNodeType) {
case \"string_literal\":
// FALLTHROUGH
case \"number\":
return b.literal(node.value);
case \"variable\":
@ -254,6 +266,7 @@ export function emitExpression(node: TypedNode): t.Expression {
case \"binary_op\": {
const lhs = emitExpression(node.lhs);
const rhs = emitExpression(node.rhs);
const op = getBinaryOp(node.binaryOp);
return b.binaryExpression(op, lhs, rhs);
}
@ -267,14 +280,15 @@ export function emitExpression(node: TypedNode): t.Expression {
b.identifier(node.name),
false
);
const args = node.parameters.map(n => emitExpression(n));
return b.callExpression(callee, args);
}
default:
throw new Error(\"Unknown expression type: \" + node.type);
}
}
"
}"
`;
exports[`test jsAst.js 1`] = `
@ -918,21 +932,21 @@ export const builders : {
/**
* @flow
*/
/* TODO Missing from the Parser API.*/
// ast-types exports all expressions as patterns.
// That seems not like it was intended.
export type Comment = {
loc: ?SourceLocation,
value: string,
leading: boolean,
trailing: boolean
};
export type SourceLocation = {
start: SourcePosition,
end: SourcePosition,
source: ?string
};
export type SourcePosition = { line: number, column: number };
export type File = {
source: ?string,
start: SourcePosition,
@ -941,6 +955,7 @@ export type File = {
type: \"File\",
program: Program
};
export type Program = {
source: ?string,
start: SourcePosition,
@ -949,6 +964,7 @@ export type Program = {
type: \"Program\",
body: Statement[]
};
export type BinaryOperator = \"==\" |
\"!=\" |
\"===\" |
@ -965,12 +981,13 @@ export type BinaryOperator = \"==\" |
\"*\" |
\"/\" |
\"%\" |
\"&\" |
\"&\" /* TODO Missing from the Parser API.*/ |
\"|\" |
\"^\" |
\"in\" |
\"instanceof\" |
\"..\";
export type UnaryOperator = \"-\" |
\"+\" |
\"!\" |
@ -978,6 +995,7 @@ export type UnaryOperator = \"-\" |
\"typeof\" |
\"void\" |
\"delete\";
export type AssignmentOperator = \"=\" |
\"+=\" |
\"-=\" |
@ -990,8 +1008,11 @@ export type AssignmentOperator = \"=\" |
\"|=\" |
\"^=\" |
\"&=\";
export type UpdateOperator = \"++\" | \"--\";
export type LogicalOperator = \"&&\" | \"||\";
export type Node = EmptyStatement |
BlockStatement |
ExpressionStatement |
@ -1024,6 +1045,7 @@ export type Node = EmptyStatement |
VariableDeclaration |
FunctionDeclaration |
VariableDeclarator;
export type Statement = BlockStatement |
EmptyStatement |
ExpressionStatement |
@ -1037,6 +1059,7 @@ export type Statement = BlockStatement |
ForInStatement |
TryStatement |
Declaration;
export type EmptyStatement = {
source: ?string,
start: SourcePosition,
@ -1044,6 +1067,7 @@ export type EmptyStatement = {
comments: ?Array<Comment>,
type: \"EmptyStatement\"
};
export type BlockStatement = {
source: ?string,
start: SourcePosition,
@ -1052,6 +1076,7 @@ export type BlockStatement = {
type: \"BlockStatement\",
body: Statement[]
};
export type ExpressionStatement = {
source: ?string,
start: SourcePosition,
@ -1060,6 +1085,7 @@ export type ExpressionStatement = {
type: \"ExpressionStatement\",
expression: Expression
};
export type IfStatement = {
source: ?string,
start: SourcePosition,
@ -1070,6 +1096,7 @@ export type IfStatement = {
consequent: Statement,
alternate: ?Statement
};
export type BreakStatement = {
source: ?string,
start: SourcePosition,
@ -1078,6 +1105,7 @@ export type BreakStatement = {
type: \"BreakStatement\",
label: ?Identifier
};
export type ContinueStatement = {
source: ?string,
start: SourcePosition,
@ -1086,6 +1114,7 @@ export type ContinueStatement = {
type: \"ContinueStatement\",
label: ?Identifier
};
export type ReturnStatement = {
source: ?string,
start: SourcePosition,
@ -1094,6 +1123,7 @@ export type ReturnStatement = {
type: \"ReturnStatement\",
argument: ?Expression
};
export type ThrowStatement = {
source: ?string,
start: SourcePosition,
@ -1102,6 +1132,7 @@ export type ThrowStatement = {
type: \"ThrowStatement\",
argument: ?Expression
};
export type WhileStatement = {
source: ?string,
start: SourcePosition,
@ -1111,6 +1142,7 @@ export type WhileStatement = {
test: Expression,
body: Statement
};
export type ForStatement = {
source: ?string,
start: SourcePosition,
@ -1122,6 +1154,7 @@ export type ForStatement = {
update: ?Expression,
body: Statement
};
export type ForInStatement = {
source: ?string,
start: SourcePosition,
@ -1132,6 +1165,7 @@ export type ForInStatement = {
right: Expression,
body: Statement
};
export type TryStatement = {
source: ?string,
start: SourcePosition,
@ -1143,6 +1177,7 @@ export type TryStatement = {
handlers: CatchClause[],
finalizer: ?BlockStatement
};
export type CatchClause = {
source: ?string,
start: SourcePosition,
@ -1153,6 +1188,7 @@ export type CatchClause = {
guard: ?Expression,
body: BlockStatement
};
export type Expression = Identifier |
ThisExpression |
Literal |
@ -1168,6 +1204,7 @@ export type Expression = Identifier |
MemberExpression |
ArrayExpression |
ObjectExpreession;
export type Identifier = {
source: ?string,
start: SourcePosition,
@ -1176,6 +1213,7 @@ export type Identifier = {
type: \"Identifier\",
name: string
};
export type Literal = {
source: ?string,
start: SourcePosition,
@ -1185,6 +1223,7 @@ export type Literal = {
value: ?(string | boolean | number | RegExp),
regex: ?{ pattern: string, flags: string }
};
export type ThisExpression = {
source: ?string,
start: SourcePosition,
@ -1192,6 +1231,7 @@ export type ThisExpression = {
comments: ?Array<Comment>,
type: \"ThisExpression\"
};
export type ArrayExpression = {
source: ?string,
start: SourcePosition,
@ -1200,6 +1240,7 @@ export type ArrayExpression = {
type: \"ArrayExpression\",
elements: Expression[]
};
export type ObjectExpreession = {
source: ?string,
start: SourcePosition,
@ -1208,6 +1249,7 @@ export type ObjectExpreession = {
type: \"ObjectExpression\",
properties: Property[]
};
export type Property = {
source: ?string,
start: SourcePosition,
@ -1218,6 +1260,7 @@ export type Property = {
key: Literal | Identifier,
value: Expression
};
export type FunctionExpression = {
source: ?string,
start: SourcePosition,
@ -1228,6 +1271,7 @@ export type FunctionExpression = {
params: Pattern[],
body: BlockStatement
};
export type BinaryExpression = {
source: ?string,
start: SourcePosition,
@ -1238,6 +1282,7 @@ export type BinaryExpression = {
left: Expression,
right: Expression
};
export type UnaryExpression = {
source: ?string,
start: SourcePosition,
@ -1248,6 +1293,7 @@ export type UnaryExpression = {
argument: Expression,
prefix: boolean
};
export type AssignmentExpression = {
source: ?string,
start: SourcePosition,
@ -1258,6 +1304,7 @@ export type AssignmentExpression = {
left: Pattern,
right: Expression
};
export type UpdateExpression = {
source: ?string,
start: SourcePosition,
@ -1268,6 +1315,7 @@ export type UpdateExpression = {
argument: Expression,
prefix: boolean
};
export type LogicalExpression = {
source: ?string,
start: SourcePosition,
@ -1278,6 +1326,7 @@ export type LogicalExpression = {
left: Expression,
right: Expression
};
export type ConditionalExpression = {
source: ?string,
start: SourcePosition,
@ -1288,6 +1337,7 @@ export type ConditionalExpression = {
consequent: Expression,
alternate: Expression
};
export type NewExpression = {
source: ?string,
start: SourcePosition,
@ -1297,6 +1347,7 @@ export type NewExpression = {
callee: Expression,
arguments: Expression[]
};
export type CallExpression = {
source: ?string,
start: SourcePosition,
@ -1306,6 +1357,7 @@ export type CallExpression = {
callee: Expression,
arguments: Expression[]
};
export type MemberExpression = {
source: ?string,
start: SourcePosition,
@ -1316,8 +1368,12 @@ export type MemberExpression = {
property: Identifier | Expression,
computed: boolean
};
// ast-types exports all expressions as patterns.
// That seems not like it was intended.
export type Pattern = Identifier;
export type Declaration = VariableDeclaration | FunctionDeclaration;
export type VariableDeclaration = {
source: ?string,
start: SourcePosition,
@ -1327,6 +1383,7 @@ export type VariableDeclaration = {
kind: \"var\" | \"let\" | \"const\",
declarations: VariableDeclarator[]
};
export type FunctionDeclaration = {
source: ?string,
start: SourcePosition,
@ -1337,6 +1394,7 @@ export type FunctionDeclaration = {
body: BlockStatement,
params: Pattern[]
};
export type VariableDeclarator = {
source: ?string,
start: SourcePosition,
@ -1346,7 +1404,9 @@ export type VariableDeclarator = {
id: Pattern,
init: ?Expression
};
const a: any = null;
export const builders: {
emptyStatement(): EmptyStatement,
blockStatement(body: Statement[]): BlockStatement,
@ -1448,6 +1508,5 @@ export const builders: {
params: Pattern[]
): FunctionDeclaration,
variableDeclarator(id: Pattern, init?: Expression): VariableDeclarator
} = a;
"
} = a;"
`;

View File

@ -6,9 +6,8 @@ exports[`test license_with_flow.js 1`] = `
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* Copyright example */
/* @flow */
// error
(\"\": void);
"
(\"\": void); // error"
`;
exports[`test max_header_tokens.js 1`] = `
@ -21,15 +20,6 @@ exports[`test max_header_tokens.js 1`] = `
* @flow
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
/* second token */
/* third token */
/**
* After max_header_tokens (in .flowconfig), we no longer care:
*
* @flow
*/
"
`;
@ -37,9 +27,6 @@ exports[`test multiple_flows_1.js 1`] = `
"/* @flow */
/* @flow */
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
/* @flow */
"
`;
@ -49,11 +36,6 @@ exports[`test multiple_flows_2.js 1`] = `
* @noflow
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @flow
* @noflow
*/
"
`;
@ -64,12 +46,6 @@ exports[`test multiple_providesModule_1.js 1`] = `
* @flow
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @providesModule Foo
* @providesModule Bar
* @flow
*/
"
`;
@ -82,14 +58,6 @@ exports[`test multiple_providesModule_2.js 1`] = `
* @providesModule Bar
*/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @providesModule Foo
* @flow
*/
/**
* @providesModule Bar
*/
"
`;
@ -99,11 +67,9 @@ exports[`test use_strict_with_flow.js 1`] = `
(\"\": void); // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error
\"use strict\";
(\"\": void);
"
/* @flow */
(\"\": void); // error"
`;
exports[`test with_flow.js 1`] = `
@ -112,9 +78,8 @@ exports[`test with_flow.js 1`] = `
(\"\": void); // error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error
(\"\": void);
"
(\"\": void); // error"
`;
exports[`test without_flow.js 1`] = `
@ -123,7 +88,6 @@ exports[`test without_flow.js 1`] = `
(\"\": void); // no error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* some other comment */
// no error
(\"\": void);
"
(\"\": void); // no error"
`;

View File

@ -14,18 +14,17 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// fillRect
// moveTo
// error: should be numbers
let tests = [
// fillRect
function(ctx: CanvasRenderingContext2D) {
ctx.fillRect(0, 0, 200, 100);
},
// moveTo
function(ctx: CanvasRenderingContext2D) {
ctx.moveTo(\"0\", \"1\");
ctx.moveTo(\"0\", \"1\"); // error: should be numbers
}
];
"
];"
`;
exports[`test CustomEvent.js 1`] = `
@ -40,14 +39,14 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// CustomEvent
let tests = [
// CustomEvent
function(document: Document) {
const event = document.createEvent(\"CustomEvent\");
event.initCustomEvent(\"butts\", true, false, { nice: 42 });
}
];
"
];"
`;
exports[`test Document.js 1`] = `
@ -64,16 +63,16 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// createElement
let tests = [
// createElement
function(document: Document) {
(document.createElement(\"canvas\"): HTMLCanvasElement);
(document.createElement(\"link\"): HTMLLinkElement);
(document.createElement(\"option\"): HTMLOptionElement);
(document.createElement(\"select\"): HTMLSelectElement);
}
];
"
];"
`;
exports[`test Element.js 1`] = `
@ -97,9 +96,9 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// scrollIntoView
// fails
let tests = [
// scrollIntoView
function(element: Element) {
element.scrollIntoView();
element.scrollIntoView(false);
@ -107,12 +106,13 @@ let tests = [
element.scrollIntoView({ behavior: \"smooth\", block: \"end\" });
element.scrollIntoView({ block: \"end\" });
element.scrollIntoView({ behavior: \"smooth\" });
// fails
element.scrollIntoView({ behavior: \"invalid\" });
element.scrollIntoView({ block: \"invalid\" });
element.scrollIntoView(1);
}
];
"
];"
`;
exports[`test HTMLCanvasElement.js 1`] = `
@ -126,13 +126,13 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// getContext
let tests = [
// getContext
function(el: HTMLCanvasElement) {
(el.getContext(\"2d\"): ?CanvasRenderingContext2D);
}
];
"
];"
`;
exports[`test HTMLElement.js 1`] = `
@ -156,9 +156,9 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// scrollIntoView
// fails
let tests = [
// scrollIntoView
function(element: HTMLElement) {
element.scrollIntoView();
element.scrollIntoView(false);
@ -166,12 +166,13 @@ let tests = [
element.scrollIntoView({ behavior: \"smooth\", block: \"end\" });
element.scrollIntoView({ block: \"end\" });
element.scrollIntoView({ behavior: \"smooth\" });
// fails
element.scrollIntoView({ behavior: \"invalid\" });
element.scrollIntoView({ block: \"invalid\" });
element.scrollIntoView(1);
}
];
"
];"
`;
exports[`test HTMLInputElement.js 1`] = `
@ -189,19 +190,18 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// setRangeText
// end is required
// invalid value
let tests = [
// setRangeText
function(el: HTMLInputElement) {
el.setRangeText(\"foo\");
el.setRangeText(\"foo\", 123);
// end is required
el.setRangeText(\"foo\", 123, 234);
el.setRangeText(\"foo\", 123, 234, \"select\");
el.setRangeText(\"foo\", 123, 234, \"bogus\");
el.setRangeText(\"foo\", 123, 234, \"bogus\"); // invalid value
}
];
"
];"
`;
exports[`test URL.js 1`] = `
@ -227,41 +227,40 @@ const q: string = c.search; // correct
const r: string = c.username; // correct
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// correct
// correct
// correct
// correct
// not correct
// correct
// correct
// correct
// correct
// correct
// correct
// correct
// correct
// correct
// correct
// correct
// correct
const a = new URL(\"http://flowtype.org/\");
// correct
const b = new URL(\"/docs\", a);
// correct
const c = new URL(\"/docs\", \"http://flowtype.org/\");
// correct
const d: URLSearchParams = c.searchParams;
// correct
const e: string = c.path;
// not correct
const f: string = c.pathname;
// correct
const g: string = c.hash;
// correct
const h: string = c.host;
// correct
const i: string = c.hostname;
// correct
const j: string = c.href;
// correct
const l: string = c.origin;
// correct
const m: string = c.password;
// correct
const n: string = c.pathname;
// correct
const o: string = c.port;
// correct
const p: string = c.protocol;
// correct
const q: string = c.search;
const r: string = c.username;
"
// correct
const r: string = c.username; // correct"
`;
exports[`test eventtarget.js 1`] = `
@ -292,31 +291,30 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// attachEvent
// invalid, may be undefined
// valid
// detachEvent
// invalid, may be undefined
// valid
let listener: EventListener = function(event: Event): void {};
let tests = [
// attachEvent
function() {
let target = new EventTarget();
(target.attachEvent(\"foo\", listener): void);
(target.attachEvent && target.attachEvent(\"foo\", listener): void);
// invalid, may be undefined
(target.attachEvent && target.attachEvent(\"foo\", listener): void); // valid
},
// detachEvent
function() {
let target = new EventTarget();
(target.detachEvent(\"foo\", listener): void);
(target.detachEvent && target.detachEvent(\"foo\", listener): void);
// invalid, may be undefined
(target.detachEvent && target.detachEvent(\"foo\", listener): void); // valid
},
function() {
window.onmessage = (event: MessageEvent) => {
(event.target: window);
};
}
];
"
];"
`;
exports[`test path2d.js 1`] = `
@ -333,19 +331,18 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// arcTo
// valid
// valid
// invalid
let tests = [
// arcTo
function() {
let path = new Path2D();
(path.arcTo(0, 0, 0, 0, 10): void);
// valid
(path.arcTo(0, 0, 0, 0, 10, 20, 5): void);
(path.arcTo(0, 0, 0, 0, 10, \"20\", 5): void);
// valid
(path.arcTo(0, 0, 0, 0, 10, \"20\", 5): void); // invalid
}
];
"
];"
`;
exports[`test registerElement.js 1`] = `
@ -409,12 +406,9 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// should work with Object.create()
// or with Object.assign()
// should complain about invalid callback parameters
// Error: This might be null
// Error: This might be null
let tests = [
// should work with Object.create()
function() {
document.registerElement(\"custom-element\", {
prototype: Object.create(HTMLElement.prototype, {
@ -432,6 +426,7 @@ let tests = [
})
});
},
// or with Object.assign()
function() {
document.registerElement(\"custom-element\", {
prototype: Object.assign(Object.create(HTMLElement.prototype), {
@ -447,20 +442,22 @@ let tests = [
})
});
},
// should complain about invalid callback parameters
function() {
document.registerElement(\"custom-element\", {
prototype: {
attributeChangedCallback(
localName: string,
oldVal: string,
// Error: This might be null
newVal: string,
// Error: This might be null
namespace: string
) {}
}
});
}
];
"
];"
`;
exports[`test traversal.js 1`] = `
@ -661,24 +658,9 @@ let tests = [
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// basic functionality
// rootNode must be a Node
// valid
// invalid
// invalid
// Type Parameters
// NodeFilterInterface
// valid
// invalid
// valid
// invalid
// invalid
// valid
// invalid
// valid
// invalid
// invalid
let tests = [
// basic functionality
function() {
const i: NodeIterator<*, *> = document.createNodeIterator(document.body);
const filter: NodeFilter = i.filter;
@ -693,14 +675,17 @@ let tests = [
typeof NodeFilter.FILTER_REJECT |
typeof NodeFilter.FILTER_SKIP = filter.acceptNode(document.body);
},
// rootNode must be a Node
function() {
document.createNodeIterator(document.body);
document.createNodeIterator({});
// valid
document.createNodeIterator({}); // invalid
},
function() {
document.createTreeWalker(document.body);
document.createTreeWalker({});
document.createTreeWalker({}); // invalid
},
// Type Parameters
function() {
const _root = document.body;
const i = document.createNodeIterator(_root, NodeFilter.SHOW_ELEMENT);
@ -854,20 +839,25 @@ let tests = [
const previousNode: Node | null = w.previousNode();
const nextNode: Node | null = w.nextNode();
},
// NodeFilterInterface
function() {
document.createNodeIterator(
document.body,
-1,
node => NodeFilter.FILTER_ACCEPT
);
// valid
document.createNodeIterator(document.body, -1, node => \"accept\");
// invalid
document.createNodeIterator(document.body, -1, {
accept: node => NodeFilter.FILTER_ACCEPT
});
// valid
document.createNodeIterator(document.body, -1, {
accept: node => \"accept\"
});
document.createNodeIterator(document.body, -1, {});
// invalid
document.createNodeIterator(document.body, -1, {}); // invalid
},
function() {
document.createTreeWalker(
@ -875,13 +865,16 @@ let tests = [
-1,
node => NodeFilter.FILTER_ACCEPT
);
// valid
document.createTreeWalker(document.body, -1, node => \"accept\");
// invalid
document.createTreeWalker(document.body, -1, {
accept: node => NodeFilter.FILTER_ACCEPT
});
// valid
document.createTreeWalker(document.body, -1, { accept: node => \"accept\" });
document.createTreeWalker(document.body, -1, {});
// invalid
document.createTreeWalker(document.body, -1, {}); // invalid
}
];
"
];"
`;

View File

@ -9,8 +9,7 @@ module.exports = num;
var num = 42;
function bar() {}
bar();
module.exports = num;
"
module.exports = num;"
`;
exports[`test test.js 1`] = `
@ -37,15 +36,18 @@ declare var obj: {a?: {b: ?{c: null | {d: number}}}};
const idxResult = idx(obj, obj => obj.a.b.c.d);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// test deduping of inferred types
var num = require(\"./import\");
function foo(x) {}
foo(0);
var a: string = num;
function unannotated(x) {
return x;
}
// test deduping of inferred types
const nullToUndefined = val => val === null ? undefined : val;
function f0(x: ?Object) {
return nullToUndefined(x);
}
@ -58,8 +60,8 @@ function f2(x: ?string) {
function f3(x: ?string) {
return nullToUndefined(x);
}
declare var idx: $Facebookism$Idx;
declare var obj: { a?: { b: ?{ c: null | { d: number } } } };
const idxResult = idx(obj, obj => obj.a.b.c.d);
"
const idxResult = idx(obj, obj => obj.a.b.c.d);"
`;

View File

@ -39,26 +39,34 @@ class C1 {
m() {}
m() {}
}
new C1().m();
class C2 {
get m() {
return 42;
}
m() {}
}
new C2().m();
class C3 {
set m(x) {}
m() {}
}
new C3().m();
class C4 {
get m() {
return 42;
}
set m(x: number) {}
}
new C4().m = new C4().m - 42;
class C5 {
m() {}
get m() {
@ -66,6 +74,6 @@ class C5 {
}
set m(x: number) {}
}
new C5().m = new C5().m - 42;
"
new C5().m = new C5().m - 42;"
`;

View File

@ -16,22 +16,21 @@ function tag2(strings,...values) {
var s3 = tag2 \`la la la\`;
(s3.foo: number); // error: string ~> number
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// error: no prop x in A
// error: string ~> number
// ok: tagged templates can return whatever
// error: string ~> number
class A {}
var a = new A();
var s1 = \`l\${a.x}r\`;
// error: no prop x in A
function tag(strings, ...values) {
var x: number = strings[0];
// error: string ~> number
return x;
}
var s2 = tag\`l\${42}r\`;
function tag2(strings, ...values) {
return { foo: \"\" };
return { foo: \"\" }; // ok: tagged templates can return whatever
}
var s3 = tag2\`la la la\`;
(s3.foo: number);
"
(s3.foo: number); // error: string ~> number"
`;

View File

@ -27,26 +27,30 @@ function keys2union(s: Keys): Union { return s; } // ok
function union2keys(s: Union): Keys { return s; } // ok
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** @flow */
// ok
// ok
function isActive(
ad: { state: $Keys<{ PAUSED: string, ACTIVE: string, DELETED: string }> }
): boolean {
return ad.state === \"ACTIVE\";
}
isActive({ state: \"PAUSE\" });
var MyStates = { PAUSED: \"PAUSED\", ACTIVE: \"ACTIVE\", DELETED: \"DELETED\" };
function isActive2(ad: { state: $Keys<typeof MyStates> }): boolean {
return ad.state === MyStates.ACTIVE;
}
isActive2({ state: \"PAUSE\" });
type Keys = $Keys<{ x: any, y: any }>;
type Union = \"x\" | \"y\";
function keys2union(s: Keys): Union {
return s;
}
// ok
function union2keys(s: Union): Keys {
return s;
}
"
} // ok"
`;

View File

@ -13,16 +13,16 @@ var x = (null : ?number);
(1 == x);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* @flow */
// error
// error
1 == 1;
\"foo\" == \"bar\";
1 == null;
null == 1;
1 == \"\";
// error
\"\" == 1;
// error
var x = (null: ?number);
x == 1;
1 == x;
"
1 == x;"
`;

View File

@ -1,6 +1,5 @@
exports[`test errors.js 1`] = `
"if (typeof define === \'function\' && define.amd) { }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (typeof define === \"function\" && define.amd) {}
"
if (typeof define === \"function\" && define.amd) {}"
`;

Some files were not shown because too many files have changed in this diff Show More