summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2019-01-08 14:44:06 -0500
committerGitHub <noreply@github.com>2019-01-08 14:44:06 -0500
commit6f79ad721a9f8c9d66d79f21ea479286f3ca5374 (patch)
tree3f8bad38a5bc109586d86846cb299717b425cdba /js
parent9ff6bca86388dab2cfa26e1712822f105985425e (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.ts6
-rw-r--r--js/workers.ts75
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;
+ }
+ }
+}