summaryrefslogtreecommitdiff
path: root/runtime/js/11_workers.js
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/js/11_workers.js')
-rw-r--r--runtime/js/11_workers.js91
1 files changed, 61 insertions, 30 deletions
diff --git a/runtime/js/11_workers.js b/runtime/js/11_workers.js
index c917a2880..7267bec38 100644
--- a/runtime/js/11_workers.js
+++ b/runtime/js/11_workers.js
@@ -3,10 +3,13 @@
((window) => {
const core = window.Deno.core;
+ const webidl = window.__bootstrap.webidl;
const { Window } = window.__bootstrap.globalInterfaces;
const { getLocationHref } = window.__bootstrap.location;
const { log, pathFromURL } = window.__bootstrap.util;
const { defineEventHandler } = window.__bootstrap.webUtil;
+ const { deserializeJsMessageData, serializeJsMessageData } =
+ window.__bootstrap.messagePort;
function createWorker(
specifier,
@@ -34,8 +37,12 @@
core.opSync("op_host_post_message", id, data);
}
- function hostGetMessage(id) {
- return core.opAsync("op_host_get_message", id);
+ function hostRecvCtrl(id) {
+ return core.opAsync("op_host_recv_ctrl", id);
+ }
+
+ function hostRecvMessage(id) {
+ return core.opAsync("op_host_recv_message", id);
}
/**
@@ -187,18 +194,9 @@
options?.name,
);
this.#id = id;
- this.#poll();
- }
-
- #handleMessage(data) {
- const msgEvent = new MessageEvent("message", {
- cancelable: false,
- data,
- });
-
- this.dispatchEvent(msgEvent);
+ this.#pollControl();
+ this.#pollMessages();
}
-
#handleError(e) {
const event = new ErrorEvent("error", {
cancelable: true,
@@ -219,9 +217,9 @@
return handled;
}
- #poll = async () => {
+ #pollControl = async () => {
while (!this.#terminated) {
- const [type, data] = await hostGetMessage(this.#id);
+ const [type, data] = await hostRecvCtrl(this.#id);
// If terminate was called then we ignore all messages
if (this.#terminated) {
@@ -229,11 +227,6 @@
}
switch (type) {
- case 0: { // Message
- const msg = core.deserialize(data);
- this.#handleMessage(msg);
- break;
- }
case 1: { // TerminalError
this.#terminated = true;
} /* falls through */
@@ -262,19 +255,57 @@
}
};
- postMessage(message, transferOrOptions) {
- if (transferOrOptions) {
- throw new Error(
- "Not yet implemented: `transfer` and `options` are not supported.",
- );
+ #pollMessages = async () => {
+ while (!this.terminated) {
+ const data = await hostRecvMessage(this.#id);
+ if (data === null) break;
+ let message, transfer;
+ try {
+ const v = deserializeJsMessageData(data);
+ message = v[0];
+ transfer = v[1];
+ } catch (err) {
+ const event = new MessageEvent("messageerror", {
+ cancelable: false,
+ data: err,
+ });
+ this.dispatchEvent(event);
+ return;
+ }
+ const event = new MessageEvent("message", {
+ cancelable: false,
+ data: message,
+ ports: transfer,
+ });
+ this.dispatchEvent(event);
}
+ };
- if (this.#terminated) {
- return;
+ postMessage(message, transferOrOptions = {}) {
+ const prefix = "Failed to execute 'postMessage' on 'MessagePort'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ message = webidl.converters.any(message);
+ let options;
+ if (
+ webidl.type(transferOrOptions) === "Object" &&
+ transferOrOptions !== undefined &&
+ transferOrOptions[Symbol.iterator] !== undefined
+ ) {
+ const transfer = webidl.converters["sequence<object>"](
+ transferOrOptions,
+ { prefix, context: "Argument 2" },
+ );
+ options = { transfer };
+ } else {
+ options = webidl.converters.PostMessageOptions(transferOrOptions, {
+ prefix,
+ context: "Argument 2",
+ });
}
-
- const bufferMsg = core.serialize(message);
- hostPostMessage(this.#id, bufferMsg);
+ const { transfer } = options;
+ const data = serializeJsMessageData(message, transfer);
+ if (this.#terminated) return;
+ hostPostMessage(this.#id, data);
}
terminate() {