diff options
Diffstat (limited to 'runtime/js')
-rw-r--r-- | runtime/js/11_workers.js | 91 | ||||
-rw-r--r-- | runtime/js/99_main.js | 40 |
2 files changed, 95 insertions, 36 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() { diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js index 91a4dcefd..d0e86bce7 100644 --- a/runtime/js/99_main.js +++ b/runtime/js/99_main.js @@ -42,6 +42,8 @@ delete Object.prototype.__proto__; const errors = window.__bootstrap.errors.errors; const webidl = window.__bootstrap.webidl; const { defineEventHandler } = window.__bootstrap.webUtil; + const { deserializeJsMessageData, serializeJsMessageData } = + window.__bootstrap.messagePort; let windowIsClosing = false; @@ -77,9 +79,31 @@ delete Object.prototype.__proto__; const onmessage = () => {}; const onerror = () => {}; - function postMessage(data) { - const dataIntArray = core.serialize(data); - core.opSync("op_worker_post_message", null, dataIntArray); + function postMessage(message, transferOrOptions = {}) { + const prefix = + "Failed to execute 'postMessage' on 'DedicatedWorkerGlobalScope'"; + 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 { transfer } = options; + const data = serializeJsMessageData(message, transfer); + core.opSync("op_worker_post_message", data); } let isClosing = false; @@ -90,12 +114,16 @@ delete Object.prototype.__proto__; globalDispatchEvent = globalThis.dispatchEvent.bind(globalThis); } while (!isClosing) { - const bufferMsg = await core.opAsync("op_worker_get_message"); - const data = core.deserialize(bufferMsg); + const data = await core.opAsync("op_worker_recv_message"); + if (data === null) break; + const v = deserializeJsMessageData(data); + const message = v[0]; + const transfer = v[1]; const msgEvent = new MessageEvent("message", { cancelable: false, - data, + data: message, + ports: transfer, }); try { |