{"version":3,"sources":["../../../../src/interceptors/WebSocket/utils/bindEvent.ts","../../../../src/interceptors/WebSocket/utils/events.ts","../../../../src/interceptors/WebSocket/WebSocketClientConnection.ts","../../../../src/interceptors/WebSocket/WebSocketServerConnection.ts","../../../../src/interceptors/WebSocket/WebSocketOverride.ts","../../../../src/interceptors/WebSocket/WebSocketClassTransport.ts","../../../../src/interceptors/WebSocket/index.ts"],"sourcesContent":["type EventWithTarget<E extends Event, T> = E & { target: T }\n\nexport function bindEvent<E extends Event, T>(\n  target: T,\n  event: E\n): EventWithTarget<E, T> {\n  Object.defineProperties(event, {\n    target: {\n      value: target,\n      enumerable: true,\n      writable: true,\n    },\n    currentTarget: {\n      value: target,\n      enumerable: true,\n      writable: true,\n    },\n  })\n\n  return event as EventWithTarget<E, T>\n}\n","const kCancelable = Symbol('kCancelable')\nconst kDefaultPrevented = Symbol('kDefaultPrevented')\n\n/**\n * A `MessageEvent` superset that supports event cancellation\n * in Node.js. It's rather non-intrusive so it can be safely\n * used in the browser as well.\n *\n * @see https://github.com/nodejs/node/issues/51767\n */\nexport class CancelableMessageEvent<T = any> extends MessageEvent<T> {\n  [kCancelable]: boolean;\n  [kDefaultPrevented]: boolean\n\n  constructor(type: string, init: MessageEventInit<T>) {\n    super(type, init)\n    this[kCancelable] = !!init.cancelable\n    this[kDefaultPrevented] = false\n  }\n\n  get cancelable() {\n    return this[kCancelable]\n  }\n\n  set cancelable(nextCancelable) {\n    this[kCancelable] = nextCancelable\n  }\n\n  get defaultPrevented() {\n    return this[kDefaultPrevented]\n  }\n\n  set defaultPrevented(nextDefaultPrevented) {\n    this[kDefaultPrevented] = nextDefaultPrevented\n  }\n\n  public preventDefault(): void {\n    if (this.cancelable && !this[kDefaultPrevented]) {\n      this[kDefaultPrevented] = true\n    }\n  }\n}\n\ninterface CloseEventInit extends EventInit {\n  code?: number\n  reason?: string\n  wasClean?: boolean\n}\n\nexport class CloseEvent extends Event {\n  public code: number\n  public reason: string\n  public wasClean: boolean\n\n  constructor(type: string, init: CloseEventInit = {}) {\n    super(type, init)\n    this.code = init.code === undefined ? 0 : init.code\n    this.reason = init.reason === undefined ? '' : init.reason\n    this.wasClean = init.wasClean === undefined ? false : init.wasClean\n  }\n}\n\nexport class CancelableCloseEvent extends CloseEvent {\n  [kCancelable]: boolean;\n  [kDefaultPrevented]: boolean\n\n  constructor(type: string, init: CloseEventInit = {}) {\n    super(type, init)\n    this[kCancelable] = !!init.cancelable\n    this[kDefaultPrevented] = false\n  }\n\n  get cancelable() {\n    return this[kCancelable]\n  }\n\n  set cancelable(nextCancelable) {\n    this[kCancelable] = nextCancelable\n  }\n\n  get defaultPrevented() {\n    return this[kDefaultPrevented]\n  }\n\n  set defaultPrevented(nextDefaultPrevented) {\n    this[kDefaultPrevented] = nextDefaultPrevented\n  }\n\n  public preventDefault(): void {\n    if (this.cancelable && !this[kDefaultPrevented]) {\n      this[kDefaultPrevented] = true\n    }\n  }\n}\n","import type { WebSocketData, WebSocketTransport } from './WebSocketTransport'\nimport type { WebSocketEventListener } from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\nimport { createRequestId } from '../../createRequestId'\n\nconst kEmitter = Symbol('kEmitter')\nconst kBoundListener = Symbol('kBoundListener')\n\ninterface WebSocketClientEventMap {\n  message: MessageEvent<WebSocketData>\n  close: CloseEvent\n}\n\nexport interface WebSocketClientConnectionProtocol {\n  id: string\n  url: URL\n  send(data: WebSocketData): void\n  close(code?: number, reason?: string): void\n}\n\n/**\n * The WebSocket client instance represents an incoming\n * client connection. The user can control the connection,\n * send and receive events.\n */\nexport class WebSocketClientConnection\n  implements WebSocketClientConnectionProtocol\n{\n  public readonly id: string\n  public readonly url: URL\n\n  private [kEmitter]: EventTarget\n\n  constructor(\n    public readonly socket: WebSocket,\n    private readonly transport: WebSocketTransport\n  ) {\n    this.id = createRequestId()\n    this.url = new URL(socket.url)\n    this[kEmitter] = new EventTarget()\n\n    // Emit outgoing client data (\"ws.send()\") as \"message\"\n    // events on the \"client\" connection.\n    this.transport.addEventListener('outgoing', (event) => {\n      const message = bindEvent(\n        this.socket,\n        new CancelableMessageEvent('message', {\n          data: event.data,\n          origin: event.origin,\n          cancelable: true,\n        })\n      )\n\n      this[kEmitter].dispatchEvent(message)\n\n      // This is a bit silly but forward the cancellation state\n      // of the \"client\" message event to the \"outgoing\" transport event.\n      // This way, other agens (like \"server\" connection) can know\n      // whether the client listener has pervented the default.\n      if (message.defaultPrevented) {\n        event.preventDefault()\n      }\n    })\n\n    /**\n     * Emit the \"close\" event on the \"client\" connection\n     * whenever the underlying transport is closed.\n     * @note \"client.close()\" does NOT dispatch the \"close\"\n     * event on the WebSocket because it uses non-configurable\n     * close status code. Thus, we listen to the transport\n     * instead of the WebSocket's \"close\" event.\n     */\n    this.transport.addEventListener('close', (event) => {\n      this[kEmitter].dispatchEvent(\n        bindEvent(this.socket, new CloseEvent('close', event))\n      )\n    })\n  }\n\n  /**\n   * Listen for the outgoing events from the connected WebSocket client.\n   */\n  public addEventListener<EventType extends keyof WebSocketClientEventMap>(\n    type: EventType,\n    listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,\n    options?: AddEventListenerOptions | boolean\n  ): void {\n    if (!Reflect.has(listener, kBoundListener)) {\n      const boundListener = listener.bind(this.socket)\n\n      // Store the bound listener on the original listener\n      // so the exact bound function can be accessed in \"removeEventListener()\".\n      Object.defineProperty(listener, kBoundListener, {\n        value: boundListener,\n        enumerable: false,\n        configurable: false,\n      })\n    }\n\n    this[kEmitter].addEventListener(\n      type,\n      Reflect.get(listener, kBoundListener) as EventListener,\n      options\n    )\n  }\n\n  /**\n   * Removes the listener for the given event.\n   */\n  public removeEventListener<EventType extends keyof WebSocketClientEventMap>(\n    event: EventType,\n    listener: WebSocketEventListener<WebSocketClientEventMap[EventType]>,\n    options?: EventListenerOptions | boolean\n  ): void {\n    this[kEmitter].removeEventListener(\n      event,\n      Reflect.get(listener, kBoundListener) as EventListener,\n      options\n    )\n  }\n\n  /**\n   * Send data to the connected client.\n   */\n  public send(data: WebSocketData): void {\n    this.transport.send(data)\n  }\n\n  /**\n   * Close the WebSocket connection.\n   * @param {number} code A status code (see https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1).\n   * @param {string} reason A custom connection close reason.\n   */\n  public close(code?: number, reason?: string): void {\n    this.transport.close(code, reason)\n  }\n}\n","import { invariant } from 'outvariant'\nimport {\n  kClose,\n  WebSocketEventListener,\n  WebSocketOverride,\n} from './WebSocketOverride'\nimport type { WebSocketData } from './WebSocketTransport'\nimport type { WebSocketClassTransport } from './WebSocketClassTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport {\n  CancelableMessageEvent,\n  CancelableCloseEvent,\n  CloseEvent,\n} from './utils/events'\n\nconst kEmitter = Symbol('kEmitter')\nconst kBoundListener = Symbol('kBoundListener')\nconst kSend = Symbol('kSend')\n\ninterface WebSocketServerEventMap {\n  open: Event\n  message: MessageEvent<WebSocketData>\n  error: Event\n  close: CloseEvent\n}\n\n/**\n * The WebSocket server instance represents the actual production\n * WebSocket server connection. It's idle by default but you can\n * establish it by calling `server.connect()`.\n */\nexport class WebSocketServerConnection {\n  /**\n   * A WebSocket instance connected to the original server.\n   */\n  private realWebSocket?: WebSocket\n  private mockCloseController: AbortController\n  private realCloseController: AbortController\n  private [kEmitter]: EventTarget\n\n  constructor(\n    private readonly client: WebSocketOverride,\n    private readonly transport: WebSocketClassTransport,\n    private readonly createConnection: () => WebSocket\n  ) {\n    this[kEmitter] = new EventTarget()\n    this.mockCloseController = new AbortController()\n    this.realCloseController = new AbortController()\n\n    // Automatically forward outgoing client events\n    // to the actual server unless the outgoing message event\n    // has been prevented. The \"outgoing\" transport event it\n    // dispatched by the \"client\" connection.\n    this.transport.addEventListener('outgoing', (event) => {\n      // Ignore client messages if the server connection\n      // hasn't been established yet. Nowhere to forward.\n      if (typeof this.realWebSocket === 'undefined') {\n        return\n      }\n\n      // Every outgoing client message can prevent this forwarding\n      // by preventing the default of the outgoing message event.\n      // This listener will be added before user-defined listeners,\n      // so execute the logic on the next tick.\n      queueMicrotask(() => {\n        if (!event.defaultPrevented) {\n          /**\n           * @note Use the internal send mechanism so consumers can tell\n           * apart direct user calls to `server.send()` and internal calls.\n           * E.g. MSW has to ignore this internal call to log out messages correctly.\n           */\n          this[kSend](event.data)\n        }\n      })\n    })\n\n    this.transport.addEventListener(\n      'incoming',\n      this.handleIncomingMessage.bind(this)\n    )\n  }\n\n  /**\n   * The `WebSocket` instance connected to the original server.\n   * Accessing this before calling `server.connect()` will throw.\n   */\n  public get socket(): WebSocket {\n    invariant(\n      this.realWebSocket,\n      'Cannot access \"socket\" on the original WebSocket server object: the connection is not open. Did you forget to call `server.connect()`?'\n    )\n\n    return this.realWebSocket\n  }\n\n  /**\n   * Open connection to the original WebSocket server.\n   */\n  public connect(): void {\n    invariant(\n      !this.realWebSocket || this.realWebSocket.readyState !== WebSocket.OPEN,\n      'Failed to call \"connect()\" on the original WebSocket instance: the connection already open'\n    )\n\n    const realWebSocket = this.createConnection()\n\n    // Inherit the binary type from the mock WebSocket client.\n    realWebSocket.binaryType = this.client.binaryType\n\n    // Allow the interceptor to listen to when the server connection\n    // has been established. This isn't necessary to operate with the connection\n    // but may be beneficial in some cases (like conditionally adding logging).\n    realWebSocket.addEventListener(\n      'open',\n      (event) => {\n        this[kEmitter].dispatchEvent(\n          bindEvent(this.realWebSocket!, new Event('open', event))\n        )\n      },\n      { once: true }\n    )\n\n    realWebSocket.addEventListener('message', (event) => {\n      // Dispatch the \"incoming\" transport event instead of\n      // invoking the internal handler directly. This way,\n      // anyone can listen to the \"incoming\" event but this\n      // class is the one resulting in it.\n      this.transport.dispatchEvent(\n        bindEvent(\n          this.realWebSocket!,\n          new MessageEvent('incoming', {\n            data: event.data,\n            origin: event.origin,\n          })\n        )\n      )\n    })\n\n    // Close the original connection when the mock client closes.\n    // E.g. \"client.close()\" was called. This is never forwarded anywhere.\n    this.client.addEventListener(\n      'close',\n      (event) => {\n        this.handleMockClose(event)\n      },\n      {\n        signal: this.mockCloseController.signal,\n      }\n    )\n\n    // Forward the \"close\" event to let the interceptor handle\n    // closures initiated by the original server.\n    realWebSocket.addEventListener(\n      'close',\n      (event) => {\n        this.handleRealClose(event)\n      },\n      {\n        signal: this.realCloseController.signal,\n      }\n    )\n\n    realWebSocket.addEventListener('error', () => {\n      const errorEvent = bindEvent(\n        realWebSocket,\n        new Event('error', { cancelable: true })\n      )\n\n      // Emit the \"error\" event on the `server` connection\n      // to let the interceptor react to original server errors.\n      this[kEmitter].dispatchEvent(errorEvent)\n\n      // If the error event from the original server hasn't been prevented,\n      // forward it to the underlying client.\n      if (!errorEvent.defaultPrevented) {\n        this.client.dispatchEvent(bindEvent(this.client, new Event('error')))\n      }\n    })\n\n    this.realWebSocket = realWebSocket\n  }\n\n  /**\n   * Listen for the incoming events from the original WebSocket server.\n   */\n  public addEventListener<EventType extends keyof WebSocketServerEventMap>(\n    event: EventType,\n    listener: WebSocketEventListener<WebSocketServerEventMap[EventType]>,\n    options?: AddEventListenerOptions | boolean\n  ): void {\n    if (!Reflect.has(listener, kBoundListener)) {\n      const boundListener = listener.bind(this.client)\n\n      // Store the bound listener on the original listener\n      // so the exact bound function can be accessed in \"removeEventListener()\".\n      Object.defineProperty(listener, kBoundListener, {\n        value: boundListener,\n        enumerable: false,\n      })\n    }\n\n    this[kEmitter].addEventListener(\n      event,\n      Reflect.get(listener, kBoundListener) as EventListener,\n      options\n    )\n  }\n\n  /**\n   * Remove the listener for the given event.\n   */\n  public removeEventListener<EventType extends keyof WebSocketServerEventMap>(\n    event: EventType,\n    listener: WebSocketEventListener<WebSocketServerEventMap[EventType]>,\n    options?: EventListenerOptions | boolean\n  ): void {\n    this[kEmitter].removeEventListener(\n      event,\n      Reflect.get(listener, kBoundListener) as EventListener,\n      options\n    )\n  }\n\n  /**\n   * Send data to the original WebSocket server.\n   * @example\n   * server.send('hello')\n   * server.send(new Blob(['hello']))\n   * server.send(new TextEncoder().encode('hello'))\n   */\n  public send(data: WebSocketData): void {\n    this[kSend](data)\n  }\n\n  private [kSend](data: WebSocketData): void {\n    const { realWebSocket } = this\n\n    invariant(\n      realWebSocket,\n      'Failed to call \"server.send()\" for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n      this.client.url\n    )\n\n    // Silently ignore writes on the closed original WebSocket.\n    if (\n      realWebSocket.readyState === WebSocket.CLOSING ||\n      realWebSocket.readyState === WebSocket.CLOSED\n    ) {\n      return\n    }\n\n    // Delegate the send to when the original connection is open.\n    // Unlike the mock, connecting to the original server may take time\n    // so we cannot call this on the next tick.\n    if (realWebSocket.readyState === WebSocket.CONNECTING) {\n      realWebSocket.addEventListener(\n        'open',\n        () => {\n          realWebSocket.send(data)\n        },\n        { once: true }\n      )\n      return\n    }\n\n    // Send the data to the original WebSocket server.\n    realWebSocket.send(data)\n  }\n\n  /**\n   * Close the actual server connection.\n   */\n  public close(): void {\n    const { realWebSocket } = this\n\n    invariant(\n      realWebSocket,\n      'Failed to close server connection for \"%s\": the connection is not open. Did you forget to call \"server.connect()\"?',\n      this.client.url\n    )\n\n    // Remove the \"close\" event listener from the server\n    // so it doesn't close the underlying WebSocket client\n    // when you call \"server.close()\". This also prevents the\n    // `close` event on the `server` connection from being dispatched twice.\n    this.realCloseController.abort()\n\n    if (\n      realWebSocket.readyState === WebSocket.CLOSING ||\n      realWebSocket.readyState === WebSocket.CLOSED\n    ) {\n      return\n    }\n\n    // Close the actual client connection.\n    realWebSocket.close()\n\n    // Dispatch the \"close\" event on the `server` connection.\n    queueMicrotask(() => {\n      this[kEmitter].dispatchEvent(\n        bindEvent(\n          this.realWebSocket,\n          new CancelableCloseEvent('close', {\n            /**\n             * @note `server.close()` in the interceptor\n             * always results in clean closures.\n             */\n            code: 1000,\n            cancelable: true,\n          })\n        )\n      )\n    })\n  }\n\n  private handleIncomingMessage(event: MessageEvent<WebSocketData>): void {\n    // Clone the event to dispatch it on this class\n    // once again and prevent the \"already being dispatched\"\n    // exception. Clone it here so we can observe this event\n    // being prevented in the \"server.on()\" listeners.\n    const messageEvent = bindEvent(\n      event.target,\n      new CancelableMessageEvent('message', {\n        data: event.data,\n        origin: event.origin,\n        cancelable: true,\n      })\n    )\n\n    /**\n     * @note Emit \"message\" event on the server connection\n     * instance to let the interceptor know about these\n     * incoming events from the original server. In that listener,\n     * the interceptor can modify or skip the event forwarding\n     * to the mock WebSocket instance.\n     */\n    this[kEmitter].dispatchEvent(messageEvent)\n\n    /**\n     * @note Forward the incoming server events to the client.\n     * Preventing the default on the message event stops this.\n     */\n    if (!messageEvent.defaultPrevented) {\n      this.client.dispatchEvent(\n        bindEvent(\n          /**\n           * @note Bind the forwarded original server events\n           * to the mock WebSocket instance so it would\n           * dispatch them straight away.\n           */\n          this.client,\n          // Clone the message event again to prevent\n          // the \"already being dispatched\" exception.\n          new MessageEvent('message', {\n            data: event.data,\n            origin: event.origin,\n          })\n        )\n      )\n    }\n  }\n\n  private handleMockClose(_event: Event): void {\n    // Close the original connection if the mock client closes.\n    if (this.realWebSocket) {\n      this.realWebSocket.close()\n    }\n  }\n\n  private handleRealClose(event: CloseEvent): void {\n    // For closures originating from the original server,\n    // remove the \"close\" listener from the mock client.\n    // original close -> (?) client[kClose]() --X--> \"close\" (again).\n    this.mockCloseController.abort()\n\n    const closeEvent = bindEvent(\n      this.realWebSocket,\n      new CancelableCloseEvent('close', {\n        code: event.code,\n        reason: event.reason,\n        wasClean: event.wasClean,\n        cancelable: true,\n      })\n    )\n\n    this[kEmitter].dispatchEvent(closeEvent)\n\n    // If the close event from the server hasn't been prevented,\n    // forward the closure to the mock client.\n    if (!closeEvent.defaultPrevented) {\n      // Close the intercepted client forcefully to\n      // allow non-configurable status codes from the server.\n      // If the socket has been closed by now, no harm calling\n      // this again—it will have no effect.\n      this.client[kClose](event.code, event.reason)\n    }\n  }\n}\n","import { invariant } from 'outvariant'\nimport type { WebSocketData } from './WebSocketTransport'\nimport { bindEvent } from './utils/bindEvent'\nimport { CloseEvent } from './utils/events'\nimport { DeferredPromise } from '@open-draft/deferred-promise'\n\nexport type WebSocketEventListener<\n  EventType extends WebSocketEventMap[keyof WebSocketEventMap] = Event\n> = (this: WebSocket, event: EventType) => void\n\nconst WEBSOCKET_CLOSE_CODE_RANGE_ERROR =\n  'InvalidAccessError: close code out of user configurable range'\n\nexport const kPassthroughPromise = Symbol('kPassthroughPromise')\nexport const kOnSend = Symbol('kOnSend')\nexport const kClose = Symbol('kClose')\n\nexport class WebSocketOverride extends EventTarget implements WebSocket {\n  static readonly CONNECTING = 0\n  static readonly OPEN = 1\n  static readonly CLOSING = 2\n  static readonly CLOSED = 3\n  readonly CONNECTING = 0\n  readonly OPEN = 1\n  readonly CLOSING = 2\n  readonly CLOSED = 3\n\n  public url: string\n  public protocol: string\n  public extensions: string\n  public binaryType: BinaryType\n  public readyState: number\n  public bufferedAmount: number\n\n  private _onopen: WebSocketEventListener | null = null\n  private _onmessage: WebSocketEventListener<\n    MessageEvent<WebSocketData>\n  > | null = null\n  private _onerror: WebSocketEventListener | null = null\n  private _onclose: WebSocketEventListener<CloseEvent> | null = null\n\n  private [kPassthroughPromise]: DeferredPromise<boolean>\n  private [kOnSend]?: (data: WebSocketData) => void\n\n  constructor(url: string | URL, protocols?: string | Array<string>) {\n    super()\n    this.url = url.toString()\n    this.protocol = ''\n    this.extensions = ''\n    this.binaryType = 'blob'\n    this.readyState = this.CONNECTING\n    this.bufferedAmount = 0\n\n    this[kPassthroughPromise] = new DeferredPromise<boolean>()\n\n    queueMicrotask(async () => {\n      if (await this[kPassthroughPromise]) {\n        return\n      }\n\n      this.protocol =\n        typeof protocols === 'string'\n          ? protocols\n          : Array.isArray(protocols) && protocols.length > 0\n          ? protocols[0]\n          : ''\n\n      /**\n       * @note Check that nothing has prevented this connection\n       * (e.g. called `client.close()` in the connection listener).\n       * If the connection has been prevented, never dispatch the open event,.\n       */\n      if (this.readyState === this.CONNECTING) {\n        this.readyState = this.OPEN\n        this.dispatchEvent(bindEvent(this, new Event('open')))\n      }\n    })\n  }\n\n  set onopen(listener: WebSocketEventListener | null) {\n    this.removeEventListener('open', this._onopen)\n    this._onopen = listener\n    if (listener !== null) {\n      this.addEventListener('open', listener)\n    }\n  }\n  get onopen(): WebSocketEventListener | null {\n    return this._onopen\n  }\n\n  set onmessage(\n    listener: WebSocketEventListener<MessageEvent<WebSocketData>> | null\n  ) {\n    this.removeEventListener(\n      'message',\n      this._onmessage as WebSocketEventListener\n    )\n    this._onmessage = listener\n    if (listener !== null) {\n      this.addEventListener('message', listener)\n    }\n  }\n  get onmessage(): WebSocketEventListener<MessageEvent<WebSocketData>> | null {\n    return this._onmessage\n  }\n\n  set onerror(listener: WebSocketEventListener | null) {\n    this.removeEventListener('error', this._onerror)\n    this._onerror = listener\n    if (listener !== null) {\n      this.addEventListener('error', listener)\n    }\n  }\n  get onerror(): WebSocketEventListener | null {\n    return this._onerror\n  }\n\n  set onclose(listener: WebSocketEventListener<CloseEvent> | null) {\n    this.removeEventListener('close', this._onclose as WebSocketEventListener)\n    this._onclose = listener\n    if (listener !== null) {\n      this.addEventListener('close', listener)\n    }\n  }\n  get onclose(): WebSocketEventListener<CloseEvent> | null {\n    return this._onclose\n  }\n\n  /**\n   * @see https://websockets.spec.whatwg.org/#ref-for-dom-websocket-send%E2%91%A0\n   */\n  public send(data: WebSocketData): void {\n    if (this.readyState === this.CONNECTING) {\n      this.close()\n      throw new DOMException('InvalidStateError')\n    }\n\n    // Sending when the socket is about to close\n    // discards the sent data.\n    if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n      return\n    }\n\n    // Buffer the data to send in this even loop\n    // but send it in the next.\n    this.bufferedAmount += getDataSize(data)\n\n    queueMicrotask(() => {\n      // This is a bit optimistic but since no actual data transfer\n      // is involved, all the data will be \"sent\" on the next tick.\n      this.bufferedAmount = 0\n\n      /**\n       * @note Notify the parent about outgoing data.\n       * This notifies the transport and the connection\n       * listens to the outgoing data to emit the \"message\" event.\n       */\n      this[kOnSend]?.(data)\n    })\n  }\n\n  public close(code: number = 1000, reason?: string): void {\n    invariant(code, WEBSOCKET_CLOSE_CODE_RANGE_ERROR)\n    invariant(\n      code === 1000 || (code >= 3000 && code <= 4999),\n      WEBSOCKET_CLOSE_CODE_RANGE_ERROR\n    )\n\n    this[kClose](code, reason)\n  }\n\n  private [kClose](\n    code: number = 1000,\n    reason?: string,\n    wasClean = true\n  ): void {\n    /**\n     * @note Move this check here so that even internall closures,\n     * like those triggered by the `server` connection, are not\n     * performed twice.\n     */\n    if (this.readyState === this.CLOSING || this.readyState === this.CLOSED) {\n      return\n    }\n\n    this.readyState = this.CLOSING\n\n    queueMicrotask(() => {\n      this.readyState = this.CLOSED\n\n      this.dispatchEvent(\n        bindEvent(\n          this,\n          new CloseEvent('close', {\n            code,\n            reason,\n            wasClean,\n          })\n        )\n      )\n\n      // Remove all event listeners once the socket is closed.\n      this._onopen = null\n      this._onmessage = null\n      this._onerror = null\n      this._onclose = null\n    })\n  }\n\n  public addEventListener<K extends keyof WebSocketEventMap>(\n    type: K,\n    listener: (this: WebSocket, event: WebSocketEventMap[K]) => void,\n    options?: boolean | AddEventListenerOptions\n  ): void\n  public addEventListener(\n    type: string,\n    listener: EventListenerOrEventListenerObject,\n    options?: boolean | AddEventListenerOptions\n  ): void\n  public addEventListener(\n    type: unknown,\n    listener: unknown,\n    options?: unknown\n  ): void {\n    return super.addEventListener(\n      type as string,\n      listener as EventListener,\n      options as AddEventListenerOptions\n    )\n  }\n\n  removeEventListener<K extends keyof WebSocketEventMap>(\n    type: K,\n    callback: EventListenerOrEventListenerObject | null,\n    options?: boolean | EventListenerOptions\n  ): void {\n    return super.removeEventListener(type, callback, options)\n  }\n}\n\nfunction getDataSize(data: WebSocketData): number {\n  if (typeof data === 'string') {\n    return data.length\n  }\n\n  if (data instanceof Blob) {\n    return data.size\n  }\n\n  return data.byteLength\n}\n","import { bindEvent } from './utils/bindEvent'\nimport {\n  StrictEventListenerOrEventListenerObject,\n  WebSocketData,\n  WebSocketTransport,\n  WebSocketTransportEventMap,\n} from './WebSocketTransport'\nimport { kOnSend, kClose, WebSocketOverride } from './WebSocketOverride'\nimport { CancelableMessageEvent, CloseEvent } from './utils/events'\n\n/**\n * Abstraction over the given mock `WebSocket` instance that allows\n * for controlling that instance (e.g. sending and receiving messages).\n */\nexport class WebSocketClassTransport\n  extends EventTarget\n  implements WebSocketTransport\n{\n  constructor(protected readonly socket: WebSocketOverride) {\n    super()\n\n    // Emit the \"close\" event on the transport if the close\n    // originates from the WebSocket client. E.g. the application\n    // calls \"ws.close()\", not the interceptor.\n    this.socket.addEventListener('close', (event) => {\n      this.dispatchEvent(bindEvent(this.socket, new CloseEvent('close', event)))\n    })\n\n    /**\n     * Emit the \"outgoing\" event on the transport\n     * whenever the WebSocket client sends data (\"ws.send()\").\n     */\n    this.socket[kOnSend] = (data) => {\n      this.dispatchEvent(\n        bindEvent(\n          this.socket,\n          // Dispatch this as cancelable because \"client\" connection\n          // re-creates this message event (cannot dispatch the same event).\n          new CancelableMessageEvent('outgoing', {\n            data,\n            origin: this.socket.url,\n            cancelable: true,\n          })\n        )\n      )\n    }\n  }\n\n  public addEventListener<EventType extends keyof WebSocketTransportEventMap>(\n    type: EventType,\n    callback: StrictEventListenerOrEventListenerObject<\n      WebSocketTransportEventMap[EventType]\n    > | null,\n    options?: boolean | AddEventListenerOptions\n  ): void {\n    return super.addEventListener(type, callback as EventListener, options)\n  }\n\n  public dispatchEvent<EventType extends keyof WebSocketTransportEventMap>(\n    event: WebSocketTransportEventMap[EventType]\n  ): boolean {\n    return super.dispatchEvent(event)\n  }\n\n  public send(data: WebSocketData): void {\n    queueMicrotask(() => {\n      if (\n        this.socket.readyState === this.socket.CLOSING ||\n        this.socket.readyState === this.socket.CLOSED\n      ) {\n        return\n      }\n\n      const dispatchEvent = () => {\n        this.socket.dispatchEvent(\n          bindEvent(\n            /**\n             * @note Setting this event's \"target\" to the\n             * WebSocket override instance is important.\n             * This way it can tell apart original incoming events\n             * (must be forwarded to the transport) from the\n             * mocked message events like the one below\n             * (must be dispatched on the client instance).\n             */\n            this.socket,\n            new MessageEvent('message', {\n              data,\n              origin: this.socket.url,\n            })\n          )\n        )\n      }\n\n      if (this.socket.readyState === this.socket.CONNECTING) {\n        this.socket.addEventListener(\n          'open',\n          () => {\n            dispatchEvent()\n          },\n          { once: true }\n        )\n      } else {\n        dispatchEvent()\n      }\n    })\n  }\n\n  public close(code: number, reason?: string): void {\n    /**\n     * @note Call the internal close method directly\n     * to allow closing the connection with the status codes\n     * that are non-configurable by the user (> 1000 <= 1015).\n     */\n    this.socket[kClose](code, reason)\n  }\n}\n","import { Interceptor } from '../../Interceptor'\nimport {\n  type WebSocketClientConnectionProtocol,\n  WebSocketClientConnection,\n} from './WebSocketClientConnection'\nimport { WebSocketServerConnection } from './WebSocketServerConnection'\nimport { WebSocketClassTransport } from './WebSocketClassTransport'\nimport {\n  kClose,\n  kPassthroughPromise,\n  WebSocketOverride,\n} from './WebSocketOverride'\nimport { bindEvent } from './utils/bindEvent'\nimport { hasConfigurableGlobal } from '../../utils/hasConfigurableGlobal'\n\nexport { type WebSocketData, WebSocketTransport } from './WebSocketTransport'\nexport {\n  WebSocketClientConnection,\n  WebSocketClientConnectionProtocol,\n  WebSocketServerConnection,\n}\n\nexport type WebSocketEventMap = {\n  connection: [args: WebSocketConnectionData]\n}\n\nexport type WebSocketConnectionData = {\n  /**\n   * The incoming WebSocket client connection.\n   */\n  client: WebSocketClientConnection\n\n  /**\n   * The original WebSocket server connection.\n   */\n  server: WebSocketServerConnection\n\n  /**\n   * The connection information.\n   */\n  info: {\n    /**\n     * The protocols supported by the WebSocket client.\n     */\n    protocols: string | Array<string> | undefined\n  }\n}\n\n/**\n * Intercept the outgoing WebSocket connections created using\n * the global `WebSocket` class.\n */\nexport class WebSocketInterceptor extends Interceptor<WebSocketEventMap> {\n  static symbol = Symbol('websocket')\n\n  constructor() {\n    super(WebSocketInterceptor.symbol)\n  }\n\n  protected checkEnvironment(): boolean {\n    return hasConfigurableGlobal('WebSocket')\n  }\n\n  protected setup(): void {\n    const originalWebSocketDescriptor = Object.getOwnPropertyDescriptor(\n      globalThis,\n      'WebSocket'\n    )\n\n    const WebSocketProxy = new Proxy(globalThis.WebSocket, {\n      construct: (\n        target,\n        args: ConstructorParameters<typeof globalThis.WebSocket>,\n        newTarget\n      ) => {\n        const [url, protocols] = args\n\n        const createConnection = (): WebSocket => {\n          return Reflect.construct(target, args, newTarget)\n        }\n\n        // All WebSocket instances are mocked and don't forward\n        // any events to the original server (no connection established).\n        // To forward the events, the user must use the \"server.send()\" API.\n        const socket = new WebSocketOverride(url, protocols)\n        const transport = new WebSocketClassTransport(socket)\n\n        // Emit the \"connection\" event to the interceptor on the next tick\n        // so the client can modify WebSocket options, like \"binaryType\"\n        // while the connection is already pending.\n        queueMicrotask(() => {\n          try {\n            const server = new WebSocketServerConnection(\n              socket,\n              transport,\n              createConnection\n            )\n\n            // The \"globalThis.WebSocket\" class stands for\n            // the client-side connection. Assume it's established\n            // as soon as the WebSocket instance is constructed.\n            const hasConnectionListeners = this.emitter.emit('connection', {\n              client: new WebSocketClientConnection(socket, transport),\n              server,\n              info: {\n                protocols,\n              },\n            })\n\n            if (hasConnectionListeners) {\n              socket[kPassthroughPromise].resolve(false)\n            } else {\n              socket[kPassthroughPromise].resolve(true)\n\n              server.connect()\n\n              // Forward the \"open\" event from the original server\n              // to the mock WebSocket client in the case of a passthrough connection.\n              server.addEventListener('open', () => {\n                socket.dispatchEvent(bindEvent(socket, new Event('open')))\n\n                // Forward the original connection protocol to the\n                // mock WebSocket client.\n                if (server['realWebSocket']) {\n                  socket.protocol = server['realWebSocket'].protocol\n                }\n              })\n            }\n          } catch (error) {\n            /**\n             * @note Translate unhandled exceptions during the connection\n             * handling (i.e. interceptor exceptions) as WebSocket connection\n             * closures with error. This prevents from the exceptions occurring\n             * in `queueMicrotask` from being process-wide and uncatchable.\n             */\n            if (error instanceof Error) {\n              socket.dispatchEvent(new Event('error'))\n\n              // No need to close the connection if it's already being closed.\n              // E.g. the interceptor called `client.close()` and then threw an error.\n              if (\n                socket.readyState !== WebSocket.CLOSING &&\n                socket.readyState !== WebSocket.CLOSED\n              ) {\n                socket[kClose](1011, error.message, false)\n              }\n\n              console.error(error)\n            }\n          }\n        })\n\n        return socket\n      },\n    })\n\n    Object.defineProperty(globalThis, 'WebSocket', {\n      value: WebSocketProxy,\n      configurable: true,\n    })\n\n    this.subscriptions.push(() => {\n      Object.defineProperty(\n        globalThis,\n        'WebSocket',\n        originalWebSocketDescriptor!\n      )\n    })\n  }\n}\n"],"mappings":"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","names":["invariant","kEmitter","kBoundListener","invariant"]}