summaryrefslogtreecommitdiff
path: root/ext/web/13_message_port.js
diff options
context:
space:
mode:
authorLeo Kettmeir <crowlkats@toaxl.com>2023-02-07 20:22:46 +0100
committerGitHub <noreply@github.com>2023-02-07 20:22:46 +0100
commitb4aa1530970f7b9cc4e6f2f27e077852c4e178d3 (patch)
tree3d008912affe8550692183bd2697a386db5e3c79 /ext/web/13_message_port.js
parent65500f36e870b4ada3996b06aa287e30177d21a3 (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.js609
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,
+};