Add support for ForOfStatement with await flag (#1073)

* Enable babylon on flow async_iteration tests

* Add support for ForOfStatement with await flag
This commit is contained in:
Brian Ng authored and Christopher Chedeau committed 2017-03-22 09:23:57 -07:00
1 parent c3199359b0
commit 41977c293e
3 files changed
+241 -9

No files matched your search

+10 -9
View File
@@ -1064,24 +1064,25 @@ function genericPrintNoParens(path, options, print) {
")",
adjustClause(path.call(print, "body"), options)
]);
case "ForOfStatement":
return concat([
"for (",
path.call(print, "left"),
" of ",
path.call(print, "right"),
")",
adjustClause(path.call(print, "body"), options)
]);
case "ForAwaitStatement":
// Babylon 7 removed ForAwaitStatement in favor of ForOfStatement
// with `"await": true`:
// https://github.com/estree/estree/pull/138
const isAwait = (n.type === "ForAwaitStatement" || n.await);
return concat([
"for await (",
"for",
isAwait ? " await" : "",
" (",
path.call(print, "left"),
" of ",
path.call(print, "right"),
")",
adjustClause(path.call(print, "body"), options)
]);
case "DoWhileStatement":
var clause = adjustClause(path.call(print, "body"), options);
var doBody = concat(["do", clause]);
@@ -57,6 +57,63 @@ async function* delegate_return() {
"
`;
exports[`delegate_yield.js 2`] = `
"async function *delegate_next() {
async function *inner() {
var x: void = yield; // error: number ~> void
}
yield *inner();
}
delegate_next().next(0);
async function *delegate_yield() {
async function *inner() {
yield 0;
}
yield *inner();
}
(async () => {
for await (const x of delegate_yield()) {
(x: void); // error: number ~> void
}
});
async function *delegate_return() {
async function *inner() {
return 0;
}
var x: void = yield *inner(); // error: number ~> void
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
async function* delegate_next() {
async function* inner() {
var x: void = yield; // error: number ~> void
}
yield* inner();
}
delegate_next().next(0);
async function* delegate_yield() {
async function* inner() {
yield 0;
}
yield* inner();
}
async () => {
for await (const x of delegate_yield()) {
(x: void); // error: number ~> void
}
};
async function* delegate_return() {
async function* inner() {
return 0;
}
var x: void = yield* inner(); // error: number ~> void
}
"
`;
exports[`generator.js 1`] = `
"declare interface File {
readLine(): Promise<string>;
@@ -112,6 +169,61 @@ async function f() {
"
`;
exports[`generator.js 2`] = `
"declare 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();
}
} finally {
file.close();
}
}
async function f() {
for await (const line of readLines(\\"/path/to/file\\")) {
(line: void); // error: string ~> void
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare 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();
}
} finally {
file.close();
}
}
async function f() {
for await (const line of readLines(\\"/path/to/file\\")) {
(line: void); // error: string ~> void
}
}
"
`;
exports[`return.js 1`] = `
"declare var gen: AsyncGenerator<void,string,void>;
@@ -161,6 +273,55 @@ refuse_return().return(\\"string\\").then(result => {
"
`;
exports[`return.js 2`] = `
"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
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.
async function *refuse_return() {
try {
yield 1;
} finally {
return 0;
}
}
refuse_return().return(\\"string\\").then(result => {
if (result.done) {
(result.value: string); // error: number | void ~> string
}
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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
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.
async function* refuse_return() {
try {
yield 1;
} finally {
return 0;
}
}
refuse_return().return(\\"string\\").then(result => {
if (result.done) {
(result.value: string); // error: number | void ~> string
}
});
"
`;
exports[`throw.js 1`] = `
"async function *catch_return() {
try {
@@ -229,3 +390,72 @@ async () => {
};
"
`;
exports[`throw.js 2`] = `
"async function *catch_return() {
try {
yield 0;
} catch (e) {
return e;
}
}
(async () => {
catch_return().throw(\\"\\").then(({value}) => {
if (value !== undefined) {
(value: void); // error: number ~> void
}
});
});
async function *yield_return() {
try {
yield 0;
return;
} catch (e) {
yield e;
}
}
(async () => {
yield_return().throw(\\"\\").then(({value}) => {
if (value !== undefined) {
(value: void); // error: number ~> void
}
});
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
async function* catch_return() {
try {
yield 0;
} catch (e) {
return e;
}
}
async () => {
catch_return().throw(\\"\\").then(({ value }) => {
if (value !== undefined) {
(value: void); // error: number ~> void
}
});
};
async function* yield_return() {
try {
yield 0;
return;
} catch (e) {
yield e;
}
}
async () => {
yield_return().throw(\\"\\").then(({ value }) => {
if (value !== undefined) {
(value: void); // error: number ~> void
}
});
};
"
`;
+1
View File
@@ -1 +1,2 @@
run_spec(__dirname);
run_spec(__dirname, { parser: 'babylon' });