diff --git a/.prettierignore b/.prettierignore index 2504e5517c..589a2a3a49 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,6 @@ cli/tests/error_syntax.js cli/tests/badly_formatted.js +cli/tests/top_level_for_await.js std/**/testdata std/**/vendor -std/node_modules \ No newline at end of file +std/node_modules diff --git a/cli/js/compiler.ts b/cli/js/compiler.ts index 57e5e3a47e..e4953cee24 100644 --- a/cli/js/compiler.ts +++ b/cli/js/compiler.ts @@ -616,6 +616,9 @@ window.compilerMain = function compilerMain(): void { diagnostics = ts.getPreEmitDiagnostics(program).filter( ({ code }): boolean => { + // TS1103: 'for-await-of' statement is only allowed within an async + // function or async generator. + if (code === 1103) return false; // TS1308: 'await' expression is only allowed within an async // function. if (code === 1308) return false; diff --git a/cli/tests/045_proxy_client.ts b/cli/tests/045_proxy_client.ts index 3d7003750f..221ac57f6a 100644 --- a/cli/tests/045_proxy_client.ts +++ b/cli/tests/045_proxy_client.ts @@ -1,7 +1,3 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -async function main(): Promise { - const res = await fetch("http://localhost:4545/std/examples/colors.ts"); - console.log(`Response http: ${await res.text()}`); -} - -main(); +const res = await fetch("http://localhost:4545/std/examples/colors.ts"); +console.log(`Response http: ${await res.text()}`); diff --git a/cli/tests/045_proxy_test.ts b/cli/tests/045_proxy_test.ts index 0e7225b3f7..98225dbf10 100644 --- a/cli/tests/045_proxy_test.ts +++ b/cli/tests/045_proxy_test.ts @@ -55,11 +55,7 @@ async function testModuleDownload(): Promise { http.close(); } -async function main(): Promise { - proxyServer(); - await testFetch(); - await testModuleDownload(); - Deno.exit(0); -} - -main(); +proxyServer(); +await testFetch(); +await testModuleDownload(); +Deno.exit(0); diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index ee8f1384c8..09f1487365 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -597,3 +597,13 @@ itest!(top_level_await_ts { args: "--allow-read top_level_await.ts", output: "top_level_await.out", }); + +itest!(top_level_for_await { + args: "top_level_for_await.js", + output: "top_level_for_await.out", +}); + +itest!(top_level_for_await_ts { + args: "top_level_for_await.ts", + output: "top_level_for_await.out", +}); diff --git a/cli/tests/top_level_for_await.js b/cli/tests/top_level_for_await.js new file mode 100644 index 0000000000..fa3b496a8c --- /dev/null +++ b/cli/tests/top_level_for_await.js @@ -0,0 +1,10 @@ +async function* asyncGenerator() { + let i = 0; + while (i < 3) { + yield i++; + } +} + +for await (const num of asyncGenerator()) { + console.log(num); +}; diff --git a/cli/tests/top_level_for_await.out b/cli/tests/top_level_for_await.out new file mode 100644 index 0000000000..4539bbf2d2 --- /dev/null +++ b/cli/tests/top_level_for_await.out @@ -0,0 +1,3 @@ +0 +1 +2 diff --git a/cli/tests/top_level_for_await.ts b/cli/tests/top_level_for_await.ts new file mode 100644 index 0000000000..9179322d78 --- /dev/null +++ b/cli/tests/top_level_for_await.ts @@ -0,0 +1,10 @@ +async function* asyncGenerator(): AsyncIterableIterator { + let i = 0; + while (i < 3) { + yield i++; + } +} + +for await (const num of asyncGenerator()) { + console.log(num); +} diff --git a/std/examples/cat.ts b/std/examples/cat.ts index 3626e3c296..9e713d862b 100644 --- a/std/examples/cat.ts +++ b/std/examples/cat.ts @@ -1,10 +1,7 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -async function cat(filenames: string[]): Promise { - for (const filename of filenames) { - const file = await Deno.open(filename); - await Deno.copy(Deno.stdout, file); - file.close(); - } +const filenames = Deno.args.slice(1); +for (const filename of filenames) { + const file = await Deno.open(filename); + await Deno.copy(Deno.stdout, file); + file.close(); } - -cat(Deno.args.slice(1)); diff --git a/std/examples/catj.ts b/std/examples/catj.ts index cbe06d4b8f..87fd6a9641 100644 --- a/std/examples/catj.ts +++ b/std/examples/catj.ts @@ -79,32 +79,28 @@ function print(data: any): void { } } -async function main(): Promise { - const parsedArgs = parse(Deno.args.slice(1)); +const parsedArgs = parse(Deno.args.slice(1)); - if (parsedArgs.h || parsedArgs.help || parsedArgs._.length === 0) { - console.log("Usage: catj [-h|--help] [file...]"); - console.log(); - console.log("Examples:"); - console.log(); - console.log("// print file:\n catj file.json"); - console.log(); - console.log("// print multiple files:\n catj file1.json file2.json"); - console.log(); - console.log("// print from stdin:\n cat file.json | catj -"); - } - - if (parsedArgs._[0] === "-") { - const contents = await Deno.readAll(Deno.stdin); - const json = JSON.parse(decoder.decode(contents)); - print(json); - } else { - for (const fileName of parsedArgs._) { - const fileContents = await Deno.readFile(fileName); - const json = JSON.parse(decoder.decode(fileContents)); - print(json); - } - } +if (parsedArgs.h || parsedArgs.help || parsedArgs._.length === 0) { + console.log("Usage: catj [-h|--help] [file...]"); + console.log(); + console.log("Examples:"); + console.log(); + console.log("// print file:\n catj file.json"); + console.log(); + console.log("// print multiple files:\n catj file1.json file2.json"); + console.log(); + console.log("// print from stdin:\n cat file.json | catj -"); } -main(); +if (parsedArgs._[0] === "-") { + const contents = await Deno.readAll(Deno.stdin); + const json = JSON.parse(decoder.decode(contents)); + print(json); +} else { + for (const fileName of parsedArgs._) { + const fileContents = await Deno.readFile(fileName); + const json = JSON.parse(decoder.decode(fileContents)); + print(json); + } +} diff --git a/std/examples/curl.ts b/std/examples/curl.ts index 04dd9d601f..e020016f8e 100644 --- a/std/examples/curl.ts +++ b/std/examples/curl.ts @@ -1,8 +1,4 @@ // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. -async function curl(url: string): Promise { - const res = await fetch(url); - await Deno.copy(Deno.stdout, res.body); -} - -await curl(Deno.args[1]); -Deno.exit(0); +const url = Deno.args[1]; +const res = await fetch(url); +await Deno.copy(Deno.stdout, res.body); diff --git a/std/http/README.md b/std/http/README.md index e4086c1a42..26fe25bf63 100644 --- a/std/http/README.md +++ b/std/http/README.md @@ -56,14 +56,11 @@ console.log("Set-Cookie:", cookieHeader); ```typescript import { serve } from "https://deno.land/std/http/server.ts"; const s = serve("0.0.0.0:8000"); +const body = new TextEncoder().encode("Hello World\n"); -async function main() { - for await (const req of s) { - req.respond({ body: new TextEncoder().encode("Hello World\n") }); - } +for await (const req of s) { + req.respond({ body }); } - -main(); ``` ### File Server diff --git a/std/http/testdata/simple_server.ts b/std/http/testdata/simple_server.ts index 67b957ad5a..d53e72dcfc 100644 --- a/std/http/testdata/simple_server.ts +++ b/std/http/testdata/simple_server.ts @@ -2,10 +2,8 @@ // This is an example of a server that responds with an empty body import { serve } from "../server.ts"; -window.onload = async function main() { - const addr = "0.0.0.0:4502"; - console.log(`Simple server listening on ${addr}`); - for await (const req of serve(addr)) { - req.respond({}); - } +const addr = "0.0.0.0:4502"; +console.log(`Simple server listening on ${addr}`); +for await (const req of serve(addr)) { + req.respond({}); } diff --git a/std/manual.md b/std/manual.md index 03042c0fd1..6da2d0ec2d 100644 --- a/std/manual.md +++ b/std/manual.md @@ -937,12 +937,10 @@ Example: import { serve } from "http/server.ts"; -window.onload = async function() { - const body = new TextEncoder().encode("Hello World\n"); - for await (const req of serve(":8000")) { - req.respond({ body }); - } -}; +const body = new TextEncoder().encode("Hello World\n"); +for await (const req of serve(":8000")) { + req.respond({ body }); +} ``` ```shell diff --git a/std/ws/README.md b/std/ws/README.md index fe5bae9834..271bf2afbf 100644 --- a/std/ws/README.md +++ b/std/ws/README.md @@ -15,61 +15,56 @@ import { WebSocket } from "https://deno.land/std/ws/mod.ts"; +/** websocket echo server */ const port = Deno.args[1] || "8080"; -async function main(): Promise { - console.log(`websocket server is running on :${port}`); - for await (const req of serve(`:${port}`)) { - const { headers, conn } = req; - acceptWebSocket({ - conn, - headers, - bufReader: req.r, - bufWriter: req.w - }) - .then( - async (sock: WebSocket): Promise => { - console.log("socket connected!"); - const it = sock.receive(); - while (true) { - try { - const { done, value } = await it.next(); - if (done) { - break; - } - const ev = value; - if (typeof ev === "string") { - // text message - console.log("ws:Text", ev); - await sock.send(ev); - } else if (ev instanceof Uint8Array) { - // binary message - console.log("ws:Binary", ev); - } else if (isWebSocketPingEvent(ev)) { - const [, body] = ev; - // ping - console.log("ws:Ping", body); - } else if (isWebSocketCloseEvent(ev)) { - // close - const { code, reason } = ev; - console.log("ws:Close", code, reason); - } - } catch (e) { - console.error(`failed to receive frame: ${e}`); - await sock.close(1000).catch(console.error); +console.log(`websocket server is running on :${port}`); +for await (const req of serve(`:${port}`)) { + const { headers, conn } = req; + acceptWebSocket({ + conn, + headers, + bufReader: req.r, + bufWriter: req.w + }) + .then( + async (sock: WebSocket): Promise => { + console.log("socket connected!"); + const it = sock.receive(); + while (true) { + try { + const { done, value } = await it.next(); + if (done) { + break; } + const ev = value; + if (typeof ev === "string") { + // text message + console.log("ws:Text", ev); + await sock.send(ev); + } else if (ev instanceof Uint8Array) { + // binary message + console.log("ws:Binary", ev); + } else if (isWebSocketPingEvent(ev)) { + const [, body] = ev; + // ping + console.log("ws:Ping", body); + } else if (isWebSocketCloseEvent(ev)) { + // close + const { code, reason } = ev; + console.log("ws:Close", code, reason); + } + } catch (e) { + console.error(`failed to receive frame: ${e}`); + await sock.close(1000).catch(console.error); } } - ) - .catch( - (err: Error): void => { - console.error(`failed to accept websocket: ${err}`); - } - ); - } -} - -if (import.meta.main) { - main(); + } + ) + .catch( + (err: Error): void => { + console.error(`failed to accept websocket: ${err}`); + } + ); } ``` @@ -88,46 +83,49 @@ import { TextProtoReader } from "https://deno.land/std/textproto/mod.ts"; import { blue, green, red, yellow } from "https://deno.land/std/fmt/colors.ts"; const endpoint = Deno.args[1] || "ws://127.0.0.1:8080"; -async function main(): Promise { - const sock = await connectWebSocket(endpoint); - console.log(green("ws connected! (type 'close' to quit)")); - (async function(): Promise { - for await (const msg of sock.receive()) { - if (typeof msg === "string") { - console.log(yellow("< " + msg)); - } else if (isWebSocketPingEvent(msg)) { - console.log(blue("< ping")); - } else if (isWebSocketPongEvent(msg)) { - console.log(blue("< pong")); - } else if (isWebSocketCloseEvent(msg)) { - console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`)); - } +/** simple websocket cli */ +const sock = await connectWebSocket(endpoint); +console.log(green("ws connected! (type 'close' to quit)")); +(async function(): Promise { + for await (const msg of sock.receive()) { + if (typeof msg === "string") { + console.log(yellow("< " + msg)); + } else if (isWebSocketPingEvent(msg)) { + console.log(blue("< ping")); + } else if (isWebSocketPongEvent(msg)) { + console.log(blue("< pong")); + } else if (isWebSocketCloseEvent(msg)) { + console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`)); } - })(); - const tpr = new TextProtoReader(new BufReader(Deno.stdin)); - while (true) { - await Deno.stdout.write(encode("> ")); - const [line, err] = await tpr.readLine(); - if (err) { - console.error(red(`failed to read line from stdin: ${err}`)); - break; - } - if (line === "close") { - break; - } else if (line === "ping") { - await sock.ping(); - } else { - await sock.send(line); - } - await new Promise((resolve): number => setTimeout(resolve, 0)); } - await sock.close(1000); - Deno.exit(0); -} +})(); -if (import.meta.main) { - main(); +const tpr = new TextProtoReader(new BufReader(Deno.stdin)); +while (true) { + await Deno.stdout.write(encode("> ")); + const [line, err] = await tpr.readLine(); + if (err) { + console.error(red(`failed to read line from stdin: ${err}`)); + break; + } + if (line === "close") { + break; + } else if (line === "ping") { + await sock.ping(); + } else { + await sock.send(line); + } + // FIXME: Without this, + // sock.receive() won't resolved though it is readable... + await new Promise( + (resolve): void => { + setTimeout(resolve, 0); + } + ); } +await sock.close(1000); +// FIXME: conn.close() won't shutdown process... +Deno.exit(0); ``` ## API diff --git a/std/ws/example_client.ts b/std/ws/example_client.ts index a6649570ea..3b132281fb 100644 --- a/std/ws/example_client.ts +++ b/std/ws/example_client.ts @@ -11,50 +11,45 @@ import { blue, green, red, yellow } from "../fmt/colors.ts"; const endpoint = Deno.args[1] || "ws://127.0.0.1:8080"; /** simple websocket cli */ -async function main(): Promise { - const sock = await connectWebSocket(endpoint); - console.log(green("ws connected! (type 'close' to quit)")); - (async function(): Promise { - for await (const msg of sock.receive()) { - if (typeof msg === "string") { - console.log(yellow("< " + msg)); - } else if (isWebSocketPingEvent(msg)) { - console.log(blue("< ping")); - } else if (isWebSocketPongEvent(msg)) { - console.log(blue("< pong")); - } else if (isWebSocketCloseEvent(msg)) { - console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`)); - } +const sock = await connectWebSocket(endpoint); +console.log(green("ws connected! (type 'close' to quit)")); +(async function(): Promise { + for await (const msg of sock.receive()) { + if (typeof msg === "string") { + console.log(yellow("< " + msg)); + } else if (isWebSocketPingEvent(msg)) { + console.log(blue("< ping")); + } else if (isWebSocketPongEvent(msg)) { + console.log(blue("< pong")); + } else if (isWebSocketCloseEvent(msg)) { + console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`)); } - })(); - const tpr = new TextProtoReader(new BufReader(Deno.stdin)); - while (true) { - await Deno.stdout.write(encode("> ")); - const [line, err] = await tpr.readLine(); - if (err) { - console.error(red(`failed to read line from stdin: ${err}`)); - break; - } - if (line === "close") { - break; - } else if (line === "ping") { - await sock.ping(); - } else { - await sock.send(line); - } - // FIXME: Without this, - // sock.receive() won't resolved though it is readable... - await new Promise( - (resolve): void => { - setTimeout(resolve, 0); - } - ); } - await sock.close(1000); - // FIXME: conn.close() won't shutdown process... - Deno.exit(0); -} +})(); -if (import.meta.main) { - main(); +const tpr = new TextProtoReader(new BufReader(Deno.stdin)); +while (true) { + await Deno.stdout.write(encode("> ")); + const [line, err] = await tpr.readLine(); + if (err) { + console.error(red(`failed to read line from stdin: ${err}`)); + break; + } + if (line === "close") { + break; + } else if (line === "ping") { + await sock.ping(); + } else { + await sock.send(line); + } + // FIXME: Without this, + // sock.receive() won't resolved though it is readable... + await new Promise( + (resolve): void => { + setTimeout(resolve, 0); + } + ); } +await sock.close(1000); +// FIXME: conn.close() won't shutdown process... +Deno.exit(0); diff --git a/std/ws/example_server.ts b/std/ws/example_server.ts index cd51ff94c7..ea981256ea 100644 --- a/std/ws/example_server.ts +++ b/std/ws/example_server.ts @@ -9,58 +9,52 @@ import { /** websocket echo server */ const port = Deno.args[1] || "8080"; -async function main(): Promise { - console.log(`websocket server is running on :${port}`); - for await (const req of serve(`:${port}`)) { - const { headers, conn } = req; - acceptWebSocket({ - conn, - headers, - bufReader: req.r, - bufWriter: req.w - }) - .then( - async (sock: WebSocket): Promise => { - console.log("socket connected!"); - const it = sock.receive(); - while (true) { - try { - const { done, value } = await it.next(); - if (done) { - break; - } - const ev = value; - if (typeof ev === "string") { - // text message - console.log("ws:Text", ev); - await sock.send(ev); - } else if (ev instanceof Uint8Array) { - // binary message - console.log("ws:Binary", ev); - } else if (isWebSocketPingEvent(ev)) { - const [, body] = ev; - // ping - console.log("ws:Ping", body); - } else if (isWebSocketCloseEvent(ev)) { - // close - const { code, reason } = ev; - console.log("ws:Close", code, reason); - } - } catch (e) { - console.error(`failed to receive frame: ${e}`); - await sock.close(1000).catch(console.error); +console.log(`websocket server is running on :${port}`); +for await (const req of serve(`:${port}`)) { + const { headers, conn } = req; + acceptWebSocket({ + conn, + headers, + bufReader: req.r, + bufWriter: req.w + }) + .then( + async (sock: WebSocket): Promise => { + console.log("socket connected!"); + const it = sock.receive(); + while (true) { + try { + const { done, value } = await it.next(); + if (done) { + break; } + const ev = value; + if (typeof ev === "string") { + // text message + console.log("ws:Text", ev); + await sock.send(ev); + } else if (ev instanceof Uint8Array) { + // binary message + console.log("ws:Binary", ev); + } else if (isWebSocketPingEvent(ev)) { + const [, body] = ev; + // ping + console.log("ws:Ping", body); + } else if (isWebSocketCloseEvent(ev)) { + // close + const { code, reason } = ev; + console.log("ws:Close", code, reason); + } + } catch (e) { + console.error(`failed to receive frame: ${e}`); + await sock.close(1000).catch(console.error); } } - ) - .catch( - (err: Error): void => { - console.error(`failed to accept websocket: ${err}`); - } - ); - } -} - -if (import.meta.main) { - main(); + } + ) + .catch( + (err: Error): void => { + console.error(`failed to accept websocket: ${err}`); + } + ); } diff --git a/tools/deno_http_proxy.ts b/tools/deno_http_proxy.ts index 728e4fd3f5..5f601723a7 100644 --- a/tools/deno_http_proxy.ts +++ b/tools/deno_http_proxy.ts @@ -5,13 +5,6 @@ const addr = Deno.args[1] || "127.0.0.1:4500"; const originAddr = Deno.args[2] || "127.0.0.1:4501"; const server = serve(addr); -async function main(): Promise { - console.log(`Proxy listening on http://${addr}/`); - for await (const req of server) { - proxyRequest(req); - } -} - async function proxyRequest(req: ServerRequest): Promise { const url = `http://${originAddr}${req.url}`; const resp = await fetch(url, { @@ -21,4 +14,7 @@ async function proxyRequest(req: ServerRequest): Promise { req.respond(resp); } -main(); +console.log(`Proxy listening on http://${addr}/`); +for await (const req of server) { + proxyRequest(req); +}