11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  ObjectDefineProperties,
51cb0ef41Sopenharmony_ci  PromiseResolve,
61cb0ef41Sopenharmony_ci  ReflectConstruct,
71cb0ef41Sopenharmony_ci} = primordials;
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  kState,
111cb0ef41Sopenharmony_ci  setPromiseHandled,
121cb0ef41Sopenharmony_ci} = require('internal/webstreams/util');
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst {
151cb0ef41Sopenharmony_ci  DOMException,
161cb0ef41Sopenharmony_ci} = internalBinding('messaging');
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciconst {
191cb0ef41Sopenharmony_ci  ReadableStream,
201cb0ef41Sopenharmony_ci  readableStreamDefaultControllerEnqueue,
211cb0ef41Sopenharmony_ci  readableStreamDefaultControllerClose,
221cb0ef41Sopenharmony_ci  readableStreamDefaultControllerError,
231cb0ef41Sopenharmony_ci  readableStreamPipeTo,
241cb0ef41Sopenharmony_ci} = require('internal/webstreams/readablestream');
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciconst {
271cb0ef41Sopenharmony_ci  WritableStream,
281cb0ef41Sopenharmony_ci  writableStreamDefaultControllerErrorIfNeeded,
291cb0ef41Sopenharmony_ci} = require('internal/webstreams/writablestream');
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ciconst {
321cb0ef41Sopenharmony_ci  createDeferredPromise,
331cb0ef41Sopenharmony_ci} = require('internal/util');
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciconst assert = require('internal/assert');
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ciconst {
381cb0ef41Sopenharmony_ci  makeTransferable,
391cb0ef41Sopenharmony_ci  kClone,
401cb0ef41Sopenharmony_ci  kDeserialize,
411cb0ef41Sopenharmony_ci} = require('internal/worker/js_transferable');
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci// This class is a bit of a hack. The Node.js implementation of
441cb0ef41Sopenharmony_ci// DOMException is not transferable/cloneable. This provides us
451cb0ef41Sopenharmony_ci// with a variant that is. Unfortunately, it means playing around
461cb0ef41Sopenharmony_ci// a bit with the message, name, and code properties and the
471cb0ef41Sopenharmony_ci// prototype. We can revisit this if DOMException is ever made
481cb0ef41Sopenharmony_ci// properly cloneable.
491cb0ef41Sopenharmony_ciclass CloneableDOMException extends DOMException {
501cb0ef41Sopenharmony_ci  constructor(message, name) {
511cb0ef41Sopenharmony_ci    super(message, name);
521cb0ef41Sopenharmony_ci    this[kDeserialize]({
531cb0ef41Sopenharmony_ci      message: this.message,
541cb0ef41Sopenharmony_ci      name: this.name,
551cb0ef41Sopenharmony_ci      code: this.code,
561cb0ef41Sopenharmony_ci    });
571cb0ef41Sopenharmony_ci    // eslint-disable-next-line no-constructor-return
581cb0ef41Sopenharmony_ci    return makeTransferable(this);
591cb0ef41Sopenharmony_ci  }
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  [kClone]() {
621cb0ef41Sopenharmony_ci    return {
631cb0ef41Sopenharmony_ci      data: {
641cb0ef41Sopenharmony_ci        message: this.message,
651cb0ef41Sopenharmony_ci        name: this.name,
661cb0ef41Sopenharmony_ci        code: this.code,
671cb0ef41Sopenharmony_ci      },
681cb0ef41Sopenharmony_ci      deserializeInfo:
691cb0ef41Sopenharmony_ci        'internal/webstreams/transfer:InternalCloneableDOMException',
701cb0ef41Sopenharmony_ci    };
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  [kDeserialize]({ message, name, code }) {
741cb0ef41Sopenharmony_ci    ObjectDefineProperties(this, {
751cb0ef41Sopenharmony_ci      message: {
761cb0ef41Sopenharmony_ci        __proto__: null,
771cb0ef41Sopenharmony_ci        configurable: true,
781cb0ef41Sopenharmony_ci        enumerable: true,
791cb0ef41Sopenharmony_ci        get() { return message; },
801cb0ef41Sopenharmony_ci      },
811cb0ef41Sopenharmony_ci      name: {
821cb0ef41Sopenharmony_ci        __proto__: null,
831cb0ef41Sopenharmony_ci        configurable: true,
841cb0ef41Sopenharmony_ci        enumerable: true,
851cb0ef41Sopenharmony_ci        get() { return name; },
861cb0ef41Sopenharmony_ci      },
871cb0ef41Sopenharmony_ci      code: {
881cb0ef41Sopenharmony_ci        __proto__: null,
891cb0ef41Sopenharmony_ci        configurable: true,
901cb0ef41Sopenharmony_ci        enumerable: true,
911cb0ef41Sopenharmony_ci        get() { return code; },
921cb0ef41Sopenharmony_ci      },
931cb0ef41Sopenharmony_ci    });
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci}
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_cifunction InternalCloneableDOMException() {
981cb0ef41Sopenharmony_ci  return makeTransferable(
991cb0ef41Sopenharmony_ci    ReflectConstruct(
1001cb0ef41Sopenharmony_ci      CloneableDOMException,
1011cb0ef41Sopenharmony_ci      [],
1021cb0ef41Sopenharmony_ci      DOMException));
1031cb0ef41Sopenharmony_ci}
1041cb0ef41Sopenharmony_ciInternalCloneableDOMException[kDeserialize] = () => {};
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ciclass CrossRealmTransformReadableSource {
1071cb0ef41Sopenharmony_ci  constructor(port) {
1081cb0ef41Sopenharmony_ci    this[kState] = {
1091cb0ef41Sopenharmony_ci      port,
1101cb0ef41Sopenharmony_ci      controller: undefined,
1111cb0ef41Sopenharmony_ci    };
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci    port.onmessage = ({ data }) => {
1141cb0ef41Sopenharmony_ci      const {
1151cb0ef41Sopenharmony_ci        controller,
1161cb0ef41Sopenharmony_ci      } = this[kState];
1171cb0ef41Sopenharmony_ci      const {
1181cb0ef41Sopenharmony_ci        type,
1191cb0ef41Sopenharmony_ci        value,
1201cb0ef41Sopenharmony_ci      } = data;
1211cb0ef41Sopenharmony_ci      switch (type) {
1221cb0ef41Sopenharmony_ci        case 'chunk':
1231cb0ef41Sopenharmony_ci          readableStreamDefaultControllerEnqueue(
1241cb0ef41Sopenharmony_ci            controller,
1251cb0ef41Sopenharmony_ci            value);
1261cb0ef41Sopenharmony_ci          break;
1271cb0ef41Sopenharmony_ci        case 'close':
1281cb0ef41Sopenharmony_ci          readableStreamDefaultControllerClose(controller);
1291cb0ef41Sopenharmony_ci          port.close();
1301cb0ef41Sopenharmony_ci          break;
1311cb0ef41Sopenharmony_ci        case 'error':
1321cb0ef41Sopenharmony_ci          readableStreamDefaultControllerError(controller, value);
1331cb0ef41Sopenharmony_ci          port.close();
1341cb0ef41Sopenharmony_ci          break;
1351cb0ef41Sopenharmony_ci      }
1361cb0ef41Sopenharmony_ci    };
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci    port.onmessageerror = () => {
1391cb0ef41Sopenharmony_ci      const error = new CloneableDOMException(
1401cb0ef41Sopenharmony_ci        'Internal transferred ReadableStream error',
1411cb0ef41Sopenharmony_ci        'DataCloneError');
1421cb0ef41Sopenharmony_ci      port.postMessage({ type: 'error', value: error });
1431cb0ef41Sopenharmony_ci      readableStreamDefaultControllerError(
1441cb0ef41Sopenharmony_ci        this[kState].controller,
1451cb0ef41Sopenharmony_ci        error);
1461cb0ef41Sopenharmony_ci      port.close();
1471cb0ef41Sopenharmony_ci    };
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  start(controller) {
1511cb0ef41Sopenharmony_ci    this[kState].controller = controller;
1521cb0ef41Sopenharmony_ci  }
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  async pull() {
1551cb0ef41Sopenharmony_ci    this[kState].port.postMessage({ type: 'pull' });
1561cb0ef41Sopenharmony_ci  }
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  async cancel(reason) {
1591cb0ef41Sopenharmony_ci    try {
1601cb0ef41Sopenharmony_ci      this[kState].port.postMessage({ type: 'error', value: reason });
1611cb0ef41Sopenharmony_ci    } catch (error) {
1621cb0ef41Sopenharmony_ci      if (error instanceof DOMException) {
1631cb0ef41Sopenharmony_ci        // eslint-disable-next-line no-ex-assign
1641cb0ef41Sopenharmony_ci        error = new CloneableDOMException(error.message, error.name);
1651cb0ef41Sopenharmony_ci      }
1661cb0ef41Sopenharmony_ci      this[kState].port.postMessage({ type: 'error', value: error });
1671cb0ef41Sopenharmony_ci      throw error;
1681cb0ef41Sopenharmony_ci    } finally {
1691cb0ef41Sopenharmony_ci      this[kState].port.close();
1701cb0ef41Sopenharmony_ci    }
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ciclass CrossRealmTransformWritableSink {
1751cb0ef41Sopenharmony_ci  constructor(port) {
1761cb0ef41Sopenharmony_ci    this[kState] = {
1771cb0ef41Sopenharmony_ci      port,
1781cb0ef41Sopenharmony_ci      controller: undefined,
1791cb0ef41Sopenharmony_ci      backpressurePromise: createDeferredPromise(),
1801cb0ef41Sopenharmony_ci    };
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci    port.onmessage = ({ data }) => {
1831cb0ef41Sopenharmony_ci      assert(typeof data === 'object');
1841cb0ef41Sopenharmony_ci      const {
1851cb0ef41Sopenharmony_ci        type,
1861cb0ef41Sopenharmony_ci        value,
1871cb0ef41Sopenharmony_ci      } = { ...data };
1881cb0ef41Sopenharmony_ci      assert(typeof type === 'string');
1891cb0ef41Sopenharmony_ci      switch (type) {
1901cb0ef41Sopenharmony_ci        case 'pull':
1911cb0ef41Sopenharmony_ci          if (this[kState].backpressurePromise !== undefined)
1921cb0ef41Sopenharmony_ci            this[kState].backpressurePromise.resolve?.();
1931cb0ef41Sopenharmony_ci          this[kState].backpressurePromise = undefined;
1941cb0ef41Sopenharmony_ci          break;
1951cb0ef41Sopenharmony_ci        case 'error':
1961cb0ef41Sopenharmony_ci          writableStreamDefaultControllerErrorIfNeeded(
1971cb0ef41Sopenharmony_ci            this[kState].controller,
1981cb0ef41Sopenharmony_ci            value);
1991cb0ef41Sopenharmony_ci          if (this[kState].backpressurePromise !== undefined)
2001cb0ef41Sopenharmony_ci            this[kState].backpressurePromise.resolve?.();
2011cb0ef41Sopenharmony_ci          this[kState].backpressurePromise = undefined;
2021cb0ef41Sopenharmony_ci          break;
2031cb0ef41Sopenharmony_ci      }
2041cb0ef41Sopenharmony_ci    };
2051cb0ef41Sopenharmony_ci    port.onmessageerror = () => {
2061cb0ef41Sopenharmony_ci      const error = new CloneableDOMException(
2071cb0ef41Sopenharmony_ci        'Internal transferred ReadableStream error',
2081cb0ef41Sopenharmony_ci        'DataCloneError');
2091cb0ef41Sopenharmony_ci      port.postMessage({ type: 'error', value: error });
2101cb0ef41Sopenharmony_ci      writableStreamDefaultControllerErrorIfNeeded(
2111cb0ef41Sopenharmony_ci        this[kState].controller,
2121cb0ef41Sopenharmony_ci        error);
2131cb0ef41Sopenharmony_ci      port.close();
2141cb0ef41Sopenharmony_ci    };
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  }
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  start(controller) {
2191cb0ef41Sopenharmony_ci    this[kState].controller = controller;
2201cb0ef41Sopenharmony_ci  }
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  async write(chunk) {
2231cb0ef41Sopenharmony_ci    if (this[kState].backpressurePromise === undefined) {
2241cb0ef41Sopenharmony_ci      this[kState].backpressurePromise = {
2251cb0ef41Sopenharmony_ci        promise: PromiseResolve(),
2261cb0ef41Sopenharmony_ci        resolve: undefined,
2271cb0ef41Sopenharmony_ci        reject: undefined,
2281cb0ef41Sopenharmony_ci      };
2291cb0ef41Sopenharmony_ci    }
2301cb0ef41Sopenharmony_ci    await this[kState].backpressurePromise.promise;
2311cb0ef41Sopenharmony_ci    this[kState].backpressurePromise = createDeferredPromise();
2321cb0ef41Sopenharmony_ci    try {
2331cb0ef41Sopenharmony_ci      this[kState].port.postMessage({ type: 'chunk', value: chunk });
2341cb0ef41Sopenharmony_ci    } catch (error) {
2351cb0ef41Sopenharmony_ci      if (error instanceof DOMException) {
2361cb0ef41Sopenharmony_ci        // eslint-disable-next-line no-ex-assign
2371cb0ef41Sopenharmony_ci        error = new CloneableDOMException(error.message, error.name);
2381cb0ef41Sopenharmony_ci      }
2391cb0ef41Sopenharmony_ci      this[kState].port.postMessage({ type: 'error', value: error });
2401cb0ef41Sopenharmony_ci      this[kState].port.close();
2411cb0ef41Sopenharmony_ci      throw error;
2421cb0ef41Sopenharmony_ci    }
2431cb0ef41Sopenharmony_ci  }
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  close() {
2461cb0ef41Sopenharmony_ci    this[kState].port.postMessage({ type: 'close' });
2471cb0ef41Sopenharmony_ci    this[kState].port.close();
2481cb0ef41Sopenharmony_ci  }
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  abort(reason) {
2511cb0ef41Sopenharmony_ci    try {
2521cb0ef41Sopenharmony_ci      this[kState].port.postMessage({ type: 'error', value: reason });
2531cb0ef41Sopenharmony_ci    } catch (error) {
2541cb0ef41Sopenharmony_ci      if (error instanceof DOMException) {
2551cb0ef41Sopenharmony_ci        // eslint-disable-next-line no-ex-assign
2561cb0ef41Sopenharmony_ci        error = new CloneableDOMException(error.message, error.name);
2571cb0ef41Sopenharmony_ci      }
2581cb0ef41Sopenharmony_ci      this[kState].port.postMessage({ type: 'error', value: error });
2591cb0ef41Sopenharmony_ci      throw error;
2601cb0ef41Sopenharmony_ci    } finally {
2611cb0ef41Sopenharmony_ci      this[kState].port.close();
2621cb0ef41Sopenharmony_ci    }
2631cb0ef41Sopenharmony_ci  }
2641cb0ef41Sopenharmony_ci}
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_cifunction newCrossRealmReadableStream(writable, port) {
2671cb0ef41Sopenharmony_ci  const readable =
2681cb0ef41Sopenharmony_ci    new ReadableStream(
2691cb0ef41Sopenharmony_ci      new CrossRealmTransformReadableSource(port));
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  const promise =
2721cb0ef41Sopenharmony_ci    readableStreamPipeTo(readable, writable, false, false, false);
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  setPromiseHandled(promise);
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  return {
2771cb0ef41Sopenharmony_ci    readable,
2781cb0ef41Sopenharmony_ci    promise,
2791cb0ef41Sopenharmony_ci  };
2801cb0ef41Sopenharmony_ci}
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_cifunction newCrossRealmWritableSink(readable, port) {
2831cb0ef41Sopenharmony_ci  const writable =
2841cb0ef41Sopenharmony_ci    new WritableStream(
2851cb0ef41Sopenharmony_ci      new CrossRealmTransformWritableSink(port));
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  const promise = readableStreamPipeTo(readable, writable, false, false, false);
2881cb0ef41Sopenharmony_ci  setPromiseHandled(promise);
2891cb0ef41Sopenharmony_ci  return {
2901cb0ef41Sopenharmony_ci    writable,
2911cb0ef41Sopenharmony_ci    promise,
2921cb0ef41Sopenharmony_ci  };
2931cb0ef41Sopenharmony_ci}
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_cimodule.exports = {
2961cb0ef41Sopenharmony_ci  newCrossRealmReadableStream,
2971cb0ef41Sopenharmony_ci  newCrossRealmWritableSink,
2981cb0ef41Sopenharmony_ci  CrossRealmTransformWritableSink,
2991cb0ef41Sopenharmony_ci  CrossRealmTransformReadableSource,
3001cb0ef41Sopenharmony_ci  CloneableDOMException,
3011cb0ef41Sopenharmony_ci  InternalCloneableDOMException,
3021cb0ef41Sopenharmony_ci};
303