diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2020-02-11 10:04:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-11 10:04:59 +0100 |
commit | 79b3bc05d6de520f1df73face1744ae3d8be0bb8 (patch) | |
tree | f4c449efa67b88c767df52dd3ecec2246dded2e5 /cli/js/workers_test.ts | |
parent | 81905a867ea3f942619229e330840d132c57a5da (diff) |
workers: basic event loop (#3828)
* establish basic event loop for workers
* make "self.close()" inside worker
* remove "runWorkerMessageLoop() - instead manually call global function
in Rust when message arrives. This is done in preparation for structured clone
* refactor "WorkerChannel" and use distinct structs for internal
and external channels; "WorkerChannelsInternal" and "WorkerHandle"
* move "State.worker_channels_internal" to "Worker.internal_channels"
* add "WorkerEvent" enum for child->host communication;
currently "Message(Buf)" and "Error(ErrBox)" variants are supported
* add tests for nested workers
* add tests for worker throwing error on startup
Diffstat (limited to 'cli/js/workers_test.ts')
-rw-r--r-- | cli/js/workers_test.ts | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/cli/js/workers_test.ts b/cli/js/workers_test.ts new file mode 100644 index 000000000..9cb4f4a07 --- /dev/null +++ b/cli/js/workers_test.ts @@ -0,0 +1,84 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +import { test, assert, assertEquals } from "./test_util.ts"; + +export interface ResolvableMethods<T> { + resolve: (value?: T | PromiseLike<T>) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + reject: (reason?: any) => void; +} + +export type Resolvable<T> = Promise<T> & ResolvableMethods<T>; + +export function createResolvable<T>(): Resolvable<T> { + let methods: ResolvableMethods<T>; + const promise = new Promise<T>((resolve, reject): void => { + methods = { resolve, reject }; + }); + // TypeScript doesn't know that the Promise callback occurs synchronously + // therefore use of not null assertion (`!`) + return Object.assign(promise, methods!) as Resolvable<T>; +} + +test(async function workersBasic(): Promise<void> { + const promise = createResolvable(); + const jsWorker = new Worker("../tests/subdir/test_worker.js", { + type: "module", + name: "jsWorker" + }); + const tsWorker = new Worker("../tests/subdir/test_worker.ts", { + type: "module", + name: "tsWorker" + }); + + tsWorker.onmessage = (e): void => { + assertEquals(e.data, "Hello World"); + promise.resolve(); + }; + + jsWorker.onmessage = (e): void => { + assertEquals(e.data, "Hello World"); + tsWorker.postMessage("Hello World"); + }; + + jsWorker.onerror = (e: Event): void => { + e.preventDefault(); + jsWorker.postMessage("Hello World"); + }; + + jsWorker.postMessage("Hello World"); + await promise; +}); + +test(async function nestedWorker(): Promise<void> { + const promise = createResolvable(); + + const nestedWorker = new Worker("../tests/subdir/nested_worker.js", { + type: "module", + name: "nested" + }); + + nestedWorker.onmessage = (e): void => { + assert(e.data.type !== "error"); + promise.resolve(); + }; + + nestedWorker.postMessage("Hello World"); + await promise; +}); + +test(async function workerThrowsWhenExecuting(): Promise<void> { + const promise = createResolvable(); + + const throwingWorker = new Worker("../tests/subdir/throwing_worker.js", { + type: "module" + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + throwingWorker.onerror = (e: any): void => { + e.preventDefault(); + assertEquals(e.message, "Uncaught Error: Thrown error"); + promise.resolve(); + }; + + await promise; +}); |