diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2019-01-08 14:44:06 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-08 14:44:06 -0500 |
commit | 6f79ad721a9f8c9d66d79f21ea479286f3ca5374 (patch) | |
tree | 3f8bad38a5bc109586d86846cb299717b425cdba /js | |
parent | 9ff6bca86388dab2cfa26e1712822f105985425e (diff) |
Minimal Worker support (#1476)
This adds the ability to spawn additional Isolates from Rust and send
and receive messages from them. This is preliminary work to support
running the typescript compiler in a separate isolate and thus support
native ES modules. Ref #975.
Diffstat (limited to 'js')
-rw-r--r-- | js/globals.ts | 6 | ||||
-rw-r--r-- | js/workers.ts | 75 |
2 files changed, 81 insertions, 0 deletions
diff --git a/js/globals.ts b/js/globals.ts index 663215341..849d2bb3f 100644 --- a/js/globals.ts +++ b/js/globals.ts @@ -19,6 +19,7 @@ import * as textEncoding from "./text_encoding"; import * as timers from "./timers"; import * as url from "./url"; import * as urlSearchParams from "./url_search_params"; +import * as workers from "./workers"; // These imports are not exposed and therefore are fine to just import the // symbols required. @@ -86,3 +87,8 @@ window.TextEncoder = textEncoding.TextEncoder; export type TextEncoder = textEncoding.TextEncoder; window.TextDecoder = textEncoding.TextDecoder; export type TextDecoder = textEncoding.TextDecoder; + +window.workerMain = workers.workerMain; +// TODO These shouldn't be available in main isolate. +window.postMessage = workers.postMessage; +window.close = workers.workerClose; diff --git a/js/workers.ts b/js/workers.ts new file mode 100644 index 000000000..f7aa857fc --- /dev/null +++ b/js/workers.ts @@ -0,0 +1,75 @@ +// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +import * as dispatch from "./dispatch"; +import { libdeno } from "./libdeno"; +import * as msg from "gen/msg_generated"; +import * as flatbuffers from "./flatbuffers"; +import { assert, log } from "./util"; +import { globalEval } from "./global_eval"; + +export async function postMessage(data: Uint8Array): Promise<void> { + const builder = flatbuffers.createBuilder(); + msg.WorkerPostMessage.startWorkerPostMessage(builder); + const inner = msg.WorkerPostMessage.endWorkerPostMessage(builder); + const baseRes = await dispatch.sendAsync( + builder, + msg.Any.WorkerPostMessage, + inner, + data + ); + assert(baseRes != null); +} + +export async function getMessage(): Promise<null | Uint8Array> { + log("getMessage"); + const builder = flatbuffers.createBuilder(); + msg.WorkerGetMessage.startWorkerGetMessage(builder); + const inner = msg.WorkerGetMessage.endWorkerGetMessage(builder); + const baseRes = await dispatch.sendAsync( + builder, + msg.Any.WorkerGetMessage, + inner + ); + assert(baseRes != null); + assert( + msg.Any.WorkerGetMessageRes === baseRes!.innerType(), + `base.innerType() unexpectedly is ${baseRes!.innerType()}` + ); + const res = new msg.WorkerGetMessageRes(); + assert(baseRes!.inner(res) != null); + + const dataArray = res.dataArray(); + if (dataArray == null) { + return null; + } else { + return new Uint8Array(dataArray!); + } +} + +let isClosing = false; + +export function workerClose(): void { + isClosing = true; +} + +export async function workerMain() { + log("workerMain"); + libdeno.recv(dispatch.handleAsyncMsgFromRust); + + // TODO avoid using globalEval to get Window. But circular imports if getting + // it from globals.ts + const window = globalEval("this"); + + while (!isClosing) { + const data = await getMessage(); + if (data == null) { + log("workerMain got null message. quitting."); + break; + } + if (window["onmessage"]) { + const event = { data }; + window.onmessage(event); + } else { + break; + } + } +} |