mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
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
This commit is contained in:
parent
81905a867e
commit
79b3bc05d6
26 changed files with 779 additions and 517 deletions
84
cli/js/workers_test.ts
Normal file
84
cli/js/workers_test.ts
Normal file
|
@ -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;
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue