osra 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/connections/bidirectional.d.ts +20 -7
- package/build/connections/index.d.ts +1 -1
- package/build/connections/utils.d.ts +10 -3
- package/build/index.d.ts +15 -6
- package/build/index.js +591 -518
- package/build/index.js.map +1 -1
- package/build/revivables/abort-signal.d.ts +2 -5
- package/build/revivables/array-buffer.d.ts +6 -10
- package/build/revivables/bigint.d.ts +6 -11
- package/build/revivables/blob.d.ts +17 -0
- package/build/revivables/error.d.ts +8 -6
- package/build/revivables/event-target.d.ts +14 -25
- package/build/revivables/event.d.ts +15 -0
- package/build/revivables/fallbacks.d.ts +136 -0
- package/build/revivables/function.d.ts +3 -16
- package/build/revivables/identity.d.ts +8 -14
- package/build/revivables/index.d.ts +21 -1
- package/build/revivables/message-port.d.ts +6 -38
- package/build/revivables/symbol.d.ts +11 -0
- package/build/revivables/transfer.d.ts +4 -19
- package/build/revivables/utils.d.ts +10 -8
- package/build/types.d.ts +11 -5
- package/build/utils/gc-tracker.d.ts +19 -0
- package/build/utils/index.d.ts +1 -0
- package/build/utils/transferable.d.ts +6 -17
- package/build/utils/type-guards.d.ts +4 -4
- package/package.json +4 -3
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/types.ts","../src/utils/type-guards.ts","../src/utils/transport.ts","../src/revivables/utils.ts","../src/revivables/array-buffer.ts","../src/revivables/date.ts","../src/revivables/headers.ts","../src/revivables/error.ts","../src/revivables/typed-array.ts","../src/utils/event-channel.ts","../src/revivables/message-port.ts","../src/revivables/promise.ts","../src/revivables/function.ts","../src/revivables/readable-stream.ts","../src/revivables/abort-signal.ts","../src/revivables/response.ts","../src/revivables/request.ts","../src/revivables/identity.ts","../src/revivables/transfer.ts","../src/revivables/map.ts","../src/revivables/set.ts","../src/revivables/bigint.ts","../src/revivables/event-target.ts","../src/revivables/index.ts","../src/connections/bidirectional.ts","../src/utils/typed-event-target.ts","../src/utils/transferable.ts","../src/connections/utils.ts","../src/connections/index.ts","../src/index.ts"],"sourcesContent":["import type { ConnectionMessage } from './connections'\nimport type { TypedEventTarget } from './utils'\nimport type {\n DefaultRevivableModules, RevivableModule,\n InferMessages, InferRevivables\n} from './revivables'\n\nexport const OSRA_KEY = '__OSRA_KEY__' as const\nexport const OSRA_DEFAULT_KEY = '__OSRA_DEFAULT_KEY__' as const\nexport const OSRA_BOX = '__OSRA_BOX__' as const\n\nexport type Uuid = `${string}-${string}-${string}-${string}-${string}`\n\nexport type Jsonable =\n | boolean\n | null\n | number\n | string\n | { [key: string]: Jsonable }\n | Array<Jsonable>\n\nexport type Structurable =\n | Jsonable\n /** not really structureable but here for convenience */\n | void\n | undefined\n | bigint\n | Date\n | RegExp\n | Blob\n | File\n | FileList\n | ArrayBuffer\n | ArrayBufferView\n | ImageBitmap\n | ImageData\n | { [key: string]: Structurable }\n | Array<Structurable>\n | Map<Structurable, Structurable>\n | Set<Structurable>\n\nexport type StructurableTransferable =\n | Structurable\n | Transferable\n | { [key: string]: StructurableTransferable }\n | Array<StructurableTransferable>\n | Map<StructurableTransferable, StructurableTransferable>\n | Set<StructurableTransferable>\n\nexport type Capable<TModules extends readonly RevivableModule[] = DefaultRevivableModules> =\n | StructurableTransferable\n | InferRevivables<TModules>\n | { [key: string]: Capable<TModules> }\n | Array<Capable<TModules>>\n | Map<Capable<TModules>, Capable<TModules>>\n | Set<Capable<TModules>>\n\nexport type MessageFields = {\n type: string\n remoteUuid: Uuid\n}\n\nexport type MessageBase = {\n [OSRA_KEY]: string\n /** UUID of the client that sent the message */\n uuid: Uuid\n name?: string\n}\n\nexport type ProtocolMessage =\n | {\n type: 'announce'\n /** Only set when acknowledging a remote announcement */\n remoteUuid?: Uuid\n }\n | {\n type: 'close'\n remoteUuid: Uuid\n }\n\nexport type MessageVariant<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> =\n | ProtocolMessage\n | ConnectionMessage<TModules>\n | InferMessages<TModules>\n\nexport type Message<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> =\n & MessageBase\n & MessageVariant<TModules>\n\nexport type MessageEventMap<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n message: CustomEvent<Message<TModules>>\n}\n\nexport type MessageEventTarget<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n > = TypedEventTarget<MessageEventMap<TModules>>\n","import type { Runtime } from 'webextension-polyfill'\nimport type { Message } from '../types'\nimport type {\n CustomEmitTransport, CustomReceiveTransport,\n CustomTransport, EmitJsonPlatformTransport,\n EmitTransport, JsonPlatformTransport,\n ReceiveJsonPlatformTransport,\n ReceiveTransport, Transport\n} from './transport'\n\nimport { OSRA_KEY } from '../types'\nimport { getWebExtensionRuntime } from './transport'\n\nconst typedArrayConstructorsByName = {\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float16Array,\n Float32Array,\n Float64Array,\n BigInt64Array,\n BigUint64Array,\n} as const\n\nexport type TypedArrayType = keyof typeof typedArrayConstructorsByName\nexport type TypedArrayConstructor = (typeof typedArrayConstructorsByName)[TypedArrayType]\nexport type TypedArray = InstanceType<TypedArrayConstructor>\n\nconst typedArrayConstructors = Object.values(typedArrayConstructorsByName)\n\nexport const typedArrayToType = (value: TypedArray): TypedArrayType => {\n const name = value.constructor.name as TypedArrayType\n if (!(name in typedArrayConstructorsByName)) throw new Error('Unknown typed array type')\n return name\n}\n\nexport const typedArrayTypeToTypedArrayConstructor = (value: TypedArrayType): TypedArrayConstructor => {\n const ctor = typedArrayConstructorsByName[value]\n if (!ctor) throw new Error('Unknown typed array type')\n return ctor\n}\n\nexport const isTypedArray = (value: unknown): value is TypedArray =>\n typedArrayConstructors.some(ctor => value instanceof ctor)\nexport const isWebSocket = (value: unknown): value is WebSocket => value instanceof WebSocket\nexport const isServiceWorkerContainer = (value: unknown): value is ServiceWorkerContainer => !!globalThis.ServiceWorkerContainer && value instanceof ServiceWorkerContainer\nexport const isWorker = (value: unknown): value is Worker => !!globalThis.Worker && value instanceof Worker\n// @ts-expect-error DedicatedWorkerGlobalScope is only present in worker scopes\nexport const isDedicatedWorker = (value: unknown): value is DedicatedWorkerGlobalScope => !!globalThis.DedicatedWorkerGlobalScope && value instanceof DedicatedWorkerGlobalScope\nexport const isSharedWorker = (value: unknown): value is SharedWorker => !!globalThis.SharedWorker && value instanceof SharedWorker\nconst isMessagePort = (value: unknown): value is MessagePort => value instanceof MessagePort\n\nexport const isOsraMessage = (value: unknown): value is Message =>\n !!value\n && typeof value === 'object'\n && OSRA_KEY in value\n && !!value[OSRA_KEY]\n\ntype AnyConstructor = abstract new (...args: any[]) => unknown\n\n/** True if `value` is an instance of any of the given (possibly undefined-on-this-platform)\n * constructors. Tolerates missing globals so callers don't have to guard each one. */\nexport const instanceOfAny = (value: unknown, ctors: readonly (AnyConstructor | undefined)[]): boolean => {\n for (const ctor of ctors) if (ctor && value instanceof ctor) return true\n return false\n}\n\nexport const isClonable = (value: unknown): boolean =>\n instanceOfAny(value, [globalThis.SharedArrayBuffer])\n\nexport const isTransferable = (value: unknown): value is Transferable =>\n instanceOfAny(value, [\n globalThis.ArrayBuffer,\n globalThis.MessagePort,\n globalThis.ReadableStream,\n globalThis.WritableStream,\n globalThis.TransformStream,\n globalThis.ImageBitmap,\n ])\n\nexport type WebExtRuntime = typeof browser.runtime\nexport const isWebExtensionRuntime = (value: unknown): value is WebExtRuntime => {\n const runtime = getWebExtensionRuntime()\n if (!runtime) return false\n return value === runtime\n}\n\nexport type WebExtPort = ReturnType<WebExtRuntime['connect']> | Runtime.Port\nexport const isWebExtensionPort = (value: unknown, connectPort: boolean = false): value is WebExtPort => {\n if (!value || typeof value !== 'object') return false\n // Prevent SecurityError when `value` is a cross-origin window.\n if (isWindow(value)) return false\n if (!('name' in value) || !('disconnect' in value) || !('postMessage' in value)) return false\n // these properties are only present on WebExtPorts created through runtime.connect()\n if (!connectPort) return true\n return 'sender' in value && 'onMessage' in value && 'onDisconnect' in value\n}\n\nexport type WebExtSender = NonNullable<WebExtPort['sender']>\n\n// Structural guard for any `addListener` / `hasListener` / `removeListener` event.\n// Not enough on its own to tell onConnect from onMessage — they have identical shapes.\nconst hasListenerApi = (value: unknown): boolean =>\n !!value\n && typeof value === 'object'\n // Prevent SecurityError when `value` is a cross-origin window.\n && !isWindow(value)\n && 'addListener' in value\n && 'hasListener' in value\n && 'removeListener' in value\n\n// Identity-compare against the runtime's onConnect events: structural checks\n// can't distinguish onConnect from onMessage, and misclassifying onMessage as\n// onConnect makes us treat each incoming message as a port and crash on\n// `message.onMessage.addListener`.\nexport type WebExtOnConnect = WebExtRuntime['onConnect']\nexport const isWebExtensionOnConnect = (value: unknown): value is WebExtOnConnect => {\n const runtime = getWebExtensionRuntime()\n if (!runtime) return false\n return value === runtime.onConnect || value === runtime.onConnectExternal\n}\n\nexport type WebExtOnMessage = WebExtRuntime['onMessage']\nexport const isWebExtensionOnMessage = (value: unknown): value is WebExtOnMessage =>\n hasListenerApi(value)\n\nexport const isWindow = (value: unknown): value is Window => {\n if (!value || typeof value !== 'object') return false\n try {\n return 'window' in value && value.window === value\n } catch {\n // Cross-origin Window access can throw SecurityError; fall back to a\n // no-read shape probe that tolerates protected properties.\n try {\n return 'closed' in value\n && typeof value.closed === 'boolean'\n && 'close' in value\n && typeof value.close === 'function'\n } catch {\n return false\n }\n }\n}\n\nexport const isEmitJsonOnlyTransport = (value: unknown): value is EmitJsonPlatformTransport =>\n isWebSocket(value)\n || isWebExtensionPort(value)\n || isWebExtensionRuntime(value)\n\nexport const isReceiveJsonOnlyTransport = (value: unknown): value is ReceiveJsonPlatformTransport =>\n isWebSocket(value)\n || isWebExtensionPort(value)\n || isWebExtensionOnConnect(value)\n || isWebExtensionOnMessage(value)\n || isWebExtensionRuntime(value)\n\nexport type IsJsonOnlyTransport<T extends Transport> = T extends JsonPlatformTransport ? true : false\nexport const isJsonOnlyTransport = (value: unknown): value is Extract<Transport, JsonPlatformTransport> =>\n (!!value && typeof value === 'object' && 'isJson' in value && value.isJson === true)\n || isEmitJsonOnlyTransport(value)\n || isReceiveJsonOnlyTransport(value)\n\nexport const isEmitTransport = (value: unknown): value is EmitTransport =>\n isWindow(value)\n || isEmitJsonOnlyTransport(value)\n || isServiceWorkerContainer(value)\n || isWorker(value)\n || isDedicatedWorker(value)\n || isSharedWorker(value)\n || isMessagePort(value)\n || isCustomEmitTransport(value)\n\nexport function assertEmitTransport(transport: Transport): asserts transport is EmitTransport {\n if (!isEmitTransport(transport)) throw new Error('Transport is not emitable')\n}\n\nexport const isReceiveTransport = (value: unknown): value is ReceiveTransport =>\n isWindow(value)\n || isReceiveJsonOnlyTransport(value)\n || isServiceWorkerContainer(value)\n || isWorker(value)\n || isDedicatedWorker(value)\n || isSharedWorker(value)\n || isMessagePort(value)\n || isCustomReceiveTransport(value)\n\nexport function assertReceiveTransport(transport: Transport): asserts transport is ReceiveTransport {\n if (!isReceiveTransport(transport)) throw new Error('Transport is not receiveable')\n}\n\nexport const isCustomEmitTransport = (value: unknown): value is CustomEmitTransport => {\n if (!value || typeof value !== 'object') return false\n // Prevent SecurityError when `value` is a cross-origin window.\n if (isWindow(value)) return false\n if (!('emit' in value)) return false\n return isEmitTransport(value.emit) || typeof value.emit === 'function'\n}\n\nexport const isCustomReceiveTransport = (value: unknown): value is CustomReceiveTransport => {\n if (!value || typeof value !== 'object') return false\n // Prevent SecurityError when `value` is a cross-origin window.\n if (isWindow(value)) return false\n if (!('receive' in value)) return false\n return isReceiveTransport(value.receive) || typeof value.receive === 'function'\n}\n\nexport const isCustomTransport = (value: unknown): value is CustomTransport =>\n isCustomEmitTransport(value)\n || isCustomReceiveTransport(value)\n\nexport const isTransport = (value: unknown): value is Transport =>\n isEmitTransport(value)\n || isReceiveTransport(value)\n || isCustomTransport(value)\n || isJsonOnlyTransport(value)\n","import type { Message} from '../types'\nimport type {\n WebExtOnConnect, WebExtOnMessage,\n WebExtPort, WebExtRuntime, WebExtSender\n} from './type-guards'\n\nimport { OSRA_KEY } from '../types'\nimport {\n isOsraMessage, isCustomTransport,\n isWebExtensionOnConnect, isWebExtensionOnMessage,\n isWebExtensionPort, isWebExtensionRuntime, isWebSocket, isWindow, isSharedWorker\n} from './type-guards'\n\nexport type MessageContext = {\n port?: MessagePort | WebExtPort // WebExtension\n sender?: WebExtSender // WebExtension\n receiveTransport?: ReceivePlatformTransport\n source?: MessageEventSource | null // Window, Worker, WebSocket, ect...\n}\n\nexport type ReceiveHandler = (listener: (event: Message, messageContext: MessageContext) => void) => void\nexport type EmitHandler = (message: Message, transferables?: Transferable[]) => void\n\ntype CustomReceive = ReceivePlatformTransport | ReceiveHandler\ntype CustomEmit = EmitPlatformTransport | EmitHandler\n\nexport type CustomTransport =\n { isJson?: boolean }\n & (\n | { receive: CustomReceive, emit: CustomEmit }\n | { receive: CustomReceive }\n | { emit: CustomEmit }\n )\n\nexport type CustomEmitTransport = Extract<CustomTransport, { emit: any }>\nexport type CustomReceiveTransport = Extract<CustomTransport, { receive: any }>\n\nexport type EmitJsonPlatformTransport =\n | WebSocket\n | WebExtPort\n | WebExtRuntime\n\nexport type ReceiveJsonPlatformTransport =\n | WebSocket\n | WebExtPort\n | WebExtOnConnect\n | WebExtOnMessage\n | WebExtRuntime\n\nexport type JsonPlatformTransport =\n | { isJson: true }\n | EmitJsonPlatformTransport\n | ReceiveJsonPlatformTransport\n\ntype StructuredClonePlatformTransport =\n | Window\n | ServiceWorker\n | Worker\n | SharedWorker\n | MessagePort\n\nexport type EmitPlatformTransport =\n | EmitJsonPlatformTransport\n | StructuredClonePlatformTransport\n\nexport type ReceivePlatformTransport =\n | ReceiveJsonPlatformTransport\n | StructuredClonePlatformTransport\n\nexport type PlatformTransport =\n | EmitPlatformTransport\n | ReceivePlatformTransport\n\nexport type EmitTransport = EmitPlatformTransport & Extract<CustomTransport, { emit: any }>\nexport type ReceiveTransport = ReceivePlatformTransport & Extract<CustomTransport, { receive: any }>\n\nexport type Transport =\n | PlatformTransport\n | CustomTransport\n\nexport const getWebExtensionGlobal = () => globalThis.browser ?? globalThis.chrome\nexport const getWebExtensionRuntime = () => getWebExtensionGlobal()?.runtime\n\nexport const checkOsraMessageKey = (message: any, key: string): message is Message =>\n isOsraMessage(message)\n && message[OSRA_KEY] === key\n\nconst onAbort = (signal: AbortSignal | undefined, fn: () => void) =>\n signal?.addEventListener('abort', fn, { once: true })\n\nexport const registerOsraMessageListener = (\n { listener, transport, remoteName, key = OSRA_KEY, unregisterSignal }:\n {\n listener: (message: Message, messageContext: MessageContext) => void\n transport: ReceiveTransport\n remoteName?: string\n key?: string\n unregisterSignal?: AbortSignal\n }\n) => {\n const receiveTransport: Extract<CustomTransport, { receive: any }>['receive'] =\n isCustomTransport(transport) ? transport.receive : transport\n\n // Custom function handler\n if (typeof receiveTransport === 'function') {\n receiveTransport((message, ctx) => {\n if (!checkOsraMessageKey(message, key)) return\n if (remoteName && message.name !== remoteName) return\n listener(message, ctx)\n })\n return\n }\n\n // WebExtension family — subscribe to an `onMessage`-style listener API.\n if (\n isWebExtensionRuntime(receiveTransport)\n || isWebExtensionPort(receiveTransport)\n || isWebExtensionOnConnect(receiveTransport)\n || isWebExtensionOnMessage(receiveTransport)\n ) {\n const listenOnWebExtOnMessage = (onMessage: WebExtOnMessage, port?: WebExtPort) => {\n const _listener = (message: object, sender?: WebExtSender) => {\n if (!checkOsraMessageKey(message, key)) return\n if (remoteName && message.name !== remoteName) return\n listener(message, { port, sender })\n }\n onMessage.addListener(_listener)\n onAbort(unregisterSignal, () => onMessage.removeListener(_listener))\n }\n\n if (isWebExtensionRuntime(receiveTransport)) {\n listenOnWebExtOnMessage(receiveTransport.onMessage)\n } else if (isWebExtensionOnConnect(receiveTransport)) {\n // Port.onMessage has a narrower (message, port) shape than the shared\n // (message, sender) Runtime.onMessage — but our listener only reads\n // `message` so the runtime shape covers both.\n const _listener = (port: WebExtPort) =>\n listenOnWebExtOnMessage(port.onMessage as WebExtOnMessage, port)\n receiveTransport.addListener(_listener)\n onAbort(unregisterSignal, () => receiveTransport.removeListener(_listener))\n } else if (isWebExtensionOnMessage(receiveTransport)) {\n listenOnWebExtOnMessage(receiveTransport)\n } else { // WebExtPort\n listenOnWebExtOnMessage(receiveTransport.onMessage as WebExtOnMessage)\n }\n return\n }\n\n // Window, Worker, WebSocket, ServiceWorker, MessagePort, …\n const messageListener = (event: MessageEvent<Message>) => {\n if (!checkOsraMessageKey(event.data, key)) return\n if (remoteName && event.data.name !== remoteName) return\n listener(event.data, { receiveTransport, source: event.source })\n }\n receiveTransport.addEventListener('message', messageListener as EventListener)\n onAbort(unregisterSignal, () =>\n receiveTransport.removeEventListener('message', messageListener as EventListener),\n )\n}\n\nexport const sendOsraMessage = (\n transport: EmitTransport,\n message: Message,\n origin = '*',\n transferables: Transferable[] = []\n) => {\n const emitTransport: Extract<EmitTransport, { emit: any }>['emit'] =\n isCustomTransport(transport) ? transport.emit : transport\n\n if (typeof emitTransport === 'function') {\n emitTransport(message, transferables)\n } else if (isWindow(emitTransport)) {\n // Must be checked first: cross-origin windows throw on other property access.\n emitTransport.postMessage(message, origin, transferables)\n } else if (isWebExtensionPort(emitTransport)) {\n emitTransport.postMessage(message)\n } else if (isWebExtensionRuntime(emitTransport)) {\n emitTransport.sendMessage(message)\n } else if (isWebSocket(emitTransport)) {\n emitTransport.send(JSON.stringify(message))\n } else if (isSharedWorker(emitTransport)) {\n emitTransport.port.postMessage(message, transferables)\n } else { // MessagePort | ServiceWorker | Worker\n emitTransport.postMessage(message, transferables)\n }\n}\n","import type { DefaultRevivableModules, RevivableModule } from '.'\nimport type {\n MessageEventTarget,\n MessageFields,\n Uuid,\n} from '../types'\nimport type { Transport } from '../utils/transport'\nimport type { IsJsonOnlyTransport } from '../utils/type-guards'\n\nimport { OSRA_BOX } from '../types'\nimport { isJsonOnlyTransport } from '../utils/type-guards'\n\nexport type { UnderlyingType } from '../utils/type'\n\nexport const BoxBase = {\n [OSRA_BOX]: 'revivable',\n} as const\n\nexport type BoxBase<T extends string = string> =\n & typeof BoxBase\n & { type: T }\n\nexport type RevivableContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n transport: Transport\n remoteUuid: Uuid\n unregisterSignal?: AbortSignal\n /** Typed as a broad dispatcher so revivables can post their own message\n * variants without triggering contravariant function-parameter mismatches\n * across modules. The shape is enforced structurally via `MessageFields`. */\n sendMessage: (message: MessageFields & Record<string, unknown>) => void\n revivableModules: TModules\n eventTarget: MessageEventTarget<TModules>\n}\n\nexport type ExtractType<T> =\n T extends { isType: (value: unknown) => value is infer S }\n ? S\n : never\n\nexport type ExtractBox<T> =\n T extends { box: (...args: any[]) => infer B }\n ? B\n : never\n\nexport type ExtractMessages<T> =\n T extends { Messages?: infer B }\n ? B extends { type: string }\n ? string extends B['type'] ? never : B\n : never\n : never\n\nexport type InferMessages<TModules extends readonly unknown[]> =\n ExtractMessages<TModules[number]>\n\nexport type InferRevivables<TModules extends readonly unknown[]> =\n ExtractType<TModules[number]>\n\nexport type InferRevivableBox<TModules extends readonly unknown[]> =\n ExtractBox<TModules[number]>\n\nexport const isRevivableBox = (value: unknown): value is BoxBase =>\n !!value\n && typeof value === 'object'\n && OSRA_BOX in value\n && value[OSRA_BOX] === 'revivable'\n\n/** Stable string form for an unknown rejection value. Errors keep their stack;\n * everything else gets coerced via `String()`. Used wherever a Promise/Function\n * rejection has to cross the wire as a serialisable string. */\nexport const serializeError = (error: unknown): string =>\n error instanceof Error ? (error.stack ?? String(error)) : String(error)\n\n/** Wire shape for an ArrayBuffer carried by a JSON or clone transport. JSON\n * paths emit a base64 string (so the buffer survives JSON.stringify); clone\n * paths pass the buffer through structured-clone unchanged. */\nexport type BoxedBuffer<TCtx extends RevivableContext = RevivableContext> =\n IsJsonOnlyTransport<TCtx['transport']> extends true ? { base64Buffer: string }\n : IsJsonOnlyTransport<TCtx['transport']> extends false ? { arrayBuffer: ArrayBuffer }\n : { base64Buffer: string } | { arrayBuffer: ArrayBuffer }\n\nexport const boxBuffer = <TCtx extends RevivableContext>(\n buffer: ArrayBuffer,\n context: TCtx,\n): BoxedBuffer<TCtx> =>\n (isJsonOnlyTransport(context.transport)\n ? { base64Buffer: new Uint8Array(buffer).toBase64() }\n : { arrayBuffer: buffer }\n ) as BoxedBuffer<TCtx>\n\nexport const reviveBuffer = (boxed: { arrayBuffer: ArrayBuffer } | { base64Buffer: string }): ArrayBuffer =>\n 'arrayBuffer' in boxed\n ? boxed.arrayBuffer\n : Uint8Array.fromBase64(boxed.base64Buffer).buffer\n","import type { RevivableContext, UnderlyingType, BoxedBuffer } from './utils'\n\nimport { BoxBase, boxBuffer, reviveBuffer } from './utils'\n\nexport const type = 'arrayBuffer' as const\n\ntype BoxedArrayBuffer<T extends ArrayBuffer, T2 extends RevivableContext> =\n & typeof BoxBase\n & { type: typeof type }\n & BoxedBuffer<T2>\n & { [UnderlyingType]: T }\n\nexport const isType = (value: unknown): value is ArrayBuffer =>\n value instanceof ArrayBuffer\n\nexport const box = <T extends ArrayBuffer, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedArrayBuffer<T, T2> =>\n ({ ...BoxBase, type, ...boxBuffer(value, context) }) as unknown as BoxedArrayBuffer<T, T2>\n\nexport const revive = <T extends BoxedArrayBuffer<ArrayBuffer, RevivableContext>>(\n value: T,\n _context: RevivableContext,\n): T[UnderlyingType] =>\n reviveBuffer(value) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const boxed = box(new ArrayBuffer(10), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: ArrayBuffer = revived\n // @ts-expect-error - not an ArrayBuffer\n const notArrayBuffer: string = revived\n // @ts-expect-error - cannot box non-ArrayBuffer\n box('not an array buffer', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\n\nexport const type = 'date' as const\n\nexport const isType = (value: unknown): value is Date =>\n value instanceof Date\n\nexport const box = <T extends Date, T2 extends RevivableContext>(\n value: T,\n _context: T2\n) => ({\n ...BoxBase,\n type,\n ISOString: value.toISOString()\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n _context: T2\n): Date => {\n return new Date(value.ISOString)\n}\n\nconst typeCheck = () => {\n const boxed = box(new Date(), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Date = revived\n // @ts-expect-error - not a Date\n const notDate: string = revived\n // @ts-expect-error - cannot box non-Date\n box('not a date', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\n\nexport const type = 'headers' as const\n\nexport const isType = (value: unknown): value is Headers =>\n value instanceof Headers\n\nexport const box = <T extends Headers, T2 extends RevivableContext>(\n value: T,\n _context: T2\n) => ({\n ...BoxBase,\n type,\n entries: [...value.entries()]\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n _context: T2\n): Headers => {\n return new Headers(value.entries)\n}\n\nconst typeCheck = () => {\n const boxed = box(new Headers(), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Headers = revived\n // @ts-expect-error - not a Headers\n const notHeaders: string = revived\n // @ts-expect-error - cannot box non-Headers\n box('not a header', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\n\nexport const type = 'error' as const\n\nexport const isType = (value: unknown): value is Error =>\n value instanceof Error\n\nexport const box = <T extends Error, T2 extends RevivableContext>(\n value: T,\n _context: T2\n) => ({\n ...BoxBase,\n type,\n message: value.message,\n stack: value.stack || value.toString()\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n _context: T2\n) => new Error(value.message, { cause: value.stack })\n\nconst typeCheck = () => {\n const boxed = box(new Error('test'), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Error = revived\n // @ts-expect-error - not an Error\n const notError: string = revived\n // @ts-expect-error - cannot box non-Error\n box('not an error', {} as RevivableContext)\n}\n","import type { RevivableContext, UnderlyingType, BoxedBuffer } from './utils'\nimport type { TypedArray, TypedArrayType } from '../utils/type-guards'\n\nimport { BoxBase, boxBuffer, reviveBuffer } from './utils'\nimport {\n isTypedArray,\n typedArrayToType,\n typedArrayTypeToTypedArrayConstructor,\n} from '../utils/type-guards'\n\nexport const type = 'typedArray' as const\n\ntype BoxedTypedArray<T extends TypedArray, T2 extends RevivableContext> =\n & typeof BoxBase\n & { type: typeof type }\n & { typedArrayType: TypedArrayType }\n & BoxedBuffer<T2>\n & { [UnderlyingType]: T }\n\nexport const isType = isTypedArray\n\nexport const box = <T extends TypedArray, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedTypedArray<T, T2> =>\n ({\n ...BoxBase,\n type,\n typedArrayType: typedArrayToType(value),\n ...boxBuffer(value.buffer as ArrayBuffer, context),\n }) as unknown as BoxedTypedArray<T, T2>\n\nexport const revive = <T extends BoxedTypedArray<TypedArray, RevivableContext>>(\n value: T,\n _context: RevivableContext,\n): T[UnderlyingType] =>\n new (typedArrayTypeToTypedArrayConstructor(value.typedArrayType))(reviveBuffer(value)) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const uint8Boxed = box(new Uint8Array(10), {} as RevivableContext)\n const uint8Revived = revive(uint8Boxed, {} as RevivableContext)\n const expectedUint8: Uint8Array = uint8Revived\n // @ts-expect-error - wrong typed array type\n const wrongType: Int32Array = uint8Revived\n\n const float32Boxed = box(new Float32Array(10), {} as RevivableContext)\n const float32Revived = revive(float32Boxed, {} as RevivableContext)\n const expectedFloat32: Float32Array = float32Revived\n // @ts-expect-error - wrong typed array type\n const wrongFloat: Uint8Array = float32Revived\n\n // @ts-expect-error - cannot box non-TypedArray\n box('not a typed array', {} as RevivableContext)\n}\n","import type { TypedMessagePort, TypedMessagePortEventMap } from './typed-message-channel'\n\nexport class EventPort<T> extends EventTarget {\n addEventListener<K extends keyof TypedMessagePortEventMap<T> & string>(\n type: K,\n listener: ((event: TypedMessagePortEventMap<T>[K]) => void) | null,\n options?: boolean | AddEventListenerOptions\n ): void\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions\n ): void\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n super.addEventListener(type, listener, options)\n }\n\n removeEventListener<K extends keyof TypedMessagePortEventMap<T> & string>(\n type: K,\n listener: ((event: TypedMessagePortEventMap<T>[K]) => void) | null,\n options?: boolean | EventListenerOptions\n ): void\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void {\n super.removeEventListener(type, listener, options)\n }\n\n _peer: EventPort<any> | undefined\n _queue: MessageEvent<T>[] = []\n _started = false\n _closed = false\n _onClose: (() => void) | undefined\n\n private _onmessage: ((this: MessagePort, ev: MessageEvent<T>) => unknown) | null = null\n\n get onmessage(): ((this: MessagePort, ev: MessageEvent<T>) => unknown) | null {\n return this._onmessage\n }\n set onmessage(value: ((this: MessagePort, ev: MessageEvent<T>) => unknown) | null) {\n this._onmessage = value\n if (value !== null) this.start()\n }\n\n onmessageerror: ((this: MessagePort, ev: MessageEvent) => unknown) | null = null\n\n dispatchEvent(event: Event): boolean {\n if (event.type === 'message') {\n this._onmessage?.call(this, event as MessageEvent<T>)\n } else if (event.type === 'messageerror') {\n this.onmessageerror?.call(this, event as MessageEvent)\n }\n return super.dispatchEvent(event)\n }\n\n postMessage(message: T, _options?: Transferable[] | StructuredSerializeOptions): void {\n const peer = this._peer\n if (!peer || peer._closed) return\n queueMicrotask(() => {\n if (peer._closed) return\n const event = new MessageEvent('message', { data: message })\n if (peer._started) {\n peer.dispatchEvent(event)\n } else {\n peer._queue.push(event)\n }\n })\n }\n\n start(): void {\n if (this._started) return\n this._started = true\n for (const event of this._queue.splice(0)) {\n this.dispatchEvent(event)\n }\n }\n\n close(): void {\n if (this._closed) return\n this._closed = true\n this._queue.length = 0\n this._onClose?.()\n }\n}\n\nexport interface EventPort<T>\n extends Omit<\n TypedMessagePort<T>,\n 'addEventListener' | 'removeEventListener'\n > {}\n\nexport class EventChannel<T1 = unknown, T2 = unknown> {\n readonly port1: EventPort<T1>\n readonly port2: EventPort<T2>\n\n constructor() {\n const port1 = new EventPort<T1>()\n const port2 = new EventPort<T2>()\n port1._peer = port2\n port2._peer = port1\n this.port1 = port1\n this.port2 = port2\n }\n}\n","import type { Capable, StructurableTransferable, Uuid } from '../types'\nimport type { TypedMessagePort } from '../utils/typed-message-channel'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '../utils/type'\nimport type {\n BadFieldValue, BadFieldPath, BadFieldParent,\n ErrorMessage, BadValue, Path, ParentObject\n} from '../utils/capable-check'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\nimport { getTransferableObjects, isJsonOnlyTransport } from '../utils'\nimport { EventChannel, EventPort } from '../utils/event-channel'\n\n/**\n * FinalizationRegistry for automatically cleaning up ports when they are garbage collected.\n * In JSON-only mode we can't transfer ports on the wire, so we track them via\n * portId and tell the remote side to close when the local handle is collected.\n */\ntype PortCleanupInfo = {\n sendMessage: (message: Messages) => void\n remoteUuid: Uuid\n portId: Uuid\n cleanup: () => void\n}\n\nconst messagePortRegistry = new FinalizationRegistry<PortCleanupInfo>((info) => {\n // Send close message to remote side\n info.sendMessage({\n type: 'message-port-close',\n remoteUuid: info.remoteUuid,\n portId: info.portId\n })\n // Perform local cleanup\n info.cleanup()\n})\n\nexport const type = 'messagePort' as const\n\nexport type Messages =\n | {\n type: 'message'\n remoteUuid: Uuid\n data: Capable\n /** uuid of the messagePort that the message was sent through */\n portId: Uuid\n }\n | {\n type: 'message-port-close'\n remoteUuid: Uuid\n /** uuid of the messagePort that closed */\n portId: Uuid\n }\n\nexport declare const Messages: Messages\n\n/** Any port-shape the message-port revivable is happy to accept. Real\n * MessagePorts (from `new MessageChannel()`) and synthetic EventPorts\n * (from `new EventChannel()`) both flow through here. Messages can be any\n * Capable value — message-port boxes/revives as they cross the transport,\n * and the in-realm side uses pass-by-reference via EventChannel. */\nexport type AnyPort<T = Capable> =\n | TypedMessagePort<T>\n | EventPort<T>\n\nexport type BoxedMessagePort<T = Capable> =\n & BoxBaseType<typeof type>\n & (\n /** The origin was a synthetic EventPort — revive must reproduce an\n * EventPort on the other side so live (non-clonable) Promises/Functions\n * etc. can flow through by reference. */\n | { portId: Uuid, synthetic: true }\n /** The origin was a real MessagePort but the transport can't carry\n * ports (JSON-only) — revive produces a real MessagePort proxy so the\n * receiver sees it as if it had been transferred. Payloads must be\n * structured-clonable; live (non-clonable) values nested in a\n * user-level MessagePort aren't supported in this mode. */\n | { portId: Uuid, synthetic: false }\n /** The origin was a real MessagePort and the transport supports\n * structured clone — the port is transferred on the wire. When\n * `autoBox` is true, the revive side wraps it in a `ProtocolPort`\n * that auto-boxes outgoing / auto-revives incoming payloads so\n * live values (Promises/Functions) flow through unchanged. When\n * `autoBox` is absent/false, the receiver gets the raw MessagePort\n * with structured-clone semantics (used for user-owned ports). */\n | { port: AnyPort<T>, autoBox?: boolean }\n )\n & { [UnderlyingType]: TypedMessagePort<T> }\n\n// `[T] extends [Capable]` disables distributive conditionals so unions like\n// `A | B` give back `AnyPort<A | B>`, not `AnyPort<A> | AnyPort<B>`.\n// The error branch intersects with AnyPort<T> so the user's port-shaped keys\n// are present on the target — otherwise TS's excess-property check flags a\n// port key instead of reporting the failure against the whole argument.\ntype StructurableTransferablePort<T> = [T] extends [Capable]\n ? AnyPort<T>\n : AnyPort<T> & {\n [ErrorMessage]: 'Message type must extend Capable'\n [BadValue]: BadFieldValue<T, Capable>\n [Path]: BadFieldPath<T, Capable>\n [ParentObject]: BadFieldParent<T, Capable>\n }\n\n// -------------------------------------------------------------------------\n// Per-connection state\n//\n// The WeakMap ties per-connection message-port state to the connection's\n// RevivableContext — when the context is collected, the state goes with it.\n// State lives only here; no sibling revivable has to know about it.\n// -------------------------------------------------------------------------\n\ntype ConnectionMessagePortState = {\n /** Direct per-portId dispatch — O(1) lookup avoids the O(N) addEventListener\n * scan that was the bottleneck for tight-loop RPC traffic. */\n portHandlers: Map<string, (message: Messages) => void>\n}\n\nconst connectionStateMap = new WeakMap<RevivableContext, ConnectionMessagePortState>()\n\nconst getState = (context: RevivableContext): ConnectionMessagePortState => {\n const state = connectionStateMap.get(context)\n if (!state) {\n throw new Error('osra message-port: connection state missing; did init() run?')\n }\n return state\n}\n\n// -------------------------------------------------------------------------\n// init hook\n//\n// Called once per connection by the bidirectional connection bootstrap.\n// Sets up the per-connection port-handler map and installs the event-target\n// listener that routes incoming 'message' envelopes to the correct local\n// handler.\n// -------------------------------------------------------------------------\n\nexport const init = (context: RevivableContext): void => {\n const state: ConnectionMessagePortState = {\n portHandlers: new Map()\n }\n connectionStateMap.set(context, state)\n\n context.eventTarget.addEventListener('message', ({ detail }) => {\n if (detail.type !== 'message' && detail.type !== 'message-port-close') return\n state.portHandlers.get(detail.portId)?.(detail)\n })\n}\n\nexport const isType = (value: unknown): value is MessagePort | EventPort<StructurableTransferable> =>\n value instanceof MessagePort || value instanceof EventPort\n\nexport const box = <T, T2 extends RevivableContext = RevivableContext>(\n value: StructurableTransferablePort<T>,\n context: T2,\n options?: { autoBox?: boolean },\n): BoxedMessagePort<T> => {\n // Synthetic EventPorts are not structured-clonable, so even when the\n // transport supports cloning we have to route them via portId — otherwise\n // sending the wrapping message would crash with DataCloneError.\n const synthetic = value instanceof EventPort\n if (synthetic || isJsonOnlyTransport(context.transport)) {\n const { portHandlers } = getState(context)\n const liveRef: AnyPort<T> = value\n const portId: Uuid = globalThis.crypto.randomUUID()\n\n let cleanedUp = false\n const performCleanup = () => {\n if (cleanedUp) return\n cleanedUp = true\n portHandlers.delete(portId)\n messagePortRegistry.unregister(liveRef)\n liveRef.removeEventListener('message', messagePortListener as EventListener)\n }\n\n // Incoming: remote side wrote to its revived port — deliver the payload\n // on our local port after reviving it back into a live value.\n const handler = (message: Messages) => {\n if (message.type === 'message-port-close') {\n performCleanup()\n liveRef.close()\n return\n }\n const revivedData = recursiveRevive(message.data, context) as T\n liveRef.postMessage(revivedData, getTransferableObjects(revivedData))\n }\n\n // Outgoing: whatever was written into our side of the user's channel gets\n // boxed and shipped over the main transport.\n function messagePortListener({ data }: MessageEvent<Capable>) {\n context.sendMessage({\n type: 'message',\n remoteUuid: context.remoteUuid,\n data: recursiveBox(data, context),\n portId,\n })\n }\n\n // Register for automatic cleanup when garbage collected. Note the handler\n // (stored in portHandlers) holds `liveRef` strongly via closure, so GC\n // will only fire once the Map entry is deleted (in performCleanup).\n messagePortRegistry.register(liveRef, {\n sendMessage: context.sendMessage,\n remoteUuid: context.remoteUuid,\n portId,\n cleanup: performCleanup,\n }, liveRef)\n\n liveRef.addEventListener('message', messagePortListener as EventListener)\n liveRef.start()\n\n // For synthetic EventPorts, close() is how the owning side signals it's\n // done — wire it up so we tear down listeners and notify the remote.\n if (liveRef instanceof EventPort) {\n liveRef._onClose = () => {\n if (cleanedUp) return\n context.sendMessage({\n type: 'message-port-close',\n remoteUuid: context.remoteUuid,\n portId,\n })\n performCleanup()\n }\n }\n\n portHandlers.set(portId, handler)\n\n return { ...BoxBase, type, portId, synthetic } as BoxedMessagePort<T>\n }\n return {\n ...BoxBase,\n type,\n port: value,\n ...(options?.autoBox ? { autoBox: true } : {}),\n } as BoxedMessagePort<T>\n}\n\nexport const revive = <T extends Capable, T2 extends RevivableContext>(\n value: BoxedMessagePort<T>,\n context: T2,\n): TypedMessagePort<T> => {\n if ('port' in value) {\n // autoBox: box side was an internal protocol channel — wrap the\n // transferred MessagePort so outgoing/incoming payloads auto-box/revive\n // and live values (Promises/Functions) flow through unchanged.\n if (value.autoBox) {\n return createProtocolPort<T>(value.port as TypedMessagePort<Capable>, context)\n }\n return value.port\n }\n // portId path: origin was either a synthetic EventPort (pass-by-ref for\n // live values) or a real MessagePort we couldn't clone (JSON-only\n // transport). EventPorts must revive as EventPorts so that live values\n // pass through unchanged; MessagePorts must revive as MessagePorts so\n // the receiver sees the same shape they'd get from a real `transfer`.\n return reviveViaPortId<T>(value.portId, context, value.synthetic)\n}\n\n/**\n * Thin wrapper around a real MessagePort: auto-boxes outgoing messages and\n * auto-revives incoming ones. Lets revivables treat it like an EventTarget\n * (addEventListener / postMessage / start / close) that transparently\n * carries live values (Promises, Functions, …) over a clone-only transport.\n */\nconst createProtocolPort = <T>(\n port: TypedMessagePort<Capable>,\n ctx: RevivableContext,\n): TypedMessagePort<T> => {\n const target = new EventTarget() as TypedMessagePort<T>\n const onMessage = ({ data }: MessageEvent<Capable>): void => {\n target.dispatchEvent(new MessageEvent('message', {\n data: recursiveRevive(data, ctx),\n }))\n }\n port.addEventListener('message', onMessage)\n target.postMessage = (data: T, opt?: Transferable[] | StructuredSerializeOptions) => {\n const boxed = recursiveBox(data as Capable, ctx)\n const transferables = getTransferableObjects(boxed)\n const extra = Array.isArray(opt) ? opt : []\n port.postMessage(boxed, extra.length ? [...transferables, ...extra] : transferables)\n }\n target.start = () => port.start()\n target.close = () => {\n port.removeEventListener('message', onMessage)\n port.close()\n }\n return target\n}\n\n/**\n * Factory for revivable-internal channels. Returns a local port used by the\n * revivable and a pre-boxed remote port ready to embed in the revivable's\n * Boxed* structure. The local port auto-boxes/revives on clone transports\n * (via ProtocolPort over a MessageChannel) and passes by reference on JSON\n * transports (via EventChannel → portId routing).\n *\n * Revivables can post live values (Promises/Functions/…) on `localPort`\n * without caring about the transport mode.\n */\nexport const createRevivableChannel = <T extends Capable>(\n context: RevivableContext,\n): { localPort: AnyPort<T>, boxedRemote: BoxedMessagePort<T> } => {\n if (isJsonOnlyTransport(context.transport)) {\n const { port1, port2 } = new EventChannel<T, T>()\n return {\n localPort: port1,\n boxedRemote: box(port2 as StructurableTransferablePort<T>, context),\n }\n }\n const { port1, port2 } = new MessageChannel() as unknown as {\n port1: TypedMessagePort<Capable>\n port2: TypedMessagePort<Capable>\n }\n return {\n localPort: createProtocolPort<T>(port1, context) as unknown as AnyPort<T>,\n boxedRemote: box(port2 as unknown as StructurableTransferablePort<T>, context, { autoBox: true }),\n }\n}\n\n/**\n * Revive a port that was routed via portId. Covers both the synthetic\n * (EventChannel, pass-by-reference) and proxy (real MessageChannel,\n * structured-clone) paths — they share all cleanup/routing logic, only\n * differing in which channel type is instantiated, whether transferables\n * are listed on internal postMessage, and whether userPort exposes an\n * explicit close hook.\n */\nconst reviveViaPortId = <T extends Capable>(\n portId: Uuid,\n context: RevivableContext,\n synthetic: boolean,\n): TypedMessagePort<T> => {\n const { portHandlers } = getState(context)\n const { port1: userPort, port2: internalPort } =\n synthetic\n ? new EventChannel<T, T>()\n : new MessageChannel() as { port1: TypedMessagePort<T>, port2: TypedMessagePort<T> }\n const userPortRef = new WeakRef(userPort)\n\n let cleanedUp = false\n const performCleanup = () => {\n if (cleanedUp) return\n cleanedUp = true\n portHandlers.delete(portId)\n internalPort.removeEventListener('message', internalPortListener as EventListener)\n internalPort.close()\n const port = userPortRef.deref()\n if (port) messagePortRegistry.unregister(port)\n }\n\n const handler = (message: Messages) => {\n if (message.type === 'message-port-close') {\n performCleanup()\n userPortRef.deref()?.close()\n return\n }\n const port = userPortRef.deref()\n if (!port) {\n performCleanup()\n return\n }\n const revivedData = recursiveRevive(message.data, context) as T\n // Real MessagePorts need must-transfer items on the transfer list;\n // EventPorts pass by reference so no transferable list applies.\n if (synthetic) internalPort.postMessage(revivedData)\n else internalPort.postMessage(revivedData, getTransferableObjects(revivedData))\n }\n\n const internalPortListener = ({ data }: MessageEvent<T>) => {\n context.sendMessage({\n type: 'message',\n remoteUuid: context.remoteUuid,\n data: recursiveBox(data, context),\n portId,\n })\n }\n\n messagePortRegistry.register(userPort, {\n sendMessage: context.sendMessage,\n remoteUuid: context.remoteUuid,\n portId,\n cleanup: performCleanup,\n }, userPort)\n\n // EventPort exposes an explicit close hook — wire it so user.close() tears\n // down listeners locally and notifies the remote side. Real MessagePorts\n // have no equivalent; they rely on the FinalizationRegistry to notify.\n if (userPort instanceof EventPort) {\n userPort._onClose = () => {\n if (cleanedUp) return\n context.sendMessage({\n type: 'message-port-close',\n remoteUuid: context.remoteUuid,\n portId,\n })\n performCleanup()\n }\n }\n\n internalPort.addEventListener('message', internalPortListener as EventListener)\n internalPort.start()\n\n portHandlers.set(portId, handler)\n\n return userPort\n}\n\nconst typeCheck = () => {\n const port = {} as TypedMessagePort<{ foo: string }>\n const boxed = box(port, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: AnyPort<{ foo: string }> = revived\n // @ts-expect-error - wrong message type\n const wrongType: AnyPort<{ bar: number }> = revived\n // Promise-valued messages are fine now — EventChannel pass-by-reference\n // means we don't need StructurableTransferable here.\n box({} as TypedMessagePort<Promise<string>>, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '.'\nimport type {\n BadFieldValue, BadFieldPath, BadFieldParent,\n ErrorMessage, BadValue, Path, ParentObject\n} from '../utils/capable-check'\n\nimport { BoxBase, serializeError } from './utils'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort,\n BoxedMessagePort,\n AnyPort,\n} from './message-port'\n\nexport const type = 'promise' as const\n\nexport type Context =\n | { type: 'resolve', data: Capable }\n | { type: 'reject', error: string }\n\n// Error branches intersect with T so the user's own keys are present on the\n// target — otherwise TS's excess-property check flags the first user key\n// (e.g. `foo`) instead of reporting the failure against the whole argument.\ntype CapablePromise<T> = T extends Promise<infer U>\n ? U extends Capable\n ? T\n : T & {\n [ErrorMessage]: 'Value type must extend a Promise that resolves to a Capable'\n [BadValue]: BadFieldValue<U, Capable>\n [Path]: BadFieldPath<U, Capable>\n [ParentObject]: BadFieldParent<U, Capable>\n }\n : T & {\n [ErrorMessage]: 'Value type must extend a Promise that resolves to a Capable'\n [BadValue]: T\n [Path]: ''\n [ParentObject]: T\n }\n\ntype ExtractCapable<T> = T extends Promise<infer U>\n ? U extends Capable ? U : never\n : never\n\nconst isCapablePromise = <T, U extends Capable = ExtractCapable<T>>(value: T): value is T & Promise<U> =>\n value instanceof Promise\n\nexport type BoxedPromise<T extends Capable = Capable> =\n & BoxBaseType<typeof type>\n & { port: BoxedMessagePort<Context> }\n & { [UnderlyingType]: T }\n\n// Pins the revived port between executor return and result arrival. The\n// port↔listener cycle has no external anchor — the caller only holds the\n// returned Promise, which references its native resolvers, not the port.\n// Without this Set, GC under memory pressure can collect the cycle before\n// the result arrives and the Promise hangs forever. Mirrors the\n// inFlightReturnPorts pattern in function.ts.\nconst inFlightPromisePorts = new Set<AnyPort<Context>>()\n\nexport const isType = (value: unknown): value is Promise<any> =>\n value instanceof Promise\n\nexport const box = <T, T2 extends RevivableContext>(\n value: CapablePromise<T>,\n context: T2\n): BoxedPromise<ExtractCapable<T>> => {\n if (!isCapablePromise(value)) throw new TypeError('Expected Promise')\n const promise = value\n // Revivable-internal channel: localPort auto-boxes on send regardless of\n // transport (ProtocolPort over MessageChannel on clone, EventChannel +\n // portId on JSON). We just post the result and let it take care of boxing.\n const { localPort, boxedRemote } = createRevivableChannel<Context>(context)\n\n const sendResult = (result: Context) => {\n localPort.postMessage(result)\n localPort.close()\n }\n\n promise\n .then((data: ExtractCapable<T>) => sendResult({ type: 'resolve', data }))\n .catch((error: unknown) => sendResult({\n type: 'reject',\n error: serializeError(error),\n }))\n\n return { ...BoxBase, type, port: boxedRemote } as BoxedPromise<ExtractCapable<T>>\n}\n\nexport const revive = <T extends BoxedPromise, T2 extends RevivableContext>(\n value: T,\n context: T2\n) => {\n const port = reviveMessagePort(value.port, context)\n inFlightPromisePorts.add(port)\n return new Promise<T[UnderlyingType]>((resolve, reject) => {\n port.addEventListener('message', ({ data: result }) => {\n if (result.type === 'resolve') {\n resolve(result.data as T[UnderlyingType])\n } else {\n reject(result.error)\n }\n port.close()\n inFlightPromisePorts.delete(port)\n }, { once: true })\n port.start()\n })\n}\n\nconst typeCheck = () => {\n const boxed = box(Promise.resolve(1 as const), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Promise<1> = revived\n // @ts-expect-error\n const notExpected: Promise<string> = revived\n // @ts-expect-error\n box(1 as const, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { UnderlyingType, RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { TypedMessagePort } from '../utils/typed-message-channel'\nimport type { AnyPort } from './message-port'\n\nimport { BoxBase, serializeError } from './utils'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort,\n BoxedMessagePort,\n} from './message-port'\n\nexport const type = 'function' as const\n\ntype ResultMessage =\n | { __osra_ok__: true, value: Capable }\n | { __osra_err__: true, error: string }\n\ntype CallMessage = CallContext | { __osra_close__: true }\n\n// Per-call record so the FinalizationRegistry callback (and the synchronous\n// postMessage-failed path) can reject the right Promise and tear down the\n// matching return port. Each record is owned by a single in-flight call.\ntype CallRecord = {\n returnLocal: AnyPort<ResultMessage>\n reject: (error: unknown) => void\n}\n\n/**\n * FinalizationRegistry for automatically cleaning up function ports when the\n * revived function is garbage collected. Also rejects any in-flight calls that\n * were initiated through this function — without this, a caller that drops\n * `func` while awaiting its result would leak the return port and leave the\n * Promise hung forever.\n */\ntype FunctionCleanupInfo = {\n port: TypedMessagePort<CallMessage>\n inFlight: Set<CallRecord>\n}\n\nconst functionRegistry = new FinalizationRegistry<FunctionCleanupInfo>((info) => {\n try {\n info.port.postMessage({ __osra_close__: true })\n } catch { /* Port may already be closed */ }\n try {\n info.port.close()\n } catch { /* Port may already be closed */ }\n for (const { returnLocal, reject } of info.inFlight) {\n try { reject(new Error('osra function was garbage collected before result arrived')) } catch { /* listener gone */ }\n inFlightReturnPorts.delete(returnLocal)\n try { returnLocal.close() } catch { /* port may already be closed */ }\n }\n info.inFlight.clear()\n})\n\n// Pins caller-side return-value ports between send and result arriving. The\n// cycle (localPort↔listener↔remotePort) has no external anchor after the\n// Promise executor returns, so under memory pressure GC can collect it before\n// the result arrives — the Promise hangs forever. We remove the entries in\n// the once-listener and in every terminal-state cleanup path below.\nconst inFlightReturnPorts = new Set<AnyPort<any>>()\n\n/** Call-site payload (sent over the wire): the return port is pre-boxed by\n * createRevivableChannel; args are passed live and boxed by the channel. */\ntype SentCallContext = [BoxedMessagePort<ResultMessage>, Capable[]]\n\n/** Call-site payload as received by the callee, after box-side revival: the\n * return port is now a live AnyPort<ResultMessage> (ProtocolPort on clone,\n * EventPort on JSON); args are revived. */\nexport type CallContext = [AnyPort<ResultMessage>, Capable[]]\n\nexport type BoxedFunction<T extends (...args: any[]) => any = (...args: any[]) => any> =\n & BoxBaseType<typeof type>\n & { port: BoxedMessagePort<CallMessage> }\n & { [UnderlyingType]: (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>> }\n\ntype CapableFunction<T> = T extends (...args: infer P) => infer R\n ? P extends Capable[]\n ? R extends Capable ? T : never\n : never\n : never\n\nexport const isType = (value: unknown): value is (...args: any[]) => any =>\n typeof value === 'function'\n\nexport const box = <T extends (...args: any[]) => any, T2 extends RevivableContext>(\n value: T & CapableFunction<T>,\n context: T2\n): BoxedFunction<T> => {\n const { localPort, boxedRemote } = createRevivableChannel<CallMessage>(context)\n\n const cleanup = () => {\n localPort.close()\n }\n\n localPort.addEventListener('message', ({ data }) => {\n if (!Array.isArray(data)) {\n // __osra_close__ sentinel — only non-array message on this channel\n cleanup()\n return\n }\n const [returnPort, args] = data\n ;(async () => value(...(args as Parameters<T>)))()\n .then(\n (resolved) => {\n try {\n returnPort.postMessage({ __osra_ok__: true, value: resolved })\n } catch (postErr) {\n // Result wasn't clonable / boxable — surface as a remote error\n // instead of letting the caller hang waiting for a message that\n // can never be sent.\n try {\n returnPort.postMessage({\n __osra_err__: true,\n error: serializeError(postErr),\n })\n } catch { /* error itself failed to serialise; caller cleanup will reject */ }\n }\n },\n (error: unknown) => {\n try {\n returnPort.postMessage({\n __osra_err__: true,\n error: serializeError(error),\n })\n } catch { /* serialised error failed to post; caller cleanup will reject */ }\n },\n )\n .finally(() => {\n // Close after the message has flushed through the microtask queue so\n // the result actually dispatches before we tear the channel down.\n queueMicrotask(() => returnPort.close())\n })\n })\n localPort.start()\n\n return { ...BoxBase, type, port: boxedRemote } as BoxedFunction<T>\n}\n\nexport const revive = <T extends BoxedFunction, T2 extends RevivableContext>(\n value: T,\n context: T2\n): T[UnderlyingType] => {\n const port = reviveMessagePort(value.port, context)\n // Per-function bag of in-flight calls — captured by both the FinalizationRegistry\n // callback (rejects on func GC) and each call's once-listener (removes on settle).\n const inFlight = new Set<CallRecord>()\n\n const func = (...args: Capable[]) =>\n new Promise((resolve, reject) => {\n const { localPort: returnLocal, boxedRemote: returnBoxedRemote } =\n createRevivableChannel<ResultMessage>(context)\n // Pin ports to a module-level Set so GC can't collect the\n // port↔listener cycle while the call is in flight. Without this,\n // under memory pressure the listener (and thus `resolve`) can be\n // collected before the result arrives — the Promise hangs forever.\n inFlightReturnPorts.add(returnLocal)\n const record: CallRecord = { returnLocal, reject }\n inFlight.add(record)\n\n returnLocal.addEventListener('message', ({ data: result }) => {\n if ('__osra_ok__' in result) resolve(result.value)\n else reject(result.error)\n returnLocal.close()\n inFlightReturnPorts.delete(returnLocal)\n inFlight.delete(record)\n }, { once: true })\n returnLocal.start()\n\n // Boxing the args may throw synchronously (DataCloneError on a clone\n // transport, JSON cycle on a JSON transport). Without this catch, the\n // pin and the in-flight record would leak forever even though the\n // Promise itself rejects via the executor's implicit try/catch.\n try {\n port.postMessage([returnBoxedRemote, args] as SentCallContext as unknown as CallMessage)\n } catch (sendErr) {\n inFlightReturnPorts.delete(returnLocal)\n inFlight.delete(record)\n try { returnLocal.close() } catch { /* may already be closed */ }\n reject(sendErr)\n }\n })\n\n // Register the function for automatic cleanup when garbage collected. The\n // callback also rejects every in-flight call so abandoned awaits stop hanging.\n functionRegistry.register(func, { port, inFlight }, func)\n\n return func\n}\n\nconst typeCheck = () => {\n const boxed = box((a: number, b: string) => a + b.length, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: (a: number, b: string) => Promise<number> = revived\n // @ts-expect-error - wrong return type\n const wrongReturn: (a: number, b: string) => Promise<string> = revived\n // @ts-expect-error - wrong parameter types\n const wrongParams: (a: string, b: number) => Promise<number> = revived\n // @ts-expect-error - non-Capable parameter type (Set is not directly Capable as parameter)\n box((a: WeakMap<object, string>) => a, {} as RevivableContext)\n // @ts-expect-error - non-Capable return type\n box(() => new WeakMap(), {} as RevivableContext)\n}\n","import type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '.'\n\nimport { BoxBase } from './utils'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort,\n BoxedMessagePort\n} from './message-port'\n\nexport const type = 'readableStream' as const\n\nexport type PullContext = {\n type: 'pull' | 'cancel'\n}\n\ntype ChunkMessage<T = unknown> = Promise<ReadableStreamReadResult<T>>\n\ntype Msg = PullContext | ChunkMessage\n\nexport type BoxedReadableStream<T extends ReadableStream = ReadableStream> =\n & BoxBaseType<typeof type>\n & { port: BoxedMessagePort<Msg> }\n & { [UnderlyingType]: T }\n\nexport const isType = (value: unknown): value is ReadableStream =>\n value instanceof ReadableStream\n\nexport const box = <T extends ReadableStream, T2 extends RevivableContext>(\n value: T,\n context: T2\n): BoxedReadableStream<T> => {\n const { localPort, boxedRemote } = createRevivableChannel<Msg>(context)\n const reader = value.getReader()\n\n localPort.addEventListener('message', ({ data }) => {\n if ('type' in data && data.type === 'pull') {\n // reader.read() is a Promise — posting it live works because localPort\n // (ProtocolPort or EventPort) boxes it internally for the transport.\n localPort.postMessage(reader.read())\n } else {\n reader.cancel()\n localPort.close()\n }\n })\n localPort.start()\n\n return { ...BoxBase, type, port: boxedRemote } as BoxedReadableStream<T>\n}\n\nexport const revive = <T extends BoxedReadableStream, T2 extends RevivableContext>(\n value: T,\n context: T2\n): T[UnderlyingType] => {\n const port = reviveMessagePort(value.port, context)\n port.start()\n\n return new ReadableStream({\n pull: (controller) => new Promise<void>((resolve, reject) => {\n port.addEventListener('message', ({ data }) => {\n if (!(data instanceof Promise)) return\n data\n .then(result => {\n if (result.done) controller.close()\n else controller.enqueue(result.value)\n resolve()\n })\n .catch(reject)\n }, { once: true })\n port.postMessage({ type: 'pull' })\n }),\n cancel: () => {\n port.postMessage({ type: 'cancel' })\n // Defer close so the cancel message dispatches before tear-down — same\n // pattern function.ts uses for return-port cleanup.\n queueMicrotask(() => port.close())\n },\n }) as T[UnderlyingType]\n}\n\nconst typeCheck = () => {\n const stream = new ReadableStream<number>()\n const boxed = box(stream, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: ReadableStream<number> = revived\n // @ts-expect-error - wrong stream type\n const wrongType: ReadableStream<string> = revived\n // @ts-expect-error - not a ReadableStream\n box('not a stream', {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '../utils/type'\nimport type { BoxedMessagePort } from './message-port'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort\n} from './message-port'\n\nexport const type = 'abortSignal' as const\n\ntype AbortMessage = {\n type: 'abort'\n reason?: Capable\n}\n\nexport type BoxedAbortSignal<T extends AbortSignal = AbortSignal> =\n & BoxBaseType<typeof type>\n & {\n aborted: boolean\n reason?: Capable\n port: BoxedMessagePort<AbortMessage>\n }\n & { [UnderlyingType]: T }\n\nexport const isType = (value: unknown): value is AbortSignal =>\n value instanceof AbortSignal\n\nexport const box = <T extends AbortSignal, T2 extends RevivableContext>(\n value: T,\n context: T2\n): BoxedAbortSignal<T> => {\n const { localPort, boxedRemote } = createRevivableChannel<AbortMessage>(context)\n\n if (!value.aborted) {\n value.addEventListener('abort', () => {\n localPort.postMessage({ type: 'abort', reason: value.reason as Capable })\n localPort.close()\n }, { once: true })\n } else {\n localPort.close()\n }\n\n // Eagerly-aborted reason rides the wrapper instead of the channel, so it\n // has to go through recursiveBox here — the outer recursiveBox will see\n // OSRA_BOX on this object and short-circuit before descending into `reason`.\n // Without this, a reason carrying live values (Function/Promise/EventTarget/…)\n // throws DataCloneError on clone transports and silently loses fields on\n // JSON transports.\n return {\n ...BoxBase,\n type,\n aborted: value.aborted,\n reason: value.aborted ? recursiveBox(value.reason as Capable, context) as Capable : undefined,\n port: boxedRemote,\n } as BoxedAbortSignal<T>\n}\n\nexport const revive = <T extends BoxedAbortSignal, T2 extends RevivableContext>(\n value: T,\n context: T2\n): AbortSignal => {\n const controller = new AbortController()\n\n if (value.aborted) {\n controller.abort(recursiveRevive(value.reason as Capable, context))\n return controller.signal\n }\n\n const port = reviveMessagePort(value.port, context)\n port.start()\n\n port.addEventListener('message', ({ data: message }) => {\n if (message.type === 'abort') {\n controller.abort(recursiveRevive(message.reason as Capable, context))\n port.close()\n }\n })\n\n return controller.signal\n}\n\nconst typeCheck = () => {\n const boxed = box(new AbortController().signal, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: AbortSignal = revived\n // @ts-expect-error - not an AbortSignal\n const notAbortSignal: string = revived\n // @ts-expect-error - cannot box non-AbortSignal\n box('not an abort signal', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\nimport { box as boxHeaders, revive as reviveHeaders } from './headers'\nimport { box as boxReadableStream, revive as reviveReadableStream } from './readable-stream'\n\nexport const type = 'response' as const\n\nexport const isType = (value: unknown): value is Response =>\n value instanceof Response\n\nexport const box = <T extends Response, T2 extends RevivableContext>(\n value: T,\n context: T2\n) => ({\n ...BoxBase,\n type,\n status: value.status,\n statusText: value.statusText,\n headers: boxHeaders(value.headers, context),\n body: value.body ? boxReadableStream(value.body, context) : null,\n url: value.url,\n redirected: value.redirected\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n context: T2\n): Response => {\n const headers = reviveHeaders(value.headers, context)\n const body = value.body ? reviveReadableStream(value.body, context) : null\n\n return new Response(body, {\n status: value.status,\n statusText: value.statusText,\n headers\n })\n}\n\nconst typeCheck = () => {\n const boxed = box(new Response('body', { status: 200 }), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Response = revived\n // @ts-expect-error - not a Response\n const notResponse: string = revived\n // @ts-expect-error - cannot box non-Response\n box('not a response', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\nimport { box as boxHeaders, revive as reviveHeaders } from './headers'\nimport { box as boxReadableStream, revive as reviveReadableStream } from './readable-stream'\n\nexport const type = 'request' as const\n\nexport const isType = (value: unknown): value is Request =>\n value instanceof Request\n\nexport const box = <T extends Request, T2 extends RevivableContext>(\n value: T,\n context: T2\n) => ({\n ...BoxBase,\n type,\n method: value.method,\n url: value.url,\n headers: boxHeaders(value.headers, context),\n body: value.body ? boxReadableStream(value.body, context) : null,\n credentials: value.credentials,\n cache: value.cache,\n redirect: value.redirect,\n referrer: value.referrer,\n referrerPolicy: value.referrerPolicy,\n integrity: value.integrity,\n keepalive: value.keepalive\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n context: T2\n): Request => {\n const headers = reviveHeaders(value.headers, context)\n const body = value.body ? reviveReadableStream(value.body, context) : null\n\n return new Request(value.url, {\n method: value.method,\n headers,\n body,\n credentials: value.credentials,\n cache: value.cache,\n redirect: value.redirect,\n referrer: value.referrer,\n referrerPolicy: value.referrerPolicy,\n integrity: value.integrity,\n keepalive: value.keepalive,\n // @ts-expect-error - duplex is needed for streaming bodies\n duplex: 'half',\n })\n}\n\nconst typeCheck = () => {\n const boxed = box(new Request('https://example.com'), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Request = revived\n // @ts-expect-error - not a Request\n const notRequest: string = revived\n // @ts-expect-error - cannot box non-Request\n box('not a request', {} as RevivableContext)\n}\n","import type { Capable, Message, Uuid } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '../utils/type'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'identity' as const\n\nexport type Messages = {\n type: 'identity-dispose'\n remoteUuid: Uuid\n /** id of the identity-wrapped value that was collected */\n id: string\n}\n\nexport declare const Messages: Messages\n\nconst IDENTITY_MARKER: unique symbol = Symbol.for('osra.identity')\n\ntype IdentityWrapper<T = unknown> = {\n readonly [IDENTITY_MARKER]: true\n readonly value: T\n}\n\nexport type BoxedIdentity<T extends Capable = Capable> = BoxBaseType<typeof type> & {\n id: string\n inner?: Capable\n [UnderlyingType]: T\n}\n\nconst isObjectOrFunction = (value: unknown): value is object =>\n value !== null && (typeof value === 'object' || typeof value === 'function')\n\nconst isIdentityWrapper = (value: unknown): value is IdentityWrapper =>\n isObjectOrFunction(value) && IDENTITY_MARKER in value && value[IDENTITY_MARKER] === true\n\nconst wrapperMemo = new WeakMap<object, IdentityWrapper>()\n\nconst wrap = (value: object): IdentityWrapper => {\n if (isIdentityWrapper(value)) return value\n const cached = wrapperMemo.get(value)\n if (cached) return cached\n const wrapper: IdentityWrapper = { [IDENTITY_MARKER]: true, value }\n wrapperMemo.set(value, wrapper)\n return wrapper\n}\n\n/**\n * Wrap a value so that osra preserves its reference identity across the\n * RPC boundary, per connection. Calling identity(X) twice on the same\n * value produces the same wrapper, and both wrapper sends resolve to the\n * same revived reference on the remote side.\n *\n * - Primitives pass through unchanged (there is no identity to preserve).\n * - Already-wrapped values pass through unchanged (idempotent).\n *\n * NOTE: This lies at the type level — the runtime value for object/function\n * inputs is an IdentityWrapper<T>, typed as T so the user's surrounding\n * code stays unchanged. The box-site unwraps it.\n */\nexport const identity = <T>(value: T): T =>\n (isObjectOrFunction(value) ? wrap(value) : value) as T\n\n/**\n * Per-connection state for the identity revivable. Stored in a module-level\n * WeakMap so the connection's RevivableContext acts as the key — when the\n * connection ends and the context is collected, the state goes with it.\n */\ntype IdentityState = {\n /** Send side: inner value → stable id for this connection. */\n readonly sendIds: WeakMap<object, string>\n /** Send side: id → weak ref to the value we originally sent. Lets a later\n * receive of our own id (round-trip: we sent, the peer sent it back)\n * resolve to the original reference instead of building a fresh proxy. */\n readonly idToSent: Map<string, WeakRef<object>>\n /** Send side: FinalizationRegistry firing when an inner value is GC'd. */\n readonly sendRegistry: FinalizationRegistry<string>\n /** Receive side: id → revived value (strong ref, explicit cleanup). */\n readonly receiveCache: Map<string, unknown>\n /** Receive side: revived value → id. Lets us detect when user code passes\n * a revived value back to its origin, so we can replay the original id\n * and the origin's revive can short-circuit to the real reference. */\n readonly revivedToId: WeakMap<object, string>\n /** True once the eventTarget listener has been installed. */\n listenerInstalled: boolean\n}\n\nconst connectionStates = new WeakMap<RevivableContext, IdentityState>()\n\nconst getOrCreateState = (context: RevivableContext): IdentityState => {\n const existing = connectionStates.get(context)\n if (existing) return existing\n // Construct the maps as locals first so the FinalizationRegistry callback\n // can close over them without a forward reference to `state` itself.\n const sendIds = new WeakMap<object, string>()\n const idToSent = new Map<string, WeakRef<object>>()\n const receiveCache = new Map<string, unknown>()\n const revivedToId = new WeakMap<object, string>()\n const sendRegistry = new FinalizationRegistry<string>((id) => {\n // Sender-side inner value was collected. Drop our send-side id record\n // (the WeakRef is already dead; keeping it would leak Map entries) and\n // tell the receiver to drop its cached revived value so both sides\n // converge. If the transport has already been torn down, swallow.\n idToSent.delete(id)\n try {\n context.sendMessage({\n type: 'identity-dispose',\n remoteUuid: context.remoteUuid,\n id,\n })\n } catch { /* connection already closed */ }\n })\n const state: IdentityState = {\n sendIds,\n idToSent,\n sendRegistry,\n receiveCache,\n revivedToId,\n listenerInstalled: false,\n }\n connectionStates.set(context, state)\n installReceiveListener(context, state)\n return state\n}\n\nconst installReceiveListener = (context: RevivableContext, state: IdentityState) => {\n if (state.listenerInstalled) return\n state.listenerInstalled = true\n context.eventTarget.addEventListener('message', ({ detail }) => {\n if (detail?.type === 'identity-dispose') {\n const revived = state.receiveCache.get(detail.id)\n state.receiveCache.delete(detail.id)\n if (revived !== undefined && isObjectOrFunction(revived)) {\n state.revivedToId.delete(revived)\n }\n }\n })\n}\n\nexport const isType = (value: unknown): value is IdentityWrapper =>\n isIdentityWrapper(value)\n\nexport const box = <T extends Capable, TContext extends RevivableContext>(\n wrapper: IdentityWrapper<T>,\n context: TContext,\n): BoxedIdentity<T> => {\n const state = getOrCreateState(context)\n const inner = wrapper.value\n const key = isObjectOrFunction(inner) ? inner : undefined\n if (key !== undefined) {\n const existingId = state.sendIds.get(key)\n if (existingId !== undefined) {\n // Subsequent send for this value on this connection: skip the inner\n // box entirely so the receiver resolves through its cache.\n return {\n ...BoxBase,\n type,\n id: existingId,\n } as BoxedIdentity<T>\n }\n const receivedId = state.revivedToId.get(key)\n if (receivedId !== undefined) {\n // Round-trip: user is handing us a value we originally revived from\n // the peer on this connection. Replay the peer's id so the peer's\n // revive resolves to its original reference (the one it first sent).\n return {\n ...BoxBase,\n type,\n id: receivedId,\n } as BoxedIdentity<T>\n }\n }\n const id = globalThis.crypto.randomUUID()\n const innerBox = recursiveBox(inner, context)\n if (key !== undefined) {\n state.sendIds.set(key, id)\n state.idToSent.set(id, new WeakRef(key))\n state.sendRegistry.register(key, id)\n }\n return {\n ...BoxBase,\n type,\n id,\n inner: innerBox,\n } as BoxedIdentity<T>\n}\n\nexport const revive = <T extends BoxedIdentity, TContext extends RevivableContext>(\n value: T,\n context: TContext,\n): T[UnderlyingType] => {\n const state = getOrCreateState(context)\n const cached = state.receiveCache.get(value.id)\n if (cached !== undefined) return cached as T[UnderlyingType]\n // The id may be one we originally sent — the peer is handing it back\n // (directly, or after arbitrary forwarding). Resolve to the original\n // reference instead of building a fresh proxy on top of one.\n const originated = state.idToSent.get(value.id)?.deref()\n if (originated !== undefined) return originated as T[UnderlyingType]\n if (!('inner' in value) || value.inner === undefined) {\n throw new Error(\n `osra identity: received id=${value.id} with no inner payload and no cached value`,\n )\n }\n const revived = recursiveRevive(value.inner, context)\n state.receiveCache.set(value.id, revived)\n if (isObjectOrFunction(revived)) {\n state.revivedToId.set(revived, value.id)\n }\n return revived as T[UnderlyingType]\n}\n\nconst typeCheck = () => {\n const fn = () => 42\n const wrapper = { [IDENTITY_MARKER]: true, value: fn } as IdentityWrapper<typeof fn>\n const boxed = box(wrapper, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n // Revive recovers the original function type via the UnderlyingType phantom.\n const expected: typeof fn = revived\n // @ts-expect-error - revived is the original function type, not string\n const notExpected: string = revived\n // @ts-expect-error - cannot box a non-Capable wrapper (Symbol not assignable)\n box({ [IDENTITY_MARKER]: true, value: Symbol() } as IdentityWrapper<symbol>, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { BoxBase as BoxBaseType, RevivableContext, UnderlyingType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { instanceOfAny, isJsonOnlyTransport } from '../utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'transfer' as const\n\nconst TRANSFER_MARKER: unique symbol = Symbol.for('osra.transfer')\n\ntype TransferWrapper<T = unknown> = {\n readonly [TRANSFER_MARKER]: true\n readonly value: T\n}\n\nexport type BoxedTransfer<T extends Capable = Capable> = BoxBaseType<typeof type> & {\n inner: Capable\n degraded: boolean\n [UnderlyingType]: T\n}\n\nconst isObject = (value: unknown): value is object =>\n value !== null && typeof value === 'object'\n\nconst isTransferWrapper = (value: unknown): value is TransferWrapper =>\n isObject(value) && TRANSFER_MARKER in value && value[TRANSFER_MARKER] === true\n\n// The set of types `transfer()` accepts. Anything else — primitives, nullish,\n// plain objects, Dates, Errors, Promises, etc. — is returned unchanged so\n// normal payloads don't blow up if someone wraps the wrong thing.\nconst isWrappableTransferable = (value: unknown): boolean => {\n if (!isObject(value)) return false\n if (ArrayBuffer.isView(value)) return true\n return instanceOfAny(value, [\n globalThis.ArrayBuffer,\n globalThis.MessagePort,\n globalThis.ReadableStream,\n globalThis.WritableStream,\n globalThis.TransformStream,\n globalThis.ImageBitmap,\n globalThis.OffscreenCanvas,\n ])\n}\n\n/**\n * Opt into transfer semantics for a transferable value. Without this wrapper\n * osra sends transferables as structured clones (copies) — the sender-side\n * reference stays usable after the RPC. Wrapping hands the underlying storage\n * off to the receiver and neuters the sender-side reference, matching what\n * you'd get by listing it in the transfer list of `postMessage(msg, [buf])`.\n *\n * - Primitives, null, undefined, plain objects, Promises, Dates, etc. are\n * returned unchanged.\n * - Typed array views (`Uint8Array`, `DataView`, …) are accepted as a\n * convenience — their underlying `.buffer` is what actually gets moved.\n * - `transfer(transfer(x))` returns the same wrapper as `transfer(x)`.\n * - If the current platform cannot transfer the given type, the wrapper\n * silently degrades to a copy — nothing throws.\n *\n * NOTE: This lies at the type level — the runtime value for transferable\n * inputs is a TransferWrapper<T>, typed as T so the user's surrounding\n * code stays unchanged. The box-site unwraps it.\n */\nexport const transfer = <T>(value: T): T =>\n (isWrappableTransferable(value)\n ? { [TRANSFER_MARKER]: true, value }\n : value\n ) as T\n\n// -------------------------------------------------------------------------\n// Revivable module interface\n// -------------------------------------------------------------------------\n\nexport const isType = (value: unknown): value is TransferWrapper =>\n isTransferWrapper(value)\n\nexport const box = <T extends Capable, TContext extends RevivableContext>(\n wrapper: TransferWrapper<T>,\n context: TContext,\n): BoxedTransfer<T> => {\n const inner = wrapper.value\n const innerBoxed = recursiveBox(inner, context)\n // The `degraded` flag carries the transport mode to the send-time walker\n // in getTransferableObjects. When true, the walker treats this box as if\n // it weren't a transfer box at all — no mode flip, no transferables on\n // the transfer list — and the wrapper silently degrades to a copy. JSON\n // transports can't move ownership over the wire, so transfer semantics\n // don't apply and we degrade.\n return {\n ...BoxBase,\n type,\n inner: innerBoxed,\n degraded: isJsonOnlyTransport(context.transport),\n } as BoxedTransfer<T>\n}\n\nexport const revive = <T extends BoxedTransfer, TContext extends RevivableContext>(\n value: T,\n context: TContext,\n): T[UnderlyingType] =>\n recursiveRevive(value.inner, context) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const ab = new ArrayBuffer(10)\n const wrapper = { [TRANSFER_MARKER]: true, value: ab } as TransferWrapper<ArrayBuffer>\n const boxed = box(wrapper, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n // Revive recovers the original ArrayBuffer type via the UnderlyingType phantom.\n const expected: ArrayBuffer = revived\n // @ts-expect-error - revived is ArrayBuffer, not string\n const notExpected: string = revived\n // @ts-expect-error - cannot box a non-Capable wrapper (Symbol not assignable)\n box({ [TRANSFER_MARKER]: true, value: Symbol() } as TransferWrapper<symbol>, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, UnderlyingType, BoxBase as BoxBaseType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'map' as const\n\nexport type BoxedMap<T extends Map<Capable, Capable> = Map<Capable, Capable>> =\n & BoxBaseType<typeof type>\n & { entries: Array<[Capable, Capable]> }\n & { [UnderlyingType]: T }\n\n// `Map<unknown, unknown>` rather than `Map<Capable, Capable>` here breaks\n// the Capable ↔ defaultRevivableModules ↔ this module type cycle.\n// box() narrows to Map<Capable, Capable> so misuse is still caught at the\n// box site.\nexport const isType = (value: unknown): value is Map<unknown, unknown> =>\n value instanceof Map\n\nexport const box = <T extends Map<Capable, Capable>, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedMap<T> => ({\n ...BoxBase,\n type,\n entries: Array.from(value, ([k, v]): [Capable, Capable] =>\n [recursiveBox(k, context) as Capable, recursiveBox(v, context) as Capable]),\n}) as BoxedMap<T>\n\nexport const revive = <T extends BoxedMap, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): T[UnderlyingType] =>\n new Map(value.entries.map(([k, v]) => [\n recursiveRevive(k, context),\n recursiveRevive(v, context),\n ])) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const m = new Map<string, number>([['a', 1]])\n const boxed = box(m, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Map<string, number> = revived\n // @ts-expect-error - wrong value type\n const wrongValue: Map<string, string> = revived\n // @ts-expect-error - cannot box non-Map\n box('not a map', {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, UnderlyingType, BoxBase as BoxBaseType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'set' as const\n\nexport type BoxedSet<T extends Set<Capable> = Set<Capable>> =\n & BoxBaseType<typeof type>\n & { values: Array<Capable> }\n & { [UnderlyingType]: T }\n\n// `Set<unknown>` rather than `Set<Capable>` here breaks the Capable ↔\n// defaultRevivableModules ↔ this module type cycle. box() narrows to\n// Set<Capable> so misuse is still caught at the box site.\nexport const isType = (value: unknown): value is Set<unknown> =>\n value instanceof Set\n\nexport const box = <T extends Set<Capable>, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedSet<T> => ({\n ...BoxBase,\n type,\n values: Array.from(value, v => recursiveBox(v, context) as Capable),\n}) as BoxedSet<T>\n\nexport const revive = <T extends BoxedSet, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): T[UnderlyingType] =>\n new Set(value.values.map(v => recursiveRevive(v, context))) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const s = new Set<number>([1, 2, 3])\n const boxed = box(s, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Set<number> = revived\n // @ts-expect-error - wrong value type\n const wrongValue: Set<string> = revived\n // @ts-expect-error - cannot box non-Set\n box('not a set', {} as RevivableContext)\n}\n","import type { RevivableContext, UnderlyingType } from './utils'\n\nimport { BoxBase } from './utils'\n\nexport const type = 'bigint' as const\n\ntype BoxedBigInt<T extends bigint> =\n & typeof BoxBase\n & { type: typeof type }\n & { value: string }\n & { [UnderlyingType]: T }\n\nexport const isType = (value: unknown): value is bigint =>\n typeof value === 'bigint'\n\nexport const box = <T extends bigint, T2 extends RevivableContext>(\n value: T,\n _context: T2,\n): BoxedBigInt<T> =>\n ({ ...BoxBase, type, value: value.toString() }) as BoxedBigInt<T>\n\nexport const revive = <T extends BoxedBigInt<bigint>>(\n value: T,\n _context: RevivableContext,\n): T[UnderlyingType] =>\n BigInt(value.value) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const boxed = box(123n, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: bigint = revived\n // @ts-expect-error - not a string\n const notString: string = revived\n // @ts-expect-error - cannot box non-bigint\n box('not a bigint', {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType, UnderlyingType } from './utils'\nimport type { AnyPort, BoxedMessagePort } from './message-port'\n\nimport { BoxBase } from './utils'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort,\n} from './message-port'\n\nexport const type = 'eventTarget' as const\n\n// Wire protocol — receiver tells source which event types to forward (so we\n// don't broadcast every dispatch); source pushes a serialised event when its\n// EventTarget fires a matching type. The `close` sentinel lets the revive\n// side notify the box side that the revived target is gone so it can tear\n// down its forwarder listeners.\ntype EventTargetMessage =\n | { kind: 'subscribe', eventType: string }\n | { kind: 'unsubscribe', eventType: string }\n | { kind: 'close' }\n | {\n kind: 'event'\n eventType: string\n bubbles: boolean\n cancelable: boolean\n composed: boolean\n // Present iff the source dispatched a CustomEvent — preserves `detail`\n // (boxed via the surrounding revivable graph so live values flow).\n detail?: Capable\n }\n\nexport type BoxedEventTarget<T extends EventTarget = EventTarget> =\n & BoxBaseType<typeof type>\n & { port: BoxedMessagePort<EventTargetMessage> }\n & { [UnderlyingType]: T }\n\n// FinalizationRegistry — when the revived EventTarget is collected the box\n// side needs to remove the forwarder listeners it installed on the user's\n// source EventTarget; otherwise long-lived sources (window, document, …)\n// retain the forwarder forever and keep posting into a dead channel on\n// every dispatch. We post a `close` sentinel through the revive-side port\n// but deliberately do NOT call .close() on the port here: on synthetic\n// EventPort channels (JSON transport) close() synchronously sends a\n// `message-port-close` to the box side via _onClose, which races ahead of\n// our queued sentinel and tears the box-side portHandlers entry down\n// before the sentinel arrives — so the sentinel gets dropped and tearDown\n// never runs. Leaving the port open lets messagePortRegistry clean it up\n// a GC cycle later, by which time the sentinel has already flushed.\ntype EventTargetCleanupInfo = {\n port: AnyPort<EventTargetMessage>\n}\n\nconst eventTargetRegistry = new FinalizationRegistry<EventTargetCleanupInfo>((info) => {\n try {\n info.port.postMessage({ kind: 'close' })\n } catch { /* Port may already be closed */ }\n})\n\nexport const isType = (value: unknown): value is EventTarget =>\n value instanceof EventTarget\n\nexport const box = <T extends EventTarget, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedEventTarget<T> => {\n const { localPort, boxedRemote } = createRevivableChannel<EventTargetMessage>(context)\n\n // One forwarder per event type, installed on demand and torn down when the\n // remote unsubscribes. Keyed by eventType so duplicate subscribes are no-ops.\n const sourceListeners = new Map<string, EventListener>()\n\n const tearDown = () => {\n for (const [eventType, listener] of sourceListeners) {\n value.removeEventListener(eventType, listener)\n }\n sourceListeners.clear()\n localPort.removeEventListener('message', messageListener as EventListener)\n localPort.close()\n }\n\n const messageListener = ({ data }: MessageEvent<EventTargetMessage>) => {\n if (data.kind === 'close') {\n tearDown()\n return\n }\n if (data.kind === 'subscribe') {\n if (sourceListeners.has(data.eventType)) return\n const listener: EventListener = (event) => {\n const message: EventTargetMessage = {\n kind: 'event',\n eventType: data.eventType,\n bubbles: event.bubbles,\n cancelable: event.cancelable,\n composed: event.composed,\n }\n if (event instanceof CustomEvent) {\n message.detail = event.detail as Capable\n }\n localPort.postMessage(message)\n }\n value.addEventListener(data.eventType, listener)\n sourceListeners.set(data.eventType, listener)\n return\n }\n if (data.kind === 'unsubscribe') {\n const existing = sourceListeners.get(data.eventType)\n if (!existing) return\n value.removeEventListener(data.eventType, existing)\n sourceListeners.delete(data.eventType)\n }\n }\n\n localPort.addEventListener('message', messageListener as EventListener)\n localPort.start()\n\n return { ...BoxBase, type, port: boxedRemote } as BoxedEventTarget<T>\n}\n\nconst extractCapture = (\n options?: boolean | EventListenerOptions | AddEventListenerOptions,\n): boolean => typeof options === 'boolean' ? options : !!options?.capture\n\nconst extractOnce = (options?: boolean | AddEventListenerOptions): boolean =>\n typeof options === 'object' && options !== null && !!options.once\n\ntype Subscriptions =\n Map<string, Map<EventListenerOrEventListenerObject, Map<boolean, EventListenerOrEventListenerObject>>>\n\n// Removes one (listener, capture) registration; returns true iff the\n// event type went from non-empty to empty so the caller can post unsubscribe.\nconst removeFromTracking = (\n subscriptions: Subscriptions,\n eventType: string,\n listener: EventListenerOrEventListenerObject,\n capture: boolean,\n): boolean => {\n const byListener = subscriptions.get(eventType)\n if (!byListener) return false\n const byCapture = byListener.get(listener)\n if (!byCapture) return false\n if (!byCapture.delete(capture)) return false\n if (byCapture.size === 0) byListener.delete(listener)\n if (byListener.size > 0) return false\n subscriptions.delete(eventType)\n return true\n}\n\n// Attaches the port-dispatch listener inside a helper so V8's closure scope\n// record for the listener contains only `targetRef` + `port` — not the outer\n// revive frame (which has a strong `target` binding that would pin the\n// revived EventTarget and defeat the FinalizationRegistry-based cleanup).\nconst wireMessageListener = (\n port: AnyPort<EventTargetMessage>,\n targetRef: WeakRef<EventTarget>,\n): void => {\n port.addEventListener('message', ({ data }: MessageEvent<EventTargetMessage>) => {\n if (data.kind !== 'event') return\n const t = targetRef.deref()\n if (!t) return\n const eventInit = {\n bubbles: data.bubbles,\n cancelable: data.cancelable,\n composed: data.composed,\n }\n const event = 'detail' in data\n ? new CustomEvent(data.eventType, { ...eventInit, detail: data.detail })\n : new Event(data.eventType, eventInit)\n t.dispatchEvent(event)\n })\n}\n\n// Builds the addEventListener/removeEventListener overrides inside a helper\n// so the closures they produce capture only the listed params — not `target`\n// from revive's scope (V8 retains whole context slots per closure, so leaving\n// `target` in the enclosing lexical scope would pin it alive indefinitely).\nconst installOverrides = (\n target: EventTarget,\n port: AnyPort<EventTargetMessage>,\n subscriptions: Subscriptions,\n): void => {\n const nativeAdd = EventTarget.prototype.addEventListener.bind(target)\n const nativeRemove = EventTarget.prototype.removeEventListener.bind(target)\n\n Object.defineProperty(target, 'addEventListener', {\n value: (\n eventType: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions,\n ) => {\n if (listener === null) return\n const capture = extractCapture(options)\n const once = extractOnce(options)\n\n let byListener = subscriptions.get(eventType)\n const isFirstForType = !byListener\n if (!byListener) {\n byListener = new Map()\n subscriptions.set(eventType, byListener)\n }\n let byCapture = byListener.get(listener)\n if (!byCapture) {\n byCapture = new Map()\n byListener.set(listener, byCapture)\n }\n if (byCapture.has(capture)) return\n\n // `{ once: true }` auto-removes the native registration after first\n // dispatch, but the DOM doesn't notify our override — so without a\n // wrapper, our tracking would diverge and we'd never send unsubscribe.\n const effective: EventListenerOrEventListenerObject = once\n ? (event: Event) => {\n const becameEmpty = removeFromTracking(subscriptions, eventType, listener, capture)\n if (becameEmpty) port.postMessage({ kind: 'unsubscribe', eventType })\n if (typeof listener === 'function') listener(event)\n else listener.handleEvent(event)\n }\n : listener\n\n byCapture.set(capture, effective)\n if (isFirstForType) port.postMessage({ kind: 'subscribe', eventType })\n nativeAdd(eventType, effective, options)\n },\n })\n\n Object.defineProperty(target, 'removeEventListener', {\n value: (\n eventType: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions,\n ) => {\n if (listener === null) return\n const capture = extractCapture(options)\n const effective = subscriptions.get(eventType)?.get(listener)?.get(capture)\n if (!effective) return\n nativeRemove(eventType, effective, options)\n const becameEmpty = removeFromTracking(subscriptions, eventType, listener, capture)\n if (becameEmpty) port.postMessage({ kind: 'unsubscribe', eventType })\n },\n })\n}\n\nexport const revive = <T extends BoxedEventTarget, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): T[UnderlyingType] => {\n const port = reviveMessagePort(value.port, context)\n port.start()\n\n const target = new EventTarget()\n // Per-type registrations keyed by `(listener, capture)` because the DOM\n // uniques on that tuple: the same listener with capture=true and capture=false\n // are two distinct registrations and must be tracked independently. Tracking\n // on listener identity alone would silently drop one registration when the\n // other is removed, and miss `{ once: true }` self-removal.\n const subscriptions: Subscriptions = new Map()\n\n // WeakRef wrapping + helpers-with-tight-scope pattern: closures created\n // inside wireMessageListener / installOverrides only capture their params,\n // not `target` from this frame. That's what lets the FinalizationRegistry\n // fire when the user drops their revived-target reference.\n wireMessageListener(port, new WeakRef(target))\n installOverrides(target, port, subscriptions)\n\n eventTargetRegistry.register(target, { port }, target)\n\n return target as T[UnderlyingType]\n}\n\nconst typeCheck = () => {\n const et = new EventTarget()\n const boxed = box(et, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: EventTarget = revived\n // @ts-expect-error - not a string\n const notString: string = revived\n // @ts-expect-error - cannot box non-EventTarget\n box('not an event target', {} as RevivableContext)\n}\n","import type { BoxBase, RevivableContext } from './utils'\nimport type { DeepReplaceWithBox, DeepReplaceWithRevive, ReplaceWithBox, ReplaceWithRevive } from '../utils/replace'\nimport type { MessageFields, Capable } from '../types'\n\nimport { isRevivableBox } from './utils'\nimport * as arrayBuffer from './array-buffer'\nimport * as date from './date'\nimport * as headers from './headers'\nimport * as error from './error'\nimport * as typedArray from './typed-array'\nimport * as promise from './promise'\nimport * as func from './function'\nimport * as messagePort from './message-port'\nimport * as readableStream from './readable-stream'\nimport * as abortSignal from './abort-signal'\nimport * as response from './response'\nimport * as request from './request'\nimport * as identity from './identity'\nimport * as transfer from './transfer'\nimport * as map from './map'\nimport * as set from './set'\nimport * as bigInt from './bigint'\nimport * as eventTarget from './event-target'\n\nexport { identity } from './identity'\nexport { transfer } from './transfer'\n\nexport * from './utils'\n\n// Module-level signatures intentionally widen to `any` on the box/revive/init\n// parameters: each module's concrete box takes a narrower input than the\n// shared interface can express, and TS treats `readonly`-property function\n// types contravariantly. The `any`s here are the bivariance escape hatch that\n// lets concrete modules be assigned to `RevivableModule[]` at all.\nexport type RevivableModule<\n T extends string = string,\n T2 = any,\n T3 extends BoxBase<T> = any,\n T4 extends MessageFields = MessageFields,\n> = {\n readonly type: T\n readonly isType: (value: unknown) => value is T2\n readonly box: ((value: T2, context: RevivableContext<any>) => T3) | ((...args: any[]) => any)\n readonly revive: (value: T3, context: RevivableContext<any>) => T2\n readonly init?: (context: RevivableContext<any>) => void\n readonly Messages?: T4\n}\n\nexport const defaultRevivableModules = [\n transfer,\n identity,\n arrayBuffer,\n date,\n headers,\n error,\n typedArray,\n promise,\n func,\n messagePort,\n readableStream,\n abortSignal,\n response,\n request,\n map,\n set,\n bigInt,\n // eventTarget MUST be last among instanceof-EventTarget revivables —\n // MessagePort, AbortSignal, EventPort, Window, Worker, etc. all extend\n // EventTarget; the more specific revivables (messagePort/abortSignal) need\n // first dibs via findBoxModule's iteration order.\n eventTarget,\n] as const\n\nexport type DefaultRevivableModules = typeof defaultRevivableModules\nexport type DefaultRevivableModule = DefaultRevivableModules[number]\n\nconst findBoxModule = (\n value: unknown,\n modules: readonly RevivableModule[]\n): RevivableModule | undefined =>\n modules.find(module => module.isType(value))\n\nconst findReviveModule = (\n value: BoxBase,\n modules: readonly RevivableModule[],\n): RevivableModule | undefined =>\n modules.find(module => module.type === value.type)\n\nconst isPlainObject = (value: unknown): value is Record<string, Capable> =>\n !!value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype\n\nconst descend = <TOut>(value: unknown, transform: (v: Capable) => unknown): TOut => {\n if (Array.isArray(value)) {\n return value.map(v => transform(v)) as TOut\n }\n if (isPlainObject(value)) {\n return Object.fromEntries(\n Object.entries<Capable>(value).map(([k, v]) => [k, transform(v)]),\n ) as TOut\n }\n return value as TOut\n}\n\nexport const box = <\n T extends Capable,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): ReplaceWithBox<T, TModules[number]> => {\n const handledByModule = findBoxModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.box(value, context) as ReplaceWithBox<T, TModules[number]>\n }\n return value as ReplaceWithBox<T, TModules[number]>\n}\n\nexport const recursiveBox = <\n T extends Capable,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): DeepReplaceWithBox<T, TModules[number]> => {\n type ReturnCastType = DeepReplaceWithBox<T, TModules[number]>\n // Already-boxed values pass through — revivables (e.g. createRevivableChannel)\n // may embed a pre-built BoxedX in their outgoing payload; descending into it\n // would re-box raw ports nested inside.\n if (isRevivableBox(value)) return value as ReturnCastType\n const handledByModule = findBoxModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.box(value, context) as ReturnCastType\n }\n return descend<ReturnCastType>(value, v => recursiveBox(v, context))\n}\n\nexport const revive = <\n T extends ReturnType<typeof box>,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): ReplaceWithRevive<T, TModules[number]> => {\n if (!isRevivableBox(value)) return value as ReplaceWithRevive<T, TModules[number]>\n const handledByModule = findReviveModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.revive(value, context) as ReplaceWithRevive<T, TModules[number]>\n }\n return value as ReplaceWithRevive<T, TModules[number]>\n}\n\nexport const recursiveRevive = <\n T extends Capable,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): DeepReplaceWithRevive<T, TModules[number]> => {\n type ReturnCastType = DeepReplaceWithRevive<T, TModules[number]>\n if (isRevivableBox(value)) {\n const handledByModule = findReviveModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.revive(value, context) as ReturnCastType\n }\n }\n return descend<ReturnCastType>(value, v => recursiveRevive(v, context))\n}","import type { Transport } from '../utils/transport'\nimport type { DefaultRevivableModules, RevivableModule } from '../revivables'\nimport type { DeepReplaceWithBox } from '../utils/replace'\nimport type { ProtocolContext } from './utils'\nimport type {\n Capable, MessageEventTarget, MessageFields,\n MessageVariant, Uuid,\n} from '../types'\n\nimport { recursiveBox, recursiveRevive } from '../revivables'\nimport { isEmitTransport, isReceiveTransport } from '../utils/type-guards'\n\nexport const type = 'bidirectional' as const\n\nexport type InitMessage<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n> = {\n type: 'init'\n remoteUuid: Uuid\n data: DeepReplaceWithBox<T, TModules[number]>\n}\n\nexport declare const Messages: <\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n>(modules: TModules, value: T) =>\n | InitMessage<TModules, T>\n\nexport type Messages<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n> = ReturnType<typeof Messages<TModules, T>>\n\nexport type ConnectionContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n type: 'bidirectional'\n eventTarget: MessageEventTarget<TModules>\n connection: BidirectionalConnection<TModules>\n}\n\nexport type ConnectionRevivableContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n transport: Transport\n remoteUuid: Uuid\n sendMessage: (message: MessageFields & Record<string, unknown>) => void\n revivableModules: TModules\n eventTarget: MessageEventTarget<TModules>\n}\n\nexport const startBidirectionalConnection = <\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n>(\n { transport, value, remoteUuid, eventTarget, send, revivableModules }:\n {\n transport: Transport\n value: Capable<TModules>\n remoteUuid: Uuid\n eventTarget: MessageEventTarget<TModules>\n send: (message: MessageFields & Record<string, unknown>) => void\n revivableModules: TModules\n },\n) => {\n const revivableContext = {\n transport,\n remoteUuid,\n sendMessage: send,\n eventTarget,\n revivableModules\n } satisfies ConnectionRevivableContext<TModules>\n\n for (const module of revivableModules) {\n module.init?.(revivableContext)\n }\n\n const { promise, resolve } = Promise.withResolvers<InitMessage<TModules>['data']>()\n\n eventTarget.addEventListener('message', function listener ({ detail }) {\n if (detail.type === 'init') {\n resolve(detail.data)\n eventTarget.removeEventListener('message', listener)\n }\n })\n\n send({\n type: 'init',\n remoteUuid,\n data: recursiveBox(value, revivableContext)\n })\n\n return {\n revivableContext,\n remoteValue:\n promise\n .then(initData => recursiveRevive(initData, revivableContext) as Capable),\n }\n}\n\nexport type BidirectionalConnection<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n revivableContext: ConnectionRevivableContext<TModules>\n remoteValue: Promise<Capable>\n}\n\n/**\n * init() — mounts the bidirectional mode on the shared protocol context.\n * Only activates when the transport can both emit and receive. Owns the\n * announce / close handshake and routes per-connection messages (init /\n * message / message-port-close) to the right connection's eventTarget.\n */\nexport const init = <TModules extends readonly RevivableModule[]>(\n ctx: ProtocolContext<TModules>\n): void => {\n if (!(isEmitTransport(ctx.transport) && isReceiveTransport(ctx.transport))) return\n\n ctx.protocolEventTarget.addEventListener('message', ({ detail: message }) => {\n if (message.type === 'announce') {\n if (!message.remoteUuid) {\n ctx.sendMessage({ type: 'announce', remoteUuid: message.uuid })\n return\n }\n if (message.remoteUuid !== ctx.getUuid()) return\n // Already-tracked uuid is the normal handshake-echo case (the peer\n // re-announcing back at us after we replied to its initial announce),\n // not a uuid collision — silently drop it so we don't double-set up\n // the same connection.\n if (ctx.connectionContexts.has(message.uuid)) return\n // Send announce back so the other side can also create a connection\n // (in case they missed our initial announce due to timing)\n ctx.sendMessage({ type: 'announce', remoteUuid: message.uuid })\n const eventTarget = ctx.createConnectionEventTarget()\n const connectionContext = {\n type: 'bidirectional',\n eventTarget,\n connection:\n startBidirectionalConnection<TModules>({\n transport: ctx.transport,\n value: ctx.value,\n remoteUuid: message.uuid,\n eventTarget,\n send: (m) => ctx.sendMessage(m as MessageVariant),\n revivableModules: ctx.revivableModules\n })\n } satisfies ConnectionContext<TModules>\n ctx.connectionContexts.set(message.uuid, connectionContext)\n connectionContext.connection.remoteValue.then((remoteValue) =>\n ctx.resolveRemoteValue(remoteValue)\n )\n return\n }\n if (message.type === 'close') {\n if (message.remoteUuid !== ctx.getUuid()) return\n ctx.connectionContexts.delete(message.uuid)\n return\n }\n // \"init\" | \"message\" | \"message-port-close\"\n if (message.remoteUuid !== ctx.getUuid()) return\n const connection = ctx.connectionContexts.get(message.uuid)\n // drop messages that arrive before the remote has announced itself,\n // or after its connection has been torn down\n if (!connection) return\n connection.eventTarget.dispatchEvent(\n new CustomEvent('message', { detail: message })\n )\n })\n\n if (ctx.presetRemoteUuid !== undefined) {\n const eventTarget = ctx.createConnectionEventTarget()\n const connectionContext = {\n type: 'bidirectional',\n eventTarget,\n connection:\n startBidirectionalConnection<TModules>({\n transport: ctx.transport,\n value: ctx.value,\n remoteUuid: ctx.presetRemoteUuid,\n eventTarget,\n send: (m) => ctx.sendMessage(m as MessageVariant),\n revivableModules: ctx.revivableModules\n })\n } satisfies ConnectionContext<TModules>\n ctx.connectionContexts.set(ctx.presetRemoteUuid, connectionContext)\n connectionContext.connection.remoteValue.then((remoteValue) =>\n ctx.resolveRemoteValue(remoteValue)\n )\n return\n }\n\n ctx.sendMessage({ type: 'announce' })\n}\n","import type { UnderlyingType } from './type'\n\nexport type EventMap = Record<string, Event>\n\nexport interface TypedEventTarget<T extends EventMap> extends EventTarget {\n [UnderlyingType]?: T\n\n addEventListener<K extends keyof T & string>(\n type: K,\n listener: ((event: T[K]) => void) | null,\n options?: boolean | AddEventListenerOptions\n ): void\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions\n ): void\n\n removeEventListener<K extends keyof T & string>(\n type: K,\n listener: ((event: T[K]) => void) | null,\n options?: boolean | EventListenerOptions\n ): void\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void\n}\n\n/**\n * Create a new `TypedEventTarget<T>` for a given event map. Centralises the\n * `EventTarget` → `TypedEventTarget<T>` cast so individual call sites don't\n * each need their own (`EventTarget` lacks the generic event map at the type\n * level, but the runtime behaviour is identical).\n */\nexport const createTypedEventTarget = <T extends EventMap>(): TypedEventTarget<T> =>\n new EventTarget() as TypedEventTarget<T>\n","import { transfer } from '../revivables/transfer'\nimport { isRevivableBox } from '../revivables/utils'\nimport { instanceOfAny, isClonable, isTransferable } from './type-guards'\n\nexport { transfer }\n\n// \"Must-transfer\" types: structured clone cannot copy these, so any occurrence\n// in the outgoing message has to go on the transfer list regardless of whether\n// the user opted in with `transfer()`. MessagePort is the canonical case —\n// cloning one would leave the remote side unable to respond.\nconst isMustTransfer = (value: unknown): value is Transferable =>\n instanceOfAny(value, [\n globalThis.MessagePort,\n globalThis.ReadableStream,\n globalThis.WritableStream,\n globalThis.TransformStream,\n globalThis.OffscreenCanvas,\n ])\n\n// Structural check for a transfer revivable box. Uses the 'transfer' string\n// literal rather than importing the module's exported `type` constant, so the\n// walker stays decoupled from the module's full graph.\n// The `degraded` flag is set by transfer.box() when the platform can't\n// actually transfer — a degraded box is a no-op for the walker.\nconst isTransferBox = (value: unknown): value is { inner: unknown, degraded: boolean } =>\n isRevivableBox(value) && value.type === 'transfer'\n\n/**\n * Walk a boxed message and collect the list of Transferable references that\n * should be moved (rather than cloned) when calling postMessage.\n *\n * The rules are:\n * 1. Must-transfer types (MessagePort, streams, OffscreenCanvas) are always\n * included — structured clone cannot represent them.\n * 2. Clonable types (SharedArrayBuffer) are skipped entirely.\n * 3. Other Transferable types (ArrayBuffer, ImageBitmap) are included only\n * when the walker is inside a non-degraded transfer box — i.e. when the\n * user explicitly opted into move semantics at the send site via\n * transfer() AND the platform supports transferring.\n *\n * The transfer intent is carried on the wire by the transfer revivable box;\n * recognising it structurally here (without importing the module) is all the\n * coupling this file needs.\n */\nexport const getTransferableObjects = (value: unknown): Transferable[] => {\n const transferables: Transferable[] = []\n const seen = new WeakSet<object>()\n\n const recurse = (value: unknown, inTransferBox: boolean): void => {\n if (!value || typeof value !== 'object') return\n if (seen.has(value)) return\n seen.add(value)\n\n if (isClonable(value)) return\n\n if (isTransferBox(value)) {\n // Non-degraded box: flip into transfer mode — every Transferable found\n // below this point on this branch of the walk gets added to the\n // transfer list. Degraded box (platform can't transfer): keep whatever\n // mode we were in, so the wrapper becomes a no-op and the inner gets\n // walked as a normal copy payload.\n recurse(value.inner, inTransferBox || !value.degraded)\n return\n }\n\n if (isMustTransfer(value)) {\n transferables.push(value)\n return\n }\n\n if (isTransferable(value)) {\n if (inTransferBox) {\n transferables.push(value)\n }\n return\n }\n\n // TypedArray / DataView expose every numeric index as an own key — iterating\n // `Object.keys` of a 100 KB buffer touches 100 K entries for no useful\n // result. The underlying buffer is the only thing we could transfer, and\n // that happens via the transfer box / typed-array revivable path anyway.\n if (ArrayBuffer.isView(value)) return\n\n if (Array.isArray(value)) {\n for (const item of value) recurse(item, inTransferBox)\n return\n }\n\n for (const item of Object.values(value)) recurse(item, inTransferBox)\n }\n\n recurse(value, false)\n return transferables\n}\n","import type {\n Message, MessageVariant, Uuid,\n Capable, MessageEventMap\n} from '../types'\nimport type { DefaultRevivableModules, RevivableModule } from '../revivables'\nimport type { Transport } from '../utils/transport'\nimport type { ConnectionContext } from '.'\nimport type { TypedEventTarget } from '../utils/typed-event-target'\n\nimport { defaultRevivableModules } from '../revivables'\nimport { isJsonOnlyTransport, isCustomTransport } from '../utils/type-guards'\n\nexport const normalizeTransport = (transport: Transport): Transport => {\n const isJson =\n 'isJson' in transport && transport.isJson !== undefined\n ? transport.isJson\n : isJsonOnlyTransport(transport)\n const ports =\n isCustomTransport(transport)\n ? transport\n : { emit: transport, receive: transport }\n return { isJson, ...ports } satisfies Transport\n}\n\nexport const mergeRevivableModules = <\n TUserModules extends readonly RevivableModule[]\n>(userModules: TUserModules | undefined) => [\n ...defaultRevivableModules.filter(\n d => !(userModules ?? []).some(u => u.type === d.type),\n ),\n ...(userModules ?? []),\n] as const\n\nexport type ProtocolEventMap<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n message: CustomEvent<Message<TModules>>\n}\n\nexport type ProtocolEventTarget<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = TypedEventTarget<ProtocolEventMap<TModules>>\n\nexport type ProtocolContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n transport: Transport\n value: Capable<TModules>\n revivableModules: TModules\n connectionContexts: Map<string, ConnectionContext<TModules>>\n getUuid: () => Uuid\n presetRemoteUuid?: Uuid\n sendMessage: (message: MessageVariant) => void\n protocolEventTarget: ProtocolEventTarget<TModules>\n resolveRemoteValue: (value: Capable<TModules>) => void\n createConnectionEventTarget: () => TypedEventTarget<MessageEventMap<TModules>>\n}\n\nexport type StartConnectionsOptions<\n TUserModules extends readonly RevivableModule[] = readonly []\n> = {\n transport: Transport\n name?: string\n remoteName?: string\n key?: string\n origin?: string\n unregisterSignal?: AbortSignal\n revivableModules?: TUserModules\n uuid?: Uuid\n remoteUuid?: Uuid\n}\n","import type { DefaultRevivableModules, RevivableModule } from '../revivables'\nimport type { ConnectionContext as BidirectionalConnectionContext } from './bidirectional'\nimport type {\n ProtocolContext,\n StartConnectionsOptions,\n} from '../utils'\nimport type {\n Message, MessageVariant, Uuid,\n Capable,\n} from '../types'\nimport type { MessageContext } from '../utils/transport'\n\nimport { OSRA_DEFAULT_KEY, OSRA_KEY } from '../types'\nimport * as bidirectional from './bidirectional'\nimport {\n isEmitTransport,\n isReceiveTransport,\n} from '../utils/type-guards'\nimport { createTypedEventTarget } from '../utils/typed-event-target'\nimport { getTransferableObjects } from '../utils/transferable'\nimport { registerOsraMessageListener, sendOsraMessage } from '../utils/transport'\nimport { mergeRevivableModules, normalizeTransport } from './utils'\n\nexport * from './bidirectional'\nexport * from './utils'\n\nexport type ConnectionModule<T> = {\n readonly type: string\n // ProtocolContext<any> rather than ProtocolContext<readonly RevivableModule[]>\n // for the same bivariance reason as RevivableModule.box — concrete modules\n // declare narrower context generics than the shared interface can express.\n readonly init: (ctx: ProtocolContext<any>) => void\n readonly Messages?: T\n}\n\nexport const connections = [\n bidirectional\n] as const\n\nexport type DefaultConnectionModules = typeof connections\nexport type DefaultConnectionModule = DefaultConnectionModules[number]\n\nexport type ConnectionMessage<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n> =\n DefaultConnectionModule extends {\n Messages: (modules: TModules, value: T) => infer R\n }\n ? R\n : never\n\nexport type ConnectionContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> =\n | BidirectionalConnectionContext<TModules>\n\nexport const startConnections = <\n T = unknown,\n const TUserModules extends readonly RevivableModule[] = readonly []\n>(\n value: Capable<[...DefaultRevivableModules, ...TUserModules]>,\n {\n transport: _transport,\n name,\n remoteName,\n key = OSRA_DEFAULT_KEY,\n origin = '*',\n unregisterSignal,\n revivableModules: _userRevivableModules,\n uuid: _uuid,\n remoteUuid: presetRemoteUuid,\n }: StartConnectionsOptions<TUserModules>\n): Promise<T> => {\n const transport = normalizeTransport(_transport)\n const mergedRevivableModules = mergeRevivableModules(_userRevivableModules)\n type MergedModules = typeof mergedRevivableModules\n const connectionContexts = new Map<string, ConnectionContext<MergedModules>>()\n\n const { promise: remoteValuePromise, resolve: resolveRemoteValue } =\n Promise.withResolvers<Capable<MergedModules>>()\n\n const uuid: Uuid = _uuid ?? globalThis.crypto.randomUUID()\n\n const sendMessage = (message: MessageVariant) => {\n if (unregisterSignal?.aborted) return\n if (!isEmitTransport(transport)) return\n const envelope = { [OSRA_KEY]: key, name, uuid, ...message }\n sendOsraMessage(transport, envelope, origin, getTransferableObjects(envelope))\n }\n\n const protocolEventTarget = createTypedEventTarget<{ message: CustomEvent<Message<MergedModules>> }>()\n\n const ctx: ProtocolContext<MergedModules> = {\n transport,\n value: value as Capable<MergedModules>,\n revivableModules: mergedRevivableModules,\n connectionContexts,\n getUuid: () => uuid,\n presetRemoteUuid,\n sendMessage,\n protocolEventTarget,\n resolveRemoteValue,\n createConnectionEventTarget: createTypedEventTarget,\n }\n\n const listener = (message: Message<MergedModules>, _: MessageContext) => {\n // own message looped back on the channel\n if (message.uuid === uuid) return\n protocolEventTarget.dispatchEvent(\n new CustomEvent('message', { detail: message }),\n )\n }\n\n if (isReceiveTransport(transport)) {\n registerOsraMessageListener({\n listener,\n transport,\n remoteName,\n key,\n unregisterSignal\n })\n }\n\n for (const connectionModule of connections) {\n connectionModule.init(ctx)\n }\n\n return remoteValuePromise as Promise<T>\n}\n","import type { Capable } from './types'\nimport type { DefaultRevivableModules } from './revivables'\nimport type { RevivableModule } from './revivables'\nimport type { StartConnectionsOptions } from './connections/utils'\nimport type {\n BadFieldValue, BadFieldPath, BadFieldParent,\n ErrorMessage, BadValue, Path, ParentObject\n} from './utils/capable-check'\n\nimport { startConnections } from './utils'\n\nexport * from './types'\nexport * from './revivables'\nexport * from './connections'\nexport * from './utils'\n\ntype CapableCheck<\n T,\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> =\n T extends Capable<TModules>\n ? T\n : T & {\n [ErrorMessage]: 'Value type must resolve to a Capable'\n [BadValue]: BadFieldValue<T, Capable<TModules>>\n [Path]: BadFieldPath<T, Capable<TModules>>\n [ParentObject]: BadFieldParent<T, Capable<TModules>>\n }\n\nexport const expose = async <\n T = unknown,\n const TUserModules extends readonly RevivableModule[] = readonly [],\n const TValue = Capable<[...DefaultRevivableModules, ...TUserModules]>\n>(\n value: CapableCheck<TValue, [...DefaultRevivableModules, ...TUserModules]>,\n options: StartConnectionsOptions<TUserModules>\n): Promise<T> =>\n startConnections<T, TUserModules>(\n value as Capable<[...DefaultRevivableModules, ...TUserModules]>,\n options\n )\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/types.ts","../src/utils/type-guards.ts","../src/utils/transport.ts","../src/revivables/utils.ts","../src/revivables/array-buffer.ts","../src/revivables/date.ts","../src/revivables/headers.ts","../src/revivables/error.ts","../src/revivables/typed-array.ts","../src/utils/event-channel.ts","../src/utils/gc-tracker.ts","../src/revivables/message-port.ts","../src/revivables/promise.ts","../src/revivables/function.ts","../src/revivables/readable-stream.ts","../src/revivables/abort-signal.ts","../src/revivables/response.ts","../src/revivables/request.ts","../src/revivables/identity.ts","../src/revivables/transfer.ts","../src/revivables/map.ts","../src/revivables/set.ts","../src/revivables/bigint.ts","../src/revivables/event.ts","../src/revivables/event-target.ts","../src/revivables/blob.ts","../src/revivables/symbol.ts","../src/revivables/fallbacks.ts","../src/revivables/index.ts","../src/connections/bidirectional.ts","../src/utils/typed-event-target.ts","../src/utils/transferable.ts","../src/connections/utils.ts","../src/connections/index.ts","../src/index.ts"],"sourcesContent":["import type { ConnectionMessage } from './connections'\nimport type { TypedEventTarget } from './utils'\nimport type { IsJsonOnlyTransport } from './utils/type-guards'\nimport type {\n DefaultRevivableModules, RevivableModule,\n InferMessages, InferRevivables, RevivableContext\n} from './revivables'\n\nexport const OSRA_KEY = '__OSRA_KEY__' as const\nexport const OSRA_DEFAULT_KEY = '__OSRA_DEFAULT_KEY__' as const\nexport const OSRA_BOX = '__OSRA_BOX__' as const\n\nexport type Uuid = `${string}-${string}-${string}-${string}-${string}`\n\nexport type Jsonable =\n | boolean\n | null\n | number\n | string\n | { [key: string]: Jsonable }\n | Array<Jsonable>\n\nexport type Structurable =\n | Jsonable\n /** not really structureable but here for convenience */\n | void\n | undefined\n | bigint\n | Date\n | RegExp\n | Blob\n | File\n | FileList\n | ArrayBuffer\n | ArrayBufferView\n | ImageBitmap\n | ImageData\n | { [key: string]: Structurable }\n | Array<Structurable>\n | Map<Structurable, Structurable>\n | Set<Structurable>\n\nexport type StructurableTransferable =\n | Structurable\n | Transferable\n | { [key: string]: StructurableTransferable }\n | Array<StructurableTransferable>\n | Map<StructurableTransferable, StructurableTransferable>\n | Set<StructurableTransferable>\n\n/** \"Free\" types in `Capable` — narrows to `Jsonable` on JSON transports so\n * user code can't type a `Date`/`Blob`/etc. that JSON would silently coerce.\n * Modules that DO support JSON (date, map, set, bigint, …) put their type\n * back via `InferRevivables`. */\ntype CapableBase<Ctx extends RevivableContext> =\n IsJsonOnlyTransport<Ctx['transport']> extends true\n ? Jsonable | undefined | void\n : StructurableTransferable\n\nexport type Capable<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n Ctx extends RevivableContext = RevivableContext,\n> =\n | CapableBase<Ctx>\n | InferRevivables<TModules, Ctx>\n | { [key: string]: Capable<TModules, Ctx> }\n | Array<Capable<TModules, Ctx>>\n | Map<Capable<TModules, Ctx>, Capable<TModules, Ctx>>\n | Set<Capable<TModules, Ctx>>\n\nexport type MessageFields = {\n type: string\n remoteUuid: Uuid\n}\n\nexport type MessageBase = {\n [OSRA_KEY]: string\n /** UUID of the client that sent the message */\n uuid: Uuid\n name?: string\n}\n\nexport type ProtocolMessage =\n | { type: 'announce', remoteUuid?: Uuid }\n | { type: 'close', remoteUuid: Uuid }\n\nexport type MessageVariant<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> =\n | ProtocolMessage\n | ConnectionMessage<TModules>\n | InferMessages<TModules>\n\nexport type Message<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> =\n & MessageBase\n & MessageVariant<TModules>\n\nexport type MessageEventMap<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n message: CustomEvent<Message<TModules>>\n}\n\nexport type MessageEventTarget<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n > = TypedEventTarget<MessageEventMap<TModules>>\n","import type { Runtime } from 'webextension-polyfill'\nimport type { Message } from '../types'\nimport type {\n CustomEmitTransport, CustomReceiveTransport,\n CustomTransport, EmitJsonPlatformTransport,\n EmitTransport, JsonPlatformTransport,\n ReceiveJsonPlatformTransport,\n ReceiveTransport, Transport\n} from './transport'\n\nimport { OSRA_KEY } from '../types'\nimport { getWebExtensionRuntime } from './transport'\n\n// Pulled from globalThis so module evaluation doesn't crash on platforms\n// that haven't shipped Float16Array yet (Node ≤ 23, Chrome ≤ 134, Firefox\n// ≤ 132). Platforms without it just don't round-trip Float16 values.\nconst Float16ArrayCtor = (globalThis as { Float16Array?: typeof Float16Array }).Float16Array\n\nconst typedArrayConstructorsByName = {\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float16Array: Float16ArrayCtor,\n Float32Array,\n Float64Array,\n BigInt64Array,\n BigUint64Array,\n} as const\n\nexport type TypedArrayType = keyof typeof typedArrayConstructorsByName\nexport type TypedArrayConstructor = NonNullable<(typeof typedArrayConstructorsByName)[TypedArrayType]>\nexport type TypedArray = InstanceType<TypedArrayConstructor>\n\nconst typedArrayConstructors = Object.values(typedArrayConstructorsByName)\n\nexport const typedArrayToType = (value: TypedArray): TypedArrayType => {\n const name = value.constructor.name as TypedArrayType\n if (!(name in typedArrayConstructorsByName)) throw new Error('Unknown typed array type')\n return name\n}\n\nexport const typedArrayTypeToTypedArrayConstructor = (value: TypedArrayType): TypedArrayConstructor => {\n const ctor = typedArrayConstructorsByName[value]\n if (!ctor) throw new Error('Unknown typed array type')\n return ctor\n}\n\nexport const isTypedArray = (value: unknown): value is TypedArray =>\n typedArrayConstructors.some(ctor => !!ctor && value instanceof ctor)\nexport const isWebSocket = (value: unknown): value is WebSocket => value instanceof WebSocket\nexport const isServiceWorkerContainer = (value: unknown): value is ServiceWorkerContainer => !!globalThis.ServiceWorkerContainer && value instanceof ServiceWorkerContainer\nexport const isWorker = (value: unknown): value is Worker => !!globalThis.Worker && value instanceof Worker\n// @ts-expect-error DedicatedWorkerGlobalScope is only present in worker scopes\nexport const isDedicatedWorker = (value: unknown): value is DedicatedWorkerGlobalScope => !!globalThis.DedicatedWorkerGlobalScope && value instanceof DedicatedWorkerGlobalScope\nexport const isSharedWorker = (value: unknown): value is SharedWorker => !!globalThis.SharedWorker && value instanceof SharedWorker\nconst isMessagePort = (value: unknown): value is MessagePort => value instanceof MessagePort\n\nexport const isOsraMessage = (value: unknown): value is Message =>\n !!value\n && typeof value === 'object'\n && OSRA_KEY in value\n && !!value[OSRA_KEY]\n\ntype AnyConstructor = abstract new (...args: any[]) => unknown\n\n/** True if `value` is an instance of any of the given constructors.\n * Tolerates undefined entries (constructors missing on this platform). */\nexport const instanceOfAny = (value: unknown, ctors: readonly (AnyConstructor | undefined)[]): boolean => {\n for (const ctor of ctors) if (ctor && value instanceof ctor) return true\n return false\n}\n\nexport const isClonable = (value: unknown): boolean =>\n instanceOfAny(value, [globalThis.SharedArrayBuffer])\n\n// Types eligible for transfer when the user opts in via `transfer()`. Some\n// entries are also clonable (ArrayBuffer, ImageBitmap, …) — outside a\n// `transfer` box they fall back to clone.\nexport const isTransferable = (value: unknown): value is Transferable =>\n instanceOfAny(value, [\n globalThis.ArrayBuffer,\n globalThis.MessagePort,\n globalThis.ReadableStream,\n globalThis.WritableStream,\n globalThis.TransformStream,\n globalThis.ImageBitmap,\n globalThis.OffscreenCanvas,\n (globalThis as { AudioData?: abstract new (...args: any[]) => unknown }).AudioData,\n (globalThis as { VideoFrame?: abstract new (...args: any[]) => unknown }).VideoFrame,\n (globalThis as { MediaSourceHandle?: abstract new (...args: any[]) => unknown }).MediaSourceHandle,\n (globalThis as { MediaStreamTrack?: abstract new (...args: any[]) => unknown }).MediaStreamTrack,\n (globalThis as { MIDIAccess?: abstract new (...args: any[]) => unknown }).MIDIAccess,\n (globalThis as { RTCDataChannel?: abstract new (...args: any[]) => unknown }).RTCDataChannel,\n (globalThis as { WebTransportReceiveStream?: abstract new (...args: any[]) => unknown }).WebTransportReceiveStream,\n (globalThis as { WebTransportSendStream?: abstract new (...args: any[]) => unknown }).WebTransportSendStream,\n ])\n\nexport type WebExtRuntime = typeof browser.runtime\nexport const isWebExtensionRuntime = (value: unknown): value is WebExtRuntime => {\n const runtime = getWebExtensionRuntime()\n if (!runtime) return false\n return value === runtime\n}\n\nexport type WebExtPort = ReturnType<WebExtRuntime['connect']> | Runtime.Port\nexport const isWebExtensionPort = (value: unknown, connectPort: boolean = false): value is WebExtPort => {\n if (!value || typeof value !== 'object') return false\n // Prevent SecurityError when `value` is a cross-origin window.\n if (isWindow(value)) return false\n if (!('name' in value) || !('disconnect' in value) || !('postMessage' in value)) return false\n // these properties are only present on WebExtPorts created through runtime.connect()\n if (!connectPort) return true\n return 'sender' in value && 'onMessage' in value && 'onDisconnect' in value\n}\n\nexport type WebExtSender = NonNullable<WebExtPort['sender']>\n\n// Structural guard. Can't distinguish onConnect from onMessage on its own —\n// they share this exact shape.\nconst hasListenerApi = (value: unknown): boolean =>\n !!value\n && typeof value === 'object'\n && !isWindow(value)\n && 'addListener' in value\n && 'hasListener' in value\n && 'removeListener' in value\n\n// Identity-compare against runtime.onConnect — structural checks can't\n// distinguish onConnect from onMessage, and misclassifying causes us to\n// treat each incoming message as a port and crash.\nexport type WebExtOnConnect = WebExtRuntime['onConnect']\nexport const isWebExtensionOnConnect = (value: unknown): value is WebExtOnConnect => {\n const runtime = getWebExtensionRuntime()\n if (!runtime) return false\n return value === runtime.onConnect || value === runtime.onConnectExternal\n}\n\nexport type WebExtOnMessage = WebExtRuntime['onMessage']\nexport const isWebExtensionOnMessage = (value: unknown): value is WebExtOnMessage =>\n hasListenerApi(value)\n\nexport const isWindow = (value: unknown): value is Window => {\n if (!value || typeof value !== 'object') return false\n try {\n return 'window' in value && value.window === value\n } catch {\n // Cross-origin Window access can throw SecurityError — fall back to a\n // shape probe over properties that don't trigger the security check.\n try {\n return 'closed' in value\n && typeof value.closed === 'boolean'\n && 'close' in value\n && typeof value.close === 'function'\n } catch {\n return false\n }\n }\n}\n\nexport const isEmitJsonOnlyTransport = (value: unknown): value is EmitJsonPlatformTransport =>\n isWebSocket(value)\n || isWebExtensionPort(value)\n || isWebExtensionRuntime(value)\n\nexport const isReceiveJsonOnlyTransport = (value: unknown): value is ReceiveJsonPlatformTransport =>\n isWebSocket(value)\n || isWebExtensionPort(value)\n || isWebExtensionOnConnect(value)\n || isWebExtensionOnMessage(value)\n || isWebExtensionRuntime(value)\n\nexport type IsJsonOnlyTransport<T extends Transport> = T extends JsonPlatformTransport ? true : false\nexport const isJsonOnlyTransport = (value: unknown): value is Extract<Transport, JsonPlatformTransport> =>\n (!!value && typeof value === 'object' && 'isJson' in value && value.isJson === true)\n || isEmitJsonOnlyTransport(value)\n || isReceiveJsonOnlyTransport(value)\n\nexport const isEmitTransport = (value: unknown): value is EmitTransport =>\n isWindow(value)\n || isEmitJsonOnlyTransport(value)\n || isServiceWorkerContainer(value)\n || isWorker(value)\n || isDedicatedWorker(value)\n || isSharedWorker(value)\n || isMessagePort(value)\n || isCustomEmitTransport(value)\n\nexport function assertEmitTransport(transport: Transport): asserts transport is EmitTransport {\n if (!isEmitTransport(transport)) throw new Error('Transport is not emitable')\n}\n\nexport const isReceiveTransport = (value: unknown): value is ReceiveTransport =>\n isWindow(value)\n || isReceiveJsonOnlyTransport(value)\n || isServiceWorkerContainer(value)\n || isWorker(value)\n || isDedicatedWorker(value)\n || isSharedWorker(value)\n || isMessagePort(value)\n || isCustomReceiveTransport(value)\n\nexport function assertReceiveTransport(transport: Transport): asserts transport is ReceiveTransport {\n if (!isReceiveTransport(transport)) throw new Error('Transport is not receiveable')\n}\n\nexport const isCustomEmitTransport = (value: unknown): value is CustomEmitTransport => {\n if (!value || typeof value !== 'object') return false\n // Prevent SecurityError when `value` is a cross-origin window.\n if (isWindow(value)) return false\n if (!('emit' in value)) return false\n return isEmitTransport(value.emit) || typeof value.emit === 'function'\n}\n\nexport const isCustomReceiveTransport = (value: unknown): value is CustomReceiveTransport => {\n if (!value || typeof value !== 'object') return false\n // Prevent SecurityError when `value` is a cross-origin window.\n if (isWindow(value)) return false\n if (!('receive' in value)) return false\n return isReceiveTransport(value.receive) || typeof value.receive === 'function'\n}\n\nexport const isCustomTransport = (value: unknown): value is CustomTransport =>\n isCustomEmitTransport(value)\n || isCustomReceiveTransport(value)\n\nexport const isTransport = (value: unknown): value is Transport =>\n isEmitTransport(value)\n || isReceiveTransport(value)\n || isCustomTransport(value)\n || isJsonOnlyTransport(value)\n","import type { Message} from '../types'\nimport type {\n WebExtOnConnect, WebExtOnMessage,\n WebExtPort, WebExtRuntime, WebExtSender\n} from './type-guards'\n\nimport { OSRA_KEY } from '../types'\nimport {\n isOsraMessage, isCustomTransport,\n isWebExtensionOnConnect, isWebExtensionOnMessage,\n isWebExtensionPort, isWebExtensionRuntime, isWebSocket, isWindow, isSharedWorker\n} from './type-guards'\n\nexport type MessageContext = {\n port?: MessagePort | WebExtPort // WebExtension\n sender?: WebExtSender // WebExtension\n receiveTransport?: ReceivePlatformTransport\n source?: MessageEventSource | null // Window, Worker, WebSocket, ect...\n}\n\nexport type ReceiveHandler = (listener: (event: Message, messageContext: MessageContext) => void) => void\nexport type EmitHandler = (message: Message, transferables?: Transferable[]) => void\n\ntype CustomReceive = ReceivePlatformTransport | ReceiveHandler\ntype CustomEmit = EmitPlatformTransport | EmitHandler\n\nexport type CustomTransport =\n { isJson?: boolean }\n & (\n | { receive: CustomReceive, emit: CustomEmit }\n | { receive: CustomReceive }\n | { emit: CustomEmit }\n )\n\nexport type CustomEmitTransport = Extract<CustomTransport, { emit: any }>\nexport type CustomReceiveTransport = Extract<CustomTransport, { receive: any }>\n\nexport type EmitJsonPlatformTransport =\n | WebSocket\n | WebExtPort\n | WebExtRuntime\n\nexport type ReceiveJsonPlatformTransport =\n | WebSocket\n | WebExtPort\n | WebExtOnConnect\n | WebExtOnMessage\n | WebExtRuntime\n\nexport type JsonPlatformTransport =\n | { isJson: true }\n | EmitJsonPlatformTransport\n | ReceiveJsonPlatformTransport\n\ntype StructuredClonePlatformTransport =\n | Window\n | ServiceWorker\n | Worker\n | SharedWorker\n | MessagePort\n\nexport type EmitPlatformTransport =\n | EmitJsonPlatformTransport\n | StructuredClonePlatformTransport\n\nexport type ReceivePlatformTransport =\n | ReceiveJsonPlatformTransport\n | StructuredClonePlatformTransport\n\nexport type PlatformTransport =\n | EmitPlatformTransport\n | ReceivePlatformTransport\n\nexport type EmitTransport = EmitPlatformTransport & Extract<CustomTransport, { emit: any }>\nexport type ReceiveTransport = ReceivePlatformTransport & Extract<CustomTransport, { receive: any }>\n\nexport type Transport =\n | PlatformTransport\n | CustomTransport\n\nexport const getWebExtensionGlobal = () => globalThis.browser ?? globalThis.chrome\nexport const getWebExtensionRuntime = () => getWebExtensionGlobal()?.runtime\n\nexport const checkOsraMessageKey = (message: any, key: string): message is Message =>\n isOsraMessage(message)\n && message[OSRA_KEY] === key\n\nconst onAbort = (signal: AbortSignal | undefined, fn: () => void) =>\n signal?.addEventListener('abort', fn, { once: true })\n\nexport const registerOsraMessageListener = (\n { listener, transport, remoteName, key = OSRA_KEY, unregisterSignal }:\n {\n listener: (message: Message, messageContext: MessageContext) => void\n transport: ReceiveTransport\n remoteName?: string\n key?: string\n unregisterSignal?: AbortSignal\n }\n) => {\n const receiveTransport: Extract<CustomTransport, { receive: any }>['receive'] =\n isCustomTransport(transport) ? transport.receive : transport\n\n // Custom function handler\n if (typeof receiveTransport === 'function') {\n receiveTransport((message, ctx) => {\n if (!checkOsraMessageKey(message, key)) return\n if (remoteName && message.name !== remoteName) return\n listener(message, ctx)\n })\n return\n }\n\n // WebExtension family — subscribe to an `onMessage`-style listener.\n if (\n isWebExtensionRuntime(receiveTransport)\n || isWebExtensionPort(receiveTransport)\n || isWebExtensionOnConnect(receiveTransport)\n || isWebExtensionOnMessage(receiveTransport)\n ) {\n const listenOnWebExtOnMessage = (onMessage: WebExtOnMessage, port?: WebExtPort) => {\n const _listener = (message: object, sender?: WebExtSender) => {\n if (!checkOsraMessageKey(message, key)) return\n if (remoteName && message.name !== remoteName) return\n listener(message, { port, sender })\n }\n onMessage.addListener(_listener)\n onAbort(unregisterSignal, () => onMessage.removeListener(_listener))\n }\n\n if (isWebExtensionRuntime(receiveTransport)) {\n listenOnWebExtOnMessage(receiveTransport.onMessage)\n } else if (isWebExtensionOnConnect(receiveTransport)) {\n const _listener = (port: WebExtPort) =>\n listenOnWebExtOnMessage(port.onMessage as WebExtOnMessage, port)\n receiveTransport.addListener(_listener)\n onAbort(unregisterSignal, () => receiveTransport.removeListener(_listener))\n } else if (isWebExtensionOnMessage(receiveTransport)) {\n listenOnWebExtOnMessage(receiveTransport)\n } else { // WebExtPort\n listenOnWebExtOnMessage(receiveTransport.onMessage as WebExtOnMessage)\n }\n return\n }\n\n // Window, Worker, WebSocket, ServiceWorker, MessagePort, …\n const messageListener = (event: MessageEvent<Message>) => {\n if (!checkOsraMessageKey(event.data, key)) return\n if (remoteName && event.data.name !== remoteName) return\n listener(event.data, { receiveTransport, source: event.source })\n }\n receiveTransport.addEventListener('message', messageListener as EventListener)\n onAbort(unregisterSignal, () =>\n receiveTransport.removeEventListener('message', messageListener as EventListener),\n )\n}\n\nexport const sendOsraMessage = (\n transport: EmitTransport,\n message: Message,\n origin = '*',\n transferables: Transferable[] = []\n) => {\n const emitTransport: Extract<EmitTransport, { emit: any }>['emit'] =\n isCustomTransport(transport) ? transport.emit : transport\n\n if (typeof emitTransport === 'function') {\n emitTransport(message, transferables)\n } else if (isWindow(emitTransport)) {\n // Must check first — cross-origin windows throw on other property access.\n emitTransport.postMessage(message, origin, transferables)\n } else if (isWebExtensionPort(emitTransport)) {\n emitTransport.postMessage(message)\n } else if (isWebExtensionRuntime(emitTransport)) {\n emitTransport.sendMessage(message)\n } else if (isWebSocket(emitTransport)) {\n emitTransport.send(JSON.stringify(message))\n } else if (isSharedWorker(emitTransport)) {\n emitTransport.port.postMessage(message, transferables)\n } else { // MessagePort | ServiceWorker | Worker\n emitTransport.postMessage(message, transferables)\n }\n}\n","import type { DefaultRevivableModules, RevivableModule } from '.'\nimport type {\n MessageEventTarget,\n MessageFields,\n Uuid,\n} from '../types'\nimport type { Transport } from '../utils/transport'\nimport type { IsJsonOnlyTransport } from '../utils/type-guards'\n\nimport { OSRA_BOX } from '../types'\nimport { isJsonOnlyTransport } from '../utils/type-guards'\n\nexport type { UnderlyingType } from '../utils/type'\n\nexport const BoxBase = {\n [OSRA_BOX]: 'revivable',\n} as const\n\nexport type BoxBase<T extends string = string> =\n & typeof BoxBase\n & { type: T }\n\nexport type RevivableContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n transport: Transport\n remoteUuid: Uuid\n unregisterSignal?: AbortSignal\n /** Typed as a broad dispatcher so revivables can post their own message\n * variants without triggering contravariant function-parameter mismatches\n * across modules. The shape is enforced structurally via `MessageFields`. */\n sendMessage: (message: MessageFields & Record<string, unknown>) => void\n revivableModules: TModules\n eventTarget: MessageEventTarget<TModules>\n}\n\n/** Extract the type a module's `isType` narrows to. Modules marked\n * `capableOnly: true` (clonable, transferable) contribute `never` on JSON\n * transports so users can't type values JSON would silently drop. */\nexport type ExtractType<T, Ctx extends RevivableContext = RevivableContext> =\n T extends { capableOnly: true }\n ? IsJsonOnlyTransport<Ctx['transport']> extends true\n ? never\n : T extends { isType: (value: unknown) => value is infer S } ? S : never\n : T extends { isType: (value: unknown) => value is infer S } ? S : never\n\nexport type ExtractBox<T> =\n T extends { box: (...args: any[]) => infer B }\n ? B\n : never\n\nexport type ExtractMessages<T> =\n T extends { Messages?: infer B }\n ? B extends { type: string }\n ? string extends B['type'] ? never : B\n : never\n : never\n\nexport type InferMessages<TModules extends readonly unknown[]> =\n ExtractMessages<TModules[number]>\n\nexport type InferRevivables<\n TModules extends readonly unknown[],\n Ctx extends RevivableContext = RevivableContext,\n> =\n ExtractType<TModules[number], Ctx>\n\nexport type InferRevivableBox<TModules extends readonly unknown[]> =\n ExtractBox<TModules[number]>\n\nexport const isRevivableBox = (value: unknown): value is BoxBase =>\n !!value\n && typeof value === 'object'\n && OSRA_BOX in value\n && value[OSRA_BOX] === 'revivable'\n\nexport const serializeError = (error: unknown): string =>\n error instanceof Error ? (error.stack ?? String(error)) : String(error)\n\n/** Wire shape for an ArrayBuffer: base64 on JSON, raw on clone. */\nexport type BoxedBuffer<TCtx extends RevivableContext = RevivableContext> =\n IsJsonOnlyTransport<TCtx['transport']> extends true ? { base64Buffer: string }\n : IsJsonOnlyTransport<TCtx['transport']> extends false ? { arrayBuffer: ArrayBuffer }\n : { base64Buffer: string } | { arrayBuffer: ArrayBuffer }\n\nexport const boxBuffer = <TCtx extends RevivableContext>(\n buffer: ArrayBuffer,\n context: TCtx,\n): BoxedBuffer<TCtx> =>\n (isJsonOnlyTransport(context.transport)\n ? { base64Buffer: new Uint8Array(buffer).toBase64() }\n : { arrayBuffer: buffer }\n ) as BoxedBuffer<TCtx>\n\nexport const reviveBuffer = (boxed: { arrayBuffer: ArrayBuffer } | { base64Buffer: string }): ArrayBuffer =>\n 'arrayBuffer' in boxed\n ? boxed.arrayBuffer\n : Uint8Array.fromBase64(boxed.base64Buffer).buffer\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase, boxBuffer, reviveBuffer } from './utils'\n\nexport const type = 'arrayBuffer' as const\n\nexport const isType = (value: unknown): value is ArrayBuffer =>\n value instanceof ArrayBuffer\n\nexport const box = <T extends ArrayBuffer, T2 extends RevivableContext>(\n value: T,\n context: T2,\n) => ({\n ...BoxBase,\n type,\n ...boxBuffer(value, context),\n})\n\nexport const revive = <T extends ReturnType<typeof box>>(\n value: T,\n _context: RevivableContext,\n) => reviveBuffer(value)\n\nconst typeCheck = () => {\n const boxed = box(new ArrayBuffer(10), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: ArrayBuffer = revived\n // @ts-expect-error - not an ArrayBuffer\n const notArrayBuffer: string = revived\n // @ts-expect-error - cannot box non-ArrayBuffer\n box('not an array buffer', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\n\nexport const type = 'date' as const\n\nexport const isType = (value: unknown): value is Date =>\n value instanceof Date\n\nexport const box = <T extends Date, T2 extends RevivableContext>(\n value: T,\n _context: T2\n) => ({\n ...BoxBase,\n type,\n ISOString: value.toISOString()\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n _context: T2\n) => new Date(value.ISOString)\n\nconst typeCheck = () => {\n const boxed = box(new Date(), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Date = revived\n // @ts-expect-error - not a Date\n const notDate: string = revived\n // @ts-expect-error - cannot box non-Date\n box('not a date', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\n\nexport const type = 'headers' as const\n\nexport const isType = (value: unknown): value is Headers =>\n value instanceof Headers\n\nexport const box = <T extends Headers, T2 extends RevivableContext>(\n value: T,\n _context: T2\n) => ({\n ...BoxBase,\n type,\n entries: [...value.entries()]\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n _context: T2\n): Headers => {\n return new Headers(value.entries)\n}\n\nconst typeCheck = () => {\n const boxed = box(new Headers(), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Headers = revived\n // @ts-expect-error - not a Headers\n const notHeaders: string = revived\n // @ts-expect-error - cannot box non-Headers\n box('not a header', {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'error' as const\n\nexport type BoxedError =\n & BoxBaseType<typeof type>\n & {\n name: string\n message: string\n stack: string\n cause?: Capable\n }\n\nexport const isType = (value: unknown): value is Error =>\n value instanceof Error\n\nexport const box = <T extends Error, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedError => {\n const hasCause = 'cause' in value && value.cause !== undefined\n return {\n ...BoxBase,\n type,\n name: value.name,\n message: value.message,\n stack: value.stack || value.toString(),\n ...(hasCause ? { cause: recursiveBox(value.cause as Capable, context) as Capable } : {}),\n }\n}\n\nexport const revive = <T extends BoxedError, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): Error => {\n const cause = value.cause !== undefined\n ? recursiveRevive(value.cause, context)\n : undefined\n const err = cause !== undefined\n ? new Error(value.message, { cause })\n : new Error(value.message)\n if (value.name) err.name = value.name\n if (value.stack) err.stack = value.stack\n return err\n}\n\nconst typeCheck = () => {\n const boxed = box(new Error('test'), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Error = revived\n // @ts-expect-error - not an Error\n const notError: string = revived\n // @ts-expect-error - cannot box non-Error\n box('not an error', {} as RevivableContext)\n}\n","import type { RevivableContext, UnderlyingType, BoxedBuffer } from './utils'\nimport type { TypedArray, TypedArrayType } from '../utils/type-guards'\n\nimport { BoxBase, boxBuffer, reviveBuffer } from './utils'\nimport {\n isTypedArray,\n typedArrayToType,\n typedArrayTypeToTypedArrayConstructor,\n} from '../utils/type-guards'\n\nexport const type = 'typedArray' as const\n\ntype BoxedTypedArray<T extends TypedArray, T2 extends RevivableContext> =\n & typeof BoxBase\n & { type: typeof type }\n & { typedArrayType: TypedArrayType }\n & BoxedBuffer<T2>\n & { [UnderlyingType]: T }\n\nexport const isType = isTypedArray\n\nexport const box = <T extends TypedArray, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedTypedArray<T, T2> =>\n ({\n ...BoxBase,\n type,\n typedArrayType: typedArrayToType(value),\n ...boxBuffer(value.buffer as ArrayBuffer, context),\n }) as unknown as BoxedTypedArray<T, T2>\n\nexport const revive = <T extends BoxedTypedArray<TypedArray, RevivableContext>>(\n value: T,\n _context: RevivableContext,\n): T[UnderlyingType] =>\n new (typedArrayTypeToTypedArrayConstructor(value.typedArrayType))(reviveBuffer(value)) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const uint8Boxed = box(new Uint8Array(10), {} as RevivableContext)\n const uint8Revived = revive(uint8Boxed, {} as RevivableContext)\n const expectedUint8: Uint8Array = uint8Revived\n // @ts-expect-error - wrong typed array type\n const wrongType: Int32Array = uint8Revived\n\n const float32Boxed = box(new Float32Array(10), {} as RevivableContext)\n const float32Revived = revive(float32Boxed, {} as RevivableContext)\n const expectedFloat32: Float32Array = float32Revived\n // @ts-expect-error - wrong typed array type\n const wrongFloat: Uint8Array = float32Revived\n\n // @ts-expect-error - cannot box non-TypedArray\n box('not a typed array', {} as RevivableContext)\n}\n","import type { TypedMessagePort, TypedMessagePortEventMap } from './typed-message-channel'\n\nexport class EventPort<T> extends EventTarget {\n addEventListener<K extends keyof TypedMessagePortEventMap<T> & string>(\n type: K,\n listener: ((event: TypedMessagePortEventMap<T>[K]) => void) | null,\n options?: boolean | AddEventListenerOptions\n ): void\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions\n ): void\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions\n ): void {\n super.addEventListener(type, listener, options)\n }\n\n removeEventListener<K extends keyof TypedMessagePortEventMap<T> & string>(\n type: K,\n listener: ((event: TypedMessagePortEventMap<T>[K]) => void) | null,\n options?: boolean | EventListenerOptions\n ): void\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void {\n super.removeEventListener(type, listener, options)\n }\n\n _peer: EventPort<any> | undefined\n _queue: MessageEvent<T>[] = []\n _started = false\n _closed = false\n _onClose: (() => void) | undefined\n\n private _onmessage: ((this: MessagePort, ev: MessageEvent<T>) => unknown) | null = null\n\n get onmessage(): ((this: MessagePort, ev: MessageEvent<T>) => unknown) | null {\n return this._onmessage\n }\n set onmessage(value: ((this: MessagePort, ev: MessageEvent<T>) => unknown) | null) {\n this._onmessage = value\n if (value !== null) this.start()\n }\n\n onmessageerror: ((this: MessagePort, ev: MessageEvent) => unknown) | null = null\n\n dispatchEvent(event: Event): boolean {\n if (event.type === 'message') {\n this._onmessage?.call(this, event as MessageEvent<T>)\n } else if (event.type === 'messageerror') {\n this.onmessageerror?.call(this, event as MessageEvent)\n }\n return super.dispatchEvent(event)\n }\n\n postMessage(message: T, _options?: Transferable[] | StructuredSerializeOptions): void {\n const peer = this._peer\n if (!peer || peer._closed) return\n queueMicrotask(() => {\n if (peer._closed) return\n const event = new MessageEvent('message', { data: message })\n if (peer._started) {\n peer.dispatchEvent(event)\n } else {\n peer._queue.push(event)\n }\n })\n }\n\n start(): void {\n if (this._started) return\n this._started = true\n for (const event of this._queue.splice(0)) {\n this.dispatchEvent(event)\n }\n }\n\n close(): void {\n if (this._closed) return\n this._closed = true\n this._queue.length = 0\n this._onClose?.()\n }\n}\n\nexport interface EventPort<T>\n extends Omit<\n TypedMessagePort<T>,\n 'addEventListener' | 'removeEventListener'\n > {}\n\nexport class EventChannel<T1 = unknown, T2 = unknown> {\n readonly port1: EventPort<T1>\n readonly port2: EventPort<T2>\n\n constructor() {\n const port1 = new EventPort<T1>()\n const port2 = new EventPort<T2>()\n port1._peer = port2\n port2._peer = port1\n this.port1 = port1\n this.port2 = port2\n }\n}\n","/**\n * Run `cleanup` after `target` is garbage-collected. Returns a handle to\n * cancel the tracking before that happens.\n *\n * Backed by a single shared FinalizationRegistry — every revivable that\n * needs FR semantics goes through this so the boilerplate (token,\n * unregister, cycle-safety contract) lives in one place.\n *\n * Contract: `cleanup` MUST NOT (transitively) reference `target`. The\n * registry strong-holds the cleanup callback, the cleanup would then\n * strong-hold target, and the engine would never see target as\n * collectable. Use a `WeakRef` if cleanup needs something that points\n * back at target.\n *\n * Errors thrown from cleanup are swallowed: the callback fires from the\n * FR thread, where there's no caller to surface them to.\n */\nexport type GcUnregister = () => void\n\nconst registry = new FinalizationRegistry<() => void>((cleanup) => {\n try { cleanup() } catch { /* no caller to surface to */ }\n})\n\nexport const trackGc = (target: WeakKey, cleanup: () => void): GcUnregister => {\n const token = {}\n registry.register(target, cleanup, token)\n return () => registry.unregister(token)\n}\n","import type { Capable, StructurableTransferable, Uuid } from '../types'\nimport type { TypedMessagePort } from '../utils/typed-message-channel'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '../utils/type'\nimport type {\n BadFieldValue, BadFieldPath, BadFieldParent,\n ErrorMessage, BadValue, Path, ParentObject\n} from '../utils/capable-check'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\nimport { getTransferableObjects, isJsonOnlyTransport } from '../utils'\nimport { EventChannel, EventPort } from '../utils/event-channel'\nimport { trackGc } from '../utils/gc-tracker'\n\nexport const type = 'messagePort' as const\n\nexport type Messages =\n | { type: 'message', remoteUuid: Uuid, data: Capable, portId: Uuid }\n | { type: 'message-port-close', remoteUuid: Uuid, portId: Uuid }\n\nexport declare const Messages: Messages\n\nexport type AnyPort<T = Capable> =\n | TypedMessagePort<T>\n | EventPort<T>\n\nexport type BoxedMessagePort<T = Capable> =\n & BoxBaseType<typeof type>\n & (\n | { portId: Uuid, synthetic: true }\n | { portId: Uuid, synthetic: false }\n | { port: AnyPort<T>, autoBox?: boolean }\n )\n & { [UnderlyingType]: TypedMessagePort<T> }\n\n// `[T] extends [Capable]` disables distributive conditionals so `A | B` gives\n// back `AnyPort<A | B>`, not `AnyPort<A> | AnyPort<B>`. The error branch\n// intersects with AnyPort<T> so excess-property check targets the failure\n// rather than the user's port-shaped keys.\ntype StructurableTransferablePort<T> = [T] extends [Capable]\n ? AnyPort<T>\n : AnyPort<T> & {\n [ErrorMessage]: 'Message type must extend Capable'\n [BadValue]: BadFieldValue<T, Capable>\n [Path]: BadFieldPath<T, Capable>\n [ParentObject]: BadFieldParent<T, Capable>\n }\n\ntype ConnectionMessagePortState = {\n /** O(1) per-portId dispatch — avoids the O(N) addEventListener scan\n * that was the bottleneck for tight-loop RPC traffic. */\n portHandlers: Map<string, (message: Messages) => void>\n}\n\nconst connectionStateMap = new WeakMap<RevivableContext, ConnectionMessagePortState>()\n\nconst getState = (context: RevivableContext): ConnectionMessagePortState => {\n const state = connectionStateMap.get(context)\n if (!state) throw new Error('osra message-port: connection state missing; did init() run?')\n return state\n}\n\nexport const init = (context: RevivableContext): void => {\n const state: ConnectionMessagePortState = { portHandlers: new Map() }\n connectionStateMap.set(context, state)\n\n context.eventTarget.addEventListener('message', ({ detail }) => {\n if (detail.type !== 'message' && detail.type !== 'message-port-close') return\n state.portHandlers.get(detail.portId)?.(detail)\n })\n}\n\nexport const isType = (value: unknown): value is MessagePort | EventPort<StructurableTransferable> =>\n value instanceof MessagePort || value instanceof EventPort\n\nconst sendClose = (context: RevivableContext, portId: Uuid) => {\n try {\n context.sendMessage({ type: 'message-port-close', remoteUuid: context.remoteUuid, portId })\n } catch { /* connection torn down */ }\n}\n\nconst postRevived = <T>(port: AnyPort<T>, data: T, synthetic: boolean) => {\n if (synthetic) port.postMessage(data)\n else port.postMessage(data, getTransferableObjects(data))\n}\n\nexport const box = <T, T2 extends RevivableContext = RevivableContext>(\n value: StructurableTransferablePort<T>,\n context: T2,\n options?: { autoBox?: boolean },\n): BoxedMessagePort<T> => {\n // Synthetic EventPorts aren't structured-clonable, so even on a clone\n // transport we route them via portId.\n const synthetic = value instanceof EventPort\n if (!synthetic && !isJsonOnlyTransport(context.transport)) {\n return {\n ...BoxBase, type, port: value,\n ...(options?.autoBox ? { autoBox: true } : {}),\n } as BoxedMessagePort<T>\n }\n\n const { portHandlers } = getState(context)\n const liveRef: AnyPort<T> = value\n const portId: Uuid = globalThis.crypto.randomUUID()\n\n let cleanedUp = false\n const performCleanup = () => {\n if (cleanedUp) return\n cleanedUp = true\n portHandlers.delete(portId)\n unregisterGc?.()\n liveRef.removeEventListener('message', outgoingListener as EventListener)\n }\n\n const handler = (message: Messages) => {\n if (message.type === 'message-port-close') {\n performCleanup()\n liveRef.close()\n return\n }\n postRevived(liveRef, recursiveRevive(message.data, context) as T, false)\n }\n\n function outgoingListener({ data }: MessageEvent<Capable>) {\n context.sendMessage({\n type: 'message',\n remoteUuid: context.remoteUuid,\n data: recursiveBox(data, context),\n portId,\n })\n }\n\n // Safety net only — `handler` strong-holds liveRef via portHandlers, so\n // the FR won't fire while the connection is alive. Real cleanup runs via\n // the wire `message-port-close` or EventPort `_onClose`.\n const unregisterGc = trackGc(liveRef, () => {\n sendClose(context, portId)\n performCleanup()\n })\n\n liveRef.addEventListener('message', outgoingListener as EventListener)\n liveRef.start()\n\n if (liveRef instanceof EventPort) {\n liveRef._onClose = () => {\n if (cleanedUp) return\n sendClose(context, portId)\n performCleanup()\n }\n }\n\n portHandlers.set(portId, handler)\n\n return { ...BoxBase, type, portId, synthetic } as BoxedMessagePort<T>\n}\n\nexport const revive = <T extends Capable, T2 extends RevivableContext>(\n value: BoxedMessagePort<T>,\n context: T2,\n): TypedMessagePort<T> => {\n if ('port' in value) {\n if (value.autoBox) return createProtocolPort<T>(value.port as TypedMessagePort<Capable>, context)\n return value.port\n }\n return reviveViaPortId<T>(value.portId, context, value.synthetic)\n}\n\n/** Wraps a real MessagePort so revivables can treat it like a transparent\n * EventTarget that auto-boxes/revives — letting live values (Promises,\n * Functions, …) ride a clone-only transport. */\nconst createProtocolPort = <T>(\n port: TypedMessagePort<Capable>,\n ctx: RevivableContext,\n): TypedMessagePort<T> => {\n const target = new EventTarget() as TypedMessagePort<T>\n const onMessage = ({ data }: MessageEvent<Capable>): void => {\n target.dispatchEvent(new MessageEvent('message', { data: recursiveRevive(data, ctx) }))\n }\n port.addEventListener('message', onMessage)\n target.postMessage = (data: T, opt?: Transferable[] | StructuredSerializeOptions) => {\n const boxed = recursiveBox(data as Capable, ctx)\n const transferables = getTransferableObjects(boxed)\n const extra = Array.isArray(opt) ? opt : []\n port.postMessage(boxed, extra.length ? [...transferables, ...extra] : transferables)\n }\n target.start = () => port.start()\n target.close = () => {\n port.removeEventListener('message', onMessage)\n port.close()\n }\n return target\n}\n\n/** Factory for revivable-internal channels. Returns a local port that\n * auto-boxes live values regardless of transport, plus a pre-boxed remote\n * port the revivable embeds in its Boxed* structure. */\nexport const createRevivableChannel = <T extends Capable>(\n context: RevivableContext,\n): { localPort: AnyPort<T>, boxedRemote: BoxedMessagePort<T> } => {\n if (isJsonOnlyTransport(context.transport)) {\n const { port1, port2 } = new EventChannel<T, T>()\n return {\n localPort: port1,\n boxedRemote: box(port2 as StructurableTransferablePort<T>, context),\n }\n }\n const { port1, port2 } = new MessageChannel() as unknown as {\n port1: TypedMessagePort<Capable>\n port2: TypedMessagePort<Capable>\n }\n return {\n localPort: createProtocolPort<T>(port1, context) as unknown as AnyPort<T>,\n boxedRemote: box(port2 as unknown as StructurableTransferablePort<T>, context, { autoBox: true }),\n }\n}\n\nconst reviveViaPortId = <T extends Capable>(\n portId: Uuid,\n context: RevivableContext,\n synthetic: boolean,\n): TypedMessagePort<T> => {\n const { portHandlers } = getState(context)\n const { port1: userPort, port2: internalPort } =\n synthetic\n ? new EventChannel<T, T>()\n : new MessageChannel() as { port1: TypedMessagePort<T>, port2: TypedMessagePort<T> }\n const userPortRef = new WeakRef(userPort)\n // For synthetic EventChannels, internalPort._peer === userPort — holding\n // internalPort strongly from the trackGc cleanup would re-pin userPort.\n const internalPortRef = new WeakRef(internalPort)\n\n let cleanedUp = false\n const performCleanup = () => {\n if (cleanedUp) return\n cleanedUp = true\n portHandlers.delete(portId)\n const internal = internalPortRef.deref()\n internal?.removeEventListener('message', internalPortListener as EventListener)\n internal?.close()\n unregisterGc?.()\n }\n\n const handler = (message: Messages) => {\n if (message.type === 'message-port-close') {\n performCleanup()\n userPortRef.deref()?.close()\n return\n }\n if (!userPortRef.deref()) {\n performCleanup()\n return\n }\n const internal = internalPortRef.deref()\n if (!internal) return\n postRevived(internal, recursiveRevive(message.data, context) as T, synthetic)\n }\n\n const internalPortListener = ({ data }: MessageEvent<T>) => {\n context.sendMessage({\n type: 'message',\n remoteUuid: context.remoteUuid,\n data: recursiveBox(data, context),\n portId,\n })\n }\n\n const unregisterGc = trackGc(userPort, () => {\n sendClose(context, portId)\n performCleanup()\n })\n\n if (userPort instanceof EventPort) {\n userPort._onClose = () => {\n if (cleanedUp) return\n sendClose(context, portId)\n performCleanup()\n }\n }\n\n internalPort.addEventListener('message', internalPortListener as EventListener)\n internalPort.start()\n\n portHandlers.set(portId, handler)\n\n return userPort\n}\n\nconst typeCheck = () => {\n const port = {} as TypedMessagePort<{ foo: string }>\n const boxed = box(port, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: AnyPort<{ foo: string }> = revived\n // @ts-expect-error - wrong message type\n const wrongType: AnyPort<{ bar: number }> = revived\n box({} as TypedMessagePort<Promise<string>>, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '.'\nimport type {\n BadFieldValue, BadFieldPath, BadFieldParent,\n ErrorMessage, BadValue, Path, ParentObject\n} from '../utils/capable-check'\n\nimport { BoxBase, serializeError } from './utils'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort,\n BoxedMessagePort,\n AnyPort,\n} from './message-port'\n\nexport const type = 'promise' as const\n\nexport type Context =\n | { type: 'resolve', data: Capable }\n | { type: 'reject', error: string }\n\n// Error branches intersect with T so the user's own keys land on the target —\n// otherwise TS's excess-property check flags a user key instead of the failure.\ntype CapablePromise<T> = T extends Promise<infer U>\n ? U extends Capable\n ? T\n : T & {\n [ErrorMessage]: 'Value type must extend a Promise that resolves to a Capable'\n [BadValue]: BadFieldValue<U, Capable>\n [Path]: BadFieldPath<U, Capable>\n [ParentObject]: BadFieldParent<U, Capable>\n }\n : T & {\n [ErrorMessage]: 'Value type must extend a Promise that resolves to a Capable'\n [BadValue]: T\n [Path]: ''\n [ParentObject]: T\n }\n\ntype ExtractCapable<T> = T extends Promise<infer U>\n ? U extends Capable ? U : never\n : never\n\nconst isCapablePromise = <T, U extends Capable = ExtractCapable<T>>(value: T): value is T & Promise<U> =>\n value instanceof Promise\n\nexport type BoxedPromise<T extends Capable = Capable> =\n & BoxBaseType<typeof type>\n & { port: BoxedMessagePort<Context> }\n & { [UnderlyingType]: T }\n\n// Pins the revived port between executor return and result arrival — the\n// port↔listener cycle has no other anchor (the caller only holds the\n// returned Promise). The once-listener removes its entry on settle.\nconst inFlightPromisePorts = new Set<AnyPort<Context>>()\n\nexport const isType = (value: unknown): value is Promise<any> =>\n value instanceof Promise\n\nexport const box = <T, T2 extends RevivableContext>(\n value: CapablePromise<T>,\n context: T2\n): BoxedPromise<ExtractCapable<T>> => {\n if (!isCapablePromise(value)) throw new TypeError('Expected Promise')\n const { localPort, boxedRemote } = createRevivableChannel<Context>(context)\n\n const sendResult = (result: Context) => {\n localPort.postMessage(result)\n localPort.close()\n }\n\n value\n .then((data: ExtractCapable<T>) => sendResult({ type: 'resolve', data }))\n .catch((error: unknown) => sendResult({ type: 'reject', error: serializeError(error) }))\n\n return { ...BoxBase, type, port: boxedRemote } as BoxedPromise<ExtractCapable<T>>\n}\n\nexport const revive = <T extends BoxedPromise, T2 extends RevivableContext>(\n value: T,\n context: T2\n) => {\n const port = reviveMessagePort(value.port, context)\n inFlightPromisePorts.add(port)\n return new Promise<T[UnderlyingType]>((resolve, reject) => {\n port.addEventListener('message', ({ data: result }) => {\n if (result.type === 'resolve') resolve(result.data as T[UnderlyingType])\n else reject(result.error)\n port.close()\n inFlightPromisePorts.delete(port)\n }, { once: true })\n port.start()\n })\n}\n\nconst typeCheck = () => {\n const boxed = box(Promise.resolve(1 as const), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Promise<1> = revived\n // @ts-expect-error\n const notExpected: Promise<string> = revived\n // @ts-expect-error\n box(1 as const, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { UnderlyingType, RevivableContext, BoxBase as BoxBaseType } from './utils'\n\nimport { BoxBase, serializeError } from './utils'\nimport { recursiveBox } from '.'\nimport { getTransferableObjects } from '../utils'\nimport { EventChannel, type EventPort } from '../utils/event-channel'\nimport { box as boxMessagePort, revive as reviveMessagePort, BoxedMessagePort } from './message-port'\n\nexport const type = 'function' as const\n\ntype ResultMessage =\n | { __osra_ok__: true, value: Capable }\n | { __osra_err__: true, error: string }\n\ntype CallContext = [EventPort<Capable>, Capable[]]\n\n// Pins return-value ports between call-site return and result arrival —\n// the (port ↔ once-listener ↔ resolve/reject) cycle has no other anchor.\nconst inFlightReturnPorts = new Set<EventPort<Capable>>()\n\nexport type BoxedFunction<T extends (...args: any[]) => any = (...args: any[]) => any> =\n & BoxBaseType<typeof type>\n & { port: BoxedMessagePort<CallContext> }\n & { [UnderlyingType]: (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>> }\n\ntype CapableFunction<T> = T extends (...args: infer P) => infer R\n ? P extends Capable[]\n ? R extends Capable ? T : never\n : never\n : never\n\nexport const isType = (value: unknown): value is (...args: any[]) => any =>\n typeof value === 'function'\n\nexport const box = <T extends (...args: any[]) => any, T2 extends RevivableContext>(\n value: T & CapableFunction<T>,\n context: T2,\n): BoxedFunction<T> => {\n // EventChannel rather than MessageChannel: revived live values arriving\n // in args (functions, EventTarget façades, …) aren't structured-clonable.\n const { port1: localPort, port2: remotePort } = new EventChannel<CallContext, CallContext>()\n\n localPort.addEventListener('message', ({ data }) => {\n // Don't recursiveRevive — message-port handler already revived in place.\n // Re-walking would Object.fromEntries plain args, breaking identity.\n const [returnPort, args] = data as CallContext\n ;(async () => {\n let message: ResultMessage\n try {\n const resolved = await value(...(args as Parameters<T>))\n message = { __osra_ok__: true, value: resolved as Capable }\n } catch (error) {\n message = { __osra_err__: true, error: serializeError(error) }\n }\n const boxedResult = recursiveBox(message as Capable, context)\n returnPort.postMessage(boxedResult, getTransferableObjects(boxedResult))\n // Defer close so the result reaches the peer before tear-down. The\n // close fires _onClose, dropping per-call routing entries on both\n // sides — without it portHandlers grows one entry per call.\n queueMicrotask(() => {\n try { returnPort.close() } catch { /* may already be closed */ }\n })\n })()\n })\n localPort.start()\n\n return {\n ...BoxBase,\n type,\n port: boxMessagePort(remotePort as unknown as MessagePort, context),\n } as unknown as BoxedFunction<T>\n}\n\nexport const revive = <T extends BoxedFunction, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): T[UnderlyingType] => {\n const port = reviveMessagePort(value.port, context) as unknown as MessagePort\n\n return ((...args: Capable[]) =>\n new Promise((resolve, reject) => {\n const { port1: returnLocal, port2: returnRemote } = new EventChannel<Capable, Capable>()\n inFlightReturnPorts.add(returnLocal)\n\n returnLocal.addEventListener('message', ({ data }) => {\n const message = data as ResultMessage\n if ('__osra_ok__' in message) resolve(message.value)\n else reject(message.error)\n returnLocal.close()\n inFlightReturnPorts.delete(returnLocal)\n }, { once: true })\n returnLocal.start()\n\n const callContext = recursiveBox([returnRemote, args] as unknown as Capable, context)\n port.postMessage(callContext, getTransferableObjects(callContext))\n })) as T[UnderlyingType]\n}\n\nconst typeCheck = () => {\n const boxed = box((a: number, b: string) => a + b.length, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: (a: number, b: string) => Promise<number> = revived\n // @ts-expect-error - wrong return type\n const wrongReturn: (a: number, b: string) => Promise<string> = revived\n // @ts-expect-error - wrong parameter types\n const wrongParams: (a: string, b: number) => Promise<number> = revived\n // @ts-expect-error - non-Capable parameter type (WeakMap isn't structured-clonable)\n box((a: WeakMap<object, string>) => a.toString(), {} as RevivableContext)\n // @ts-expect-error - non-Capable return type\n box(() => new WeakMap<object, string>(), {} as RevivableContext)\n}\n","import type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '.'\n\nimport { BoxBase } from './utils'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort,\n BoxedMessagePort\n} from './message-port'\n\nexport const type = 'readableStream' as const\n\nexport type PullContext = {\n type: 'pull' | 'cancel'\n}\n\ntype ChunkMessage<T = unknown> = Promise<ReadableStreamReadResult<T>>\n\ntype Msg = PullContext | ChunkMessage\n\nexport type BoxedReadableStream<T extends ReadableStream = ReadableStream> =\n & BoxBaseType<typeof type>\n & { port: BoxedMessagePort<Msg> }\n & { [UnderlyingType]: T }\n\nexport const isType = (value: unknown): value is ReadableStream =>\n value instanceof ReadableStream\n\nexport const box = <T extends ReadableStream, T2 extends RevivableContext>(\n value: T,\n context: T2\n): BoxedReadableStream<T> => {\n const { localPort, boxedRemote } = createRevivableChannel<Msg>(context)\n const reader = value.getReader()\n\n localPort.addEventListener('message', ({ data }) => {\n if ('type' in data && data.type === 'pull') {\n // reader.read() is a Promise — localPort boxes it for the transport.\n localPort.postMessage(reader.read())\n } else {\n reader.cancel()\n localPort.close()\n }\n })\n localPort.start()\n\n return { ...BoxBase, type, port: boxedRemote } as BoxedReadableStream<T>\n}\n\nexport const revive = <T extends BoxedReadableStream, T2 extends RevivableContext>(\n value: T,\n context: T2\n): T[UnderlyingType] => {\n const port = reviveMessagePort(value.port, context)\n port.start()\n\n return new ReadableStream({\n pull: (controller) => new Promise<void>((resolve, reject) => {\n port.addEventListener('message', ({ data }) => {\n if (!(data instanceof Promise)) return\n data\n .then(result => {\n if (result.done) controller.close()\n else controller.enqueue(result.value)\n resolve()\n })\n .catch(reject)\n }, { once: true })\n port.postMessage({ type: 'pull' })\n }),\n cancel: () => {\n port.postMessage({ type: 'cancel' })\n // Defer close so the cancel message dispatches before tear-down.\n queueMicrotask(() => port.close())\n },\n }) as T[UnderlyingType]\n}\n\nconst typeCheck = () => {\n const stream = new ReadableStream<number>()\n const boxed = box(stream, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: ReadableStream<number> = revived\n // @ts-expect-error - wrong stream type\n const wrongType: ReadableStream<string> = revived\n // @ts-expect-error - not a ReadableStream\n box('not a stream', {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { BoxedMessagePort } from './message-port'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\nimport {\n createRevivableChannel,\n revive as reviveMessagePort,\n} from './message-port'\n\nexport const type = 'abortSignal' as const\n\ntype AbortMessage = {\n type: 'abort'\n reason?: Capable\n}\n\nexport type BoxedAbortSignal =\n & BoxBaseType<typeof type>\n & {\n aborted: boolean\n reason?: Capable\n port: BoxedMessagePort<AbortMessage>\n }\n\nexport const isType = (value: unknown): value is AbortSignal =>\n value instanceof AbortSignal\n\nexport const box = <T extends AbortSignal, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedAbortSignal => {\n const { localPort, boxedRemote } = createRevivableChannel<AbortMessage>(context)\n\n if (!value.aborted) {\n value.addEventListener('abort', () => {\n localPort.postMessage({ type: 'abort', reason: value.reason as Capable })\n localPort.close()\n }, { once: true })\n } else {\n localPort.close()\n }\n\n // Eagerly-aborted reason rides the wrapper, so we must box it here —\n // recursiveBox short-circuits on OSRA_BOX without descending in.\n return {\n ...BoxBase,\n type,\n aborted: value.aborted,\n reason: value.aborted ? recursiveBox(value.reason as Capable, context) as Capable : undefined,\n port: boxedRemote,\n }\n}\n\nexport const revive = <T extends BoxedAbortSignal, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): AbortSignal => {\n const controller = new AbortController()\n\n if (value.aborted) {\n controller.abort(recursiveRevive(value.reason as Capable, context))\n return controller.signal\n }\n\n const port = reviveMessagePort(value.port, context)\n port.start()\n\n port.addEventListener('message', ({ data: message }) => {\n if (message.type === 'abort') {\n controller.abort(recursiveRevive(message.reason as Capable, context))\n port.close()\n }\n })\n\n return controller.signal\n}\n\nconst typeCheck = () => {\n const boxed = box(new AbortController().signal, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: AbortSignal = revived\n // @ts-expect-error - not an AbortSignal\n const notAbortSignal: string = revived\n // @ts-expect-error - cannot box non-AbortSignal\n box('not an abort signal', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\nimport { box as boxHeaders, revive as reviveHeaders } from './headers'\nimport { box as boxReadableStream, revive as reviveReadableStream } from './readable-stream'\n\nexport const type = 'response' as const\n\nexport const isType = (value: unknown): value is Response =>\n value instanceof Response\n\nexport const box = <T extends Response, T2 extends RevivableContext>(\n value: T,\n context: T2\n) => ({\n ...BoxBase,\n type,\n status: value.status,\n statusText: value.statusText,\n headers: boxHeaders(value.headers, context),\n body: value.body ? boxReadableStream(value.body, context) : null,\n url: value.url,\n redirected: value.redirected\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n context: T2\n): Response => {\n const headers = reviveHeaders(value.headers, context)\n const body = value.body ? reviveReadableStream(value.body, context) : null\n\n return new Response(body, {\n status: value.status,\n statusText: value.statusText,\n headers\n })\n}\n\nconst typeCheck = () => {\n const boxed = box(new Response('body', { status: 200 }), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Response = revived\n // @ts-expect-error - not a Response\n const notResponse: string = revived\n // @ts-expect-error - cannot box non-Response\n box('not a response', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\nimport { box as boxHeaders, revive as reviveHeaders } from './headers'\nimport { box as boxReadableStream, revive as reviveReadableStream } from './readable-stream'\n\nexport const type = 'request' as const\n\nexport const isType = (value: unknown): value is Request =>\n value instanceof Request\n\nexport const box = <T extends Request, T2 extends RevivableContext>(\n value: T,\n context: T2\n) => ({\n ...BoxBase,\n type,\n method: value.method,\n url: value.url,\n headers: boxHeaders(value.headers, context),\n body: value.body ? boxReadableStream(value.body, context) : null,\n credentials: value.credentials,\n cache: value.cache,\n redirect: value.redirect,\n referrer: value.referrer,\n referrerPolicy: value.referrerPolicy,\n integrity: value.integrity,\n keepalive: value.keepalive\n})\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(\n value: T,\n context: T2\n): Request => {\n const headers = reviveHeaders(value.headers, context)\n const body = value.body ? reviveReadableStream(value.body, context) : null\n\n return new Request(value.url, {\n method: value.method,\n headers,\n body,\n credentials: value.credentials,\n cache: value.cache,\n redirect: value.redirect,\n referrer: value.referrer,\n referrerPolicy: value.referrerPolicy,\n integrity: value.integrity,\n keepalive: value.keepalive,\n // @ts-expect-error - duplex is needed for streaming bodies\n duplex: 'half',\n })\n}\n\nconst typeCheck = () => {\n const boxed = box(new Request('https://example.com'), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Request = revived\n // @ts-expect-error - not a Request\n const notRequest: string = revived\n // @ts-expect-error - cannot box non-Request\n box('not a request', {} as RevivableContext)\n}\n","import type { Capable, Uuid } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '../utils/type'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'identity' as const\n\nexport type Messages = {\n type: 'identity-dispose'\n remoteUuid: Uuid\n id: string\n}\n\nexport declare const Messages: Messages\n\nconst IDENTITY_MARKER: unique symbol = Symbol.for('osra.identity')\n\ntype IdentityWrapper<T = unknown> = {\n readonly [IDENTITY_MARKER]: true\n readonly value: T\n}\n\nexport type BoxedIdentity<T extends Capable = Capable> = BoxBaseType<typeof type> & {\n id: string\n inner?: Capable\n [UnderlyingType]: T\n}\n\nconst isObjectOrFunction = (value: unknown): value is object =>\n value !== null && (typeof value === 'object' || typeof value === 'function')\n\n/** Anything we can hand to WeakMap/WeakRef/FinalizationRegistry. Excludes\n * registered symbols (Symbol.for) — those throw at runtime. */\nconst isWeakKeyable = (value: unknown): value is WeakKey => {\n if (value === null) return false\n const t = typeof value\n if (t === 'object' || t === 'function') return true\n if (t === 'symbol') return Symbol.keyFor(value as symbol) === undefined\n return false\n}\n\nconst isIdentityWrapper = (value: unknown): value is IdentityWrapper =>\n isObjectOrFunction(value) && IDENTITY_MARKER in value && value[IDENTITY_MARKER] === true\n\nconst wrapperMemo = new WeakMap<object, IdentityWrapper>()\n\nconst wrap = (value: object): IdentityWrapper => {\n if (isIdentityWrapper(value)) return value\n const cached = wrapperMemo.get(value)\n if (cached) return cached\n const wrapper: IdentityWrapper = { [IDENTITY_MARKER]: true, value }\n wrapperMemo.set(value, wrapper)\n return wrapper\n}\n\n/** Wrap a value so osra preserves reference identity across the RPC\n * boundary. Idempotent; primitives pass through unchanged. Lies at the\n * type level — runtime value is an IdentityWrapper<T> typed as T. */\nexport const identity = <T>(value: T): T =>\n (isObjectOrFunction(value) ? wrap(value) : value) as T\n\ntype IdentityState = {\n readonly sendIds: WeakMap<WeakKey, string>\n /** id → ref to the value we sent, so a round-trip resolves to the\n * original reference instead of building a fresh proxy. */\n readonly idToSent: Map<string, WeakRef<WeakKey>>\n readonly sendRegistry: FinalizationRegistry<string>\n readonly receiveCache: Map<string, unknown>\n /** Revived value → id, so user code passing a revived value back to\n * its origin replays the peer's id and short-circuits to the real ref. */\n readonly revivedToId: WeakMap<WeakKey, string>\n listenerInstalled: boolean\n}\n\nconst connectionStates = new WeakMap<RevivableContext, IdentityState>()\n\nconst getOrCreateState = (context: RevivableContext): IdentityState => {\n const existing = connectionStates.get(context)\n if (existing) return existing\n const sendIds = new WeakMap<WeakKey, string>()\n const idToSent = new Map<string, WeakRef<WeakKey>>()\n const receiveCache = new Map<string, unknown>()\n const revivedToId = new WeakMap<WeakKey, string>()\n const sendRegistry = new FinalizationRegistry<string>((id) => {\n idToSent.delete(id)\n try {\n context.sendMessage({ type: 'identity-dispose', remoteUuid: context.remoteUuid, id })\n } catch { /* connection already closed */ }\n })\n const state: IdentityState = {\n sendIds, idToSent, sendRegistry, receiveCache, revivedToId,\n listenerInstalled: false,\n }\n connectionStates.set(context, state)\n installReceiveListener(context, state)\n return state\n}\n\nconst installReceiveListener = (context: RevivableContext, state: IdentityState) => {\n if (state.listenerInstalled) return\n state.listenerInstalled = true\n context.eventTarget.addEventListener('message', ({ detail }) => {\n if (detail?.type !== 'identity-dispose') return\n const revived = state.receiveCache.get(detail.id)\n state.receiveCache.delete(detail.id)\n if (revived !== undefined && isWeakKeyable(revived)) state.revivedToId.delete(revived)\n })\n}\n\nexport const isType = (value: unknown): value is IdentityWrapper =>\n isIdentityWrapper(value)\n\n/** Look up or assign the id for a referenceable value. Returns whether\n * the id is already-known (resend or round-trip) so the caller can skip\n * shipping the inner payload. */\nconst registerForReference = (\n value: WeakKey,\n state: IdentityState,\n): { id: string, isExisting: boolean } => {\n const existingId = state.sendIds.get(value)\n if (existingId !== undefined) return { id: existingId, isExisting: true }\n const receivedId = state.revivedToId.get(value)\n if (receivedId !== undefined) return { id: receivedId, isExisting: true }\n const id = globalThis.crypto.randomUUID()\n state.sendIds.set(value, id)\n state.idToSent.set(id, new WeakRef(value))\n state.sendRegistry.register(value, id)\n return { id, isExisting: false }\n}\n\nexport const box = <T extends Capable, TContext extends RevivableContext>(\n wrapper: IdentityWrapper<T>,\n context: TContext,\n): BoxedIdentity<T> => {\n const state = getOrCreateState(context)\n const inner = wrapper.value\n const innerBox = recursiveBox(inner, context)\n if (!isWeakKeyable(inner)) {\n // Inner can't anchor a WeakMap key — emit fresh id+inner each time, no dedup.\n return { ...BoxBase, type, id: globalThis.crypto.randomUUID(), inner: innerBox } as BoxedIdentity<T>\n }\n const { id, isExisting } = registerForReference(inner, state)\n if (isExisting) return { ...BoxBase, type, id } as BoxedIdentity<T>\n return { ...BoxBase, type, id, inner: innerBox } as BoxedIdentity<T>\n}\n\n/** Identity-box a referenceable value with a caller-supplied inner box,\n * bypassing the recursive-box step. Used by revivables (symbol with\n * description=undefined) where recursing back through their own box\n * would loop into this module again. */\nexport const boxByReference = <T extends WeakKey, TContext extends RevivableContext>(\n value: T,\n innerBox: Capable,\n context: TContext,\n): BoxedIdentity => {\n const state = getOrCreateState(context)\n const { id, isExisting } = registerForReference(value, state)\n if (isExisting) return { ...BoxBase, type, id } as BoxedIdentity\n return { ...BoxBase, type, id, inner: innerBox } as BoxedIdentity\n}\n\nexport const revive = <T extends BoxedIdentity, TContext extends RevivableContext>(\n value: T,\n context: TContext,\n): T[UnderlyingType] => {\n const state = getOrCreateState(context)\n const cached = state.receiveCache.get(value.id)\n if (cached !== undefined) return cached as T[UnderlyingType]\n const originated = state.idToSent.get(value.id)?.deref()\n if (originated !== undefined) return originated as T[UnderlyingType]\n if (!('inner' in value) || value.inner === undefined) {\n throw new Error(`osra identity: received id=${value.id} with no inner payload and no cached value`)\n }\n const revived = recursiveRevive(value.inner, context)\n state.receiveCache.set(value.id, revived)\n if (isWeakKeyable(revived)) state.revivedToId.set(revived, value.id)\n return revived as T[UnderlyingType]\n}\n\nconst typeCheck = () => {\n const fn = () => 42\n const wrapper = { [IDENTITY_MARKER]: true, value: fn } as IdentityWrapper<typeof fn>\n const boxed = box(wrapper, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: typeof fn = revived\n // @ts-expect-error - revived is the original function type, not string\n const notExpected: string = revived\n // @ts-expect-error - cannot box a non-Capable wrapper (WeakMap not assignable)\n box({ [IDENTITY_MARKER]: true, value: new WeakMap() } as IdentityWrapper<WeakMap<object, string>>, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { BoxBase as BoxBaseType, RevivableContext, UnderlyingType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { instanceOfAny, isJsonOnlyTransport } from '../utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'transfer' as const\n\nconst TRANSFER_MARKER: unique symbol = Symbol.for('osra.transfer')\n\ntype TransferWrapper<T = unknown> = {\n readonly [TRANSFER_MARKER]: true\n readonly value: T\n}\n\nexport type BoxedTransfer<T extends Capable = Capable> = BoxBaseType<typeof type> & {\n inner: Capable\n degraded: boolean\n [UnderlyingType]: T\n}\n\nconst isObject = (value: unknown): value is object =>\n value !== null && typeof value === 'object'\n\nconst isTransferWrapper = (value: unknown): value is TransferWrapper =>\n isObject(value) && TRANSFER_MARKER in value && value[TRANSFER_MARKER] === true\n\nconst isWrappableTransferable = (value: unknown): boolean => {\n if (!isObject(value)) return false\n if (ArrayBuffer.isView(value)) return true\n return instanceOfAny(value, [\n globalThis.ArrayBuffer,\n globalThis.MessagePort,\n globalThis.ReadableStream,\n globalThis.WritableStream,\n globalThis.TransformStream,\n globalThis.ImageBitmap,\n globalThis.OffscreenCanvas,\n ])\n}\n\n/** Opt into transfer (move) semantics for a transferable value. Idempotent;\n * non-transferable inputs pass through unchanged. Silently degrades to a\n * copy when the platform/transport can't transfer the given type. Lies at\n * the type level — runtime value is a TransferWrapper<T> typed as T. */\nexport const transfer = <T>(value: T): T =>\n (isWrappableTransferable(value)\n ? { [TRANSFER_MARKER]: true, value }\n : value\n ) as T\n\nexport const isType = (value: unknown): value is TransferWrapper =>\n isTransferWrapper(value)\n\nexport const box = <T extends Capable, TContext extends RevivableContext>(\n wrapper: TransferWrapper<T>,\n context: TContext,\n): BoxedTransfer<T> =>\n // `degraded` tells the send-time walker in getTransferableObjects to treat\n // this box as a regular value (no transfer-list entry). JSON transports\n // can't move ownership, so transfer semantics don't apply.\n ({\n ...BoxBase,\n type,\n inner: recursiveBox(wrapper.value, context),\n degraded: isJsonOnlyTransport(context.transport),\n }) as unknown as BoxedTransfer<T>\n\nexport const revive = <T extends BoxedTransfer, TContext extends RevivableContext>(\n value: T,\n context: TContext,\n): T[UnderlyingType] =>\n recursiveRevive(value.inner, context) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const ab = new ArrayBuffer(10)\n const wrapper = { [TRANSFER_MARKER]: true, value: ab } as TransferWrapper<ArrayBuffer>\n const boxed = box(wrapper, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: ArrayBuffer = revived\n // @ts-expect-error - revived is ArrayBuffer, not string\n const notExpected: string = revived\n // @ts-expect-error - cannot box a non-Capable wrapper (WeakMap not assignable)\n box({ [TRANSFER_MARKER]: true, value: new WeakMap() } as TransferWrapper<WeakMap<object, string>>, {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, UnderlyingType, BoxBase as BoxBaseType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'map' as const\n\nexport type BoxedMap<T extends Map<Capable, Capable> = Map<Capable, Capable>> =\n & BoxBaseType<typeof type>\n & { entries: Array<[Capable, Capable]> }\n & { [UnderlyingType]: T }\n\n// `Map<unknown, unknown>` (rather than `Map<Capable, Capable>`) breaks the\n// Capable ↔ defaultRevivableModules ↔ this module type cycle. box() still\n// narrows to `Map<Capable, Capable>` so misuse is caught there.\nexport const isType = (value: unknown): value is Map<unknown, unknown> =>\n value instanceof Map\n\nexport const box = <T extends Map<Capable, Capable>, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedMap<T> => ({\n ...BoxBase,\n type,\n entries: Array.from(value, ([k, v]): [Capable, Capable] =>\n [recursiveBox(k, context) as Capable, recursiveBox(v, context) as Capable]),\n}) as BoxedMap<T>\n\nexport const revive = <T extends BoxedMap, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): T[UnderlyingType] =>\n new Map(value.entries.map(([k, v]) => [\n recursiveRevive(k, context),\n recursiveRevive(v, context),\n ])) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const m = new Map<string, number>([['a', 1]])\n const boxed = box(m, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Map<string, number> = revived\n // @ts-expect-error - wrong value type\n const wrongValue: Map<string, string> = revived\n // @ts-expect-error - cannot box non-Map\n box('not a map', {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, UnderlyingType, BoxBase as BoxBaseType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'set' as const\n\nexport type BoxedSet<T extends Set<Capable> = Set<Capable>> =\n & BoxBaseType<typeof type>\n & { values: Array<Capable> }\n & { [UnderlyingType]: T }\n\n// `Set<unknown>` breaks the Capable ↔ defaultRevivableModules ↔ this module\n// type cycle; box() narrows to `Set<Capable>` so misuse is caught there.\nexport const isType = (value: unknown): value is Set<unknown> =>\n value instanceof Set\n\nexport const box = <T extends Set<Capable>, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedSet<T> => ({\n ...BoxBase,\n type,\n values: Array.from(value, v => recursiveBox(v, context) as Capable),\n}) as BoxedSet<T>\n\nexport const revive = <T extends BoxedSet, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): T[UnderlyingType] =>\n new Set(value.values.map(v => recursiveRevive(v, context))) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const s = new Set<number>([1, 2, 3])\n const boxed = box(s, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Set<number> = revived\n // @ts-expect-error - wrong value type\n const wrongValue: Set<string> = revived\n // @ts-expect-error - cannot box non-Set\n box('not a set', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\n\nexport const type = 'bigint' as const\n\nexport const isType = (value: unknown): value is bigint =>\n typeof value === 'bigint'\n\nexport const box = <T extends bigint, T2 extends RevivableContext>(\n value: T,\n _context: T2,\n) => ({\n ...BoxBase,\n type,\n value: value.toString(),\n})\n\nexport const revive = <T extends ReturnType<typeof box>>(\n value: T,\n _context: RevivableContext,\n) => BigInt(value.value)\n\nconst typeCheck = () => {\n const boxed = box(123n, {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: bigint = revived\n // @ts-expect-error - not a string\n const notString: string = revived\n // @ts-expect-error - cannot box non-bigint\n box('not a bigint', {} as RevivableContext)\n}\n","import type { Capable } from '../types'\nimport type { RevivableContext, BoxBase as BoxBaseType } from './utils'\n\nimport { BoxBase } from './utils'\nimport { recursiveBox, recursiveRevive } from '.'\n\nexport const type = 'event' as const\n\n/** Boxes Event/CustomEvent only. Subclass-specific fields (MessageEvent.data,\n * ErrorEvent.error, ProgressEvent.loaded, etc.) are dropped on the wire. */\nexport type BoxedEvent =\n & BoxBaseType<typeof type>\n & { eventType: string, bubbles: boolean, cancelable: boolean, composed: boolean, detail?: Capable }\n\nexport const isType = (value: unknown): value is Event =>\n value instanceof Event\n\nexport const box = <T extends Event, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedEvent => ({\n ...BoxBase,\n type,\n eventType: value.type,\n bubbles: value.bubbles,\n cancelable: value.cancelable,\n composed: value.composed,\n ...(value instanceof CustomEvent ? { detail: recursiveBox(value.detail as Capable, context) as Capable } : {}),\n})\n\nexport const revive = <T extends BoxedEvent, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): Event => {\n const init = { bubbles: value.bubbles, cancelable: value.cancelable, composed: value.composed }\n return 'detail' in value\n ? new CustomEvent(value.eventType, { ...init, detail: recursiveRevive(value.detail as Capable, context) })\n : new Event(value.eventType, init)\n}\n\nconst typeCheck = () => {\n const boxed = box(new Event('foo'), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Event = revived\n // @ts-expect-error - not an Event\n const notEvent: string = revived\n // @ts-expect-error - cannot box non-Event\n box('not an event', {} as RevivableContext)\n}\n","import { BoxBase, type RevivableContext } from './utils'\nimport { identity } from './identity'\nimport { box as boxFunction, revive as reviveFunction } from './function'\nimport { trackGc } from '../utils/gc-tracker'\n\nexport const type = 'eventTarget' as const\n\ntype ListenerOpts = boolean | { capture?: boolean, once?: boolean, passive?: boolean, signal?: AbortSignal }\n\nexport const isType = (value: unknown): value is EventTarget => value instanceof EventTarget\n\nexport const box = <T extends EventTarget, T2 extends RevivableContext>(value: T, context: T2) => ({\n ...BoxBase,\n type,\n addListener: boxFunction(\n (type: string, listener: EventListener, options?: ListenerOpts) =>\n value.addEventListener(type, listener, options),\n context,\n ),\n removeListener: boxFunction(\n (type: string, listener: EventListener, options?: ListenerOpts) =>\n value.removeEventListener(type, listener, options),\n context,\n ),\n})\n\nexport type BoxedEventTarget = ReturnType<typeof box>\n\n// Stable EventListener per EventListenerObject so identity() yields the\n// same id on add and remove.\nconst objectWrappers = new WeakMap<EventListenerObject, EventListener>()\nconst toListener = (listerObject: EventListenerOrEventListenerObject): EventListener => {\n if (typeof listerObject === 'function') return listerObject\n let listener = objectWrappers.get(listerObject)\n if (!listener) objectWrappers.set(listerObject, listener = (e) => listerObject.handleEvent(e))\n return listener\n}\n\ntype Reg = { eventType: string, listener: EventListener, capture: boolean }\n\nconst findReg = (regs: Reg[], eventType: string, listener: EventListener, capture: boolean): Reg | undefined =>\n regs.find(r => r.eventType === eventType && r.listener === listener && r.capture === capture)\n\nexport const revive = <T extends ReturnType<typeof box>, T2 extends RevivableContext>(value: T, context: T2) => {\n const addRpc = reviveFunction(value.addListener, context)\n const removeRpc = reviveFunction(value.removeListener, context)\n // Façade only — events never dispatch through it. Source-side EventTarget\n // owns all semantics; we just track regs for trackGc cleanup.\n const target = new EventTarget()\n const regs: Reg[] = []\n\n Object.defineProperty(target, 'addEventListener', {\n value: (eventType: string, listener: EventListenerOrEventListenerObject | null, options?: ListenerOpts) => {\n if (listener === null) return\n const fn = toListener(listener)\n const capture = typeof options === 'boolean' ? options : !!options?.capture\n if (findReg(regs, eventType, fn, capture)) return\n regs.push({ eventType, listener: fn, capture })\n addRpc(eventType, identity(fn), options).catch(() => {})\n },\n })\n\n Object.defineProperty(target, 'removeEventListener', {\n value: (eventType: string, listener: EventListenerOrEventListenerObject | null, options?: ListenerOpts) => {\n if (listener === null) return\n const fn = toListener(listener)\n const capture = typeof options === 'boolean' ? options : !!options?.capture\n const reg = findReg(regs, eventType, fn, capture)\n if (!reg) return\n regs.splice(regs.indexOf(reg), 1)\n removeRpc(eventType, identity(fn), { capture }).catch(() => {})\n },\n })\n\n // Cleanup must NOT close over `target` — otherwise the FR can never fire.\n trackGc(target, () => {\n for (const { eventType, listener, capture } of regs) {\n removeRpc(eventType, identity(listener), { capture }).catch(() => {})\n }\n regs.length = 0\n })\n\n return target\n}\n\nconst typeCheck = () => {\n const r = revive(box(new EventTarget(), {} as RevivableContext), {} as RevivableContext)\n const expected: EventTarget = r\n // @ts-expect-error - not a string\n const notString: string = r\n // @ts-expect-error - cannot box non-EventTarget\n box('not an event target', {} as RevivableContext)\n}\n","import type { RevivableContext, BoxBase as BoxBaseType } from './utils'\nimport type { UnderlyingType } from '../utils/type'\nimport type { BoxedPromise } from './promise'\n\nimport { BoxBase } from './utils'\nimport { box as boxPromise, revive as revivePromise } from './promise'\n\nexport const type = 'blob' as const\n\nexport type BoxedBlob<T extends Blob = Blob> =\n & BoxBaseType<typeof type>\n & { mimeType: string }\n & { buffer: BoxedPromise<ArrayBuffer> }\n & { fileName?: string, lastModified?: number }\n & { [UnderlyingType]: Promise<T> }\n\n// File extends Blob and is handled here too — encoding `name` + `lastModified`\n// when present so the receiver reconstructs a File rather than dropping to a\n// plain Blob. Avoids a runtime/type mismatch where File would type-check as\n// Capable but silently coerce.\nexport const isType = (value: unknown): value is Blob =>\n value instanceof Blob\n\nconst isFile = (value: Blob): value is File =>\n typeof File !== 'undefined' && value instanceof File\n\nexport const box = <T extends Blob, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): BoxedBlob<T> => ({\n ...BoxBase,\n type,\n mimeType: value.type,\n buffer: boxPromise(value.arrayBuffer(), context),\n ...(isFile(value)\n ? { fileName: value.name, lastModified: value.lastModified }\n : {}),\n}) as unknown as BoxedBlob<T>\n\n// Blob bytes are fetched async (`blob.arrayBuffer()`), so revive can't\n// hand back a Blob synchronously — receivers `await` to get the Blob.\nexport const revive = <T extends BoxedBlob, T2 extends RevivableContext>(\n value: T,\n context: T2,\n): T[UnderlyingType] =>\n revivePromise(value.buffer, context)\n .then(buffer =>\n value.fileName !== undefined && typeof File !== 'undefined'\n ? new File([buffer], value.fileName, {\n type: value.mimeType,\n lastModified: value.lastModified,\n })\n : new Blob([buffer], { type: value.mimeType })) as T[UnderlyingType]\n\nconst typeCheck = () => {\n const boxed = box(new Blob(['x'], { type: 'text/plain' }), {} as RevivableContext)\n const revived = revive(boxed, {} as RevivableContext)\n const expected: Promise<Blob> = revived\n // @ts-expect-error - revived is Promise<Blob>, not a sync Blob\n const notBlob: Blob = revived\n // @ts-expect-error - cannot box non-Blob\n box('not a blob', {} as RevivableContext)\n}\n","import type { RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\nimport { boxByReference } from './identity'\n\nexport const type = 'symbol' as const\n\nexport const isType = (value: unknown): value is symbol =>\n typeof value === 'symbol'\n\nexport const box = <T extends symbol, T2 extends RevivableContext>(\n value: T,\n context: T2,\n) => {\n const box = {\n ...BoxBase,\n type,\n description: value.description,\n }\n return (\n value.description === undefined\n ? boxByReference(value, box, context)\n : box\n )\n}\n\nexport const revive = <T extends { description: string | undefined }, T2 extends RevivableContext>(\n value: T,\n _context: T2,\n): symbol => Symbol(value.description)\n\nconst typeCheck = () => {\n const boxed = box(Symbol('foo'), {} as RevivableContext)\n // Description-bearing symbols still round-trip through this revive.\n const revived = revive({ description: 'foo' }, {} as RevivableContext)\n const expected: symbol = revived\n // @ts-expect-error - not a string\n const notString: string = revived\n // @ts-expect-error - cannot box non-symbol\n box('not a symbol', {} as RevivableContext)\n}\n","import type { BoxBase as BoxBaseType, RevivableContext } from './utils'\n\nimport { BoxBase } from './utils'\nimport { instanceOfAny } from '../utils/type-guards'\n\ntype AnyCtor = abstract new (...args: any[]) => unknown\n\n// -------------------------------------------------------------------------\n// clonable — pass-through fast path for HTML structured-clone types not\n// owned by another revivable. Short-circuits findBoxModule so unclonable's\n// structuredClone probe never fires on a known-safe value.\n// -------------------------------------------------------------------------\n\nconst TYPED_CLONABLE_CTORS = [\n globalThis.File,\n globalThis.FileList,\n globalThis.RegExp,\n globalThis.DataView,\n globalThis.ImageData,\n globalThis.FormData,\n globalThis.DOMException,\n globalThis.DOMMatrix,\n globalThis.DOMMatrixReadOnly,\n globalThis.DOMPoint,\n globalThis.DOMPointReadOnly,\n globalThis.DOMQuad,\n globalThis.DOMRect,\n globalThis.DOMRectReadOnly,\n globalThis.CryptoKey,\n globalThis.FileSystemHandle,\n globalThis.FileSystemFileHandle,\n globalThis.FileSystemDirectoryHandle,\n globalThis.RTCCertificate,\n] as const\n\nconst EXPERIMENTAL_CLONABLE_CTORS = [\n (globalThis as { CropTarget?: AnyCtor }).CropTarget,\n (globalThis as { EncodedAudioChunk?: AnyCtor }).EncodedAudioChunk,\n (globalThis as { EncodedVideoChunk?: AnyCtor }).EncodedVideoChunk,\n (globalThis as { FencedFrameConfig?: AnyCtor }).FencedFrameConfig,\n (globalThis as { GPUCompilationInfo?: AnyCtor }).GPUCompilationInfo,\n (globalThis as { GPUCompilationMessage?: AnyCtor }).GPUCompilationMessage,\n (globalThis as { GPUPipelineError?: AnyCtor }).GPUPipelineError,\n (globalThis as { RTCEncodedAudioFrame?: AnyCtor }).RTCEncodedAudioFrame,\n (globalThis as { RTCEncodedVideoFrame?: AnyCtor }).RTCEncodedVideoFrame,\n (globalThis as { WebTransportError?: AnyCtor }).WebTransportError,\n] as const\n\nexport type Clonable = InstanceType<typeof TYPED_CLONABLE_CTORS[number]>\nexport type BoxedClonable = BoxBaseType<'clonable'>\n\n// `capableOnly: true` tells ExtractType to elide this module from the\n// Capable union on JSON transports — TS can't narrow `isType<Ctx>` via\n// generic inference, so we use a marker flag.\nconst isClonable = (value: unknown): value is Clonable =>\n instanceOfAny(value, TYPED_CLONABLE_CTORS) || instanceOfAny(value, EXPERIMENTAL_CLONABLE_CTORS)\n\nexport const clonable = {\n type: 'clonable',\n capableOnly: true,\n isType: isClonable,\n // Pass-through; structured-clone handles these on the wire. `revive` is\n // never reached — `box` returns the raw value so isRevivableBox is false.\n box: (value: Clonable, _context: RevivableContext<any>): Clonable => value,\n revive: (value: BoxedClonable, _context: RevivableContext<any>): Clonable => value as unknown as Clonable,\n} as const\n\n// -------------------------------------------------------------------------\n// transferable — pass-through fast path for transfer-only host objects.\n// getTransferableObjects pulls them out of the envelope at send time.\n// -------------------------------------------------------------------------\n\nconst TYPED_TRANSFERABLE_CTORS = [\n globalThis.ImageBitmap,\n globalThis.OffscreenCanvas,\n globalThis.WritableStream,\n globalThis.TransformStream,\n globalThis.MediaStreamTrack,\n globalThis.RTCDataChannel,\n] as const\n\nconst EXPERIMENTAL_TRANSFERABLE_CTORS = [\n (globalThis as { AudioData?: AnyCtor }).AudioData,\n (globalThis as { VideoFrame?: AnyCtor }).VideoFrame,\n (globalThis as { MediaSourceHandle?: AnyCtor }).MediaSourceHandle,\n (globalThis as { MIDIAccess?: AnyCtor }).MIDIAccess,\n (globalThis as { WebTransportReceiveStream?: AnyCtor }).WebTransportReceiveStream,\n (globalThis as { WebTransportSendStream?: AnyCtor }).WebTransportSendStream,\n] as const\n\nexport type Transferable = InstanceType<typeof TYPED_TRANSFERABLE_CTORS[number]>\nexport type BoxedTransferable = BoxBaseType<'transferable'>\n\nconst isTransferable = (value: unknown): value is Transferable =>\n instanceOfAny(value, TYPED_TRANSFERABLE_CTORS) || instanceOfAny(value, EXPERIMENTAL_TRANSFERABLE_CTORS)\n\nexport const transferable = {\n type: 'transferable',\n capableOnly: true,\n isType: isTransferable,\n box: (value: Transferable, _context: RevivableContext<any>): Transferable => value,\n revive: (value: BoxedTransferable, _context: RevivableContext<any>): Transferable => value as unknown as Transferable,\n} as const\n\n// -------------------------------------------------------------------------\n// unclonable — catch-all that probes via structuredClone and coerces\n// unclonables to `{}` so the wire never blows up on exotic host objects.\n// -------------------------------------------------------------------------\n\nconst isPlainObject = (value: unknown): boolean => {\n if (value === null || typeof value !== 'object') return false\n const proto = Object.getPrototypeOf(value)\n return proto === Object.prototype || proto === null\n}\n\nconst isUnclonable = (value: unknown): boolean => {\n if (value === null) return false\n const t = typeof value\n if (t !== 'object') return false\n if (Array.isArray(value)) return false\n if (isPlainObject(value)) return false\n try {\n structuredClone(value)\n return false\n } catch {\n return true\n }\n}\n\nexport type BoxedUnclonable = BoxBaseType<'unclonable'>\n\n// Type-level lie: `value is never` so this module doesn't widen Capable.\n// Coercion to `{}` is a runtime rescue for values we shouldn't see.\nconst isUnclonableTyped = isUnclonable as (value: unknown) => value is never\n\nexport const unclonable = {\n type: 'unclonable',\n isType: isUnclonableTyped,\n box: (_value: never, _context: RevivableContext<any>): BoxedUnclonable => ({ ...BoxBase, type: 'unclonable' }),\n revive: (_value: BoxedUnclonable, _context: RevivableContext<any>): Record<string, never> => ({}),\n} as const\n","import type { BoxBase, RevivableContext } from './utils'\nimport type { DeepReplaceWithBox, DeepReplaceWithRevive, ReplaceWithBox, ReplaceWithRevive } from '../utils/replace'\nimport type { MessageFields, Capable } from '../types'\n\nimport { isRevivableBox } from './utils'\nimport * as arrayBuffer from './array-buffer'\nimport * as date from './date'\nimport * as headers from './headers'\nimport * as error from './error'\nimport * as typedArray from './typed-array'\nimport * as promise from './promise'\nimport * as func from './function'\nimport * as messagePort from './message-port'\nimport * as readableStream from './readable-stream'\nimport * as abortSignal from './abort-signal'\nimport * as response from './response'\nimport * as request from './request'\nimport * as identity from './identity'\nimport * as transfer from './transfer'\nimport * as map from './map'\nimport * as set from './set'\nimport * as bigInt from './bigint'\nimport * as event from './event'\nimport * as eventTarget from './event-target'\nimport * as blob from './blob'\nimport * as symbol from './symbol'\nimport { clonable, transferable, unclonable } from './fallbacks'\n\nexport { identity } from './identity'\nexport { transfer } from './transfer'\n\nexport * from './utils'\n\n// `any` on box/revive/init: each module's concrete box has a narrower input\n// than the shared interface can express, and TS treats readonly function\n// types contravariantly. The bivariance escape hatch lets modules assign.\nexport type RevivableModule<\n T extends string = string,\n T2 = any,\n T3 extends BoxBase<T> = any,\n T4 extends MessageFields = MessageFields,\n> = {\n readonly type: T\n readonly isType: (value: unknown) => value is T2\n readonly box: ((value: T2, context: RevivableContext<any>) => T3) | ((...args: any[]) => any)\n readonly revive: (value: T3, context: RevivableContext<any>) => T2\n readonly init?: (context: RevivableContext<any>) => void\n readonly Messages?: T4\n}\n\nexport const defaultRevivableModules = [\n transfer,\n identity,\n arrayBuffer,\n date,\n headers,\n error,\n typedArray,\n // blob MUST come before clonable — clonable would otherwise pass-through\n // a Blob unboxed, which works on clone transports but loses the data on\n // JSON. Blob's isType excludes File so File still rides clonable.\n blob,\n promise,\n func,\n messagePort,\n readableStream,\n abortSignal,\n response,\n request,\n map,\n set,\n bigInt,\n symbol,\n event,\n // eventTarget MUST be last among instanceof-EventTarget revivables —\n // MessagePort/AbortSignal/Window/Worker all extend EventTarget; the\n // specific ones need first dibs via findBoxModule iteration order.\n eventTarget,\n // Pass-through fast paths for wire-safe types — short-circuit findBoxModule\n // before unclonable's structuredClone probe runs on a known-safe value.\n clonable,\n transferable,\n // Catch-all: structuredClone-probes and coerces unclonables to `{}`,\n // matching JSON.stringify(new WeakMap()) === \"{}\".\n unclonable,\n] as const\n\nexport type DefaultRevivableModules = typeof defaultRevivableModules\nexport type DefaultRevivableModule = DefaultRevivableModules[number]\n\nconst findBoxModule = (\n value: unknown,\n modules: readonly RevivableModule[]\n): RevivableModule | undefined =>\n modules.find(module => module.isType(value))\n\nconst findReviveModule = (\n value: BoxBase,\n modules: readonly RevivableModule[],\n): RevivableModule | undefined =>\n modules.find(module => module.type === value.type)\n\nconst isPlainObject = (value: unknown): value is Record<string, Capable> =>\n !!value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype\n\nconst descend = <TOut>(value: unknown, transform: (v: Capable) => unknown): TOut => {\n if (Array.isArray(value)) {\n return value.map(v => transform(v)) as TOut\n }\n if (isPlainObject(value)) {\n return Object.fromEntries(\n Object.entries<Capable>(value).map(([k, v]) => [k, transform(v)]),\n ) as TOut\n }\n return value as TOut\n}\n\nexport const box = <\n T extends Capable,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): ReplaceWithBox<T, TModules[number]> => {\n const handledByModule = findBoxModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.box(value, context) as ReplaceWithBox<T, TModules[number]>\n }\n return value as ReplaceWithBox<T, TModules[number]>\n}\n\nexport const recursiveBox = <\n T extends Capable,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): DeepReplaceWithBox<T, TModules[number]> => {\n type ReturnCastType = DeepReplaceWithBox<T, TModules[number]>\n // Already-boxed values pass through — revivables may embed a pre-built\n // BoxedX in their outgoing payload; descending would re-box raw ports.\n if (isRevivableBox(value)) return value as ReturnCastType\n const handledByModule = findBoxModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.box(value, context) as ReturnCastType\n }\n return descend<ReturnCastType>(value, v => recursiveBox(v, context))\n}\n\nexport const revive = <\n T extends ReturnType<typeof box>,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): ReplaceWithRevive<T, TModules[number]> => {\n if (!isRevivableBox(value)) return value as ReplaceWithRevive<T, TModules[number]>\n const handledByModule = findReviveModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.revive(value, context) as ReplaceWithRevive<T, TModules[number]>\n }\n return value as ReplaceWithRevive<T, TModules[number]>\n}\n\nexport const recursiveRevive = <\n T extends Capable,\n TModules extends readonly RevivableModule[]\n>(\n value: T,\n context: RevivableContext<TModules>\n): DeepReplaceWithRevive<T, TModules[number]> => {\n type ReturnCastType = DeepReplaceWithRevive<T, TModules[number]>\n if (isRevivableBox(value)) {\n const handledByModule = findReviveModule(value, context.revivableModules)\n if (handledByModule) {\n return handledByModule.revive(value, context) as ReturnCastType\n }\n }\n return descend<ReturnCastType>(value, v => recursiveRevive(v, context))\n}","import type { Transport } from '../utils/transport'\nimport type { DefaultRevivableModules, RevivableModule } from '../revivables'\nimport type { DeepReplaceWithBox } from '../utils/replace'\nimport type { ProtocolContext } from './utils'\nimport type {\n Capable, MessageEventTarget, MessageFields,\n MessageVariant, Uuid,\n} from '../types'\n\nimport { recursiveBox, recursiveRevive } from '../revivables'\nimport { isEmitTransport, isReceiveTransport } from '../utils/type-guards'\n\nexport const type = 'bidirectional' as const\n\nexport type InitMessage<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n> = {\n type: 'init'\n remoteUuid: Uuid\n data: DeepReplaceWithBox<T, TModules[number]>\n}\n\nexport declare const Messages: <\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n>(modules: TModules, value: T) =>\n | InitMessage<TModules, T>\n\nexport type Messages<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n> = ReturnType<typeof Messages<TModules, T>>\n\nexport type ConnectionContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n type: 'bidirectional'\n eventTarget: MessageEventTarget<TModules>\n connection: BidirectionalConnection<TModules>\n}\n\nexport type ConnectionRevivableContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n transport: Transport\n remoteUuid: Uuid\n sendMessage: (message: MessageFields & Record<string, unknown>) => void\n revivableModules: TModules\n eventTarget: MessageEventTarget<TModules>\n}\n\nexport const startBidirectionalConnection = <\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n>(\n { transport, value, remoteUuid, eventTarget, send, revivableModules }:\n {\n transport: Transport\n value: Capable<TModules>\n remoteUuid: Uuid\n eventTarget: MessageEventTarget<TModules>\n send: (message: MessageFields & Record<string, unknown>) => void\n revivableModules: TModules\n },\n) => {\n const revivableContext = {\n transport,\n remoteUuid,\n sendMessage: send,\n eventTarget,\n revivableModules\n } satisfies ConnectionRevivableContext<TModules>\n\n for (const module of revivableModules) {\n module.init?.(revivableContext)\n }\n\n const { promise, resolve } = Promise.withResolvers<InitMessage<TModules>['data']>()\n\n eventTarget.addEventListener('message', function listener ({ detail }) {\n if (detail.type === 'init') {\n resolve(detail.data)\n eventTarget.removeEventListener('message', listener)\n }\n })\n\n send({\n type: 'init',\n remoteUuid,\n data: recursiveBox(value, revivableContext)\n })\n\n return {\n revivableContext,\n remoteValue:\n promise\n .then(initData => recursiveRevive(initData, revivableContext) as Capable),\n }\n}\n\nexport type BidirectionalConnection<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n revivableContext: ConnectionRevivableContext<TModules>\n remoteValue: Promise<Capable>\n}\n\n/** Mounts bidirectional mode on the shared protocol context. Only active\n * when the transport can both emit and receive. */\nexport const init = <TModules extends readonly RevivableModule[]>(\n ctx: ProtocolContext<TModules>\n): void => {\n if (!(isEmitTransport(ctx.transport) && isReceiveTransport(ctx.transport))) return\n\n ctx.protocolEventTarget.addEventListener('message', ({ detail: message }) => {\n if (message.type === 'announce') {\n if (!message.remoteUuid) {\n ctx.sendMessage({ type: 'announce', remoteUuid: message.uuid })\n return\n }\n if (message.remoteUuid !== ctx.getUuid()) return\n // Already-tracked uuid is the normal handshake-echo (peer re-announcing\n // back after our reply), not a collision — drop it.\n if (ctx.connectionContexts.has(message.uuid)) return\n // Echo announce back in case the peer missed our initial one.\n ctx.sendMessage({ type: 'announce', remoteUuid: message.uuid })\n const eventTarget = ctx.createConnectionEventTarget()\n const connectionContext = {\n type: 'bidirectional',\n eventTarget,\n connection:\n startBidirectionalConnection<TModules>({\n transport: ctx.transport,\n value: ctx.value,\n remoteUuid: message.uuid,\n eventTarget,\n send: (m) => ctx.sendMessage(m as MessageVariant),\n revivableModules: ctx.revivableModules\n })\n } satisfies ConnectionContext<TModules>\n ctx.connectionContexts.set(message.uuid, connectionContext)\n connectionContext.connection.remoteValue.then((remoteValue) =>\n ctx.resolveRemoteValue(remoteValue)\n )\n return\n }\n if (message.type === 'close') {\n if (message.remoteUuid !== ctx.getUuid()) return\n ctx.connectionContexts.delete(message.uuid)\n return\n }\n // \"init\" | \"message\" | \"message-port-close\"\n if (message.remoteUuid !== ctx.getUuid()) return\n const connection = ctx.connectionContexts.get(message.uuid)\n // drop messages from peers we haven't tracked (pre-announce or post-close)\n if (!connection) return\n connection.eventTarget.dispatchEvent(\n new CustomEvent('message', { detail: message })\n )\n })\n\n if (ctx.presetRemoteUuid !== undefined) {\n const eventTarget = ctx.createConnectionEventTarget()\n const connectionContext = {\n type: 'bidirectional',\n eventTarget,\n connection:\n startBidirectionalConnection<TModules>({\n transport: ctx.transport,\n value: ctx.value,\n remoteUuid: ctx.presetRemoteUuid,\n eventTarget,\n send: (m) => ctx.sendMessage(m as MessageVariant),\n revivableModules: ctx.revivableModules\n })\n } satisfies ConnectionContext<TModules>\n ctx.connectionContexts.set(ctx.presetRemoteUuid, connectionContext)\n connectionContext.connection.remoteValue.then((remoteValue) =>\n ctx.resolveRemoteValue(remoteValue)\n )\n return\n }\n\n ctx.sendMessage({ type: 'announce' })\n}\n","import type { UnderlyingType } from './type'\n\nexport type EventMap = Record<string, Event>\n\nexport interface TypedEventTarget<T extends EventMap> extends EventTarget {\n [UnderlyingType]?: T\n\n addEventListener<K extends keyof T & string>(\n type: K,\n listener: ((event: T[K]) => void) | null,\n options?: boolean | AddEventListenerOptions\n ): void\n addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions\n ): void\n\n removeEventListener<K extends keyof T & string>(\n type: K,\n listener: ((event: T[K]) => void) | null,\n options?: boolean | EventListenerOptions\n ): void\n removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | EventListenerOptions\n ): void\n}\n\n/**\n * Create a new `TypedEventTarget<T>` for a given event map. Centralises the\n * `EventTarget` → `TypedEventTarget<T>` cast so individual call sites don't\n * each need their own (`EventTarget` lacks the generic event map at the type\n * level, but the runtime behaviour is identical).\n */\nexport const createTypedEventTarget = <T extends EventMap>(): TypedEventTarget<T> =>\n new EventTarget() as TypedEventTarget<T>\n","import { transfer } from '../revivables/transfer'\nimport { isRevivableBox } from '../revivables/utils'\nimport { instanceOfAny, isClonable, isTransferable } from './type-guards'\n\nexport { transfer }\n\n// Must-transfer types: structured clone can't copy these, so any occurrence\n// in the outgoing message must go on the transfer list — opt-in or not.\n// (MessagePort is the canonical case: cloning would leave the peer mute.)\nconst isMustTransfer = (value: unknown): value is Transferable =>\n instanceOfAny(value, [\n globalThis.MessagePort,\n globalThis.ReadableStream,\n globalThis.WritableStream,\n globalThis.TransformStream,\n globalThis.OffscreenCanvas,\n (globalThis as { MediaSourceHandle?: abstract new (...args: any[]) => unknown }).MediaSourceHandle,\n (globalThis as { MediaStreamTrack?: abstract new (...args: any[]) => unknown }).MediaStreamTrack,\n (globalThis as { MIDIAccess?: abstract new (...args: any[]) => unknown }).MIDIAccess,\n (globalThis as { RTCDataChannel?: abstract new (...args: any[]) => unknown }).RTCDataChannel,\n (globalThis as { WebTransportReceiveStream?: abstract new (...args: any[]) => unknown }).WebTransportReceiveStream,\n (globalThis as { WebTransportSendStream?: abstract new (...args: any[]) => unknown }).WebTransportSendStream,\n ])\n\n// Structural check — keeps the walker decoupled from the module graph.\n// `degraded` (set by transfer.box) means the wrapper is a no-op here.\nconst isTransferBox = (value: unknown): value is { inner: unknown, degraded: boolean } =>\n isRevivableBox(value) && value.type === 'transfer'\n\n/** Walk a boxed message and collect Transferables to move (rather than copy)\n * on postMessage:\n * 1. Must-transfer types are always included.\n * 2. Clonable types (SharedArrayBuffer) are skipped.\n * 3. Other Transferables are included only inside a non-degraded transfer\n * box (user opted in AND the platform supports transferring). */\nexport const getTransferableObjects = (value: unknown): Transferable[] => {\n const transferables: Transferable[] = []\n const seen = new WeakSet<object>()\n\n const recurse = (value: unknown, inTransferBox: boolean): void => {\n if (!value || typeof value !== 'object') return\n if (seen.has(value)) return\n seen.add(value)\n\n if (isClonable(value)) return\n\n if (isTransferBox(value)) {\n // Non-degraded box flips into transfer mode for everything below.\n recurse(value.inner, inTransferBox || !value.degraded)\n return\n }\n\n if (isMustTransfer(value)) {\n transferables.push(value)\n return\n }\n\n if (isTransferable(value)) {\n if (inTransferBox) {\n transferables.push(value)\n }\n return\n }\n\n // TypedArray / DataView expose every numeric index — iterating a 100 KB\n // buffer would walk 100 K entries for nothing. The underlying buffer is\n // the only candidate; the typed-array revivable handles that path.\n if (ArrayBuffer.isView(value)) return\n\n if (Array.isArray(value)) {\n for (const item of value) recurse(item, inTransferBox)\n return\n }\n\n for (const item of Object.values(value)) recurse(item, inTransferBox)\n }\n\n recurse(value, false)\n return transferables\n}\n","import type {\n Message, MessageVariant, Uuid,\n Capable, MessageEventMap\n} from '../types'\nimport type { DefaultRevivableModules, RevivableModule } from '../revivables'\nimport type { Transport } from '../utils/transport'\nimport type { ConnectionContext } from '.'\nimport type { TypedEventTarget } from '../utils/typed-event-target'\n\nimport { defaultRevivableModules } from '../revivables'\nimport { isJsonOnlyTransport, isCustomTransport } from '../utils/type-guards'\n\nexport const normalizeTransport = (transport: Transport): Transport => {\n const isJson =\n 'isJson' in transport && transport.isJson !== undefined\n ? transport.isJson\n : isJsonOnlyTransport(transport)\n const ports =\n isCustomTransport(transport)\n ? transport\n : { emit: transport, receive: transport }\n return { isJson, ...ports } satisfies Transport\n}\n\n/** Resolves the final revivable module list. The user supplies a function\n * that takes the defaults and returns whatever ordering/composition they\n * want — add modules, drop defaults, reorder, override per-type. When\n * omitted, the defaults are used as-is. */\nexport const mergeRevivableModules = <\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n>(\n configure: ((defaults: DefaultRevivableModules) => TModules) | undefined,\n): TModules =>\n configure\n ? configure(defaultRevivableModules)\n : defaultRevivableModules as unknown as TModules\n\nexport type ProtocolEventMap<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n message: CustomEvent<Message<TModules>>\n}\n\nexport type ProtocolEventTarget<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = TypedEventTarget<ProtocolEventMap<TModules>>\n\nexport type ProtocolContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n transport: Transport\n value: Capable<TModules>\n revivableModules: TModules\n connectionContexts: Map<string, ConnectionContext<TModules>>\n getUuid: () => Uuid\n presetRemoteUuid?: Uuid\n sendMessage: (message: MessageVariant) => void\n protocolEventTarget: ProtocolEventTarget<TModules>\n resolveRemoteValue: (value: Capable<TModules>) => void\n createConnectionEventTarget: () => TypedEventTarget<MessageEventMap<TModules>>\n}\n\nexport type StartConnectionsOptions<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> = {\n transport: Transport\n name?: string\n remoteName?: string\n key?: string\n origin?: string\n unregisterSignal?: AbortSignal\n /** Configure the revivable module list. Receives the defaults and\n * returns the final ordered list — add modules, drop defaults, reorder,\n * or override per-type as needed. */\n revivableModules?: (defaults: DefaultRevivableModules) => TModules\n uuid?: Uuid\n remoteUuid?: Uuid\n}\n","import type { DefaultRevivableModules, RevivableModule } from '../revivables'\nimport type { ConnectionContext as BidirectionalConnectionContext } from './bidirectional'\nimport type {\n ProtocolContext,\n StartConnectionsOptions,\n} from '../utils'\nimport type {\n Message, MessageVariant, Uuid,\n Capable,\n} from '../types'\nimport type { MessageContext } from '../utils/transport'\n\nimport { OSRA_DEFAULT_KEY, OSRA_KEY } from '../types'\nimport * as bidirectional from './bidirectional'\nimport {\n isEmitTransport,\n isReceiveTransport,\n} from '../utils/type-guards'\nimport { createTypedEventTarget } from '../utils/typed-event-target'\nimport { getTransferableObjects } from '../utils/transferable'\nimport { registerOsraMessageListener, sendOsraMessage } from '../utils/transport'\nimport { mergeRevivableModules, normalizeTransport } from './utils'\n\nexport * from './bidirectional'\nexport * from './utils'\n\nexport type ConnectionModule<T> = {\n readonly type: string\n // ProtocolContext<any> rather than ProtocolContext<readonly RevivableModule[]>\n // for the same bivariance reason as RevivableModule.box — concrete modules\n // declare narrower context generics than the shared interface can express.\n readonly init: (ctx: ProtocolContext<any>) => void\n readonly Messages?: T\n}\n\nexport const connections = [\n bidirectional\n] as const\n\nexport type DefaultConnectionModules = typeof connections\nexport type DefaultConnectionModule = DefaultConnectionModules[number]\n\nexport type ConnectionMessage<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n T extends Capable<TModules> = Capable<TModules>\n> =\n DefaultConnectionModule extends {\n Messages: (modules: TModules, value: T) => infer R\n }\n ? R\n : never\n\nexport type ConnectionContext<\n TModules extends readonly RevivableModule[] = DefaultRevivableModules\n> =\n | BidirectionalConnectionContext<TModules>\n\nexport const startConnections = <\n T = unknown,\n const TModules extends readonly RevivableModule[] = DefaultRevivableModules\n>(\n value: Capable<TModules>,\n {\n transport: _transport,\n name,\n remoteName,\n key = OSRA_DEFAULT_KEY,\n origin = '*',\n unregisterSignal,\n revivableModules: configureRevivableModules,\n uuid: _uuid,\n remoteUuid: presetRemoteUuid,\n }: StartConnectionsOptions<TModules>\n): Promise<T> => {\n const transport = normalizeTransport(_transport)\n const mergedRevivableModules = mergeRevivableModules<TModules>(configureRevivableModules)\n type MergedModules = typeof mergedRevivableModules\n const connectionContexts = new Map<string, ConnectionContext<MergedModules>>()\n\n const { promise: remoteValuePromise, resolve: resolveRemoteValue } =\n Promise.withResolvers<Capable<MergedModules>>()\n\n const uuid: Uuid = _uuid ?? globalThis.crypto.randomUUID()\n\n const sendMessage = (message: MessageVariant) => {\n if (unregisterSignal?.aborted) return\n if (!isEmitTransport(transport)) return\n const envelope = { [OSRA_KEY]: key, name, uuid, ...message }\n sendOsraMessage(transport, envelope, origin, getTransferableObjects(envelope))\n }\n\n const protocolEventTarget = createTypedEventTarget<{ message: CustomEvent<Message<MergedModules>> }>()\n\n const ctx: ProtocolContext<MergedModules> = {\n transport,\n value: value as Capable<MergedModules>,\n revivableModules: mergedRevivableModules,\n connectionContexts,\n getUuid: () => uuid,\n presetRemoteUuid,\n sendMessage,\n protocolEventTarget,\n resolveRemoteValue,\n createConnectionEventTarget: createTypedEventTarget,\n }\n\n const listener = (message: Message, _: MessageContext) => {\n // own message looped back on the channel\n if (message.uuid === uuid) return\n protocolEventTarget.dispatchEvent(\n new CustomEvent('message', { detail: message as Message<MergedModules> }),\n )\n }\n\n if (isReceiveTransport(transport)) {\n registerOsraMessageListener({\n listener,\n transport,\n remoteName,\n key,\n unregisterSignal\n })\n }\n\n for (const connectionModule of connections) {\n connectionModule.init(ctx)\n }\n\n return remoteValuePromise as Promise<T>\n}\n","import type { Capable } from './types'\nimport type { DefaultRevivableModules, RevivableContext } from './revivables'\nimport type { RevivableModule } from './revivables'\nimport type { StartConnectionsOptions } from './connections/utils'\nimport type { Transport } from './utils/transport'\nimport type {\n BadFieldValue, BadFieldPath, BadFieldParent,\n ErrorMessage, BadValue, Path, ParentObject\n} from './utils/capable-check'\n\nimport { startConnections } from './utils'\n\nexport * from './types'\nexport * from './revivables'\nexport * from './connections'\nexport * from './utils'\n\n/** Synthetic context so `Capable` can narrow on the inferred transport\n * without an actual context object at the call site. Only `transport`\n * matters; the rest is stubbed with the broadest types. */\ntype ContextOf<TTransport extends Transport> = RevivableContext & { transport: TTransport }\n\ntype CapableCheck<\n T,\n TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n Ctx extends RevivableContext = RevivableContext,\n> =\n T extends Capable<TModules, Ctx>\n ? T\n : T & {\n [ErrorMessage]: 'Value type must resolve to a Capable'\n [BadValue]: BadFieldValue<T, Capable<TModules, Ctx>>\n [Path]: BadFieldPath<T, Capable<TModules, Ctx>>\n [ParentObject]: BadFieldParent<T, Capable<TModules, Ctx>>\n }\n\nexport const expose = async <\n T = unknown,\n const TModules extends readonly RevivableModule[] = DefaultRevivableModules,\n const TTransport extends Transport = Transport,\n const TValue = Capable<TModules, ContextOf<TTransport>>\n>(\n value: CapableCheck<TValue, TModules, ContextOf<TTransport>>,\n options: StartConnectionsOptions<TModules> & { transport: TTransport }\n): Promise<T> =>\n startConnections<T, TModules>(\n value as Capable<TModules>,\n options\n )\n"],"mappings":"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"}
|