diff options
Diffstat (limited to 'tests/testdata/workers')
85 files changed, 853 insertions, 0 deletions
diff --git a/tests/testdata/workers/async_error.ts b/tests/testdata/workers/async_error.ts new file mode 100644 index 000000000..154b957b1 --- /dev/null +++ b/tests/testdata/workers/async_error.ts @@ -0,0 +1,4 @@ +// deno-lint-ignore require-await +(async () => { + throw new Error("bar"); +})(); diff --git a/tests/testdata/workers/bench_large_message.ts b/tests/testdata/workers/bench_large_message.ts new file mode 100644 index 000000000..4bab9fb5c --- /dev/null +++ b/tests/testdata/workers/bench_large_message.ts @@ -0,0 +1,31 @@ +// Copyright 2020 the Deno authors. All rights reserved. MIT license. + +function oneWorker(i: number) { + return new Promise<void>((resolve) => { + let countDown = 10; + const worker = new Worker( + import.meta.resolve("./worker_large_message.js"), + { type: "module" }, + ); + worker.onmessage = (_e) => { + if (countDown > 0) { + countDown--; + return; + } + worker.terminate(); + resolve(); + }; + worker.postMessage("hi " + i); + }); +} + +function bench() { + const promises = []; + for (let i = 0; i < 50; i++) { + promises.push(oneWorker(i)); + } + + return Promise.all(promises); +} + +bench(); diff --git a/tests/testdata/workers/bench_round_robin.ts b/tests/testdata/workers/bench_round_robin.ts new file mode 100644 index 000000000..0380d7979 --- /dev/null +++ b/tests/testdata/workers/bench_round_robin.ts @@ -0,0 +1,65 @@ +// Benchmark measures time it takes to send a message to a group of workers one +// at a time and wait for a response from all of them. Just a general +// throughput and consistency benchmark. +const data = "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n"; +const workerCount = 4; +const cmdsPerWorker = 400; + +function handleAsyncMsgFromWorker( + promiseTable: Map<number, ReturnType<typeof Promise.withResolvers<string>>>, + msg: { cmdId: number; data: string }, +) { + const promise = promiseTable.get(msg.cmdId); + if (promise === null) { + throw new Error(`Failed to find promise: cmdId: ${msg.cmdId}, msg: ${msg}`); + } + promise?.resolve(data); +} + +async function main() { + const workers: Array< + [Map<number, ReturnType<typeof Promise.withResolvers<string>>>, Worker] + > = []; + for (let i = 1; i <= workerCount; ++i) { + const worker = new Worker( + import.meta.resolve("./bench_worker.ts"), + { type: "module" }, + ); + const { promise, resolve } = Promise.withResolvers<void>(); + worker.onmessage = (e) => { + if (e.data.cmdId === 0) resolve(); + }; + worker.postMessage({ cmdId: 0, action: 2 }); + await promise; + workers.push([new Map(), worker]); + } + // assign callback function + for (const [promiseTable, worker] of workers) { + worker.onmessage = (e) => { + handleAsyncMsgFromWorker(promiseTable, e.data); + }; + } + for (const cmdId of Array(cmdsPerWorker).keys()) { + const promises: Array<Promise<string>> = []; + for (const [promiseTable, worker] of workers) { + const deferred = Promise.withResolvers<string>(); + promiseTable.set(cmdId, deferred); + worker.postMessage({ cmdId: cmdId, action: 1, data }); + promises.push(deferred.promise); + } + for (const promise of promises) { + await promise; + } + } + for (const [, worker] of workers) { + const { promise, resolve } = Promise.withResolvers<void>(); + worker.onmessage = (e) => { + if (e.data.cmdId === 3) resolve(); + }; + worker.postMessage({ action: 3 }); + await promise; + } + console.log("Finished!"); +} + +main(); diff --git a/tests/testdata/workers/bench_startup.ts b/tests/testdata/workers/bench_startup.ts new file mode 100644 index 000000000..a4233d34c --- /dev/null +++ b/tests/testdata/workers/bench_startup.ts @@ -0,0 +1,33 @@ +// Benchmark measures time it takes to start and stop a number of workers. +const workerCount = 50; + +async function bench() { + const workers: Worker[] = []; + for (let i = 1; i <= workerCount; ++i) { + const worker = new Worker( + import.meta.resolve("./bench_worker.ts"), + { type: "module" }, + ); + const promise = new Promise<void>((resolve) => { + worker.onmessage = (e) => { + if (e.data.cmdId === 0) resolve(); + }; + }); + worker.postMessage({ cmdId: 0, action: 2 }); + await promise; + workers.push(worker); + } + console.log("Done creating workers closing workers!"); + for (const worker of workers) { + const promise = new Promise<void>((resolve) => { + worker.onmessage = (e) => { + if (e.data.cmdId === 3) resolve(); + }; + }); + worker.postMessage({ action: 3 }); + await promise; + } + console.log("Finished!"); +} + +bench(); diff --git a/tests/testdata/workers/bench_worker.ts b/tests/testdata/workers/bench_worker.ts new file mode 100644 index 000000000..1edd2750f --- /dev/null +++ b/tests/testdata/workers/bench_worker.ts @@ -0,0 +1,21 @@ +onmessage = function (e) { + const { cmdId, action, data } = e.data; + switch (action) { + case 0: // Static response + postMessage({ + cmdId, + data: "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n", + }); + break; + case 1: // Respond with request data + postMessage({ cmdId, data }); + break; + case 2: // Ping + postMessage({ cmdId }); + break; + case 3: // Close + postMessage({ cmdId: 3 }); + close(); + break; + } +}; diff --git a/tests/testdata/workers/broadcast_channel.ts b/tests/testdata/workers/broadcast_channel.ts new file mode 100644 index 000000000..5076e9eb7 --- /dev/null +++ b/tests/testdata/workers/broadcast_channel.ts @@ -0,0 +1,5 @@ +new BroadcastChannel("intercom").onmessage = function (e) { + this.postMessage(e.data); +}; + +self.postMessage("go"); diff --git a/tests/testdata/workers/busy_worker.js b/tests/testdata/workers/busy_worker.js new file mode 100644 index 000000000..7deba0321 --- /dev/null +++ b/tests/testdata/workers/busy_worker.js @@ -0,0 +1,8 @@ +self.onmessage = function (_evt) { + // infinite loop + for (let i = 0; true; i++) { + if (i % 1000 == 0) { + postMessage(i); + } + } +}; diff --git a/tests/testdata/workers/close_in_wasm_reactions.js b/tests/testdata/workers/close_in_wasm_reactions.js new file mode 100644 index 000000000..abe573108 --- /dev/null +++ b/tests/testdata/workers/close_in_wasm_reactions.js @@ -0,0 +1,21 @@ +// https://github.com/denoland/deno/issues/12263 +// Test for a panic that happens when a worker is closed in the reactions of a +// WASM async operation. + +// The minimum valid wasm module, plus two additional zero bytes. +const buffer = new Uint8Array([ + 0x00, + 0x61, + 0x73, + 0x6D, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, +]); +WebAssembly.compile(buffer).catch((err) => { + console.log("Error:", err); + self.close(); +}); diff --git a/tests/testdata/workers/close_nested_child.js b/tests/testdata/workers/close_nested_child.js new file mode 100644 index 000000000..97980c689 --- /dev/null +++ b/tests/testdata/workers/close_nested_child.js @@ -0,0 +1,8 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +console.log("Starting the child worker"); + +setTimeout(() => { + console.log("The child worker survived the death of the parent!!!"); + Deno.exit(1); +}, 2000); diff --git a/tests/testdata/workers/close_nested_parent.js b/tests/testdata/workers/close_nested_parent.js new file mode 100644 index 000000000..d1fe47553 --- /dev/null +++ b/tests/testdata/workers/close_nested_parent.js @@ -0,0 +1,13 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +console.log("Starting the parent worker"); + +new Worker( + import.meta.resolve("./close_nested_child.js"), + { type: "module" }, +); + +self.addEventListener("message", () => { + console.log("Closing"); + self.close(); +}); diff --git a/tests/testdata/workers/close_race_worker.js b/tests/testdata/workers/close_race_worker.js new file mode 100644 index 000000000..6964be34a --- /dev/null +++ b/tests/testdata/workers/close_race_worker.js @@ -0,0 +1,6 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +setTimeout(() => { + self.postMessage(""); + self.close(); +}, 500); diff --git a/tests/testdata/workers/custom_inspect/main.out b/tests/testdata/workers/custom_inspect/main.out new file mode 100644 index 000000000..40d9b88ad --- /dev/null +++ b/tests/testdata/workers/custom_inspect/main.out @@ -0,0 +1 @@ +ReadableStream { locked: false } diff --git a/tests/testdata/workers/custom_inspect/main.ts b/tests/testdata/workers/custom_inspect/main.ts new file mode 100644 index 000000000..93d4eec2d --- /dev/null +++ b/tests/testdata/workers/custom_inspect/main.ts @@ -0,0 +1,4 @@ +new Worker( + import.meta.resolve("./worker.ts"), + { type: "module" }, +); diff --git a/tests/testdata/workers/custom_inspect/worker.ts b/tests/testdata/workers/custom_inspect/worker.ts new file mode 100644 index 000000000..5be82724e --- /dev/null +++ b/tests/testdata/workers/custom_inspect/worker.ts @@ -0,0 +1,2 @@ +console.log(new ReadableStream()); +close(); diff --git a/tests/testdata/workers/deno_worker.ts b/tests/testdata/workers/deno_worker.ts new file mode 100644 index 000000000..cbebde94a --- /dev/null +++ b/tests/testdata/workers/deno_worker.ts @@ -0,0 +1,16 @@ +import { assert } from "../../../test_util/std/assert/mod.ts"; + +onmessage = function (e) { + if (typeof self.Deno === "undefined") { + throw new Error("Deno namespace not available in worker"); + } + + assert(!Object.isFrozen(self.Deno)); + + const desc = Object.getOwnPropertyDescriptor(self, "Deno"); + assert(desc); + assert(desc.configurable); + assert(!desc.writable); + + postMessage(e.data); +}; diff --git a/tests/testdata/workers/drop_handle_race.js b/tests/testdata/workers/drop_handle_race.js new file mode 100644 index 000000000..30676a600 --- /dev/null +++ b/tests/testdata/workers/drop_handle_race.js @@ -0,0 +1,3 @@ +setTimeout(() => { + throw new Error(); +}, 1000); diff --git a/tests/testdata/workers/dynamic_remote.ts b/tests/testdata/workers/dynamic_remote.ts new file mode 100644 index 000000000..54e4a4714 --- /dev/null +++ b/tests/testdata/workers/dynamic_remote.ts @@ -0,0 +1,2 @@ +// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +await import("" + "https://example.com/some/file.ts"); diff --git a/tests/testdata/workers/env_read_check_worker.js b/tests/testdata/workers/env_read_check_worker.js new file mode 100644 index 000000000..72ad31df2 --- /dev/null +++ b/tests/testdata/workers/env_read_check_worker.js @@ -0,0 +1,14 @@ +onmessage = async ({ data }) => { + const permissions = []; + for (const name of data.names) { + const { state } = await Deno.permissions.query({ + name: "env", + variable: name, + }); + permissions.push(state === "granted"); + } + + postMessage({ + permissions, + }); +}; diff --git a/tests/testdata/workers/error.ts b/tests/testdata/workers/error.ts new file mode 100644 index 000000000..495971090 --- /dev/null +++ b/tests/testdata/workers/error.ts @@ -0,0 +1,5 @@ +function foo() { + throw new Error("foo"); +} + +foo(); diff --git a/tests/testdata/workers/error_event.ts b/tests/testdata/workers/error_event.ts new file mode 100644 index 000000000..70e7728ab --- /dev/null +++ b/tests/testdata/workers/error_event.ts @@ -0,0 +1,11 @@ +const worker = new Worker(import.meta.resolve("./error.ts"), { + type: "module", +}); +worker.addEventListener("error", (e) => { + console.log({ + "message": e.message, + "filename": e.filename?.slice?.(-100), + "lineno": e.lineno, + "colno": e.colno, + }); +}); diff --git a/tests/testdata/workers/error_event.ts.out b/tests/testdata/workers/error_event.ts.out new file mode 100644 index 000000000..833cca8be --- /dev/null +++ b/tests/testdata/workers/error_event.ts.out @@ -0,0 +1,13 @@ +error: Uncaught (in worker "") (in promise) Error: foo + throw new Error("foo"); + ^ + at foo ([WILDCARD]/error.ts:2:9) + at [WILDCARD]/error.ts:5:1 +{ + message: "Uncaught (in promise) Error: foo", + filename: "[WILDCARD]/error.ts", + lineno: 2, + colno: 9 +} +error: Uncaught (in promise) Error: Unhandled error in child worker. + at [WILDCARD] diff --git a/tests/testdata/workers/error_worker_permissions_local.ts b/tests/testdata/workers/error_worker_permissions_local.ts new file mode 100644 index 000000000..1a4b4c0a9 --- /dev/null +++ b/tests/testdata/workers/error_worker_permissions_local.ts @@ -0,0 +1,4 @@ +new Worker( + import.meta.resolve("../subdir/worker_types.ts"), + { type: "module" }, +); diff --git a/tests/testdata/workers/error_worker_permissions_local.ts.out b/tests/testdata/workers/error_worker_permissions_local.ts.out new file mode 100644 index 000000000..cacc8ae38 --- /dev/null +++ b/tests/testdata/workers/error_worker_permissions_local.ts.out @@ -0,0 +1,2 @@ +error: Uncaught (in worker "") Requires read access to "[WILDCARD]worker_types.ts", run again with the --allow-read flag +[WILDCARD] diff --git a/tests/testdata/workers/error_worker_permissions_remote.ts b/tests/testdata/workers/error_worker_permissions_remote.ts new file mode 100644 index 000000000..878c7080a --- /dev/null +++ b/tests/testdata/workers/error_worker_permissions_remote.ts @@ -0,0 +1,4 @@ +new Worker( + "http://localhost:4545/subdir/worker_types.ts", + { type: "module" }, +); diff --git a/tests/testdata/workers/error_worker_permissions_remote.ts.out b/tests/testdata/workers/error_worker_permissions_remote.ts.out new file mode 100644 index 000000000..afecff0a8 --- /dev/null +++ b/tests/testdata/workers/error_worker_permissions_remote.ts.out @@ -0,0 +1,2 @@ +error: Uncaught (in worker "") Requires net access to "localhost:4545", run again with the --allow-net flag +[WILDCARD] diff --git a/tests/testdata/workers/event_worker.js b/tests/testdata/workers/event_worker.js new file mode 100644 index 000000000..849b6026c --- /dev/null +++ b/tests/testdata/workers/event_worker.js @@ -0,0 +1,7 @@ +onmessage = function (e) { + if (e.data === "boom") { + throw new Error("boom error!"); + } + + postMessage(e.data); +}; diff --git a/tests/testdata/workers/event_worker_scope.js b/tests/testdata/workers/event_worker_scope.js new file mode 100644 index 000000000..0381801a8 --- /dev/null +++ b/tests/testdata/workers/event_worker_scope.js @@ -0,0 +1,43 @@ +let messageHandlersCalled = 0; +let errorHandlersCalled = 0; + +onmessage = function (e) { + if (e.data === "boom") { + throw new Error("boom error!"); + } + messageHandlersCalled++; +}; + +self.addEventListener("message", (_e) => { + messageHandlersCalled++; +}); + +self.addEventListener("message", (_e) => { + messageHandlersCalled++; +}); + +self.addEventListener("message", (_e) => { + messageHandlersCalled++; + + postMessage({ + messageHandlersCalled, + errorHandlersCalled, + }); +}); + +onerror = function (_e) { + errorHandlersCalled++; +}; + +self.addEventListener("error", (_e) => { + errorHandlersCalled++; +}); + +self.addEventListener("error", (_e) => { + errorHandlersCalled++; +}); + +self.addEventListener("error", (e) => { + errorHandlersCalled++; + e.preventDefault(); +}); diff --git a/tests/testdata/workers/fetching_worker.js b/tests/testdata/workers/fetching_worker.js new file mode 100644 index 000000000..77ff471d7 --- /dev/null +++ b/tests/testdata/workers/fetching_worker.js @@ -0,0 +1,6 @@ +const r = await fetch( + "http://localhost:4545/workers/fetching_worker.js", +); +await r.text(); +postMessage("Done!"); +close(); diff --git a/tests/testdata/workers/http_worker.js b/tests/testdata/workers/http_worker.js new file mode 100644 index 000000000..3cd1625ab --- /dev/null +++ b/tests/testdata/workers/http_worker.js @@ -0,0 +1,11 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. +const listener = Deno.listen({ hostname: "127.0.0.1", port: 4506 }); +postMessage("ready"); +for await (const conn of listener) { + (async () => { + const requests = Deno.serveHttp(conn); + for await (const { respondWith } of requests) { + respondWith(new Response("Hello world")); + } + })(); +} diff --git a/tests/testdata/workers/image_data_worker.ts b/tests/testdata/workers/image_data_worker.ts new file mode 100644 index 000000000..bf920d2f3 --- /dev/null +++ b/tests/testdata/workers/image_data_worker.ts @@ -0,0 +1,2 @@ +const data = new ImageData(2, 2, { colorSpace: "display-p3" }); +postMessage(data.data.length); diff --git a/tests/testdata/workers/immediately_close_worker.js b/tests/testdata/workers/immediately_close_worker.js new file mode 100644 index 000000000..8fd27343a --- /dev/null +++ b/tests/testdata/workers/immediately_close_worker.js @@ -0,0 +1 @@ +self.close(); diff --git a/tests/testdata/workers/message_before_close.js b/tests/testdata/workers/message_before_close.js new file mode 100644 index 000000000..9364b6d82 --- /dev/null +++ b/tests/testdata/workers/message_before_close.js @@ -0,0 +1,4 @@ +onmessage = () => { + postMessage({}); + close(); +}; diff --git a/tests/testdata/workers/message_handler_error.ts b/tests/testdata/workers/message_handler_error.ts new file mode 100644 index 000000000..3416faad1 --- /dev/null +++ b/tests/testdata/workers/message_handler_error.ts @@ -0,0 +1,4 @@ +postMessage("ready"); +onmessage = () => { + throw new Error("bar"); +}; diff --git a/tests/testdata/workers/message_port.ts b/tests/testdata/workers/message_port.ts new file mode 100644 index 000000000..d78304a39 --- /dev/null +++ b/tests/testdata/workers/message_port.ts @@ -0,0 +1,14 @@ +const channel = new MessageChannel(); + +channel.port2.onmessage = (e) => { + channel.port2.postMessage(e.data === "2"); + channel.port2.close(); +}; + +self.postMessage("1", [channel.port1]); + +self.onmessage = (e) => { + const port1 = e.ports[0]; + port1.postMessage(e.data === "3"); + port1.close(); +}; diff --git a/tests/testdata/workers/nested_worker.js b/tests/testdata/workers/nested_worker.js new file mode 100644 index 000000000..2273cdbfa --- /dev/null +++ b/tests/testdata/workers/nested_worker.js @@ -0,0 +1,18 @@ +// Specifier should be resolved relative to current file +const jsWorker = new Worker( + import.meta.resolve("./sibling_worker.js"), + { type: "module", name: "sibling" }, +); + +jsWorker.onerror = (_e) => { + postMessage({ type: "error" }); +}; + +jsWorker.onmessage = (e) => { + postMessage({ type: "msg", text: e.data }); + close(); +}; + +onmessage = function (e) { + jsWorker.postMessage(e.data); +}; diff --git a/tests/testdata/workers/no_permissions_worker.js b/tests/testdata/workers/no_permissions_worker.js new file mode 100644 index 000000000..f49f690ab --- /dev/null +++ b/tests/testdata/workers/no_permissions_worker.js @@ -0,0 +1,17 @@ +self.onmessage = async () => { + const hrtime = await Deno.permissions.query({ name: "hrtime" }); + const net = await Deno.permissions.query({ name: "net" }); + const ffi = await Deno.permissions.query({ name: "ffi" }); + const read = await Deno.permissions.query({ name: "read" }); + const run = await Deno.permissions.query({ name: "run" }); + const write = await Deno.permissions.query({ name: "write" }); + self.postMessage( + hrtime.state === "prompt" && + net.state === "prompt" && + ffi.state === "prompt" && + read.state === "prompt" && + run.state === "prompt" && + write.state === "prompt", + ); + self.close(); +}; diff --git a/tests/testdata/workers/non_deno_worker.js b/tests/testdata/workers/non_deno_worker.js new file mode 100644 index 000000000..773721560 --- /dev/null +++ b/tests/testdata/workers/non_deno_worker.js @@ -0,0 +1,7 @@ +onmessage = function (e) { + if (typeof self.Deno !== "undefined") { + throw new Error("Deno namespace unexpectedly available in worker"); + } + + postMessage(e.data); +}; diff --git a/tests/testdata/workers/nonexistent_worker.out b/tests/testdata/workers/nonexistent_worker.out new file mode 100644 index 000000000..a624c0b51 --- /dev/null +++ b/tests/testdata/workers/nonexistent_worker.out @@ -0,0 +1,3 @@ +[WILDCARD]error: Uncaught (in worker "") Module not found "file:///[WILDCARD]/workers/doesnt_exist.js". +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl[WILDCARD] diff --git a/tests/testdata/workers/nonexistent_worker.ts b/tests/testdata/workers/nonexistent_worker.ts new file mode 100644 index 000000000..b30d08636 --- /dev/null +++ b/tests/testdata/workers/nonexistent_worker.ts @@ -0,0 +1,5 @@ +const w = new Worker(import.meta.resolve("./doesnt_exist.js"), { + type: "module", +}); + +w.postMessage("hello"); diff --git a/tests/testdata/workers/parent_read_check_worker.js b/tests/testdata/workers/parent_read_check_worker.js new file mode 100644 index 000000000..3221fc597 --- /dev/null +++ b/tests/testdata/workers/parent_read_check_worker.js @@ -0,0 +1,12 @@ +const worker = new Worker( + import.meta.resolve("./read_check_granular_worker.js"), + { type: "module", deno: { permissions: "none" } }, +); + +onmessage = ({ data }) => { + worker.postMessage(data); +}; + +worker.onmessage = ({ data }) => { + postMessage(data); +}; diff --git a/tests/testdata/workers/permission_echo.js b/tests/testdata/workers/permission_echo.js new file mode 100644 index 000000000..f492a25f2 --- /dev/null +++ b/tests/testdata/workers/permission_echo.js @@ -0,0 +1,19 @@ +self.onmessage = async () => { + const env = await Deno.permissions.query({ name: "env" }); + const ffi = await Deno.permissions.query({ name: "ffi" }); + const hrtime = await Deno.permissions.query({ name: "hrtime" }); + const net = await Deno.permissions.query({ name: "net" }); + const read = await Deno.permissions.query({ name: "read" }); + const run = await Deno.permissions.query({ name: "run" }); + const write = await Deno.permissions.query({ name: "write" }); + self.postMessage({ + env: env.state, + ffi: ffi.state, + hrtime: hrtime.state, + net: net.state, + read: read.state, + run: run.state, + write: write.state, + }); + self.close(); +}; diff --git a/tests/testdata/workers/permissions_blob_local.ts b/tests/testdata/workers/permissions_blob_local.ts new file mode 100644 index 000000000..52f630bd8 --- /dev/null +++ b/tests/testdata/workers/permissions_blob_local.ts @@ -0,0 +1,6 @@ +// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +const code = `import "file:///${ + Deno.build.os == "windows" ? "C:/" : "" +}local_file.ts";`; +const blob = new Blob([code]); +new Worker(URL.createObjectURL(blob), { type: "module" }); diff --git a/tests/testdata/workers/permissions_blob_local.ts.out b/tests/testdata/workers/permissions_blob_local.ts.out new file mode 100644 index 000000000..0cd581f7b --- /dev/null +++ b/tests/testdata/workers/permissions_blob_local.ts.out @@ -0,0 +1,4 @@ +error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag + at blob:null/[WILDCARD]:1:8 +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/permissions_blob_remote.ts b/tests/testdata/workers/permissions_blob_remote.ts new file mode 100644 index 000000000..4808bc57b --- /dev/null +++ b/tests/testdata/workers/permissions_blob_remote.ts @@ -0,0 +1,4 @@ +// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +const code = `import "https://example.com/some/file.ts";`; +const blob = new Blob([code]); +new Worker(URL.createObjectURL(blob), { type: "module" }); diff --git a/tests/testdata/workers/permissions_blob_remote.ts.out b/tests/testdata/workers/permissions_blob_remote.ts.out new file mode 100644 index 000000000..618f552dc --- /dev/null +++ b/tests/testdata/workers/permissions_blob_remote.ts.out @@ -0,0 +1,4 @@ +error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag + at blob:null/[WILDCARD]:1:8 +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl[WILDCARD] diff --git a/tests/testdata/workers/permissions_data_local.ts b/tests/testdata/workers/permissions_data_local.ts new file mode 100644 index 000000000..cda80bed6 --- /dev/null +++ b/tests/testdata/workers/permissions_data_local.ts @@ -0,0 +1,7 @@ +// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +const code = `import "file:///${ + Deno.build.os == "windows" ? "C:/" : "" +}local_file.ts";`; +new Worker(`data:application/javascript;base64,${btoa(code)}`, { + type: "module", +}); diff --git a/tests/testdata/workers/permissions_data_local.ts.out b/tests/testdata/workers/permissions_data_local.ts.out new file mode 100644 index 000000000..4e0f72779 --- /dev/null +++ b/tests/testdata/workers/permissions_data_local.ts.out @@ -0,0 +1,4 @@ +error: Uncaught (in worker "") Requires read access to "[WILDCARD]local_file.ts", run again with the --allow-read flag + at data:application/javascript;base64,[WILDCARD]:1:8 +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl[WILDCARD] diff --git a/tests/testdata/workers/permissions_data_remote.ts b/tests/testdata/workers/permissions_data_remote.ts new file mode 100644 index 000000000..b37bd661d --- /dev/null +++ b/tests/testdata/workers/permissions_data_remote.ts @@ -0,0 +1,5 @@ +// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +const code = `import "https://example.com/some/file.ts";`; +new Worker(`data:application/javascript;base64,${btoa(code)}`, { + type: "module", +}); diff --git a/tests/testdata/workers/permissions_data_remote.ts.out b/tests/testdata/workers/permissions_data_remote.ts.out new file mode 100644 index 000000000..3f7c8cb63 --- /dev/null +++ b/tests/testdata/workers/permissions_data_remote.ts.out @@ -0,0 +1,4 @@ +error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag + at data:application/javascript;base64,aW1wb3J0ICJodHRwczovL2V4YW1wbGUuY29tL3NvbWUvZmlsZS50cyI7:1:8 +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl[WILDCARD] diff --git a/tests/testdata/workers/permissions_dynamic_remote.ts b/tests/testdata/workers/permissions_dynamic_remote.ts new file mode 100644 index 000000000..54a361bc0 --- /dev/null +++ b/tests/testdata/workers/permissions_dynamic_remote.ts @@ -0,0 +1,11 @@ +new Worker( + "http://localhost:4545/workers/dynamic_remote.ts", + { + type: "module", + deno: { + permissions: { + net: false, + }, + }, + }, +); diff --git a/tests/testdata/workers/permissions_dynamic_remote.ts.out b/tests/testdata/workers/permissions_dynamic_remote.ts.out new file mode 100644 index 000000000..91f3cc6d5 --- /dev/null +++ b/tests/testdata/workers/permissions_dynamic_remote.ts.out @@ -0,0 +1,6 @@ +error: Uncaught (in worker "") (in promise) TypeError: Requires net access to "example.com", run again with the --allow-net flag +await import("" + "https://example.com/some/file.ts"); +^ + at async http://localhost:4545/workers/dynamic_remote.ts:2:1 +[WILDCARD]error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/permissions_remote_remote.ts b/tests/testdata/workers/permissions_remote_remote.ts new file mode 100644 index 000000000..4df2a8a5d --- /dev/null +++ b/tests/testdata/workers/permissions_remote_remote.ts @@ -0,0 +1,3 @@ +new Worker("http://localhost:4545/workers/static_remote.ts", { + type: "module", +}); diff --git a/tests/testdata/workers/permissions_remote_remote.ts.out b/tests/testdata/workers/permissions_remote_remote.ts.out new file mode 100644 index 000000000..bb065740a --- /dev/null +++ b/tests/testdata/workers/permissions_remote_remote.ts.out @@ -0,0 +1,4 @@ +error: Uncaught (in worker "") Requires net access to "example.com", run again with the --allow-net flag + at http://localhost:4545/workers/static_remote.ts:2:8 +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/post_undefined.ts b/tests/testdata/workers/post_undefined.ts new file mode 100644 index 000000000..1b9b8d6ca --- /dev/null +++ b/tests/testdata/workers/post_undefined.ts @@ -0,0 +1,5 @@ +self.onmessage = (ev: MessageEvent) => { + console.log("received in worker", ev.data); + self.postMessage(undefined); + console.log("posted from worker"); +}; diff --git a/tests/testdata/workers/racy_worker.js b/tests/testdata/workers/racy_worker.js new file mode 100644 index 000000000..0f66c6278 --- /dev/null +++ b/tests/testdata/workers/racy_worker.js @@ -0,0 +1,25 @@ +// See issue for details +// https://github.com/denoland/deno/issues/4080 +// +// After first received message, this worker schedules +// [assert(), close(), assert()] ops on the same turn of microtask queue +// All tasks after close should not make it + +onmessage = async function () { + let stage = 0; + await new Promise((_) => { + setTimeout(() => { + if (stage !== 0) throw "Unexpected stage"; + stage = 1; + }, 50); + setTimeout(() => { + if (stage !== 1) throw "Unexpected stage"; + stage = 2; + postMessage("DONE"); + close(); + }, 50); + setTimeout(() => { + throw "This should not be run"; + }, 50); + }); +}; diff --git a/tests/testdata/workers/read_check_granular_worker.js b/tests/testdata/workers/read_check_granular_worker.js new file mode 100644 index 000000000..d40fac876 --- /dev/null +++ b/tests/testdata/workers/read_check_granular_worker.js @@ -0,0 +1,29 @@ +// deno-fmt-ignore-file +postMessage({ + envGlobal: (await Deno.permissions.query({ name: "env" })).state, + envFoo: (await Deno.permissions.query({ name: "env", variable: "foo" })).state, + envAbsent: (await Deno.permissions.query({ name: "env", variable: "absent" })).state, + hrtime: (await Deno.permissions.query({ name: "hrtime" })).state, + netGlobal: (await Deno.permissions.query({ name: "net" })).state, + netFoo: (await Deno.permissions.query({ name: "net", host: "foo" })).state, + netFoo8000: (await Deno.permissions.query({ name: "net", host: "foo:8000" })).state, + netBar: (await Deno.permissions.query({ name: "net", host: "bar" })).state, + netBar8000: (await Deno.permissions.query({ name: "net", host: "bar:8000" })).state, + ffiGlobal: (await Deno.permissions.query({ name: "ffi" })).state, + ffiFoo: (await Deno.permissions.query({ name: "ffi", path: new URL("foo", import.meta.url) })).state, + ffiBar: (await Deno.permissions.query({ name: "ffi", path: "bar" })).state, + ffiAbsent: (await Deno.permissions.query({ name: "ffi", path: "absent" })).state, + readGlobal: (await Deno.permissions.query({ name: "read" })).state, + readFoo: (await Deno.permissions.query({ name: "read", path: new URL("foo", import.meta.url) })).state, + readBar: (await Deno.permissions.query({ name: "read", path: "bar" })).state, + readAbsent: (await Deno.permissions.query({ name: "read", path: "absent" })).state, + runGlobal: (await Deno.permissions.query({ name: "run" })).state, + runFoo: (await Deno.permissions.query({ name: "run", command: new URL("foo", import.meta.url) })).state, + runBar: (await Deno.permissions.query({ name: "run", command: "bar" })).state, + runBaz: (await Deno.permissions.query({ name: "run", command: "./baz" })).state, + runAbsent: (await Deno.permissions.query({ name: "run", command: "absent" })).state, + writeGlobal: (await Deno.permissions.query({ name: "write" })).state, + writeFoo: (await Deno.permissions.query({ name: "write", path: new URL("foo", import.meta.url) })).state, + writeBar: (await Deno.permissions.query({ name: "write", path: "bar" })).state, + writeAbsent: (await Deno.permissions.query({ name: "write", path: "absent" })).state, +}); diff --git a/tests/testdata/workers/read_check_worker.js b/tests/testdata/workers/read_check_worker.js new file mode 100644 index 000000000..2ad01bf5b --- /dev/null +++ b/tests/testdata/workers/read_check_worker.js @@ -0,0 +1,7 @@ +onmessage = async () => { + const { state } = await Deno.permissions.query({ + name: "read", + }); + postMessage(state === "granted"); + close(); +}; diff --git a/tests/testdata/workers/shared_array_buffer.ts b/tests/testdata/workers/shared_array_buffer.ts new file mode 100644 index 000000000..4af95863a --- /dev/null +++ b/tests/testdata/workers/shared_array_buffer.ts @@ -0,0 +1,9 @@ +self.postMessage("ready"); + +globalThis.addEventListener("message", (e) => { + const bytes1 = new Uint8Array(e.data[0]); + const bytes2 = new Uint8Array(e.data[1]); + bytes1[0] = 1; + bytes2[0] = 2; + self.postMessage("done"); +}); diff --git a/tests/testdata/workers/sibling_worker.js b/tests/testdata/workers/sibling_worker.js new file mode 100644 index 000000000..99707e5d6 --- /dev/null +++ b/tests/testdata/workers/sibling_worker.js @@ -0,0 +1,4 @@ +onmessage = (e) => { + postMessage(e.data); + close(); +}; diff --git a/tests/testdata/workers/static_remote.ts b/tests/testdata/workers/static_remote.ts new file mode 100644 index 000000000..2d6e820fd --- /dev/null +++ b/tests/testdata/workers/static_remote.ts @@ -0,0 +1,2 @@ +// This file doesn't really exist, but it doesn't matter, a "PermissionsDenied" error should be thrown. +import "https://example.com/some/file.ts"; diff --git a/tests/testdata/workers/terminate_tla_crash.js b/tests/testdata/workers/terminate_tla_crash.js new file mode 100644 index 000000000..f793b8c8e --- /dev/null +++ b/tests/testdata/workers/terminate_tla_crash.js @@ -0,0 +1,21 @@ +// Test for https://github.com/denoland/deno/issues/12658 +// +// If a worker is terminated immediately after construction, and the worker's +// main module uses top-level await, V8 has a chance to crash. +// +// These crashes are so rare in debug mode that I've only seen them once. They +// happen a lot more often in release mode. + +const workerModule = ` + await new Promise(resolve => setTimeout(resolve, 1000)); +`; + +// Iterating 10 times to increase the likelihood of triggering the crash, at +// least in release mode. +for (let i = 0; i < 10; i++) { + const worker = new Worker( + `data:application/javascript;base64,${btoa(workerModule)}`, + { type: "module" }, + ); + worker.terminate(); +} diff --git a/tests/testdata/workers/terminate_tla_crash.js.out b/tests/testdata/workers/terminate_tla_crash.js.out new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/testdata/workers/terminate_tla_crash.js.out diff --git a/tests/testdata/workers/test_worker.js b/tests/testdata/workers/test_worker.js new file mode 100644 index 000000000..2b2d1eeec --- /dev/null +++ b/tests/testdata/workers/test_worker.js @@ -0,0 +1,8 @@ +if (self.name !== "") { + throw Error(`Bad worker name: ${self.name}, expected empty string.`); +} + +onmessage = function (e) { + postMessage(e.data); + close(); +}; diff --git a/tests/testdata/workers/test_worker.ts b/tests/testdata/workers/test_worker.ts new file mode 100644 index 000000000..996476058 --- /dev/null +++ b/tests/testdata/workers/test_worker.ts @@ -0,0 +1,8 @@ +if (self.name !== "tsWorker") { + throw Error(`Invalid worker name: ${self.name}, expected tsWorker`); +} + +onmessage = function (e) { + postMessage(e.data); + close(); +}; diff --git a/tests/testdata/workers/throwing_worker.js b/tests/testdata/workers/throwing_worker.js new file mode 100644 index 000000000..56ee4ff88 --- /dev/null +++ b/tests/testdata/workers/throwing_worker.js @@ -0,0 +1,2 @@ +// This worker just throws error when it's being executed +throw Error("Thrown error"); diff --git a/tests/testdata/workers/worker_async_error.ts b/tests/testdata/workers/worker_async_error.ts new file mode 100644 index 000000000..7941a5bbe --- /dev/null +++ b/tests/testdata/workers/worker_async_error.ts @@ -0,0 +1,5 @@ +const worker = new Worker( + import.meta.resolve("./async_error.ts"), + { type: "module", name: "foo" }, +); +setTimeout(() => worker.terminate(), 30000); diff --git a/tests/testdata/workers/worker_async_error.ts.out b/tests/testdata/workers/worker_async_error.ts.out new file mode 100644 index 000000000..8d017859c --- /dev/null +++ b/tests/testdata/workers/worker_async_error.ts.out @@ -0,0 +1,7 @@ +error: Uncaught (in worker "foo") (in promise) Error: bar + throw new Error("bar"); + ^ + at [WILDCARD]/async_error.ts:[WILDCARD] + at [WILDCARD]/async_error.ts:[WILDCARD] +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/worker_crypto.js b/tests/testdata/workers/worker_crypto.js new file mode 100644 index 000000000..4398ad068 --- /dev/null +++ b/tests/testdata/workers/worker_crypto.js @@ -0,0 +1,5 @@ +self.crypto.getRandomValues(new Uint8Array(16)); + +onmessage = function () { + postMessage(!!self.crypto); +}; diff --git a/tests/testdata/workers/worker_doest_stall_event_loop.ts b/tests/testdata/workers/worker_doest_stall_event_loop.ts new file mode 100644 index 000000000..bfddee2ec --- /dev/null +++ b/tests/testdata/workers/worker_doest_stall_event_loop.ts @@ -0,0 +1,29 @@ +const moduleCode = ` +console.log('module start'); +const hash = await crypto.subtle.digest('SHA-1', new TextEncoder().encode('data')); +const __default = {}; +export { __default as default }; +console.log('module finish'); +`; + +const workerCode = ` + console.log('worker!'); + + globalThis.onmessage = (msg) => { + const { moduleCode } = msg.data; + (async () => { + console.log('before import'); + await import(URL.createObjectURL(new Blob([ moduleCode ]))); + console.log('after import'); + self.postMessage('thanks'); + })(); + } +`; +const worker = new Worker(URL.createObjectURL(new Blob([workerCode])), { + type: "module", +}); +worker.onmessage = () => { + console.log("worker.terminate"); + worker.terminate(); +}; +worker.postMessage({ moduleCode }); diff --git a/tests/testdata/workers/worker_doest_stall_event_loop.ts.out b/tests/testdata/workers/worker_doest_stall_event_loop.ts.out new file mode 100644 index 000000000..5ed65b02f --- /dev/null +++ b/tests/testdata/workers/worker_doest_stall_event_loop.ts.out @@ -0,0 +1,6 @@ +worker! +before import +module start +module finish +after import +worker.terminate diff --git a/tests/testdata/workers/worker_error.ts b/tests/testdata/workers/worker_error.ts new file mode 100644 index 000000000..403223d0a --- /dev/null +++ b/tests/testdata/workers/worker_error.ts @@ -0,0 +1,5 @@ +const worker = new Worker( + import.meta.resolve("./error.ts"), + { type: "module", name: "bar" }, +); +setTimeout(() => worker.terminate(), 30000); diff --git a/tests/testdata/workers/worker_error.ts.out b/tests/testdata/workers/worker_error.ts.out new file mode 100644 index 000000000..1dd017770 --- /dev/null +++ b/tests/testdata/workers/worker_error.ts.out @@ -0,0 +1,5 @@ +[WILDCARD]error: Uncaught (in worker "bar") (in promise) Error: foo[WILDCARD] + at foo ([WILDCARD]) + at [WILDCARD] +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/worker_event_handlers.js b/tests/testdata/workers/worker_event_handlers.js new file mode 100644 index 000000000..5e457cd2e --- /dev/null +++ b/tests/testdata/workers/worker_event_handlers.js @@ -0,0 +1,26 @@ +self.onmessage = (evt) => { + console.log("Target from self.onmessage:", String(evt.target)); +}; + +self.addEventListener("message", (evt) => { + console.log("Target from message event listener:", String(evt.target)); + + // Throw an error here so the global's error event will fire. + throw new Error("Some error message"); +}); + +self.onerror = (...args) => { + // Take the last 100 characters so the filename doesn't get truncated + // depending on the dev's FS structure. + args = args.map((v) => typeof v == "string" ? v.slice(-100) : v); + console.log("Arguments from self.onerror:", args); + return true; +}; + +self.addEventListener("error", (evt) => { + // Returning true from self.onerror means that subsequent event listeners + // should see the event as canceled. + console.log("Is event canceled?:", evt.defaultPrevented); + + self.close(); +}); diff --git a/tests/testdata/workers/worker_globals.ts b/tests/testdata/workers/worker_globals.ts new file mode 100644 index 000000000..90e369e41 --- /dev/null +++ b/tests/testdata/workers/worker_globals.ts @@ -0,0 +1,13 @@ +onmessage = function () { + postMessage( + [ + self instanceof DedicatedWorkerGlobalScope, + self instanceof WorkerGlobalScope, + self instanceof EventTarget, + // TODO(nayeemrmn): Add `WorkerNavigator` to deno_lint globals. + // deno-lint-ignore no-undef + navigator instanceof WorkerNavigator, + ].join(", "), + ); + close(); +}; diff --git a/tests/testdata/workers/worker_large_message.js b/tests/testdata/workers/worker_large_message.js new file mode 100644 index 000000000..a1ddae4f9 --- /dev/null +++ b/tests/testdata/workers/worker_large_message.js @@ -0,0 +1,14 @@ +// Copyright 2020 the Deno authors. All rights reserved. MIT license. + +const dataSmall = ""; +const dataLarge = "x".repeat(10 * 1024); + +onmessage = function (_e) { + for (let i = 0; i <= 10; i++) { + if (i % 2 == 0) { + postMessage(dataLarge); + } else { + postMessage(dataSmall); + } + } +}; diff --git a/tests/testdata/workers/worker_location.ts b/tests/testdata/workers/worker_location.ts new file mode 100644 index 000000000..c3c1bb26f --- /dev/null +++ b/tests/testdata/workers/worker_location.ts @@ -0,0 +1,6 @@ +onmessage = function () { + postMessage( + `${location.href}, ${location instanceof WorkerLocation}`, + ); + close(); +}; diff --git a/tests/testdata/workers/worker_message_handler_error.ts b/tests/testdata/workers/worker_message_handler_error.ts new file mode 100644 index 000000000..355d86770 --- /dev/null +++ b/tests/testdata/workers/worker_message_handler_error.ts @@ -0,0 +1,8 @@ +const worker = new Worker( + import.meta.resolve("./message_handler_error.ts"), + { type: "module", name: "foo" }, +); +worker.onmessage = () => { + worker.postMessage("ready"); +}; +setTimeout(() => worker.terminate(), 30000); diff --git a/tests/testdata/workers/worker_message_handler_error.ts.out b/tests/testdata/workers/worker_message_handler_error.ts.out new file mode 100644 index 000000000..0f97e9703 --- /dev/null +++ b/tests/testdata/workers/worker_message_handler_error.ts.out @@ -0,0 +1,7 @@ +error: Uncaught (in worker "foo") Error: bar + throw new Error("bar"); + ^ + at onmessage ([WILDCARD]/message_handler_error.ts:[WILDCARD]) + at [WILDCARD] +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/worker_navigator.ts b/tests/testdata/workers/worker_navigator.ts new file mode 100644 index 000000000..bd364a8f9 --- /dev/null +++ b/tests/testdata/workers/worker_navigator.ts @@ -0,0 +1,11 @@ +onmessage = function () { + postMessage( + [ + typeof navigator.language, + typeof navigator.languages, + typeof navigator.userAgent, + typeof navigator.hardwareConcurrency, + ].join(", "), + ); + close(); +}; diff --git a/tests/testdata/workers/worker_nested_error.ts b/tests/testdata/workers/worker_nested_error.ts new file mode 100644 index 000000000..48bdea109 --- /dev/null +++ b/tests/testdata/workers/worker_nested_error.ts @@ -0,0 +1,5 @@ +const worker = new Worker( + import.meta.resolve("./worker_error.ts"), + { type: "module", name: "baz" }, +); +setTimeout(() => worker.terminate(), 30000); diff --git a/tests/testdata/workers/worker_nested_error.ts.out b/tests/testdata/workers/worker_nested_error.ts.out new file mode 100644 index 000000000..3622acfb3 --- /dev/null +++ b/tests/testdata/workers/worker_nested_error.ts.out @@ -0,0 +1,9 @@ +[WILDCARD]error: Uncaught (in worker "bar") (in promise) Error: foo[WILDCARD] + throw new Error("foo"); + ^ + at foo ([WILDCARD]/workers/error.ts:[WILDCARD]) + at [WILDCARD]/workers/error.ts:[WILDCARD] +error: Uncaught (in worker "baz") (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] +error: Uncaught (in promise) Error: Unhandled error in child worker. + at Worker.#pollControl [WILDCARD] diff --git a/tests/testdata/workers/worker_structured_cloning.ts b/tests/testdata/workers/worker_structured_cloning.ts new file mode 100644 index 000000000..eb1719a9a --- /dev/null +++ b/tests/testdata/workers/worker_structured_cloning.ts @@ -0,0 +1,15 @@ +// More info on structured cloning can be found here: +// https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm + +self.onmessage = () => { + const arr = ["a", true, 432]; + const set = new Set([1, 3, 5, 7, 9]); + const selfReference = { + a: arr, + b: arr, + c: set, + }; + // deno-lint-ignore no-explicit-any + (selfReference as any).self = selfReference; + self.postMessage(selfReference); +}; diff --git a/tests/testdata/workers/worker_types.ts b/tests/testdata/workers/worker_types.ts new file mode 100644 index 000000000..b67a3b782 --- /dev/null +++ b/tests/testdata/workers/worker_types.ts @@ -0,0 +1,4 @@ +// deno-lint-ignore require-await +self.onmessage = async (_msg: MessageEvent) => { + self.postMessage("hello"); +}; diff --git a/tests/testdata/workers/worker_unstable.ts b/tests/testdata/workers/worker_unstable.ts new file mode 100644 index 000000000..219f34e7b --- /dev/null +++ b/tests/testdata/workers/worker_unstable.ts @@ -0,0 +1,5 @@ +console.log(Deno.permissions.query); +console.log(Deno.consoleSize); +self.onmessage = () => { + self.close(); +}; diff --git a/tests/testdata/workers/worker_with_top_level_await.ts b/tests/testdata/workers/worker_with_top_level_await.ts new file mode 100644 index 000000000..1d20bb736 --- /dev/null +++ b/tests/testdata/workers/worker_with_top_level_await.ts @@ -0,0 +1,15 @@ +function delay(ms: number) { + return new Promise<void>((resolve) => { + setTimeout(() => { + resolve(); + }, ms); + }); +} + +onmessage = (_e: MessageEvent) => { + postMessage("triggered worker handler"); + close(); +}; +postMessage("ready"); +await delay(1000); +postMessage("never"); |
