import type { ITransportBackend } from './types';
/**
 * Options for MessageChannelTransportBackend.
 */
export interface IMessageChannelTransportBackendOptions {
    /**
     * The origin to use for postMessage calls and origin checks.
     * When not provided, the wildcard origin ('*') is used for the initial port transfer,
     * which means any origin can receive the port. For production use with cross-origin
     * iframes, always specify the expected origin to prevent port interception.
     */
    origin?: string;
    /**
     * A scope identifier used to namespace channel initialization messages,
     * allowing multiple independent channels on the same window.
     */
    scope?: string;
    /**
     * Whether this side should create the MessageChannel.
     * When true, creates a new MessageChannel and sends port2 to the target window.
     * When false, listens for an incoming channel initialization message.
     */
    shouldCreateChannel?: boolean;
    /**
     * The target window to send the initial channel port to.
     * Defaults to window.parent.
     */
    targetWindow?: Window;
}
/**
 * Implements message transport using the MessageChannel API.
 *
 * When shouldCreateChannel is true, a new MessageChannel is created and port2 is
 * transferred to the target window via postMessage. When false, the backend listens
 * for an incoming init_channel message carrying the port.
 *
 * Outgoing messages sent before the port is established (receiver side) are buffered and
 * flushed automatically once the handshake completes. Incoming messages are buffered
 * natively by the MessagePort until a receive callback is wired via setReceiveCallback,
 * since assigning onmessage implicitly starts the port.
 *
 * Re-handshake: on the receiver side the init_channel listener stays attached for the
 * lifetime of the backend. If the creator (e.g. an iframe) self-navigates or reloads
 * and posts a fresh init_channel, the receiver closes the previous (now-dead) port and
 * adopts the new one transparently. MessageChannel exposes no liveness signal, so this
 * "always re-adopt the latest matching port" policy is the only way to keep working
 * across in-creator reloads without cooperation from the creator side.
 */
export default class MessageChannelTransportBackend implements ITransportBackend {
    /**
     * The underlying MessageChannel instance used when this side creates the channel.
     */
    private channel?;
    /**
     * The expected origin for postMessage calls and origin validation.
     * When set, incoming messages from other origins are rejected.
     */
    private origin?;
    /**
     * Messages buffered before the port was established on the receiver side.
     * Flushed in order once the port becomes available.
     */
    private pendingMessages;
    /**
     * The MessagePort used for sending and receiving messages.
     */
    private port?;
    /**
     * A scope identifier used to namespace channel initialization messages.
     */
    private scope?;
    /**
     * Callback function for receiving messages. Undefined until setReceiveCallback is called;
     * while undefined the MessagePort remains unstarted and buffers incoming messages natively.
     */
    private receiveCallback?;
    /**
     * Creates a new MessageChannelTransportBackend instance.
     *
     * @param {IMessageChannelTransportBackendOptions} options - Configuration options for the transport backend.
     */
    constructor({ shouldCreateChannel, targetWindow, origin, scope }: IMessageChannelTransportBackendOptions);
    /**
     * Handles the initial postMessage event to receive the MessagePort from the channel creator.
     *
     * The listener remains attached for the lifetime of the backend so that if the creator
     * self-reloads (its previous document and port1 are gone, leaving the receiver with an
     * inert port2 that the platform never signals), a fresh init_channel can replace the
     * dead port without cooperation from the creator.
     *
     * @param {MessageEvent} event - The incoming message event.
     */
    private initialMessageHandler;
    /**
     * Forwards messages from the MessagePort to the current receive callback.
     *
     * @param {MessageEvent} event - The incoming port message event.
     */
    private handlePortMessage;
    /**
     * Flushes any messages that were buffered before the port was established.
     */
    private flushPendingMessages;
    /**
     * Disposes the allocated resources.
     *
     * @returns {void}
     */
    dispose(): void;
    /**
     * Sends the passed message. If the port has not yet been established (receiver side),
     * the message is buffered and will be sent once the handshake completes.
     *
     * @param {any} message - The message to be sent.
     * @param {Transferable[]} [transfer] - Optional array of transferable objects.
     * @returns {void}
     */
    send(message: any, transfer?: Transferable[]): void;
    /**
     * Sets the callback for receiving data. If the MessagePort is available and has not
     * yet been started, this also starts it (by assigning onmessage), flushing any messages
     * buffered natively by the port since the handshake completed.
     *
     * @param {Function} callback - The new callback.
     * @returns {void}
     */
    setReceiveCallback(callback: (message: any) => void): void;
}
