{"version":3,"file":"MessagePortStream.cjs","sourceRoot":"","sources":["../../src/browser/MessagePortStream.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * This module provides a pair of classes for creating readable and writable streams\n * over a [MessagePort](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort).\n * The classes are naive passthrough mechanisms for data that assume exclusive access\n * to their ports. The lifetime of the underlying message port is expected to be\n * coextensive with \"the other side\".\n *\n * At the time of writing, there is no ergonomic way to detect the closure of a port. For\n * this reason, ports have to be ended manually via `.return()` or `.throw()`. Ending a\n * {@link MessagePortWriter} will end any {@link MessagePortReader} reading from the\n * remote port and close the entangled ports, but it will not affect any other streams\n * connected to the remote or local port, which must also be ended manually. Use\n * {@link MessagePortDuplexStream} to create a duplex stream over a single port.\n *\n * Regarding limitations around detecting `MessagePort` closure, see:\n * - https://github.com/fergald/explainer-messageport-close\n * - https://github.com/whatwg/html/issues/10201\n *\n * @module MessagePort streams\n */\n\nimport type { OnMessage } from './utils.ts';\nimport {\n  BaseDuplexStream,\n  makeDuplexStreamInputValidator,\n} from '../BaseDuplexStream.ts';\nimport type {\n  BaseReaderArgs,\n  BaseWriterArgs,\n  ValidateInput,\n} from '../BaseStream.ts';\nimport { BaseReader, BaseWriter } from '../BaseStream.ts';\nimport type { Dispatchable } from '../utils.ts';\n\n/**\n * A readable stream over a {@link MessagePort}.\n *\n * This class is a naive passthrough mechanism for data over a pair of linked message\n * ports. Ignores message events dispatched on its port that contain ports, but\n * otherwise expects {@link Dispatchable} values to be posted to its port.\n *\n * @see\n * - {@link MessagePortWriter} for the corresponding writable stream.\n * - The module-level documentation for more details.\n */\nexport class MessagePortReader<Read> extends BaseReader<Read> {\n  /**\n   * Constructs a new {@link MessagePortReader}.\n   *\n   * @param port - The message port to read from.\n   * @param options - Options bag for configuring the reader.\n   * @param options.validateInput - A function that validates input from the transport.\n   * @param options.onEnd - A function that is called when the stream ends.\n   */\n  constructor(\n    port: MessagePort,\n    { validateInput, onEnd }: BaseReaderArgs<Read> = {},\n  ) {\n    super({\n      validateInput,\n      onEnd: async (error) => {\n        // eslint-disable-next-line @typescript-eslint/no-use-before-define\n        port.removeEventListener('message', onMessage);\n        port.close();\n        await onEnd?.(error);\n      },\n    });\n\n    const receiveInput = super.getReceiveInput();\n\n    const onMessage: OnMessage = (messageEvent) => {\n      if (messageEvent.ports.length > 0) {\n        return;\n      }\n\n      receiveInput(messageEvent.data).catch(async (error) => this.throw(error));\n    };\n    port.addEventListener('message', onMessage);\n    port.start();\n\n    harden(this);\n  }\n}\nharden(MessagePortReader);\n\n/**\n * A writable stream over a {@link MessagePort}.\n *\n * @see\n * - {@link MessagePortReader} for the corresponding readable stream.\n * - The module-level documentation for more details.\n */\nexport class MessagePortWriter<Write> extends BaseWriter<Write> {\n  /**\n   * Constructs a new {@link MessagePortWriter}.\n   *\n   * @param port - The message port to write to.\n   * @param options - Options bag for configuring the writer.\n   * @param options.name - The name of the stream, for logging purposes.\n   * @param options.onEnd - A function that is called when the stream ends.\n   */\n  constructor(\n    port: MessagePort,\n    { name, onEnd }: Omit<BaseWriterArgs<Write>, 'onDispatch'> = {},\n  ) {\n    super({\n      name,\n      onDispatch: (value: Dispatchable<Write>) => port.postMessage(value),\n      onEnd: async (error) => {\n        port.close();\n        await onEnd?.(error);\n      },\n    });\n    port.start();\n    harden(this);\n  }\n}\nharden(MessagePortWriter);\n\n/**\n * A duplex stream over a {@link MessagePort}.\n */\nexport class MessagePortDuplexStream<\n  Read,\n  Write = Read,\n> extends BaseDuplexStream<\n  Read,\n  MessagePortReader<Read>,\n  Write,\n  MessagePortWriter<Write>\n> {\n  /**\n   * Constructs a new {@link MessagePortDuplexStream}.\n   *\n   * @param port - The message port to use for bidirectional communication.\n   * @param validateInput - A function that validates input from the transport.\n   */\n  constructor(port: MessagePort, validateInput?: ValidateInput<Read>) {\n    let writer: MessagePortWriter<Write>; // eslint-disable-line prefer-const\n    const reader = new MessagePortReader<Read>(port, {\n      name: 'MessagePortDuplexStream',\n      validateInput: makeDuplexStreamInputValidator(validateInput),\n      onEnd: async () => {\n        await writer.return();\n      },\n    });\n    writer = new MessagePortWriter<Write>(port, {\n      name: 'MessagePortDuplexStream',\n      onEnd: async () => {\n        await reader.return();\n      },\n    });\n    super(reader, writer);\n  }\n\n  /**\n   * Creates and synchronizes a new {@link MessagePortDuplexStream}.\n   *\n   * @param port - The message port to use for bidirectional communication.\n   * @param validateInput - A function that validates input from the transport.\n   * @returns A synchronized duplex stream.\n   */\n  static async make<Read, Write = Read>(\n    port: MessagePort,\n    validateInput?: ValidateInput<Read>,\n  ): Promise<MessagePortDuplexStream<Read, Write>> {\n    const stream = new MessagePortDuplexStream<Read, Write>(\n      port,\n      validateInput,\n    );\n    await stream.synchronize();\n    return stream;\n  }\n}\nharden(MessagePortDuplexStream);\n"]}