{"version":3,"file":"penpal.mjs","names":["brand","#remoteWindow","#allowedOrigins","#log","#validateReceivedMessage","#handleMessageFromRemoteWindow","#getOriginForSendingMessage","#setPort","#destroyPort","#port","#messageCallbacks","#concreteRemoteOrigin","#handleMessageFromPort","#isAllowedOrigin","#worker","#log","#validateReceivedMessage","#handleMessage","#setPort","#destroyPort","#port","#messageCallbacks","#port","#validateReceivedMessage","#handleMessage","#messageCallbacks"],"sources":["../src/PenpalError.ts","../src/errorSerialization.ts","../src/Reply.ts","../src/namespace.ts","../src/guards.ts","../src/methodPath.ts","../src/connectCallHandler.ts","../src/generateId.ts","../src/CallOptions.ts","../src/connectRemoteProxy.ts","../src/shakeHands.ts","../src/once.ts","../src/connect.ts","../src/messengers/WindowMessenger.ts","../src/messengers/WorkerMessenger.ts","../src/messengers/PortMessenger.ts","../src/ErrorCodeObj.ts","../src/debug.ts"],"sourcesContent":["import type { ErrorCode } from './types.js';\n\nclass PenpalError extends Error {\n  public code: ErrorCode;\n\n  constructor(code: ErrorCode, message: string) {\n    super(message);\n    this.name = 'PenpalError';\n    this.code = code;\n  }\n}\n\nexport default PenpalError;\n","import type { SerializedError } from './types.js';\nimport PenpalError from './PenpalError.js';\n\n/**\n * Converts an error object into a plain object.\n */\nexport const serializeError = (error: Error): SerializedError => ({\n  name: error.name,\n  message: error.message,\n  stack: error.stack,\n  penpalCode: error instanceof PenpalError ? error.code : undefined,\n});\n\n/**\n * Converts a plain object into an error object.\n */\nexport const deserializeError = ({\n  name,\n  message,\n  stack,\n  penpalCode,\n}: SerializedError): Error => {\n  const deserializedError = penpalCode\n    ? new PenpalError(penpalCode, message)\n    : new Error(message);\n\n  deserializedError.name = name;\n  // TypeScript declares Error.stack as `stack?: string`. With\n  // exactOptionalPropertyTypes, that permits a missing property but rejects\n  // assigning undefined. A serialized error can legitimately have no stack,\n  // and Penpal must overwrite the locally generated stack with that undefined\n  // value to preserve the remote error, so widen the property for this write.\n  (deserializedError as { stack: string | undefined }).stack = stack;\n\n  return deserializedError;\n};\n","const brand: unique symbol = Symbol('Reply');\n\nclass Reply<T = unknown> {\n  readonly value: T;\n  readonly transferables: Transferable[] | undefined;\n\n  // Allows TypeScript to distinguish between an actual instance of this\n  // class versus an object that looks structurally similar.\n  // eslint-disable-next-line no-unused-private-class-members\n  #brand = brand;\n\n  constructor(\n    value: T,\n    options?: {\n      transferables?: Transferable[] | undefined;\n    },\n  ) {\n    this.value = value;\n    this.transferables = options?.transferables;\n  }\n}\n\nexport default Reply;\n","export default 'penpal' as const;\n","import namespace from './namespace.js';\nimport type {\n  Ack2Message,\n  CallMessage,\n  Message,\n  ReplyMessage,\n  Ack1Message,\n  SynMessage,\n  DestroyMessage,\n} from './types.js';\n\nexport const isObject = (\n  value: unknown,\n): value is Record<string | number | symbol, unknown> => {\n  return typeof value === 'object' && value !== null;\n};\n\nexport const isFunction = (value: unknown): value is Function => {\n  return typeof value === 'function';\n};\n\nexport const isMessage = (data: unknown): data is Message => {\n  return isObject(data) && data.namespace === namespace;\n};\n\nexport const isSynMessage = (message: Message): message is SynMessage => {\n  return message.type === 'SYN';\n};\n\nexport const isAck1Message = (message: Message): message is Ack1Message => {\n  return message.type === 'ACK1';\n};\n\nexport const isAck2Message = (message: Message): message is Ack2Message => {\n  return message.type === 'ACK2';\n};\n\nexport const isCallMessage = (message: Message): message is CallMessage => {\n  return message.type === 'CALL';\n};\n\nexport const isReplyMessage = (message: Message): message is ReplyMessage => {\n  return message.type === 'REPLY';\n};\n\nexport const isDestroyMessage = (\n  message: Message,\n): message is DestroyMessage => {\n  return message.type === 'DESTROY';\n};\n","import type { MethodPath, Methods } from './types.js';\nimport { isFunction, isObject } from './guards.js';\n\nexport const getMethodAtMethodPath = (\n  methodPath: MethodPath,\n  methods: Methods,\n): Function | undefined => {\n  const result = methodPath.reduce<Methods | Function | undefined>(\n    (acc, pathSegment) => {\n      if (!isObject(acc) || !Object.hasOwn(acc, pathSegment)) {\n        return undefined;\n      }\n\n      return acc[pathSegment];\n    },\n    methods,\n  );\n\n  return isFunction(result) ? result : undefined;\n};\n\nexport const formatMethodPath = (methodPath: MethodPath): string => {\n  return methodPath.join('.');\n};\n","import { serializeError } from './errorSerialization.js';\nimport type { Message, ReplyMessage, Methods, Log } from './types.js';\nimport Reply from './Reply.js';\nimport type Messenger from './messengers/Messenger.js';\nimport PenpalError from './PenpalError.js';\nimport { formatMethodPath, getMethodAtMethodPath } from './methodPath.js';\nimport { isCallMessage } from './guards.js';\nimport namespace from './namespace.js';\n\nconst createErrorReplyMessage = (\n  channel: string | undefined,\n  callId: string,\n  error: unknown,\n): ReplyMessage => ({\n  namespace,\n  channel,\n  type: 'REPLY',\n  callId,\n  isError: true,\n  ...(error instanceof Error\n    ? { value: serializeError(error), isSerializedErrorInstance: true }\n    : { value: error }),\n});\n\n/**\n * Listens for \"call\" messages from the remote, executes the corresponding method,\n * and responds with the return value or error.\n */\nconst connectCallHandler = (\n  messenger: Messenger,\n  methods: Methods,\n  channel: string | undefined,\n  log: Log | undefined,\n): (() => void) => {\n  let isDestroyed = false;\n\n  const handleCallMessage = async (message: Message): Promise<void> => {\n    if (isDestroyed) {\n      // It's possible to throw an error here, but it would only be catchable\n      // using window.onerror since we're in an asynchronously-called function.\n      // There is no method call the consumer is making that they could wrap in\n      // a try-catch. Even if the consumer were to catch the error somehow,\n      // the value of doing so is questionable.\n      return;\n    }\n\n    if (!isCallMessage(message)) {\n      return;\n    }\n\n    log?.(`Received ${formatMethodPath(message.methodPath)}() call`, message);\n\n    const { methodPath, args, id: callId } = message;\n    let replyMessage: ReplyMessage;\n    let transferables: Transferable[] | undefined;\n\n    try {\n      const method = getMethodAtMethodPath(methodPath, methods);\n\n      if (!method) {\n        throw new PenpalError(\n          'METHOD_NOT_FOUND',\n          `Method \\`${formatMethodPath(methodPath)}\\` is not found.`,\n        );\n      }\n\n      let value: unknown = await method(...args);\n\n      if (value instanceof Reply) {\n        transferables = value.transferables;\n        value = await value.value;\n      }\n\n      replyMessage = {\n        namespace,\n        channel,\n        type: 'REPLY',\n        callId,\n        value,\n      };\n    } catch (error) {\n      replyMessage = createErrorReplyMessage(channel, callId, error);\n    }\n\n    // Although we checked this at the beginning of the function, we need to\n    // check it again because we've made async calls, and the connection may\n    // have been destroyed in the meantime.\n    if (isDestroyed) {\n      return;\n    }\n\n    try {\n      log?.(`Sending ${formatMethodPath(methodPath)}() reply`, replyMessage);\n      messenger.sendMessage(replyMessage, transferables);\n    } catch (error) {\n      // If a consumer attempts to send an object that's not\n      // cloneable (e.g., window), we want to ensure the receiver's promise\n      // gets rejected.\n      if ((error as Error).name === 'DataCloneError') {\n        replyMessage = createErrorReplyMessage(channel, callId, error as Error);\n        log?.(`Sending ${formatMethodPath(methodPath)}() reply`, replyMessage);\n        messenger.sendMessage(replyMessage);\n        // Don't return prematurely here, because we still want the error to\n        // hit the console so it's easier for developers to notice and debug.\n      }\n\n      throw error;\n    }\n  };\n\n  // Messenger dispatch is synchronous, so start the async work without\n  // returning its Promise and handle any rejection here.\n  const handleMessage = (message: Message): void => {\n    void handleCallMessage(message).catch((error: unknown) => {\n      console.error(error);\n    });\n  };\n\n  messenger.addMessageHandler(handleMessage);\n\n  return () => {\n    isDestroyed = true;\n    messenger.removeMessageHandler(handleMessage);\n  };\n};\n\nexport default connectCallHandler;\n","/**\n * @return A unique ID\n */\n// crypto.randomUUID is not available in insecure contexts.\nconst generateId: () => string =\n  crypto.randomUUID?.bind(crypto) ??\n  (() =>\n    new Array(4)\n      .fill(0)\n      .map(() =>\n        Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16),\n      )\n      .join('-'));\n\nexport default generateId;\n","const brand: unique symbol = Symbol('CallOptions');\n\nclass CallOptions {\n  readonly transferables: Transferable[] | undefined;\n  readonly timeout: number | undefined;\n\n  // Allows TypeScript to distinguish between an actual instance of this\n  // class versus an object that looks structurally similar.\n  // eslint-disable-next-line no-unused-private-class-members\n  #brand = brand;\n\n  constructor(options?: {\n    transferables?: Transferable[] | undefined;\n    timeout?: number | undefined;\n  }) {\n    this.transferables = options?.transferables;\n    this.timeout = options?.timeout;\n  }\n}\n\nexport default CallOptions;\n","import generateId from './generateId.js';\nimport { deserializeError } from './errorSerialization.js';\nimport { formatMethodPath } from './methodPath.js';\nimport type {\n  Message,\n  RemoteProxy,\n  Methods,\n  MethodPath,\n  CallMessage,\n  Log,\n} from './types.js';\nimport CallOptions from './CallOptions.js';\nimport type Messenger from './messengers/Messenger.js';\nimport PenpalError from './PenpalError.js';\nimport { isReplyMessage } from './guards.js';\nimport namespace from './namespace.js';\n\ntype ReplyHandler = {\n  methodPath: MethodPath;\n  resolve: (value: unknown) => void;\n  reject: (reason: unknown) => void;\n  timeoutId: ReturnType<typeof globalThis.setTimeout> | undefined;\n};\n\ntype ConnectedRemoteProxy<TMethods extends Methods> = {\n  remoteProxy: RemoteProxy<TMethods>;\n  destroy: () => void;\n};\n\nconst methodsToTreatAsNative = new Set(['apply', 'call', 'bind']);\n\nconst createRemoteProxy = (\n  callback: (path: MethodPath, args: unknown[]) => Promise<unknown>,\n  log: Log | undefined,\n  path: MethodPath = [],\n): Methods => {\n  return new Proxy(\n    path.length\n      ? () => {\n          // Intentionally empty\n        }\n      : Object.create(null),\n    {\n      get(target, prop: string) {\n        // If a promise is resolved with this proxy object, the JavaScript\n        // runtime will look for a `then` property on this object to determine\n        // if it should be treated as a promise (to support promise chaining).\n        // If we don't return undefined here, the JavaScript runtime will treat\n        // this object as a promise and attempt to call `then`, which will\n        // then send a call message to the remote. This is not what we want.\n        if (prop === 'then') {\n          return;\n        }\n\n        // Because we're using a proxy and because Penpal supports developers\n        // exposing nested methods, we have a predicament. If a developer\n        // calls, for example, remote.auth.apply(), are they\n        // attempting to call a nested apply() method that a developer has\n        // explicitly exposed from the remote? Could they instead be attempting\n        // to call Function.prototype.apply() on the remote.auth() method?\n        // Without the remote telling the local Penpal which methods the\n        // developer has exposed, it has no way of knowing (and the main reason\n        // we use a proxy is so that Penpal doesn't have to communicate which\n        // methods are exposed). So, we treat certain methods as native methods\n        // and return the native method rather than a proxy. The downside of\n        // this is that if a developer has explicitly exposed a nested method\n        // with the same name as one of these native method names, the developer\n        // will be unable to call the exposed remote method because they will\n        // be calling the method on the Function prototype instead.\n        if (path.length && methodsToTreatAsNative.has(prop)) {\n          return Reflect.get(target, prop);\n        }\n\n        return createRemoteProxy(callback, log, [...path, prop]);\n      },\n      apply(target, _thisArg, args) {\n        return callback(path, args);\n      },\n    },\n  );\n};\n\nconst getDestroyedConnectionMethodCallError = (methodPath: MethodPath) => {\n  return new PenpalError(\n    'CONNECTION_DESTROYED',\n    `Method call ${formatMethodPath(\n      methodPath,\n    )}() failed due to destroyed connection`,\n  );\n};\n\n/**\n * Creates a proxy. When methods are called on the proxy, a \"call\" message will\n * be sent to the remote, the remote's corresponding method will be\n * executed, and the method's return value will be returned via a message.\n */\nconst connectRemoteProxy = <TMethods extends Methods>(\n  messenger: Messenger,\n  channel: string | undefined,\n  log: Log | undefined,\n): ConnectedRemoteProxy<TMethods> => {\n  let isDestroyed = false;\n  const replyHandlers = new Map<string, ReplyHandler>();\n\n  const handleMessage = (message: Message) => {\n    if (!isReplyMessage(message)) {\n      return;\n    }\n\n    const { callId, value, isError, isSerializedErrorInstance } = message;\n    const replyHandler = replyHandlers.get(callId);\n\n    if (!replyHandler) {\n      return;\n    }\n\n    replyHandlers.delete(callId);\n    clearTimeout(replyHandler.timeoutId);\n    log?.(\n      `Received ${formatMethodPath(replyHandler.methodPath)}() reply`,\n      message,\n    );\n\n    if (isError) {\n      replyHandler.reject(\n        isSerializedErrorInstance ? deserializeError(value) : value,\n      );\n    } else {\n      replyHandler.resolve(value);\n    }\n  };\n\n  messenger.addMessageHandler(handleMessage);\n\n  const remoteProxy = createRemoteProxy((methodPath, args) => {\n    if (isDestroyed) {\n      throw getDestroyedConnectionMethodCallError(methodPath);\n    }\n\n    const callId = generateId();\n    const lastArg = args[args.length - 1];\n    const lastArgIsOptions = lastArg instanceof CallOptions;\n    const { timeout, transferables } = lastArgIsOptions ? lastArg : {};\n    const argsWithoutOptions = lastArgIsOptions ? args.slice(0, -1) : args;\n\n    return new Promise((resolve, reject) => {\n      // Use globalThis so this works in both window and worker contexts.\n      const timeoutId =\n        timeout !== undefined\n          ? globalThis.setTimeout(() => {\n              replyHandlers.delete(callId);\n              reject(\n                new PenpalError(\n                  'METHOD_CALL_TIMEOUT',\n                  `Method call ${formatMethodPath(\n                    methodPath,\n                  )}() timed out after ${timeout}ms`,\n                ),\n              );\n            }, timeout)\n          : undefined;\n\n      replyHandlers.set(callId, { methodPath, resolve, reject, timeoutId });\n\n      try {\n        const callMessage: CallMessage = {\n          namespace,\n          channel,\n          type: 'CALL',\n          id: callId,\n          methodPath,\n          args: argsWithoutOptions,\n        };\n        log?.(`Sending ${formatMethodPath(methodPath)}() call`, callMessage);\n        messenger.sendMessage(callMessage, transferables);\n      } catch (error) {\n        replyHandlers.delete(callId);\n        clearTimeout(timeoutId);\n        reject(\n          new PenpalError('TRANSMISSION_FAILED', (error as Error).message),\n        );\n      }\n    });\n  }, log) as RemoteProxy<TMethods>;\n\n  const destroy = () => {\n    isDestroyed = true;\n    messenger.removeMessageHandler(handleMessage);\n\n    for (const { methodPath, reject, timeoutId } of replyHandlers.values()) {\n      clearTimeout(timeoutId);\n      reject(getDestroyedConnectionMethodCallError(methodPath));\n    }\n\n    replyHandlers.clear();\n  };\n\n  return {\n    remoteProxy,\n    destroy,\n  };\n};\n\nexport default connectRemoteProxy;\n","import type Messenger from './messengers/Messenger.js';\nimport type {\n  Ack2Message,\n  Methods,\n  Message,\n  RemoteProxy,\n  Ack1Message,\n  SynMessage,\n  Log,\n} from './types.js';\nimport PenpalError from './PenpalError.js';\nimport connectCallHandler from './connectCallHandler.js';\nimport connectRemoteProxy from './connectRemoteProxy.js';\nimport { isAck2Message, isAck1Message, isSynMessage } from './guards.js';\nimport generateId from './generateId.js';\nimport namespace from './namespace.js';\n\ntype Options = {\n  messenger: Messenger;\n  methods: Methods;\n  timeout: number | undefined;\n  channel: string | undefined;\n  log: Log | undefined;\n};\n\ntype Handshake<TMethods extends Methods> = {\n  promise: Promise<RemoteProxy<TMethods>>;\n  destroy: () => void;\n};\n\n/**\n * Attempts to establish communication with the remote via a handshake protocol.\n * The handshake protocol fulfills a few requirements:\n *\n * 1. One participant in the handshake may not be available when the other\n *    participant starts the handshake. For example, a document inside an iframe\n *    may not be loaded when the parent window starts a handshake.\n * 2. While #1 could be solved by having the consumer of Penpal specify which\n *    participant should initiate the handshake, we'd rather avoid this\n *    unnecessary cognitive load.\n * 3. While #1 could be solved by having the consumer of Penpal specify which\n *    participant is the \"parent\" or \"child\" and then having Penpal assume\n *    the child should initiate the handshake, we'd rather avoid parent-child\n *    terminology since Penpal can support communication between two\n *    participants where neither would be considered a parent nor child. It may\n *    also be too presumptive that the child should always initiate the\n *    handshake.\n * 4. For robustness, each participant must know that the other participant is\n *    receiving its messages for the handshake to be considered complete.\n * 5. The handshake should support a participant attempting to\n *    re-establish the connection. This can occur, for example, if an end user\n *    were to right-click within an iframe and click reload.\n * 6. The handshake should allow a Messenger to easily attach something to\n *    a handshake message from one participant to the other unidirectionally\n *    (rather than from both participants to each other).\n *    This is important when a participant needs to be in charge of, for\n *    example, creating a MessageChannel and sending one MessagePort from the\n *    MessagePort pair to the other participant. If both participants attempted\n *    to do this it could lead to confusion.\n * 7. The handshake ideally shouldn't require sending handshake messages on an\n *    interval (retrying until the other participant is ready to receive them).\n *    Intervals can increase compute resources if the interval is too short\n *    or increase latency if the interval is too long. While we could make this\n *    configurable, it's additional mental load for the consumer. Additionally,\n *    setInterval and setTimeout are not available within some contexts\n *    (like AudioWorklet), where a consumer may like to use Penpal.\n *\n * To accomplish these requirements, the handshake protocol is as follows:\n * 1. Each participant generates a random participant ID.\n * 2. As soon as possible, each participant sends a SYN message containing its\n *    participant ID to the other participant.\n * 3. When the SYN messages were sent, one of the participants may not have\n *    been ready to receive the SYN message from the other. At least one\n *    of the participants was ready, however, and should have received a SYN\n *    message from the other participant. Each participant that did receive\n *    a SYN message knows for sure that the other participant is now ready\n *    to receive a SYN message, so it will send another SYN message in case\n *    the other participant did not receive the first SYN message. This\n *    ultimately results in each participant sending two SYN messages.\n * 4. Each participant now should have received at least one SYN message from\n *    the other participant. Each participant compares their own ID with the\n *    other participant's ID. Whichever participant has the higher ID\n *    (using a simple string comparison) is considered the handshake leader\n *    and will send an ACK1 message to the other participant.\n * 5. At this point, the handshake leader does not know whether the other\n *    participant is actually receiving messages. The participant receiving\n *    the ACK1 message will respond with an ACK2, informing the handshake\n *    leader that it is indeed receiving messages.\n * 6. At this point, both participants know the other is receiving messages\n *    and the handshake is complete.\n */\nconst shakeHands = <TMethods extends Methods>({\n  messenger,\n  methods,\n  timeout,\n  channel,\n  log,\n}: Options): Handshake<TMethods> => {\n  const participantId = generateId();\n  let remoteParticipantId: string;\n  const destroyHandlers: (() => void)[] = [];\n  let isComplete = false;\n  let isDestroyed = false;\n\n  const { promise, resolve, reject } =\n    Promise.withResolvers<RemoteProxy<TMethods>>();\n\n  const timeoutId =\n    timeout !== undefined\n      ? setTimeout(() => {\n          rejectAndCleanUp(\n            new PenpalError(\n              'CONNECTION_TIMEOUT',\n              `Connection timed out after ${timeout}ms`,\n            ),\n          );\n        }, timeout)\n      : undefined;\n\n  const cleanUp = () => {\n    clearTimeout(timeoutId);\n\n    for (const destroyHandler of destroyHandlers.splice(0)) {\n      destroyHandler();\n    }\n  };\n\n  const rejectAndCleanUp = (error: PenpalError) => {\n    if (isDestroyed) {\n      return;\n    }\n\n    isDestroyed = true;\n    cleanUp();\n    reject(error);\n  };\n\n  const destroy = () => {\n    rejectAndCleanUp(\n      new PenpalError('CONNECTION_DESTROYED', 'Connection destroyed'),\n    );\n  };\n\n  const completeHandshake = () => {\n    if (isDestroyed || isComplete) {\n      // Ignore messages after cleanup, and keep completion idempotent when\n      // the remote attempts to re-connect.\n      return;\n    }\n\n    destroyHandlers.push(connectCallHandler(messenger, methods, channel, log));\n\n    const { remoteProxy, destroy: destroyMethodProxies } =\n      connectRemoteProxy<TMethods>(messenger, channel, log);\n\n    destroyHandlers.push(destroyMethodProxies);\n\n    clearTimeout(timeoutId);\n    isComplete = true;\n\n    resolve(remoteProxy);\n  };\n\n  const sendHandshakeMessage = (\n    message: SynMessage | Ack1Message | Ack2Message,\n  ) => {\n    if (isDestroyed) {\n      return false;\n    }\n\n    log?.(`Sending handshake ${message.type}`, message);\n\n    try {\n      messenger.sendMessage(message);\n      return true;\n    } catch (error) {\n      rejectAndCleanUp(\n        new PenpalError('TRANSMISSION_FAILED', (error as Error).message),\n      );\n      return false;\n    }\n  };\n\n  const sendSynMessage = () => {\n    const synMessage: SynMessage = {\n      namespace,\n      type: 'SYN',\n      channel,\n      participantId: participantId,\n    };\n\n    return sendHandshakeMessage(synMessage);\n  };\n\n  const handleSynMessage = (message: SynMessage) => {\n    log?.(`Received handshake SYN`, message);\n\n    if (message.participantId === remoteParticipantId) {\n      return;\n    }\n\n    remoteParticipantId = message.participantId;\n\n    // We send another SYN message in case the other participant was not ready\n    // when we sent the first SYN message.\n    if (!sendSynMessage()) {\n      return;\n    }\n\n    const isHandshakeLeader = participantId > remoteParticipantId;\n\n    if (!isHandshakeLeader) {\n      return;\n    }\n\n    const ack1Message: Ack1Message = {\n      namespace,\n      channel,\n      type: 'ACK1',\n    };\n\n    if (!sendHandshakeMessage(ack1Message)) {\n      return;\n    }\n  };\n\n  const handleAck1Message = (message: Ack1Message) => {\n    log?.(`Received handshake ACK1`, message);\n    const ack2Message: Ack2Message = {\n      namespace,\n      channel,\n      type: 'ACK2',\n    };\n\n    if (sendHandshakeMessage(ack2Message)) {\n      completeHandshake();\n    }\n  };\n\n  const handleAck2Message = (message: Ack2Message) => {\n    log?.(`Received handshake ACK2`, message);\n    completeHandshake();\n  };\n\n  const handleMessage = (message: Message) => {\n    if (isDestroyed) {\n      return;\n    }\n\n    if (isSynMessage(message)) {\n      handleSynMessage(message);\n    } else if (isAck1Message(message)) {\n      handleAck1Message(message);\n    } else if (isAck2Message(message)) {\n      handleAck2Message(message);\n    }\n  };\n\n  messenger.addMessageHandler(handleMessage);\n  destroyHandlers.push(() => messenger.removeMessageHandler(handleMessage));\n\n  sendSynMessage();\n\n  return {\n    promise,\n    destroy,\n  };\n};\n\nexport default shakeHands;\n","// eslint-disable-next-line typescript/no-explicit-any\nconst once = <T extends (...args: any[]) => any>(\n  fn: T,\n): ((...args: Parameters<T>) => ReturnType<T>) => {\n  let isCalled = false;\n  let result: ReturnType<T>;\n\n  return (...args: Parameters<T>): ReturnType<T> => {\n    if (!isCalled) {\n      isCalled = true;\n      result = fn(...args);\n    }\n    return result;\n  };\n};\n\nexport default once;\n","import type {\n  DestroyMessage,\n  Connection,\n  Log,\n  Message,\n  Methods,\n  RemoteProxy,\n} from './types.js';\nimport PenpalError from './PenpalError.js';\nimport type Messenger from './messengers/Messenger.js';\nimport shakeHands from './shakeHands.js';\nimport { isDestroyMessage, isMessage } from './guards.js';\nimport once from './once.js';\nimport namespace from './namespace.js';\n\ntype Options = {\n  /**\n   * Messenger in charge of handling communication with the remote.\n   */\n  messenger: Messenger;\n  /**\n   * Methods that may be called by the remote.\n   */\n  methods?: Methods | undefined;\n  /**\n   * The amount of time, in milliseconds, Penpal should wait\n   * for a connection to be established before rejecting the connection promise.\n   */\n  timeout?: number | undefined;\n  /**\n   * A string identifier that disambiguates communication when establishing\n   * multiple, parallel connections between two participants (e.g., two windows,\n   * a window and a worker).\n   */\n  channel?: string | undefined;\n  /**\n   * A function for logging debug messages. Debug messages will only be\n   * logged when this is defined.\n   */\n  log?: Log | undefined;\n};\n\nconst usedMessengers = new WeakSet<Messenger>();\n\nconst getConnectionDestroyedError = () => {\n  return new PenpalError('CONNECTION_DESTROYED', 'Connection destroyed');\n};\n\n/**\n * Attempts to establish communication with the remote.\n */\nconst connect = <TMethods extends Methods>({\n  messenger,\n  methods = {},\n  timeout,\n  channel,\n  log,\n}: Options): Connection<TMethods> => {\n  if (!messenger) {\n    throw new PenpalError('INVALID_ARGUMENT', 'messenger must be defined');\n  }\n\n  if (usedMessengers.has(messenger)) {\n    throw new PenpalError(\n      'INVALID_ARGUMENT',\n      'A messenger can only be used for a single connection',\n    );\n  }\n\n  usedMessengers.add(messenger);\n\n  const connectionPromise = Promise.withResolvers<RemoteProxy<TMethods>>();\n  let isConnectionDestroyed = false;\n  let destroyHandshake: (() => void) | undefined;\n\n  const sendDestroyMessage = () => {\n    const destroyMessage: DestroyMessage = {\n      namespace,\n      channel,\n      type: 'DESTROY',\n    };\n\n    try {\n      messenger.sendMessage(destroyMessage);\n    } catch (_) {\n      // We do our best to notify the other participant of the connection,\n      // but if there's an error in doing so (e.g., maybe the handshake\n      // hasn't completed and a messenger can't send the message), it's\n      // probably not worth bothering the consumer with an error.\n    }\n  };\n\n  const destroyConnection = once(\n    (\n      connectionPromiseRejection: PenpalError,\n      notifyOtherParticipant: boolean,\n    ) => {\n      isConnectionDestroyed = true;\n\n      if (notifyOtherParticipant) {\n        sendDestroyMessage();\n      }\n\n      messenger.destroy();\n      destroyHandshake?.();\n\n      connectionPromise.reject(connectionPromiseRejection);\n\n      log?.('Connection destroyed');\n    },\n  );\n\n  const validateReceivedMessage = (data: unknown): data is Message => {\n    return isMessage(data) && data.channel === channel;\n  };\n\n  void (async () => {\n    try {\n      messenger.initialize({ log, validateReceivedMessage });\n      messenger.addMessageHandler((message) => {\n        if (isDestroyMessage(message)) {\n          destroyConnection(getConnectionDestroyedError(), false);\n        }\n      });\n\n      const handshake = shakeHands<TMethods>({\n        messenger,\n        methods,\n        timeout,\n        channel,\n        log,\n      });\n\n      destroyHandshake = handshake.destroy;\n\n      const remoteProxy = await handshake.promise;\n\n      if (isConnectionDestroyed) {\n        handshake.destroy();\n        return;\n      }\n\n      connectionPromise.resolve(remoteProxy);\n    } catch (error) {\n      destroyConnection(error as PenpalError, true);\n    }\n  })();\n\n  return {\n    promise: connectionPromise.promise,\n    destroy: () => {\n      destroyConnection(getConnectionDestroyedError(), true);\n    },\n  };\n};\n\nexport default connect;\n","import type { Log, Message } from '../types.js';\nimport type Messenger from './Messenger.js';\nimport type {\n  InitializeMessengerOptions,\n  MessageHandler,\n} from './Messenger.js';\nimport { isAck2Message, isAck1Message, isSynMessage } from '../guards.js';\nimport PenpalError from '../PenpalError.js';\n\n// Keep this structural so generated .d.ts files don't reference the DOM-only\n// Window global. Penpal also supports worker-only projects, and those projects\n// should be able to type-check the package without adding \"dom\" to tsconfig libs\n// just because WindowMessenger is one of Penpal's exports.\ntype WindowLike = {\n  postMessage: (\n    message: unknown,\n    options?: {\n      targetOrigin?: string;\n      transfer?: Transferable[];\n    },\n  ) => void;\n};\n\ntype Options = {\n  /**\n   * The window with which the current window will communicate.\n   */\n  remoteWindow: WindowLike;\n  /**\n   * An array of strings or regular expressions defining to which origins\n   * communication will be allowed. If not provided, communication will be\n   * restricted to the origin of the current page. You may specify an allowed\n   * origin of `*` to not restrict communication, but beware the risks of\n   * doing so.\n   */\n  allowedOrigins?: (string | RegExp)[] | undefined;\n};\n\n/**\n * Handles the details of communicating with a child window.\n */\nclass WindowMessenger implements Messenger {\n  readonly #remoteWindow: WindowLike;\n  readonly #allowedOrigins: [string | RegExp, ...(string | RegExp)[]];\n  #log: Log | undefined;\n  #validateReceivedMessage: ((data: unknown) => data is Message) | undefined;\n  #concreteRemoteOrigin: string | undefined;\n  #messageCallbacks = new Set<MessageHandler>();\n  #port: MessagePort | undefined;\n\n  constructor({ remoteWindow, allowedOrigins }: Options) {\n    if (!remoteWindow) {\n      throw new PenpalError('INVALID_ARGUMENT', 'remoteWindow must be defined');\n    }\n\n    this.#remoteWindow = remoteWindow;\n    this.#allowedOrigins = allowedOrigins?.length\n      ? (allowedOrigins as [string | RegExp, ...(string | RegExp)[]])\n      : [window.origin];\n  }\n\n  initialize = ({\n    log,\n    validateReceivedMessage,\n  }: InitializeMessengerOptions): void => {\n    this.#log = log;\n    this.#validateReceivedMessage = validateReceivedMessage;\n    window.addEventListener('message', this.#handleMessageFromRemoteWindow);\n  };\n\n  sendMessage = (message: Message, transferables?: Transferable[]): void => {\n    if (isSynMessage(message)) {\n      const originForSending = this.#getOriginForSendingMessage(message);\n      this.#remoteWindow.postMessage(message, {\n        targetOrigin: originForSending,\n        ...(transferables === undefined ? {} : { transfer: transferables }),\n      });\n      return;\n    }\n\n    if (isAck1Message(message)) {\n      const originForSending = this.#getOriginForSendingMessage(message);\n      this.#remoteWindow.postMessage(message, {\n        targetOrigin: originForSending,\n        ...(transferables === undefined ? {} : { transfer: transferables }),\n      });\n      return;\n    }\n\n    if (isAck2Message(message)) {\n      const { port1, port2 } = new MessageChannel();\n      this.#setPort(port1);\n      const transferablesToSend = [port2, ...(transferables || [])];\n      const originForSending = this.#getOriginForSendingMessage(message);\n\n      try {\n        this.#remoteWindow.postMessage(message, {\n          targetOrigin: originForSending,\n          transfer: transferablesToSend,\n        });\n      } catch (error) {\n        this.#destroyPort();\n        port2.close();\n        throw error;\n      }\n\n      return;\n    }\n\n    if (this.#port) {\n      this.#port.postMessage(message, {\n        ...(transferables === undefined ? {} : { transfer: transferables }),\n      });\n      return;\n    }\n\n    throw new PenpalError(\n      'TRANSMISSION_FAILED',\n      'Cannot send message because the MessagePort is not connected',\n    );\n  };\n\n  addMessageHandler = (callback: MessageHandler): void => {\n    this.#messageCallbacks.add(callback);\n  };\n\n  removeMessageHandler = (callback: MessageHandler): void => {\n    this.#messageCallbacks.delete(callback);\n  };\n\n  destroy = (): void => {\n    window.removeEventListener('message', this.#handleMessageFromRemoteWindow);\n    this.#destroyPort();\n    this.#messageCallbacks.clear();\n  };\n\n  #isAllowedOrigin = (origin: string) => {\n    return this.#allowedOrigins.some((allowedOrigin) => {\n      if (allowedOrigin instanceof RegExp) {\n        // RegExp.test() mutates lastIndex for global and sticky expressions,\n        // so test a copy to keep repeated handshake messages deterministic.\n        return new RegExp(allowedOrigin).test(origin);\n      }\n\n      return allowedOrigin === origin || allowedOrigin === '*';\n    });\n  };\n\n  #getOriginForSendingMessage = (message: Message) => {\n    // It's safe to send the SYN message to any origin because it doesn't contain\n    // anything sensitive. When Penpal receives a SYN message, the origin on\n    // the message (which we call the concrete origin) is validated against the\n    // configured allowed origins. All subsequent messages will be sent to the\n    // concrete origin.\n    // If you decide to change this, consider https://github.com/Aaronius/penpal/issues/103\n    if (isSynMessage(message)) {\n      return '*';\n    }\n\n    if (!this.#concreteRemoteOrigin) {\n      throw new PenpalError(\n        'TRANSMISSION_FAILED',\n        'Cannot send message because the remote origin is not established',\n      );\n    }\n\n    // If the concrete remote origin (the origin we received from the remote\n    // on a prior message) is 'null', it means the remote is within\n    // an \"opaque origin\". The only way to post a message to an\n    // opaque origin is by using '*'. This does carry some security risk,\n    // so we only do this if the consumer has specifically defined '*' as\n    // an allowed origin. Opaque origins occur, for example, when\n    // loading an HTML document directly from the filesystem (not a\n    // web server) or through a data URI.\n    return this.#concreteRemoteOrigin === 'null' &&\n      this.#allowedOrigins.includes('*')\n      ? '*'\n      : this.#concreteRemoteOrigin;\n  };\n\n  #destroyPort = () => {\n    this.#port?.removeEventListener('message', this.#handleMessageFromPort);\n    this.#port?.close();\n    this.#port = undefined;\n  };\n\n  #setPort = (port: MessagePort) => {\n    this.#destroyPort();\n    this.#port = port;\n    this.#port.addEventListener('message', this.#handleMessageFromPort);\n    this.#port.start();\n  };\n\n  #handleMessageFromRemoteWindow = ({\n    source,\n    origin,\n    ports,\n    data,\n  }: MessageEvent): void => {\n    if (source !== this.#remoteWindow) {\n      return;\n    }\n\n    if (!this.#validateReceivedMessage?.(data)) {\n      return;\n    }\n\n    if (!this.#isAllowedOrigin(origin)) {\n      this.#log?.(\n        `Received a message from origin \\`${origin}\\` which did not match ` +\n          `allowed origins \\`[${this.#allowedOrigins.join(', ')}]\\``,\n      );\n      return;\n    }\n\n    if (isSynMessage(data)) {\n      // If we receive a SYN message and already have a port, it means\n      // the child is re-connecting, in which case we'll receive a new port.\n      // For this reason, we always make sure we destroy the existing port.\n      this.#destroyPort();\n      this.#concreteRemoteOrigin = origin;\n    }\n\n    if (isAck2Message(data)) {\n      const port = ports[0];\n\n      if (!port) {\n        this.#log?.('Ignoring ACK2 because it did not include a MessagePort');\n        return;\n      }\n\n      this.#setPort(port);\n    }\n\n    for (const callback of this.#messageCallbacks) {\n      callback(data);\n    }\n  };\n\n  #handleMessageFromPort = ({ data }: MessageEvent): void => {\n    if (!this.#validateReceivedMessage?.(data)) {\n      return;\n    }\n\n    for (const callback of this.#messageCallbacks) {\n      callback(data);\n    }\n  };\n}\n\nexport default WindowMessenger;\n","import type { Log, Message } from '../types.js';\nimport type Messenger from './Messenger.js';\nimport type {\n  InitializeMessengerOptions,\n  MessageHandler,\n} from './Messenger.js';\nimport { isAck2Message, isAck1Message, isSynMessage } from '../guards.js';\nimport PenpalError from '../PenpalError.js';\n\n// Keep this structural so generated .d.ts files don't depend on\n// DedicatedWorkerGlobalScope being present in consumer tsconfig libs.\ntype WorkerLike = Pick<\n  Worker,\n  'postMessage' | 'addEventListener' | 'removeEventListener'\n>;\n\ntype Options = {\n  /**\n   * The web worker receiving/sending communication from/to the parent window.\n   * If this messenger is being used within the worker, `worker` should\n   * typically be set to `self`.\n   */\n  worker: WorkerLike;\n};\n\n/**\n * Handles the details of communicating with a child web worker.\n */\nclass WorkerMessenger implements Messenger {\n  #worker: WorkerLike;\n  #log: Log | undefined;\n  #validateReceivedMessage: ((data: unknown) => data is Message) | undefined;\n  #messageCallbacks = new Set<MessageHandler>();\n  #port: MessagePort | undefined;\n\n  constructor({ worker }: Options) {\n    if (!worker) {\n      throw new PenpalError('INVALID_ARGUMENT', 'worker must be defined');\n    }\n\n    this.#worker = worker;\n  }\n\n  initialize = ({\n    log,\n    validateReceivedMessage,\n  }: InitializeMessengerOptions): void => {\n    this.#log = log;\n    this.#validateReceivedMessage = validateReceivedMessage;\n    this.#worker.addEventListener('message', this.#handleMessage);\n  };\n\n  sendMessage = (message: Message, transferables?: Transferable[]): void => {\n    if (isSynMessage(message) || isAck1Message(message)) {\n      this.#worker.postMessage(message, {\n        ...(transferables === undefined ? {} : { transfer: transferables }),\n      });\n      return;\n    }\n\n    if (isAck2Message(message)) {\n      const { port1, port2 } = new MessageChannel();\n      this.#setPort(port1);\n\n      try {\n        this.#worker.postMessage(message, {\n          transfer: [port2, ...(transferables || [])],\n        });\n      } catch (error) {\n        this.#destroyPort();\n        port2.close();\n        throw error;\n      }\n\n      return;\n    }\n\n    if (this.#port) {\n      this.#port.postMessage(message, {\n        ...(transferables === undefined ? {} : { transfer: transferables }),\n      });\n      return;\n    }\n\n    throw new PenpalError(\n      'TRANSMISSION_FAILED',\n      'Cannot send message because the MessagePort is not connected',\n    );\n  };\n\n  addMessageHandler = (callback: MessageHandler): void => {\n    this.#messageCallbacks.add(callback);\n  };\n\n  removeMessageHandler = (callback: MessageHandler): void => {\n    this.#messageCallbacks.delete(callback);\n  };\n\n  destroy = (): void => {\n    this.#worker.removeEventListener('message', this.#handleMessage);\n    this.#destroyPort();\n    this.#messageCallbacks.clear();\n  };\n\n  #destroyPort = () => {\n    this.#port?.removeEventListener('message', this.#handleMessage);\n    this.#port?.close();\n    this.#port = undefined;\n  };\n\n  #setPort = (port: MessagePort) => {\n    this.#destroyPort();\n    this.#port = port;\n    this.#port.addEventListener('message', this.#handleMessage);\n    this.#port.start();\n  };\n\n  #handleMessage = ({ ports, data }: MessageEvent): void => {\n    if (!this.#validateReceivedMessage?.(data)) {\n      return;\n    }\n\n    if (isSynMessage(data)) {\n      // If we receive a SYN message and already have a port, it means\n      // the child is re-connecting, in which case we'll receive a new port.\n      // For this reason, we always make sure we destroy the existing port.\n      this.#destroyPort();\n    }\n\n    if (isAck2Message(data)) {\n      const port = ports[0];\n\n      if (!port) {\n        this.#log?.('Ignoring ACK2 because it did not include a MessagePort');\n        return;\n      }\n\n      this.#setPort(port);\n    }\n\n    for (const callback of this.#messageCallbacks) {\n      callback(data);\n    }\n  };\n}\n\nexport default WorkerMessenger;\n","import type { Message } from '../types.js';\nimport type Messenger from './Messenger.js';\nimport type {\n  InitializeMessengerOptions,\n  MessageHandler,\n} from './Messenger.js';\nimport PenpalError from '../PenpalError.js';\n\ntype Options = {\n  /**\n   * The port used to communicate to the other port of the port pair.\n   */\n  port: MessagePort;\n};\n\n/**\n * Handles the details of communicating on a MessagePort.\n */\nclass PortMessenger implements Messenger {\n  #port: MessagePort;\n  #validateReceivedMessage: ((data: unknown) => data is Message) | undefined;\n  #messageCallbacks = new Set<MessageHandler>();\n\n  constructor({ port }: Options) {\n    if (!port) {\n      throw new PenpalError('INVALID_ARGUMENT', 'port must be defined');\n    }\n\n    this.#port = port;\n  }\n\n  initialize = ({\n    validateReceivedMessage,\n  }: InitializeMessengerOptions): void => {\n    this.#validateReceivedMessage = validateReceivedMessage;\n    this.#port.addEventListener('message', this.#handleMessage);\n    this.#port.start();\n  };\n\n  sendMessage = (message: Message, transferables?: Transferable[]): void => {\n    this.#port?.postMessage(message, {\n      ...(transferables === undefined ? {} : { transfer: transferables }),\n    });\n  };\n\n  addMessageHandler = (callback: MessageHandler): void => {\n    this.#messageCallbacks.add(callback);\n  };\n\n  removeMessageHandler = (callback: MessageHandler): void => {\n    this.#messageCallbacks.delete(callback);\n  };\n\n  destroy = (): void => {\n    this.#port.removeEventListener('message', this.#handleMessage);\n    this.#port.close();\n    this.#messageCallbacks.clear();\n  };\n\n  #handleMessage = ({ data }: MessageEvent): void => {\n    if (!this.#validateReceivedMessage?.(data)) {\n      return;\n    }\n\n    for (const callback of this.#messageCallbacks) {\n      callback(data);\n    }\n  };\n}\n\nexport default PortMessenger;\n","// Not intended to be used internally. Can be useful externally\n// in projects not using TypeScript. It has the `Obj` suffix to disambiguate\n// it from the ErrorCode string union.\nconst ErrorCodeObj = {\n  ConnectionDestroyed: 'CONNECTION_DESTROYED',\n  ConnectionTimeout: 'CONNECTION_TIMEOUT',\n  InvalidArgument: 'INVALID_ARGUMENT',\n  MethodCallTimeout: 'METHOD_CALL_TIMEOUT',\n  MethodNotFound: 'METHOD_NOT_FOUND',\n  TransmissionFailed: 'TRANSMISSION_FAILED',\n} as const;\n\nexport default ErrorCodeObj;\n","import type { Log } from './types.js';\n\nconst debug = (prefix?: string): Log => {\n  return (...args: unknown[]) => {\n    console.log(`✍️ %c${prefix}%c`, 'font-weight: bold;', '', ...args);\n  };\n};\n\nexport default debug;\n"],"mappings":"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"}