diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2023-02-07 20:22:46 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-07 20:22:46 +0100 |
commit | b4aa1530970f7b9cc4e6f2f27e077852c4e178d3 (patch) | |
tree | 3d008912affe8550692183bd2697a386db5e3c79 /ext/web/13_message_port.js | |
parent | 65500f36e870b4ada3996b06aa287e30177d21a3 (diff) |
refactor: Use ES modules for internal runtime code (#17648)
This PR refactors all internal js files (except core) to be written as
ES modules.
`__bootstrap`has been mostly replaced with static imports in form in
`internal:[path to file from repo root]`.
To specify if files are ESM, an `esm` method has been added to
`Extension`, similar to the `js` method.
A new ModuleLoader called `InternalModuleLoader` has been added to
enable the loading of internal specifiers, which is used in all
situations except when a snapshot is only loaded, and not a new one is
created from it.
---------
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Diffstat (limited to 'ext/web/13_message_port.js')
-rw-r--r-- | ext/web/13_message_port.js | 609 |
1 files changed, 305 insertions, 304 deletions
diff --git a/ext/web/13_message_port.js b/ext/web/13_message_port.js index 7ab2beb82..2a784bf3f 100644 --- a/ext/web/13_message_port.js +++ b/ext/web/13_message_port.js @@ -6,338 +6,339 @@ /// <reference path="./internal.d.ts" /> /// <reference path="./lib.deno_web.d.ts" /> -"use strict"; - -((window) => { - const core = window.Deno.core; - const { InterruptedPrototype, ops } = core; - const webidl = window.__bootstrap.webidl; - const { EventTarget, setEventTargetData } = window.__bootstrap.eventTarget; - const { MessageEvent, defineEventHandler } = window.__bootstrap.event; - const { DOMException } = window.__bootstrap.domException; - const { - ArrayBufferPrototype, - ArrayPrototypeFilter, - ArrayPrototypeIncludes, - ArrayPrototypePush, - ObjectPrototypeIsPrototypeOf, - ObjectSetPrototypeOf, - Symbol, - SymbolFor, - SymbolIterator, - TypeError, - } = window.__bootstrap.primordials; - - class MessageChannel { - /** @type {MessagePort} */ - #port1; - /** @type {MessagePort} */ - #port2; - - constructor() { - this[webidl.brand] = webidl.brand; - const { 0: port1Id, 1: port2Id } = opCreateEntangledMessagePort(); - const port1 = createMessagePort(port1Id); - const port2 = createMessagePort(port2Id); - this.#port1 = port1; - this.#port2 = port2; - } - - get port1() { - webidl.assertBranded(this, MessageChannelPrototype); - return this.#port1; - } - - get port2() { - webidl.assertBranded(this, MessageChannelPrototype); - return this.#port2; - } +const core = globalThis.Deno.core; +const { InterruptedPrototype, ops } = core; +import * as webidl from "internal:ext/webidl/00_webidl.js"; +import { + defineEventHandler, + EventTarget, + MessageEvent, + setEventTargetData, +} from "internal:ext/web/02_event.js"; +import DOMException from "internal:ext/web/01_dom_exception.js"; +const primordials = globalThis.__bootstrap.primordials; +const { + ArrayBufferPrototype, + ArrayPrototypeFilter, + ArrayPrototypeIncludes, + ArrayPrototypePush, + ObjectPrototypeIsPrototypeOf, + ObjectSetPrototypeOf, + Symbol, + SymbolFor, + SymbolIterator, + TypeError, +} = primordials; + +class MessageChannel { + /** @type {MessagePort} */ + #port1; + /** @type {MessagePort} */ + #port2; + + constructor() { + this[webidl.brand] = webidl.brand; + const { 0: port1Id, 1: port2Id } = opCreateEntangledMessagePort(); + const port1 = createMessagePort(port1Id); + const port2 = createMessagePort(port2Id); + this.#port1 = port1; + this.#port2 = port2; + } - [SymbolFor("Deno.inspect")](inspect) { - return `MessageChannel ${ - inspect({ port1: this.port1, port2: this.port2 }) - }`; - } + get port1() { + webidl.assertBranded(this, MessageChannelPrototype); + return this.#port1; } - webidl.configurePrototype(MessageChannel); - const MessageChannelPrototype = MessageChannel.prototype; + get port2() { + webidl.assertBranded(this, MessageChannelPrototype); + return this.#port2; + } - const _id = Symbol("id"); - const _enabled = Symbol("enabled"); + [SymbolFor("Deno.inspect")](inspect) { + return `MessageChannel ${ + inspect({ port1: this.port1, port2: this.port2 }) + }`; + } +} + +webidl.configurePrototype(MessageChannel); +const MessageChannelPrototype = MessageChannel.prototype; + +const _id = Symbol("id"); +const _enabled = Symbol("enabled"); + +/** + * @param {number} id + * @returns {MessagePort} + */ +function createMessagePort(id) { + const port = core.createHostObject(); + ObjectSetPrototypeOf(port, MessagePortPrototype); + port[webidl.brand] = webidl.brand; + setEventTargetData(port); + port[_id] = id; + return port; +} + +class MessagePort extends EventTarget { + /** @type {number | null} */ + [_id] = null; + /** @type {boolean} */ + [_enabled] = false; + + constructor() { + super(); + webidl.illegalConstructor(); + } /** - * @param {number} id - * @returns {MessagePort} + * @param {any} message + * @param {object[] | StructuredSerializeOptions} transferOrOptions */ - function createMessagePort(id) { - const port = core.createHostObject(); - ObjectSetPrototypeOf(port, MessagePortPrototype); - port[webidl.brand] = webidl.brand; - setEventTargetData(port); - port[_id] = id; - return port; - } - - class MessagePort extends EventTarget { - /** @type {number | null} */ - [_id] = null; - /** @type {boolean} */ - [_enabled] = false; - - constructor() { - super(); - webidl.illegalConstructor(); + postMessage(message, transferOrOptions = {}) { + webidl.assertBranded(this, MessagePortPrototype); + 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[SymbolIterator] !== undefined + ) { + const transfer = webidl.converters["sequence<object>"]( + transferOrOptions, + { prefix, context: "Argument 2" }, + ); + options = { transfer }; + } else { + options = webidl.converters.StructuredSerializeOptions( + transferOrOptions, + { + prefix, + context: "Argument 2", + }, + ); } - - /** - * @param {any} message - * @param {object[] | StructuredSerializeOptions} transferOrOptions - */ - postMessage(message, transferOrOptions = {}) { - webidl.assertBranded(this, MessagePortPrototype); - 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[SymbolIterator] !== undefined - ) { - const transfer = webidl.converters["sequence<object>"]( - transferOrOptions, - { prefix, context: "Argument 2" }, - ); - options = { transfer }; - } else { - options = webidl.converters.StructuredSerializeOptions( - transferOrOptions, - { - prefix, - context: "Argument 2", - }, - ); - } - const { transfer } = options; - if (ArrayPrototypeIncludes(transfer, this)) { - throw new DOMException("Can not tranfer self", "DataCloneError"); - } - const data = serializeJsMessageData(message, transfer); - if (this[_id] === null) return; - ops.op_message_port_post_message(this[_id], data); + const { transfer } = options; + if (ArrayPrototypeIncludes(transfer, this)) { + throw new DOMException("Can not tranfer self", "DataCloneError"); } + const data = serializeJsMessageData(message, transfer); + if (this[_id] === null) return; + ops.op_message_port_post_message(this[_id], data); + } - start() { - webidl.assertBranded(this, MessagePortPrototype); - if (this[_enabled]) return; - (async () => { - this[_enabled] = true; - while (true) { - if (this[_id] === null) break; - let data; - try { - data = await core.opAsync( - "op_message_port_recv_message", - this[_id], - ); - } catch (err) { - if (ObjectPrototypeIsPrototypeOf(InterruptedPrototype, err)) break; - throw err; - } - if (data === null) break; - let message, transferables; - try { - const v = deserializeJsMessageData(data); - message = v[0]; - transferables = v[1]; - } catch (err) { - const event = new MessageEvent("messageerror", { data: err }); - this.dispatchEvent(event); - return; - } - const event = new MessageEvent("message", { - data: message, - ports: ArrayPrototypeFilter( - transferables, - (t) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, t), - ), - }); + start() { + webidl.assertBranded(this, MessagePortPrototype); + if (this[_enabled]) return; + (async () => { + this[_enabled] = true; + while (true) { + if (this[_id] === null) break; + let data; + try { + data = await core.opAsync( + "op_message_port_recv_message", + this[_id], + ); + } catch (err) { + if (ObjectPrototypeIsPrototypeOf(InterruptedPrototype, err)) break; + throw err; + } + if (data === null) break; + let message, transferables; + try { + const v = deserializeJsMessageData(data); + message = v[0]; + transferables = v[1]; + } catch (err) { + const event = new MessageEvent("messageerror", { data: err }); this.dispatchEvent(event); + return; } - this[_enabled] = false; - })(); - } - - close() { - webidl.assertBranded(this, MessagePortPrototype); - if (this[_id] !== null) { - core.close(this[_id]); - this[_id] = null; + const event = new MessageEvent("message", { + data: message, + ports: ArrayPrototypeFilter( + transferables, + (t) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, t), + ), + }); + this.dispatchEvent(event); } - } + this[_enabled] = false; + })(); } - defineEventHandler(MessagePort.prototype, "message", function (self) { - self.start(); - }); - defineEventHandler(MessagePort.prototype, "messageerror"); - - webidl.configurePrototype(MessagePort); - const MessagePortPrototype = MessagePort.prototype; - - /** - * @returns {[number, number]} - */ - function opCreateEntangledMessagePort() { - return ops.op_message_port_create_entangled(); + close() { + webidl.assertBranded(this, MessagePortPrototype); + if (this[_id] !== null) { + core.close(this[_id]); + this[_id] = null; + } } - - /** - * @param {globalThis.__bootstrap.messagePort.MessageData} messageData - * @returns {[any, object[]]} - */ - function deserializeJsMessageData(messageData) { - /** @type {object[]} */ - const transferables = []; - const hostObjects = []; - const arrayBufferIdsInTransferables = []; - const transferredArrayBuffers = []; - - for (let i = 0; i < messageData.transferables.length; ++i) { - const transferable = messageData.transferables[i]; - switch (transferable.kind) { - case "messagePort": { - const port = createMessagePort(transferable.data); - ArrayPrototypePush(transferables, port); - ArrayPrototypePush(hostObjects, port); - break; - } - case "arrayBuffer": { - ArrayPrototypePush(transferredArrayBuffers, transferable.data); - const index = ArrayPrototypePush(transferables, null); - ArrayPrototypePush(arrayBufferIdsInTransferables, index); - break; - } - default: - throw new TypeError("Unreachable"); +} + +defineEventHandler(MessagePort.prototype, "message", function (self) { + self.start(); +}); +defineEventHandler(MessagePort.prototype, "messageerror"); + +webidl.configurePrototype(MessagePort); +const MessagePortPrototype = MessagePort.prototype; + +/** + * @returns {[number, number]} + */ +function opCreateEntangledMessagePort() { + return ops.op_message_port_create_entangled(); +} + +/** + * @param {messagePort.MessageData} messageData + * @returns {[any, object[]]} + */ +function deserializeJsMessageData(messageData) { + /** @type {object[]} */ + const transferables = []; + const hostObjects = []; + const arrayBufferIdsInTransferables = []; + const transferredArrayBuffers = []; + + for (let i = 0; i < messageData.transferables.length; ++i) { + const transferable = messageData.transferables[i]; + switch (transferable.kind) { + case "messagePort": { + const port = createMessagePort(transferable.data); + ArrayPrototypePush(transferables, port); + ArrayPrototypePush(hostObjects, port); + break; + } + case "arrayBuffer": { + ArrayPrototypePush(transferredArrayBuffers, transferable.data); + const index = ArrayPrototypePush(transferables, null); + ArrayPrototypePush(arrayBufferIdsInTransferables, index); + break; } + default: + throw new TypeError("Unreachable"); } + } - const data = core.deserialize(messageData.data, { - hostObjects, - transferredArrayBuffers, - }); - - for (let i = 0; i < arrayBufferIdsInTransferables.length; ++i) { - const id = arrayBufferIdsInTransferables[i]; - transferables[id] = transferredArrayBuffers[i]; - } + const data = core.deserialize(messageData.data, { + hostObjects, + transferredArrayBuffers, + }); - return [data, transferables]; + for (let i = 0; i < arrayBufferIdsInTransferables.length; ++i) { + const id = arrayBufferIdsInTransferables[i]; + transferables[id] = transferredArrayBuffers[i]; } - /** - * @param {any} data - * @param {object[]} transferables - * @returns {globalThis.__bootstrap.messagePort.MessageData} - */ - function serializeJsMessageData(data, transferables) { - const transferredArrayBuffers = []; - for (let i = 0, j = 0; i < transferables.length; i++) { - const ab = transferables[i]; - if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) { - if (ab.byteLength === 0 && core.ops.op_arraybuffer_was_detached(ab)) { - throw new DOMException( - `ArrayBuffer at index ${j} is already detached`, - "DataCloneError", - ); - } - j++; - transferredArrayBuffers.push(ab); + return [data, transferables]; +} + +/** + * @param {any} data + * @param {object[]} transferables + * @returns {messagePort.MessageData} + */ +function serializeJsMessageData(data, transferables) { + const transferredArrayBuffers = []; + for (let i = 0, j = 0; i < transferables.length; i++) { + const ab = transferables[i]; + if (ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, ab)) { + if (ab.byteLength === 0 && ops.op_arraybuffer_was_detached(ab)) { + throw new DOMException( + `ArrayBuffer at index ${j} is already detached`, + "DataCloneError", + ); } + j++; + transferredArrayBuffers.push(ab); } + } - const serializedData = core.serialize(data, { - hostObjects: ArrayPrototypeFilter( - transferables, - (a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a), - ), - transferredArrayBuffers, - }, (err) => { - throw new DOMException(err, "DataCloneError"); - }); - - /** @type {globalThis.__bootstrap.messagePort.Transferable[]} */ - const serializedTransferables = []; + const serializedData = core.serialize(data, { + hostObjects: ArrayPrototypeFilter( + transferables, + (a) => ObjectPrototypeIsPrototypeOf(MessagePortPrototype, a), + ), + transferredArrayBuffers, + }, (err) => { + throw new DOMException(err, "DataCloneError"); + }); - let arrayBufferI = 0; - for (let i = 0; i < transferables.length; ++i) { - const transferable = transferables[i]; - if (ObjectPrototypeIsPrototypeOf(MessagePortPrototype, transferable)) { - webidl.assertBranded(transferable, MessagePortPrototype); - const id = transferable[_id]; - if (id === null) { - throw new DOMException( - "Can not transfer disentangled message port", - "DataCloneError", - ); - } - transferable[_id] = null; - ArrayPrototypePush(serializedTransferables, { - kind: "messagePort", - data: id, - }); - } else if ( - ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, transferable) - ) { - ArrayPrototypePush(serializedTransferables, { - kind: "arrayBuffer", - data: transferredArrayBuffers[arrayBufferI], - }); - arrayBufferI++; - } else { - throw new DOMException("Value not transferable", "DataCloneError"); + /** @type {messagePort.Transferable[]} */ + const serializedTransferables = []; + + let arrayBufferI = 0; + for (let i = 0; i < transferables.length; ++i) { + const transferable = transferables[i]; + if (ObjectPrototypeIsPrototypeOf(MessagePortPrototype, transferable)) { + webidl.assertBranded(transferable, MessagePortPrototype); + const id = transferable[_id]; + if (id === null) { + throw new DOMException( + "Can not transfer disentangled message port", + "DataCloneError", + ); } + transferable[_id] = null; + ArrayPrototypePush(serializedTransferables, { + kind: "messagePort", + data: id, + }); + } else if ( + ObjectPrototypeIsPrototypeOf(ArrayBufferPrototype, transferable) + ) { + ArrayPrototypePush(serializedTransferables, { + kind: "arrayBuffer", + data: transferredArrayBuffers[arrayBufferI], + }); + arrayBufferI++; + } else { + throw new DOMException("Value not transferable", "DataCloneError"); } - - return { - data: serializedData, - transferables: serializedTransferables, - }; } - webidl.converters.StructuredSerializeOptions = webidl - .createDictionaryConverter( - "StructuredSerializeOptions", - [ - { - key: "transfer", - converter: webidl.converters["sequence<object>"], - get defaultValue() { - return []; - }, - }, - ], - ); - - function structuredClone(value, options) { - const prefix = "Failed to execute 'structuredClone'"; - webidl.requiredArguments(arguments.length, 1, { prefix }); - options = webidl.converters.StructuredSerializeOptions(options, { - prefix, - context: "Argument 2", - }); - const messageData = serializeJsMessageData(value, options.transfer); - return deserializeJsMessageData(messageData)[0]; - } - - window.__bootstrap.messagePort = { - MessageChannel, - MessagePort, - MessagePortPrototype, - deserializeJsMessageData, - serializeJsMessageData, - structuredClone, + return { + data: serializedData, + transferables: serializedTransferables, }; -})(globalThis); +} + +webidl.converters.StructuredSerializeOptions = webidl + .createDictionaryConverter( + "StructuredSerializeOptions", + [ + { + key: "transfer", + converter: webidl.converters["sequence<object>"], + get defaultValue() { + return []; + }, + }, + ], + ); + +function structuredClone(value, options) { + const prefix = "Failed to execute 'structuredClone'"; + webidl.requiredArguments(arguments.length, 1, { prefix }); + options = webidl.converters.StructuredSerializeOptions(options, { + prefix, + context: "Argument 2", + }); + const messageData = serializeJsMessageData(value, options.transfer); + return deserializeJsMessageData(messageData)[0]; +} + +export { + deserializeJsMessageData, + MessageChannel, + MessagePort, + MessagePortPrototype, + serializeJsMessageData, + structuredClone, +}; |