export interface MessageEndpoint { postMessage(message: any, transferables?: Transferable[]): void; addEventListener( event: 'message', listener: (event: MessageEvent) => void, ): void; removeEventListener( event: 'message', listener: (event: MessageEvent) => void, ): void; terminate?(): void; } export type RemoteCallable = {[K in keyof T]: RemoteCallableField}; type RemoteCallableField = T extends ( ...args: infer Args ) => infer TypeReturned ? (...args: Args) => AlwaysAsync : never; export type MaybePromise = T extends Promise ? T : T | Promise; type AlwaysAsync = T extends Promise ? T : T extends infer U | Promise ? Promise : T extends (...args: infer Args) => infer TypeReturned ? (...args: Args) => AlwaysAsync : T extends (infer ArrayElement)[] ? AlwaysAsync[] : T extends ReadonlyArray ? ReadonlyArray> : T extends object ? {[K in keyof T]: AlwaysAsync} : T; export type SafeRpcArgument = T extends ( ...args: infer Args ) => infer TypeReturned ? TypeReturned extends Promise ? (...args: Args) => TypeReturned : (...args: Args) => TypeReturned | Promise : T extends (infer ArrayElement)[] ? SafeRpcArgument[] : T extends ReadonlyArray ? ReadonlyArray> : T extends object ? {[K in keyof T]: SafeRpcArgument} : T; export const RETAIN_METHOD = Symbol.for('RemoteUi::Retain'); export const RELEASE_METHOD = Symbol.for('RemoteUi::Release'); export const RETAINED_BY = Symbol.for('RemoteUi::RetainedBy'); export interface Retainer { add(manageable: MemoryManageable): void; } export interface MemoryManageable { readonly [RETAINED_BY]: Set; [RETAIN_METHOD](): void; [RELEASE_METHOD](): void; } export interface EncodingStrategy { encode(value: unknown): [any, Transferable[]?]; decode(value: unknown, retainedBy?: Iterable): unknown; call(id: string, args: any[]): Promise; release(id: string): void; terminate?(): void; } export interface EncodingStrategyApi { uuid(): string; release(id: string): void; call(id: string, args: any[], retainedBy?: Iterable): Promise; }