@xylabs/threads
Version:
Web workers & worker threads as simple as a function call
1 lines • 34.2 kB
Source Map (JSON)
{"version":3,"sources":["../../../src/master/spawn.ts","../../../src/serializers.ts","../../../src/common.ts","../../../src/promise.ts","../../../src/symbols.ts","../../../src/master/invocation-proxy.ts","../../../src/observable-promise.ts","../../../src/transferable.ts"],"sourcesContent":["/* eslint-disable import-x/no-internal-modules */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-floating-promises */\nimport DebugLogger from 'debug'\nimport { Observable } from 'observable-fns'\n\nimport { deserialize } from '../common.ts'\nimport { createPromiseWithResolver } from '../promise.ts'\nimport {\n $errors, $events, $terminate, $worker,\n} from '../symbols.ts'\nimport type {\n FunctionThread,\n ModuleThread,\n PrivateThreadProps,\n StripAsync,\n Worker as WorkerType,\n WorkerEvent,\n WorkerInternalErrorEvent,\n WorkerMessageEvent,\n WorkerTerminationEvent,\n} from '../types/master.ts'\nimport { WorkerEventType } from '../types/master.ts'\nimport type { WorkerInitMessage, WorkerUncaughtErrorMessage } from '../types/messages.ts'\nimport type { WorkerFunction, WorkerModule } from '../types/worker.ts'\nimport { createProxyFunction, createProxyModule } from './invocation-proxy.ts'\n\ntype ArbitraryWorkerInterface = WorkerFunction & WorkerModule<string> & { somekeythatisneverusedinproductioncode123: 'magicmarker123' }\ntype ArbitraryThreadType = FunctionThread<any, any> & ModuleThread<any>\n\nexport type ExposedToThreadType<Exposed extends WorkerFunction | WorkerModule<any>> =\n Exposed extends ArbitraryWorkerInterface ? ArbitraryThreadType\n : Exposed extends WorkerFunction ? FunctionThread<Parameters<Exposed>, StripAsync<ReturnType<Exposed>>>\n : Exposed extends WorkerModule<any> ? ModuleThread<Exposed>\n : never\n\nconst debugMessages = DebugLogger('threads:master:messages')\nconst debugSpawn = DebugLogger('threads:master:spawn')\nconst debugThreadUtils = DebugLogger('threads:master:thread-utils')\n\nconst isInitMessage = (data: any): data is WorkerInitMessage => data && data.type === ('init' as const)\nconst isUncaughtErrorMessage = (data: any): data is WorkerUncaughtErrorMessage => data && data.type === ('uncaughtError' as const)\n\nconst initMessageTimeout\n = typeof process !== 'undefined' && process.env !== undefined && process.env.THREADS_WORKER_INIT_TIMEOUT\n ? Number.parseInt(process.env.THREADS_WORKER_INIT_TIMEOUT, 10)\n : 10_000\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutInMs: number, errorMessage: string): Promise<T> {\n let timeoutHandle: any\n\n const timeout = new Promise<never>((resolve, reject) => {\n timeoutHandle = setTimeout(() => reject(new Error(errorMessage)), timeoutInMs)\n })\n const result = await Promise.race([promise, timeout])\n\n clearTimeout(timeoutHandle)\n return result\n}\n\nfunction receiveInitMessage(worker: WorkerType): Promise<WorkerInitMessage> {\n return new Promise((resolve, reject) => {\n const messageHandler = ((event: MessageEvent) => {\n debugMessages('Message from worker before finishing initialization:', event.data)\n if (isInitMessage(event.data)) {\n worker.removeEventListener('message', messageHandler)\n resolve(event.data)\n } else if (isUncaughtErrorMessage(event.data)) {\n worker.removeEventListener('message', messageHandler)\n reject(deserialize(event.data.error))\n }\n }) as EventListener\n worker.addEventListener('message', messageHandler)\n })\n}\n\nfunction createEventObservable(worker: WorkerType, workerTermination: Promise<any>): Observable<WorkerEvent> {\n return new Observable<WorkerEvent>((observer) => {\n const messageHandler = ((messageEvent: MessageEvent) => {\n const workerEvent: WorkerMessageEvent<any> = {\n data: messageEvent.data,\n type: WorkerEventType.message,\n }\n observer.next(workerEvent)\n }) as EventListener\n const rejectionHandler = ((errorEvent: PromiseRejectionEvent) => {\n debugThreadUtils('Unhandled promise rejection event in thread:', errorEvent)\n const workerEvent: WorkerInternalErrorEvent = {\n error: new Error(errorEvent.reason),\n type: WorkerEventType.internalError,\n }\n observer.next(workerEvent)\n }) as EventListener\n worker.addEventListener('message', messageHandler)\n worker.addEventListener('unhandledrejection', rejectionHandler)\n\n workerTermination.then(() => {\n const terminationEvent: WorkerTerminationEvent = { type: WorkerEventType.termination }\n worker.removeEventListener('message', messageHandler)\n worker.removeEventListener('unhandledrejection', rejectionHandler)\n observer.next(terminationEvent)\n observer.complete()\n })\n })\n}\n\nfunction createTerminator(worker: WorkerType): { terminate: () => Promise<void>; termination: Promise<void> } {\n const [termination, resolver] = createPromiseWithResolver<void>()\n const terminate = async () => {\n debugThreadUtils('Terminating worker')\n // Newer versions of worker_threads workers return a promise\n await worker.terminate()\n resolver()\n }\n return { terminate, termination }\n}\n\nfunction setPrivateThreadProps<T>(\n raw: T,\n worker: WorkerType,\n workerEvents: Observable<WorkerEvent>,\n terminate: () => Promise<void>,\n): T & PrivateThreadProps {\n const workerErrors = workerEvents\n .filter(event => event.type === WorkerEventType.internalError)\n .map(errorEvent => (errorEvent as WorkerInternalErrorEvent).error)\n\n return Object.assign(raw as any, {\n [$errors]: workerErrors,\n [$events]: workerEvents,\n [$terminate]: terminate,\n [$worker]: worker,\n })\n}\n\n/**\n * Spawn a new thread. Takes a fresh worker instance, wraps it in a thin\n * abstraction layer to provide the transparent API and verifies that\n * the worker has initialized successfully.\n *\n * @param worker Instance of `Worker`. Either a web worker, `worker_threads` worker or `tiny-worker` worker.\n * @param [options]\n * @param [options.timeout] Init message timeout. Default: 10000 or set by environment variable.\n */\nexport async function spawn<Exposed extends WorkerFunction | WorkerModule<any> = ArbitraryWorkerInterface>(\n worker: WorkerType,\n options?: { timeout?: number },\n): Promise<ExposedToThreadType<Exposed>> {\n debugSpawn('Initializing new thread')\n\n const timeout = options && options.timeout ? options.timeout : initMessageTimeout\n const initMessage = await withTimeout(\n receiveInitMessage(worker),\n timeout,\n `Timeout: Did not receive an init message from worker after ${timeout}ms. Make sure the worker calls expose().`,\n )\n const exposed = initMessage.exposed\n\n const { termination, terminate } = createTerminator(worker)\n const events = createEventObservable(worker, termination)\n\n if (exposed.type === 'function') {\n const proxy = createProxyFunction(worker)\n return setPrivateThreadProps(proxy, worker, events, terminate) as ExposedToThreadType<Exposed>\n } else if (exposed.type === 'module') {\n const proxy = createProxyModule(worker, exposed.methods)\n return setPrivateThreadProps(proxy, worker, events, terminate) as ExposedToThreadType<Exposed>\n } else {\n const type = (exposed as WorkerInitMessage['exposed']).type\n throw new Error(`Worker init message states unexpected type of expose(): ${type}`)\n }\n}\n","/* eslint-disable import-x/no-internal-modules */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { SerializedError } from './types/messages.ts'\n\nexport interface Serializer<Msg = JsonSerializable, Input = any> {\n deserialize(message: Msg): Input\n serialize(input: Input): Msg\n}\n\nexport interface SerializerImplementation<Msg = JsonSerializable, Input = any> {\n deserialize(message: Msg, defaultDeserialize: (msg: Msg) => Input): Input\n serialize(input: Input, defaultSerialize: (inp: Input) => Msg): Msg\n}\n\nexport function extendSerializer<MessageType, InputType = any>(\n extend: Serializer<MessageType, InputType>,\n implementation: SerializerImplementation<MessageType, InputType>,\n): Serializer<MessageType, InputType> {\n const fallbackDeserializer = extend.deserialize.bind(extend)\n const fallbackSerializer = extend.serialize.bind(extend)\n\n return {\n deserialize(message: MessageType): InputType {\n return implementation.deserialize(message, fallbackDeserializer)\n },\n\n serialize(input: InputType): MessageType {\n return implementation.serialize(input, fallbackSerializer)\n },\n }\n}\n\ntype JsonSerializablePrimitive = string | number | boolean | null\n\ntype JsonSerializableObject = {\n [key: string]: JsonSerializablePrimitive | JsonSerializablePrimitive[] | JsonSerializableObject | JsonSerializableObject[] | undefined\n}\n\nexport type JsonSerializable = JsonSerializablePrimitive | JsonSerializablePrimitive[] | JsonSerializableObject | JsonSerializableObject[]\n\nconst DefaultErrorSerializer: Serializer<SerializedError, Error> = {\n deserialize(message: SerializedError): Error {\n return Object.assign(new Error(message.message), {\n name: message.name,\n stack: message.stack,\n })\n },\n serialize(error: Error): SerializedError {\n return {\n __error_marker: '$$error',\n message: error.message,\n name: error.name,\n stack: error.stack,\n }\n },\n}\n\nconst isSerializedError = (thing: any): thing is SerializedError =>\n thing && typeof thing === 'object' && '__error_marker' in thing && thing.__error_marker === '$$error'\n\nexport const DefaultSerializer: Serializer<JsonSerializable> = {\n deserialize(message: JsonSerializable): any {\n return isSerializedError(message) ? DefaultErrorSerializer.deserialize(message) : message\n },\n serialize(input: any): JsonSerializable {\n return input instanceof Error ? (DefaultErrorSerializer.serialize(input) as any as JsonSerializable) : input\n },\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n JsonSerializable, Serializer, SerializerImplementation,\n} from './serializers.ts'\nimport { DefaultSerializer, extendSerializer } from './serializers.ts'\n\ndeclare global {\n var registeredSerializer: Serializer<JsonSerializable>\n}\n\nglobalThis.registeredSerializer = globalThis.registeredSerializer ?? DefaultSerializer\n\nexport function registerSerializer(serializer: SerializerImplementation<JsonSerializable>) {\n globalThis.registeredSerializer = extendSerializer(globalThis.registeredSerializer, serializer)\n}\n\nexport function deserialize(message: JsonSerializable): any {\n return globalThis.registeredSerializer.deserialize(message)\n}\n\nexport function serialize(input: any): JsonSerializable {\n return globalThis.registeredSerializer.serialize(input)\n}\n","// eslint-disable-next-line unicorn/no-useless-undefined\nconst doNothing = () => undefined\n\n/**\n * Creates a new promise and exposes its resolver function.\n * Use with care!\n */\nexport function createPromiseWithResolver<T>(): [Promise<T>, (result: T) => void] {\n let alreadyResolved = false\n let resolvedTo: T\n let resolver: (value: T | PromiseLike<T>) => void = doNothing\n\n const promise = new Promise<T>((resolve) => {\n if (alreadyResolved) {\n resolve(resolvedTo)\n } else {\n resolver = resolve\n }\n })\n const exposedResolver = (value: T) => {\n alreadyResolved = true\n resolvedTo = value\n resolver(resolvedTo)\n }\n return [promise, exposedResolver]\n}\n","export const $errors = Symbol('thread.errors')\nexport const $events = Symbol('thread.events')\nexport const $terminate = Symbol('thread.terminate')\nexport const $transferable = Symbol('thread.transferable')\nexport const $worker = Symbol('thread.worker')\n","/// <reference lib=\"webworker\" />\n\n/* eslint-disable import-x/no-internal-modules */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/*\n * This source file contains the code for proxying calls in the master thread to calls in the workers\n * by `.postMessage()`-ing.\n *\n * Keep in mind that this code can make or break the program's performance! Need to optimize more…\n */\n\nimport DebugLogger from 'debug'\nimport { multicast, Observable } from 'observable-fns'\n\nimport { deserialize, serialize } from '../common.ts'\nimport { ObservablePromise } from '../observable-promise.ts'\nimport { isTransferDescriptor } from '../transferable.ts'\nimport type {\n ModuleMethods, ModuleProxy, ProxyableFunction, Worker as WorkerType,\n} from '../types/master.ts'\nimport type {\n MasterJobCancelMessage,\n MasterJobRunMessage,\n WorkerJobErrorMessage,\n WorkerJobResultMessage,\n WorkerJobStartMessage,\n} from '../types/messages.ts'\nimport {\n MasterMessageType,\n WorkerMessageType,\n} from '../types/messages.ts'\n\nconst debugMessages = DebugLogger('threads:master:messages')\n\nlet nextJobUID = 1\n\nconst dedupe = <T>(array: T[]): T[] => [...new Set(array)]\n\nconst isJobErrorMessage = (data: any): data is WorkerJobErrorMessage => data && data.type === WorkerMessageType.error\nconst isJobResultMessage = (data: any): data is WorkerJobResultMessage => data && data.type === WorkerMessageType.result\nconst isJobStartMessage = (data: any): data is WorkerJobStartMessage => data && data.type === WorkerMessageType.running\n\nfunction createObservableForJob<ResultType>(worker: WorkerType, jobUID: number): Observable<ResultType> {\n return new Observable((observer) => {\n let asyncType: 'observable' | 'promise' | undefined\n\n const messageHandler = ((event: MessageEvent) => {\n debugMessages('Message from worker:', event.data)\n if (!event.data || event.data.uid !== jobUID) return\n\n if (isJobStartMessage(event.data)) {\n asyncType = event.data.resultType\n } else if (isJobResultMessage(event.data)) {\n if (asyncType === 'promise') {\n if (event.data.payload !== undefined) {\n observer.next(deserialize(event.data.payload))\n }\n observer.complete()\n worker.removeEventListener('message', messageHandler)\n } else {\n if (event.data.payload) {\n observer.next(deserialize(event.data.payload))\n }\n if (event.data.complete) {\n observer.complete()\n worker.removeEventListener('message', messageHandler)\n }\n }\n } else if (isJobErrorMessage(event.data)) {\n const error = deserialize(event.data.error as any)\n if (asyncType === 'promise' || !asyncType) {\n observer.error(error)\n } else {\n observer.error(error)\n }\n worker.removeEventListener('message', messageHandler)\n }\n }) as EventListener\n\n worker.addEventListener('message', messageHandler)\n\n return () => {\n if (asyncType === 'observable' || !asyncType) {\n const cancelMessage: MasterJobCancelMessage = {\n type: MasterMessageType.cancel,\n uid: jobUID,\n }\n worker.postMessage(cancelMessage)\n }\n worker.removeEventListener('message', messageHandler)\n }\n })\n}\n\nfunction prepareArguments(rawArgs: any[]): { args: any[]; transferables: Transferable[] } {\n if (rawArgs.length === 0) {\n // Exit early if possible\n return {\n args: [],\n transferables: [],\n }\n }\n\n const args: any[] = []\n const transferables: Transferable[] = []\n\n for (const arg of rawArgs) {\n if (isTransferDescriptor(arg)) {\n args.push(serialize(arg.send))\n transferables.push(...arg.transferables)\n } else {\n args.push(serialize(arg))\n }\n }\n\n return {\n args,\n transferables: transferables.length === 0 ? transferables : dedupe(transferables),\n }\n}\n\nexport function createProxyFunction<Args extends any[], ReturnType>(worker: WorkerType, method?: string) {\n return ((...rawArgs: Args) => {\n const uid = nextJobUID++\n const { args, transferables } = prepareArguments(rawArgs)\n const runMessage: MasterJobRunMessage = {\n args,\n method,\n type: MasterMessageType.run,\n uid,\n }\n\n debugMessages('Sending command to run function to worker:', runMessage)\n\n try {\n worker.postMessage(runMessage, transferables)\n } catch (error) {\n return ObservablePromise.from(Promise.reject(error))\n }\n\n return ObservablePromise.from(multicast(createObservableForJob<ReturnType>(worker, uid)))\n }) as any as ProxyableFunction<Args, ReturnType>\n}\n\nexport function createProxyModule<Methods extends ModuleMethods>(worker: WorkerType, methodNames: string[]): ModuleProxy<Methods> {\n const proxy: any = {}\n\n for (const methodName of methodNames) {\n proxy[methodName] = createProxyFunction(worker, methodName)\n }\n\n return proxy\n}\n","/* eslint-disable unicorn/no-thenable */\n/* eslint-disable @typescript-eslint/member-ordering */\n/* eslint-disable @typescript-eslint/no-floating-promises */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-this-alias */\n/* eslint-disable unicorn/no-this-assignment */\nimport type { ObservableLike, SubscriptionObserver } from 'observable-fns'\nimport { Observable } from 'observable-fns'\n\ntype OnFulfilled<T, Result = void> = (value: T) => Result\ntype OnRejected<Result = void> = (error: Error) => Result\n\ntype Initializer<T> = (observer: SubscriptionObserver<T>) => UnsubscribeFn | void\n\ntype Thenable<T> = { then: (onFulfilled?: (value: T) => any, onRejected?: (error: any) => any) => any }\n\ntype UnsubscribeFn = () => void\n\nconst doNothing = () => {}\nconst returnInput = <T>(input: T): T => input\nconst runDeferred = (fn: () => void) => Promise.resolve().then(fn)\n\nfunction fail(error: Error): never {\n throw error\n}\n\nfunction isThenable(thing: any): thing is Thenable<any> {\n return thing && typeof thing.then === 'function'\n}\n\n/**\n * Creates a hybrid, combining the APIs of an Observable and a Promise.\n *\n * It is used to proxy async process states when we are initially not sure\n * if that async process will yield values once (-> Promise) or multiple\n * times (-> Observable).\n *\n * Note that the observable promise inherits some of the observable's characteristics:\n * The `init` function will be called *once for every time anyone subscribes to it*.\n *\n * If this is undesired, derive a hot observable from it using `makeHot()` and\n * subscribe to that.\n */\nexport class ObservablePromise<T> extends Observable<T> implements Promise<T> {\n readonly [Symbol.toStringTag] = '[object ObservablePromise]'\n private initHasRun = false\n private fulfillmentCallbacks: Array<OnFulfilled<T>> = []\n private rejectionCallbacks: OnRejected[] = []\n\n private firstValue: T | undefined\n private firstValueSet = false\n private rejection: Error | undefined\n private state: 'fulfilled' | 'pending' | 'rejected' = 'pending'\n\n constructor(init: Initializer<T>) {\n super((originalObserver: SubscriptionObserver<T>) => {\n // tslint:disable-next-line no-this-assignment\n const self = this\n const observer: SubscriptionObserver<T> = {\n ...originalObserver,\n complete() {\n originalObserver.complete()\n self.onCompletion()\n },\n error(error: Error) {\n originalObserver.error(error)\n self.onError(error)\n },\n next(value: T) {\n originalObserver.next(value)\n self.onNext(value)\n },\n }\n\n try {\n this.initHasRun = true\n return init(observer)\n } catch (error) {\n observer.error(error)\n }\n })\n }\n\n private onNext(value: T) {\n if (!this.firstValueSet) {\n this.firstValue = value\n this.firstValueSet = true\n }\n }\n\n private onError(error: Error) {\n this.state = 'rejected'\n this.rejection = error\n\n for (const onRejected of this.rejectionCallbacks) {\n // Promisifying the call to turn errors into unhandled promise rejections\n // instead of them failing sync and cancelling the iteration\n runDeferred(() => onRejected(error))\n }\n }\n\n private onCompletion() {\n this.state = 'fulfilled'\n\n for (const onFulfilled of this.fulfillmentCallbacks) {\n // Promisifying the call to turn errors into unhandled promise rejections\n // instead of them failing sync and cancelling the iteration\n runDeferred(() => onFulfilled(this.firstValue as T))\n }\n }\n\n then<TResult1 = T, TResult2 = never>(\n onFulfilledRaw?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null,\n onRejectedRaw?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null,\n ): Promise<TResult1 | TResult2> {\n const onFulfilled: OnFulfilled<T, TResult1> = onFulfilledRaw || (returnInput as any)\n const onRejected = onRejectedRaw || fail\n let onRejectedCalled = false\n\n return new Promise<TResult1 | TResult2>((resolve, reject) => {\n const rejectionCallback = (error: Error) => {\n if (onRejectedCalled) return\n onRejectedCalled = true\n\n try {\n resolve(onRejected(error))\n } catch (anotherError) {\n reject(anotherError)\n }\n }\n const fulfillmentCallback = (value: T) => {\n try {\n resolve(onFulfilled(value))\n } catch (ex) {\n const error = ex as Error\n rejectionCallback(error)\n }\n }\n if (!this.initHasRun) {\n this.subscribe({ error: rejectionCallback })\n }\n if (this.state === 'fulfilled') {\n return resolve(onFulfilled(this.firstValue as T))\n }\n if (this.state === 'rejected') {\n onRejectedCalled = true\n return resolve(onRejected(this.rejection as Error))\n }\n this.fulfillmentCallbacks.push(fulfillmentCallback)\n this.rejectionCallbacks.push(rejectionCallback)\n })\n }\n\n catch<Result = never>(onRejected: ((error: Error) => Promise<Result> | Result) | null | undefined) {\n return this.then(undefined, onRejected) as Promise<Result>\n }\n\n finally(onCompleted?: (() => void) | null | undefined) {\n const handler = onCompleted || doNothing\n return this.then(\n (value: T) => {\n handler()\n return value\n },\n () => handler(),\n ) as Promise<T>\n }\n\n static override from<T>(thing: Observable<T> | ObservableLike<T> | ArrayLike<T> | Thenable<T>): ObservablePromise<T> {\n return isThenable(thing)\n ? new ObservablePromise((observer) => {\n const onFulfilled = (value: T) => {\n observer.next(value)\n observer.complete()\n }\n const onRejected = (error: any) => {\n observer.error(error)\n }\n thing.then(onFulfilled, onRejected)\n })\n : (super.from(thing) as ObservablePromise<T>)\n }\n}\n","/// <reference lib=\"webworker\" />\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { $transferable } from './symbols.ts'\n\nexport interface TransferDescriptor<T = any> {\n [$transferable]: true\n send: T\n transferables: Transferable[]\n}\n\nfunction isTransferable(thing: any): thing is Transferable {\n if (!thing || typeof thing !== 'object') return false\n // Don't check too thoroughly, since the list of transferable things in JS might grow over time\n return true\n}\n\nexport function isTransferDescriptor(thing: any): thing is TransferDescriptor {\n return thing && typeof thing === 'object' && thing[$transferable]\n}\n\n/**\n * Mark a transferable object as such, so it will no be serialized and\n * deserialized on messaging with the main thread, but to transfer\n * ownership of it to the receiving thread.\n *\n * Only works with array buffers, message ports and few more special\n * types of objects, but it's much faster than serializing and\n * deserializing them.\n *\n * Note:\n * The transferable object cannot be accessed by this thread again\n * unless the receiving thread transfers it back again!\n *\n * @param transferable Array buffer, message port or similar.\n * @see <https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast>\n */\nexport function Transfer(transferable: Transferable): TransferDescriptor\n\n/**\n * Mark transferable objects within an arbitrary object or array as\n * being a transferable object. They will then not be serialized\n * and deserialized on messaging with the main thread, but ownership\n * of them will be tranferred to the receiving thread.\n *\n * Only array buffers, message ports and few more special types of\n * objects can be transferred, but it's much faster than serializing and\n * deserializing them.\n *\n * Note:\n * The transferable object cannot be accessed by this thread again\n * unless the receiving thread transfers it back again!\n *\n * @param transferable Array buffer, message port or similar.\n * @see <https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast>\n */\nexport function Transfer<T>(payload: T, transferables: Transferable[]): TransferDescriptor\n\nexport function Transfer<T>(payload: T, transferables?: Transferable[]): TransferDescriptor {\n console.log('Transfer')\n if (!transferables) {\n if (!isTransferable(payload)) throw new Error('Not transferable')\n transferables = [payload]\n }\n\n return {\n [$transferable]: true,\n send: payload,\n transferables,\n }\n}\n"],"mappings":"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","names":["DebugLogger","Observable","Observable","doNothing","Observable","debugMessages","DebugLogger","Observable"]}