@dmop/puru 0.1.13 → 0.1.14

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/serialize.ts","../src/configure.ts","../src/runtime.ts","../src/adapters/node.ts","../src/bootstrap.ts","../src/adapters/bun.ts","../src/channel.ts","../src/adapters/inline.ts","../src/pool.ts","../src/spawn.ts","../src/waitgroup.ts","../src/errgroup.ts","../src/mutex.ts","../src/semaphore.ts","../src/cond.ts","../src/once.ts","../src/select.ts","../src/after.ts","../src/ticker.ts","../src/timer.ts","../src/registry.ts","../src/context.ts"],"sourcesContent":["export { spawn } from \"./spawn.js\";\nexport { chan } from \"./channel.js\";\nexport type { Channel, SendOnly, RecvOnly } from \"./channel.js\";\nexport { WaitGroup } from \"./waitgroup.js\";\nexport { ErrGroup } from \"./errgroup.js\";\nexport { Mutex, RWMutex } from \"./mutex.js\";\nexport { Semaphore } from \"./semaphore.js\";\nexport { Cond } from \"./cond.js\";\nexport { Once } from \"./once.js\";\nexport { select } from \"./select.js\";\nexport type { SelectOptions } from \"./select.js\";\nexport { after } from \"./after.js\";\nexport { Ticker, ticker } from \"./ticker.js\";\nexport { Timer } from \"./timer.js\";\nexport { task } from \"./registry.js\";\nexport {\n background,\n withCancel,\n withTimeout,\n withDeadline,\n withValue,\n CancelledError,\n DeadlineExceededError,\n} from \"./context.js\";\nexport type { Context, CancelFunc, ContextError } from \"./context.js\";\nexport { configure } from \"./configure.js\";\nexport { stats, resize, shutdown } from \"./pool.js\";\nexport type { PoolStats } from \"./pool.js\";\nexport { detectRuntime, detectCapability } from \"./runtime.js\";\nexport type { Runtime, Capability } from \"./runtime.js\";\nexport type { SpawnResult, PuruConfig } from \"./types.js\";\n","const NATIVE_CODE_RE = /\\[native code\\]/;\nconst METHOD_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*\\s*\\(/;\n\n// A valid serialized function must start with one of these patterns.\n// This guards against prototype pollution on Function.prototype.toString\n// returning arbitrary strings.\nconst VALID_FN_START_RE =\n /^(?:function\\b|async\\s+function\\b|async\\s*\\(|\\(|[a-zA-Z_$][a-zA-Z0-9_$]*\\s*=>|async\\s+[a-zA-Z_$])/;\n\nconst serializeCache = new WeakMap<Function, string>();\n\nexport function serializeFunction(fn: Function): string {\n if (typeof fn !== \"function\") {\n throw new TypeError(\"Expected a function\");\n }\n\n const cached = serializeCache.get(fn);\n if (cached) return cached;\n\n const str = fn.toString();\n\n if (typeof str !== \"string\" || str.length === 0) {\n throw new TypeError(\n \"Function serialization returned an invalid result. \" +\n \"This may indicate Function.prototype.toString has been tampered with.\",\n );\n }\n\n if (NATIVE_CODE_RE.test(str)) {\n throw new TypeError(\n \"Native functions cannot be serialized. Use an arrow function wrapper instead.\",\n );\n }\n\n if (!VALID_FN_START_RE.test(str)) {\n throw new TypeError(\n \"Function serialization produced unexpected output. \" +\n \"Only arrow functions, function expressions, and async functions are supported.\",\n );\n }\n\n // Detect class methods like \"method() { ... }\" — not valid standalone functions\n if (\n METHOD_RE.test(str) &&\n !str.startsWith(\"function\") &&\n !str.startsWith(\"async function\") &&\n !str.startsWith(\"async (\") &&\n !str.startsWith(\"async=\") &&\n !str.startsWith(\"(\") &&\n !str.includes(\"=>\")\n ) {\n throw new TypeError(\n \"Class methods cannot be serialized. Use an arrow function wrapper instead.\",\n );\n }\n\n serializeCache.set(fn, str);\n return str;\n}\n","import { availableParallelism } from \"node:os\";\nimport type { PuruConfig } from \"./types.js\";\n\nconst DEFAULT_CONFIG: PuruConfig = {\n maxThreads: availableParallelism?.() ?? 4,\n strategy: \"fifo\",\n idleTimeout: 30_000,\n adapter: \"auto\",\n concurrency: 64,\n};\n\nlet currentConfig: PuruConfig = { ...DEFAULT_CONFIG };\nlet configLocked = false;\n\n/**\n * Configure the global thread pool. **Must be called before the first `spawn()`.**\n *\n * After the pool is initialized, calling `configure()` throws. Call it once at\n * application startup or in test setup.\n *\n * @example\n * configure({\n * maxThreads: 4, // default: os.availableParallelism()\n * concurrency: 64, // max concurrent tasks per shared worker (default: 64)\n * idleTimeout: 30_000, // kill idle workers after 30s (default: 30_000)\n * adapter: 'auto', // 'auto' | 'node' | 'bun' | 'inline' (default: 'auto')\n * })\n *\n * @example\n * // In tests: run tasks on the main thread with no real workers\n * configure({ adapter: 'inline' })\n */\nexport function configure(opts: Partial<PuruConfig>): void {\n if (configLocked) {\n throw new Error(\n \"configure() must be called before the first spawn(). The worker pool has already been initialized.\",\n );\n }\n currentConfig = { ...currentConfig, ...opts };\n}\n\nexport function getConfig(): PuruConfig {\n configLocked = true;\n return { ...currentConfig };\n}\n\n/** @internal For testing only */\nexport function resetConfig(): void {\n currentConfig = { ...DEFAULT_CONFIG };\n configLocked = false;\n}\n","export type Runtime = \"node\" | \"deno\" | \"bun\" | \"browser\";\nexport type Capability = \"full-threads\" | \"single-thread\";\n\nexport function detectRuntime(): Runtime {\n if (\"Bun\" in globalThis) return \"bun\";\n if (\"Deno\" in globalThis) return \"deno\";\n if (typeof globalThis.process !== \"undefined\" && globalThis.process.versions?.node) return \"node\";\n return \"browser\";\n}\n\nexport function detectCapability(): Capability {\n const runtime = detectRuntime();\n if (runtime === \"node\" || runtime === \"bun\") return \"full-threads\";\n if (\"Worker\" in globalThis) return \"full-threads\";\n return \"single-thread\";\n}\n","import { Worker } from \"node:worker_threads\";\nimport { NODE_BOOTSTRAP_CODE } from \"../bootstrap.js\";\nimport type { ManagedWorker, WorkerAdapter } from \"./base.js\";\nimport type { WorkerMessage, WorkerResponse } from \"../types.js\";\n\nclass NodeManagedWorker implements ManagedWorker {\n private worker: Worker;\n\n constructor() {\n this.worker = new Worker(NODE_BOOTSTRAP_CODE, { eval: true });\n }\n\n get id(): number {\n return this.worker.threadId;\n }\n\n postMessage(data: WorkerMessage): void {\n this.worker.postMessage(data);\n }\n\n terminate(): Promise<number> {\n return this.worker.terminate();\n }\n\n on(event: \"message\", handler: (data: WorkerResponse) => void): void;\n on(event: \"error\", handler: (err: Error) => void): void;\n on(event: \"exit\", handler: (code: number) => void): void;\n on(\n event: \"message\" | \"error\" | \"exit\",\n handler: ((data: WorkerResponse) => void) | ((err: Error) => void) | ((code: number) => void),\n ): void {\n this.worker.on(event, handler);\n }\n\n unref(): void {\n this.worker.unref();\n }\n\n ref(): void {\n this.worker.ref();\n }\n}\n\nexport class NodeWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new NodeManagedWorker();\n }\n}\n","/**\n * Channel proxy code shared between Node and Web bootstraps.\n * Injected at the top of the worker, inert unless channels are passed.\n */\nconst CHANNEL_PROXY_CODE = `\nconst __chCallbacks = new Map();\nlet __chRpcId = 0;\n\nclass __ChannelProxy {\n constructor(id) {\n this._id = id;\n }\n\n _rpc(op, value) {\n const correlationId = ++__chRpcId;\n return new Promise((resolve, reject) => {\n __chCallbacks.set(correlationId, { resolve, reject });\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op,\n correlationId,\n value\n });\n });\n }\n\n send(value) {\n return this._rpc('send', value);\n }\n\n recv() {\n return this._rpc('recv', undefined);\n }\n\n close() {\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op: 'close',\n correlationId: ++__chRpcId\n });\n }\n\n [Symbol.asyncIterator]() {\n const proxy = this;\n return {\n async next() {\n const value = await proxy.recv();\n if (value === null) return { done: true, value: undefined };\n return { done: false, value };\n }\n };\n }\n}\n\nfunction __handleChannelResult(msg) {\n if (msg.type === 'channel-result') {\n const cb = __chCallbacks.get(msg.correlationId);\n if (cb) {\n __chCallbacks.delete(msg.correlationId);\n if (msg.error) {\n cb.reject(new Error(msg.error));\n } else {\n cb.resolve(msg.value);\n }\n }\n }\n}\n\nfunction __buildChannelProxies(channels) {\n if (!channels) return undefined;\n const proxies = {};\n for (const name of Object.keys(channels)) {\n proxies[name] = new __ChannelProxy(channels[name]);\n }\n return proxies;\n}\n\nconst __fnCache = new Map();\nconst __FN_CACHE_MAX = 1000;\n\nfunction __execFn(fnStr, channels, args) {\n let parsedFn = __fnCache.get(fnStr);\n if (!parsedFn) {\n parsedFn = (new Function('return (' + fnStr + ')'))();\n if (__fnCache.size >= __FN_CACHE_MAX) __fnCache.delete(__fnCache.keys().next().value);\n __fnCache.set(fnStr, parsedFn);\n }\n if (args) {\n return parsedFn(...args);\n }\n if (channels) {\n return parsedFn(__buildChannelProxies(channels));\n }\n return parsedFn();\n}\n`;\n\n/** Bootstrap code for Node.js workers (eval: true, CJS context) */\nexport const NODE_BOOTSTRAP_CODE = `\n'use strict';\nconst { parentPort } = require('worker_threads');\n\nconst __postMsg = (d) => parentPort.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nparentPort.on('message', (msg) => {\n __handleChannelResult(msg);\n});\n\nparentPort.on('message', async (msg) => {\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnStr, msg.channels, msg.args);\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnStr, msg.channels, msg.args);\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n process.exit(0);\n }\n});\n\nparentPort.postMessage({ type: 'ready' });\n`;\n\n/** Bootstrap code for Bun/Web Workers (file-based, Web Worker API) */\nexport const WEB_BOOTSTRAP_CODE = `\nconst __postMsg = (d) => self.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nself.addEventListener('message', (event) => {\n __handleChannelResult(event.data);\n});\n\nself.onmessage = async (event) => {\n const msg = event.data;\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnStr, msg.channels, msg.args);\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnStr, msg.channels, msg.args);\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n self.close();\n }\n};\n\nself.postMessage({ type: 'ready' });\n`;\n\n/** @deprecated Use NODE_BOOTSTRAP_CODE instead */\nexport const BOOTSTRAP_CODE = NODE_BOOTSTRAP_CODE;\n","import { WEB_BOOTSTRAP_CODE } from \"../bootstrap.js\";\nimport type { ManagedWorker, WorkerAdapter } from \"./base.js\";\nimport type { WorkerMessage, WorkerResponse } from \"../types.js\";\nimport { writeFileSync, unlinkSync, mkdtempSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\n\ninterface BunWorkerMessageEvent {\n data: WorkerResponse;\n}\n\ninterface BunWorkerErrorEvent {\n message: string;\n error?: Error;\n}\n\ninterface BunWorkerCloseEvent {\n code?: number;\n}\n\ninterface BunRuntimeWorker {\n postMessage(data: WorkerMessage): void;\n terminate(): void;\n addEventListener(type: \"message\", handler: (event: BunWorkerMessageEvent) => void): void;\n addEventListener(type: \"error\", handler: (event: BunWorkerErrorEvent) => void): void;\n addEventListener(type: \"close\", handler: (event: BunWorkerCloseEvent) => void): void;\n unref?(): void;\n ref?(): void;\n}\n\ntype BunWorkerConstructor = new (url: string | URL) => BunRuntimeWorker;\n\nlet workerIdCounter = 0;\nlet bootstrapFile: string | null = null;\n\n/**\n * Returns the path to a temporary JS file containing the bootstrap code.\n * Bun's Blob URL workers break when the URL is revoked before the worker\n * fully initializes its message handler, so we use a file-based worker instead.\n */\nfunction getBootstrapFile(): string {\n if (!bootstrapFile) {\n const dir = mkdtempSync(join(tmpdir(), \"puru-\"));\n bootstrapFile = join(dir, \"worker.js\");\n writeFileSync(bootstrapFile, WEB_BOOTSTRAP_CODE);\n }\n return bootstrapFile;\n}\n\nclass BunManagedWorker implements ManagedWorker {\n private worker: BunRuntimeWorker;\n readonly id: number;\n\n constructor() {\n this.id = ++workerIdCounter;\n const WorkerConstructor = (globalThis as { Worker?: BunWorkerConstructor }).Worker;\n if (!WorkerConstructor) {\n throw new Error(\"Bun Worker constructor is not available in this runtime\");\n }\n this.worker = new WorkerConstructor(getBootstrapFile());\n }\n\n postMessage(data: WorkerMessage): void {\n this.worker.postMessage(data);\n }\n\n terminate(): Promise<number> {\n this.worker.terminate();\n // Web Worker terminate() is synchronous and void; return resolved 0\n return Promise.resolve(0);\n }\n\n on(event: \"message\", handler: (data: WorkerResponse) => void): void;\n on(event: \"error\", handler: (err: Error) => void): void;\n on(event: \"exit\", handler: (code: number) => void): void;\n on(\n event: \"message\" | \"error\" | \"exit\",\n handler: ((data: WorkerResponse) => void) | ((err: Error) => void) | ((code: number) => void),\n ): void {\n if (event === \"message\") {\n this.worker.addEventListener(\"message\", (e) => {\n (handler as (data: WorkerResponse) => void)(e.data);\n });\n } else if (event === \"error\") {\n this.worker.addEventListener(\"error\", (e) => {\n (handler as (err: Error) => void)(e.error ?? new Error(e.message));\n });\n } else if (event === \"exit\") {\n // Bun emits 'close' on worker termination; the event carries a numeric exit code\n this.worker.addEventListener(\"close\", (e) => {\n (handler as (code: number) => void)(e.code ?? 0);\n });\n }\n }\n\n unref(): void {\n // Bun Workers support unref() — not in standard Web Worker types\n if (\n \"unref\" in this.worker &&\n typeof (this.worker as { unref?: () => void }).unref === \"function\"\n ) {\n (this.worker as { unref(): void }).unref();\n }\n }\n\n ref(): void {\n // Bun Workers support ref() — not in standard Web Worker types\n if (\"ref\" in this.worker && typeof (this.worker as { ref?: () => void }).ref === \"function\") {\n (this.worker as { ref(): void }).ref();\n }\n }\n}\n\nexport class BunWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new BunManagedWorker();\n }\n}\n\n/** Clean up the temporary bootstrap file. Called during pool drain. */\nexport function cleanupBootstrapFile(): void {\n if (bootstrapFile) {\n try {\n unlinkSync(bootstrapFile);\n } catch {}\n bootstrapFile = null;\n }\n}\n","import type { ChannelValue } from \"./types.js\";\n\n// Internal sentinel used to signal channel closure.\n// Using a symbol instead of null means null is a valid value to send through a channel\n// at the implementation level, and avoids silent failures if someone attempts to send null.\n// The public recv() API still returns null for a closed channel — the symbol is not leaked.\nconst CLOSED = Symbol(\"puru.channel.closed\");\n\n/**\n * A Go-style channel for communicating between async tasks and across worker threads.\n *\n * Use `chan<T>(capacity?)` to create a channel. Values must be structured-cloneable\n * (no functions, symbols, or WeakRefs). `null` cannot be sent — `recv()` returns\n * `null` only when the channel is closed.\n *\n * @example\n * const ch = chan<number>(10)\n * await ch.send(42)\n * const value = await ch.recv() // 42\n * ch.close()\n * await ch.recv() // null — channel closed\n *\n * @example\n * // Async iteration ends automatically when the channel is closed\n * for await (const item of ch) {\n * process(item)\n * }\n */\nexport interface Channel<T extends ChannelValue> {\n send(value: T): Promise<void>;\n /** Resolves with the next value, or `null` if the channel is closed. */\n recv(): Promise<T | null>;\n close(): void;\n /** Number of values currently buffered. Like Go's `len(ch)`. */\n readonly len: number;\n /** Buffer capacity. Like Go's `cap(ch)`. */\n readonly cap: number;\n /** Returns a send-only view of this channel. Like Go's `chan<- T`. */\n sendOnly(): SendOnly<T>;\n /** Returns a receive-only view of this channel. Like Go's `<-chan T`. */\n recvOnly(): RecvOnly<T>;\n [Symbol.asyncIterator](): AsyncIterator<T>;\n}\n\n/** Send-only view of a channel. Like Go's `chan<- T`. */\nexport interface SendOnly<T extends ChannelValue> {\n send(value: T): Promise<void>;\n close(): void;\n readonly len: number;\n readonly cap: number;\n}\n\n/** Receive-only view of a channel. Like Go's `<-chan T`. */\nexport interface RecvOnly<T extends ChannelValue> {\n recv(): Promise<T | null>;\n readonly len: number;\n readonly cap: number;\n [Symbol.asyncIterator](): AsyncIterator<T>;\n}\n\ninterface ChannelHandle<T extends ChannelValue> extends Channel<T> {\n readonly _id: string;\n}\n\ninterface PendingRecv<T> {\n resolve: (value: T | typeof CLOSED) => void;\n}\n\ninterface PendingSend<T> {\n value: T;\n resolve: () => void;\n reject: (reason: Error) => void;\n}\n\nlet channelIdCounter = 0;\nconst channelRegistry = new Map<string, ChannelHandle<ChannelValue>>();\n\nclass ChannelImpl<T extends ChannelValue> implements ChannelHandle<T> {\n // constraint: can't create channels of nullable type\n /** @internal */\n readonly _id: string;\n /** @internal — true once the channel ID has been sent to a worker */\n _shared = false;\n private buffer: T[] = [];\n private capacity: number;\n private closed = false;\n private recvQueue: PendingRecv<T>[] = [];\n private sendQueue: PendingSend<T>[] = [];\n\n constructor(capacity: number) {\n this._id = `__ch_${++channelIdCounter}`;\n this.capacity = capacity;\n channelRegistry.set(this._id, this as ChannelHandle<ChannelValue>);\n }\n\n get len(): number {\n return this.buffer.length;\n }\n\n get cap(): number {\n return this.capacity;\n }\n\n send(value: T): Promise<void> {\n if (this.closed) {\n return Promise.reject(new Error(\"send on closed channel\"));\n }\n\n // If there's a waiting receiver, deliver directly\n const receiver = this.recvQueue.shift();\n if (receiver) {\n receiver.resolve(value);\n return Promise.resolve();\n }\n\n // If buffer has room, buffer it\n if (this.buffer.length < this.capacity) {\n this.buffer.push(value);\n return Promise.resolve();\n }\n\n // Block until a receiver is ready\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ value, resolve, reject });\n });\n }\n\n recv(): Promise<T | null> {\n // If buffer has a value, take it and unblock a pending sender\n if (this.buffer.length > 0) {\n const value = this.buffer.shift()!;\n const sender = this.sendQueue.shift();\n if (sender) {\n this.buffer.push(sender.value);\n sender.resolve();\n }\n this.maybeUnregister();\n return Promise.resolve(value);\n }\n\n // If there's a pending sender (unbuffered or buffer was empty), take directly\n const sender = this.sendQueue.shift();\n if (sender) {\n sender.resolve();\n return Promise.resolve(sender.value);\n }\n\n // If closed, return null\n if (this.closed) {\n this.maybeUnregister();\n return Promise.resolve(null);\n }\n\n // Block until a sender provides a value or channel closes\n return new Promise<T | null>((resolve) => {\n this.recvQueue.push({\n resolve: (v) => resolve(v === CLOSED ? null : (v as T)),\n });\n });\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n\n // Resolve all pending receivers with the CLOSED sentinel (converted to null at the public boundary)\n for (const receiver of this.recvQueue) {\n receiver.resolve(CLOSED);\n }\n this.recvQueue = [];\n\n // Reject all pending senders\n for (const sender of this.sendQueue) {\n sender.reject(new Error(\"send on closed channel\"));\n }\n this.sendQueue = [];\n }\n\n private maybeUnregister(): void {\n if (!this._shared && this.closed && this.buffer.length === 0 && this.recvQueue.length === 0) {\n channelRegistry.delete(this._id);\n }\n }\n\n sendOnly(): SendOnly<T> {\n const send = (value: T) => this.send(value);\n const close = () => this.close();\n const getLen = () => this.len;\n const getCap = () => this.cap;\n return {\n send,\n close,\n get len() {\n return getLen();\n },\n get cap() {\n return getCap();\n },\n };\n }\n\n recvOnly(): RecvOnly<T> {\n const recv = () => this.recv();\n const getLen = () => this.len;\n const getCap = () => this.cap;\n const getIter = () => this[Symbol.asyncIterator]();\n return {\n recv,\n get len() {\n return getLen();\n },\n get cap() {\n return getCap();\n },\n [Symbol.asyncIterator]() {\n return getIter();\n },\n };\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n while (true) {\n const value = await this.recv();\n if (value === null) return;\n yield value;\n }\n }\n}\n\n/**\n * Create a Go-style channel for communicating between tasks and across worker threads.\n *\n * Provides backpressure: `send()` blocks when the buffer is full,\n * `recv()` blocks when the buffer is empty. Channel values must be structured-cloneable\n * (no functions, symbols, or WeakRefs). `null` cannot be sent — it signals closure.\n *\n * @param capacity Buffer size. `0` (default) = unbuffered: each `send()` blocks until a `recv()` is ready.\n *\n * @example\n * const ch = chan<string>(5) // buffered channel, capacity 5\n * await ch.send('hello')\n * const msg = await ch.recv() // 'hello'\n * ch.close()\n *\n * @example\n * // Fan-out: multiple workers pulling from the same channel\n * const input = chan<Job>(50)\n * const output = chan<Result>(50)\n *\n * for (let i = 0; i < 4; i++) {\n * spawn(async ({ input, output }) => {\n * for await (const job of input) {\n * await output.send(processJob(job))\n * }\n * }, { channels: { input, output } })\n * }\n */\nexport function chan<T extends ChannelValue>(capacity: number = 0): Channel<T> {\n if (capacity < 0 || !Number.isInteger(capacity)) {\n throw new RangeError(\"Channel capacity must be a non-negative integer\");\n }\n return new ChannelImpl<T>(capacity);\n}\n\n/** @internal */\nexport function getChannelById(id: string): ChannelHandle<ChannelValue> | undefined {\n return channelRegistry.get(id);\n}\n\n/** @internal */\nexport function getChannelId<T extends ChannelValue>(channel: Channel<T>): string {\n const impl = channel as ChannelImpl<T>;\n impl._shared = true;\n return impl._id;\n}\n\n/** @internal */\nexport function resetChannelRegistry(): void {\n channelRegistry.clear();\n channelIdCounter = 0;\n}\n","import type { ManagedWorker, WorkerAdapter } from \"./base.js\";\nimport { getChannelById } from \"../channel.js\";\nimport type {\n ChannelMap,\n ChannelValue,\n JsonValue,\n StructuredCloneValue,\n WorkerMessage,\n WorkerResponse,\n} from \"../types.js\";\n\nlet inlineIdCounter = 0;\n\ninterface ChannelProxy {\n _id: string;\n send(value: ChannelValue): Promise<void>;\n recv(): Promise<ChannelValue | null>;\n close(): void;\n [Symbol.asyncIterator](): AsyncIterator<ChannelValue>;\n}\n\ntype MessageHandler = (data: WorkerResponse) => void;\ntype ErrorHandler = (err: Error) => void;\ntype ExitHandler = (code: number) => void;\n\nclass InlineManagedWorker implements ManagedWorker {\n readonly id: number;\n private messageHandlers: MessageHandler[] = [];\n private errorHandlers: ErrorHandler[] = [];\n private exitHandlers: ExitHandler[] = [];\n private terminated = false;\n private cancelledTasks = new Set<string>();\n private fnCache = new Map<\n string,\n (...args: JsonValue[]) => StructuredCloneValue | Promise<StructuredCloneValue>\n >();\n\n constructor() {\n this.id = ++inlineIdCounter;\n // Emit ready on next microtask (matches real worker timing)\n queueMicrotask(() => {\n this.emit(\"message\", { type: \"ready\" });\n });\n }\n\n postMessage(msg: WorkerMessage): void {\n if (this.terminated) return;\n\n if (msg.type === \"execute\") {\n this.executeTask(msg.taskId, msg.fnStr, msg.concurrent, msg.channels, msg.args);\n } else if (msg.type === \"cancel\") {\n this.cancelledTasks.add(msg.taskId);\n } else if (msg.type === \"channel-result\") {\n // The inline adapter calls channels directly, so there is no worker-side RPC to route.\n return;\n } else if (msg.type === \"shutdown\") {\n this.terminated = true;\n this.emit(\"exit\", 0);\n }\n }\n\n terminate(): Promise<number> {\n this.terminated = true;\n this.emit(\"exit\", 1);\n return Promise.resolve(1);\n }\n\n on(event: \"message\", handler: (data: WorkerResponse) => void): void;\n on(event: \"error\", handler: ErrorHandler): void;\n on(event: \"exit\", handler: ExitHandler): void;\n on(\n event: \"message\" | \"error\" | \"exit\",\n handler: MessageHandler | ErrorHandler | ExitHandler,\n ): void {\n if (event === \"message\") this.messageHandlers.push(handler as MessageHandler);\n else if (event === \"error\") this.errorHandlers.push(handler as ErrorHandler);\n else if (event === \"exit\") this.exitHandlers.push(handler as ExitHandler);\n }\n\n unref(): void {}\n ref(): void {}\n\n private emit(event: \"message\", data: WorkerResponse): void;\n private emit(event: \"error\", err: Error): void;\n private emit(event: \"exit\", code: number): void;\n private emit(event: \"message\" | \"error\" | \"exit\", value: WorkerResponse | Error | number): void {\n if (event === \"message\") {\n for (const h of this.messageHandlers) h(value as WorkerResponse);\n } else if (event === \"error\") {\n for (const h of this.errorHandlers) h(value as Error);\n } else if (event === \"exit\") {\n for (const h of this.exitHandlers) h(value as number);\n }\n }\n\n private buildChannelProxies(channels: ChannelMap): Record<string, ChannelProxy> {\n const proxies: Record<string, ChannelProxy> = {};\n for (const [name, channelId] of Object.entries(channels)) {\n proxies[name] = {\n _id: channelId,\n async send(value: ChannelValue) {\n const ch = getChannelById(channelId);\n if (!ch) throw new Error(`Channel ${channelId} not found`);\n await ch.send(value);\n },\n async recv() {\n const ch = getChannelById(channelId);\n if (!ch) throw new Error(`Channel ${channelId} not found`);\n return ch.recv();\n },\n close() {\n const ch = getChannelById(channelId);\n if (ch) ch.close();\n },\n [Symbol.asyncIterator]() {\n const ch = getChannelById(channelId);\n if (!ch) throw new Error(`Channel ${channelId} not found`);\n return ch[Symbol.asyncIterator]();\n },\n };\n }\n return proxies;\n }\n\n private executeTask(\n taskId: string,\n fnStr: string,\n concurrent: boolean,\n channels?: ChannelMap,\n args?: JsonValue[],\n ): void {\n // Run on next microtask to simulate async worker behavior\n queueMicrotask(async () => {\n if (this.terminated) return;\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId);\n return;\n }\n try {\n let parsedFn = this.fnCache.get(fnStr);\n if (!parsedFn) {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n parsedFn = new Function(\"return (\" + fnStr + \")\")() as (\n ...args: JsonValue[]\n ) => StructuredCloneValue | Promise<StructuredCloneValue>;\n if (this.fnCache.size >= 1000) this.fnCache.clear();\n this.fnCache.set(fnStr, parsedFn);\n }\n let result: StructuredCloneValue;\n if (args) {\n result = await parsedFn(...args);\n } else if (channels) {\n const proxies = this.buildChannelProxies(channels);\n result = await parsedFn(proxies as never);\n } else {\n result = await parsedFn();\n }\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId);\n return;\n }\n this.emit(\"message\", { type: \"result\", taskId, value: result });\n } catch (error) {\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId);\n return;\n }\n this.emit(\"message\", {\n type: \"error\",\n taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n });\n }\n}\n\nexport class InlineAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new InlineManagedWorker();\n }\n}\n","import type { ManagedWorker, WorkerAdapter } from \"./adapters/base.js\";\nimport type {\n ChannelValue,\n PuruConfig,\n StructuredCloneValue,\n Task,\n TaskError,\n WorkerMessage,\n WorkerResponse,\n} from \"./types.js\";\nimport { getConfig } from \"./configure.js\";\nimport { detectRuntime, detectCapability } from \"./runtime.js\";\nimport { NodeWorkerAdapter } from \"./adapters/node.js\";\nimport { BunWorkerAdapter } from \"./adapters/bun.js\";\nimport { InlineAdapter } from \"./adapters/inline.js\";\nimport { getChannelById } from \"./channel.js\";\n\ninterface PriorityQueues {\n high: Task[];\n normal: Task[];\n low: Task[];\n}\n\nexport class WorkerPool {\n private config: PuruConfig;\n private adapter: WorkerAdapter;\n private idleWorkers: ManagedWorker[] = [];\n private exclusiveWorkers = new Map<string, ManagedWorker>();\n private sharedWorkers = new Map<ManagedWorker, Set<string>>();\n private queues: PriorityQueues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n };\n private concurrentQueues: PriorityQueues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n };\n private allWorkers = new Set<ManagedWorker>();\n private idleTimers = new Map<ManagedWorker, ReturnType<typeof setTimeout>>();\n private pendingWorkerCount = 0;\n private pendingTasksForWorkers: Task[] = [];\n private draining = false;\n private totalCompleted = 0;\n private totalFailed = 0;\n private taskMap = new Map<string, Task>();\n\n // Per-worker deques for work-stealing strategy\n private workerDeques = new Map<ManagedWorker, PriorityQueues>();\n\n constructor(config: PuruConfig, adapter: WorkerAdapter) {\n this.config = config;\n this.adapter = adapter;\n }\n\n // --- Queue helpers ---\n\n private enqueue(task: Task): void {\n this.queues[task.priority].push(task);\n }\n\n private dequeue(): Task | undefined {\n return this.queues.high.shift() ?? this.queues.normal.shift() ?? this.queues.low.shift();\n }\n\n private enqueueConcurrent(task: Task): void {\n this.concurrentQueues[task.priority].push(task);\n }\n\n private dequeueConcurrent(): Task | undefined {\n return (\n this.concurrentQueues.high.shift() ??\n this.concurrentQueues.normal.shift() ??\n this.concurrentQueues.low.shift()\n );\n }\n\n private removeFromQueue(taskId: string): Task | undefined {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n const queue = this.queues[priority];\n const idx = queue.findIndex((t) => t.id === taskId);\n if (idx !== -1) {\n return queue.splice(idx, 1)[0];\n }\n }\n return undefined;\n }\n\n private removeFromConcurrentQueue(taskId: string): Task | undefined {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n const queue = this.concurrentQueues[priority];\n const idx = queue.findIndex((t) => t.id === taskId);\n if (idx !== -1) {\n return queue.splice(idx, 1)[0];\n }\n }\n return undefined;\n }\n\n // --- Work-stealing helpers ---\n\n private getOrCreateDeque(worker: ManagedWorker): PriorityQueues {\n let deque = this.workerDeques.get(worker);\n if (!deque) {\n deque = { high: [], normal: [], low: [] };\n this.workerDeques.set(worker, deque);\n }\n return deque;\n }\n\n private dequeSize(worker: ManagedWorker): number {\n const deque = this.workerDeques.get(worker);\n if (!deque) return 0;\n return deque.high.length + deque.normal.length + deque.low.length;\n }\n\n private enqueueToWorker(worker: ManagedWorker, task: Task): void {\n this.getOrCreateDeque(worker)[task.priority].push(task);\n }\n\n /** Pop from own deque — FIFO within each priority level. */\n private dequeueFromOwn(worker: ManagedWorker): Task | undefined {\n const deque = this.workerDeques.get(worker);\n if (!deque) return undefined;\n return deque.high.shift() ?? deque.normal.shift() ?? deque.low.shift();\n }\n\n /** Steal from a victim's deque — takes lowest-priority work from the back. */\n private stealFrom(victim: ManagedWorker): Task | undefined {\n const deque = this.workerDeques.get(victim);\n if (!deque) return undefined;\n return deque.low.pop() ?? deque.normal.pop() ?? deque.high.pop();\n }\n\n /** Find the exclusive worker with the shortest deque to push a new task to. */\n private findShortestDequeWorker(): ManagedWorker | undefined {\n let best: ManagedWorker | undefined;\n let bestSize = Infinity;\n const seen = new Set<ManagedWorker>();\n for (const worker of this.exclusiveWorkers.values()) {\n if (seen.has(worker)) continue;\n seen.add(worker);\n const size = this.dequeSize(worker);\n if (size < bestSize) {\n bestSize = size;\n best = worker;\n }\n }\n return best;\n }\n\n /** Steal a task from the busiest worker's deque, excluding the thief. */\n private stealFromBusiest(thief: ManagedWorker): Task | undefined {\n let victim: ManagedWorker | undefined;\n let maxSize = 0;\n for (const [worker, deque] of this.workerDeques) {\n if (worker === thief) continue;\n const size = deque.high.length + deque.normal.length + deque.low.length;\n if (size > maxSize) {\n maxSize = size;\n victim = worker;\n }\n }\n if (!victim || maxSize === 0) return undefined;\n return this.stealFrom(victim);\n }\n\n /** Steal from any deque (no thief exclusion — used by resize). */\n private stealFromAny(): Task | undefined {\n let victim: ManagedWorker | undefined;\n let maxSize = 0;\n for (const [worker, deque] of this.workerDeques) {\n const size = deque.high.length + deque.normal.length + deque.low.length;\n if (size > maxSize) {\n maxSize = size;\n victim = worker;\n }\n }\n if (!victim || maxSize === 0) return undefined;\n return this.stealFrom(victim);\n }\n\n /** Remove a task by ID from any worker's deque. */\n private removeFromDeques(taskId: string): Task | undefined {\n for (const [, deque] of this.workerDeques) {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n const queue = deque[priority];\n const idx = queue.findIndex((t) => t.id === taskId);\n if (idx !== -1) {\n return queue.splice(idx, 1)[0];\n }\n }\n }\n return undefined;\n }\n\n /** Flush a worker's deque back to the global queue (for redistribution). */\n private flushDeque(worker: ManagedWorker): void {\n const deque = this.workerDeques.get(worker);\n if (!deque) return;\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of deque[priority]) {\n this.queues[priority].push(task);\n }\n }\n this.workerDeques.delete(worker);\n }\n\n /** Clean up a deque if it's empty. */\n private cleanupDeque(worker: ManagedWorker): void {\n if (this.dequeSize(worker) === 0) {\n this.workerDeques.delete(worker);\n }\n }\n\n // --- Submit ---\n\n submit(task: Task): void {\n if (this.draining) {\n task.reject(new Error(\"Pool is shutting down\"));\n return;\n }\n\n if (task.concurrent) {\n this.submitConcurrent(task);\n } else {\n this.submitExclusive(task);\n }\n }\n\n private submitExclusive(task: Task): void {\n // Try to assign to an idle worker\n const worker = this.idleWorkers.pop();\n if (worker) {\n this.dispatch(worker, task);\n return;\n }\n\n // Try to create a new worker\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount;\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++;\n this.pendingTasksForWorkers.push(task);\n this.createAndReadyWorker();\n return;\n }\n\n // Work-stealing: push to the busy worker with the shortest deque\n if (this.config.strategy === \"work-stealing\") {\n const target = this.findShortestDequeWorker();\n if (target) {\n this.enqueueToWorker(target, task);\n return;\n }\n }\n\n // FIFO fallback (or no exclusive workers for work-stealing)\n this.enqueue(task);\n }\n\n private submitConcurrent(task: Task): void {\n // 1. Find a shared worker under the concurrency limit\n for (const [worker, tasks] of this.sharedWorkers) {\n if (tasks.size < this.config.concurrency) {\n this.dispatchConcurrent(worker, task);\n return;\n }\n }\n\n // 2. Grab an idle worker and convert to shared mode\n const idleWorker = this.idleWorkers.pop();\n if (idleWorker) {\n this.dispatchConcurrent(idleWorker, task);\n return;\n }\n\n // 3. Spin up a new worker if under limit\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount;\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++;\n this.pendingTasksForWorkers.push(task);\n this.createAndReadyWorker();\n return;\n }\n\n // 4. All workers busy/saturated — queue it\n this.enqueueConcurrent(task);\n }\n\n // --- Dispatch ---\n\n private dispatch(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n\n worker.ref();\n this.exclusiveWorkers.set(task.id, worker);\n this.taskMap.set(task.id, task);\n\n const msg: WorkerMessage = {\n type: \"execute\",\n taskId: task.id,\n fnStr: task.fnStr,\n args: task.args,\n concurrent: false,\n channels: task.channels,\n };\n worker.postMessage(msg);\n }\n\n private dispatchConcurrent(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n\n worker.ref();\n\n if (!this.sharedWorkers.has(worker)) {\n this.sharedWorkers.set(worker, new Set());\n }\n this.sharedWorkers.get(worker)!.add(task.id);\n this.taskMap.set(task.id, task);\n\n const msg: WorkerMessage = {\n type: \"execute\",\n taskId: task.id,\n fnStr: task.fnStr,\n args: task.args,\n concurrent: true,\n channels: task.channels,\n };\n worker.postMessage(msg);\n }\n\n // --- Task completion ---\n\n private handleWorkerMessage(worker: ManagedWorker, response: WorkerResponse): void {\n if (response.type === \"channel-op\") {\n this.handleChannelOp(worker, response);\n return;\n }\n\n if (response.type === \"result\") {\n const taskId = response.taskId;\n this.resolveTask(taskId, response.value);\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId);\n this.assignNextOrIdle(worker);\n } else {\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n taskSet.delete(taskId);\n this.assignNextConcurrentOrIdle(worker);\n }\n }\n } else if (response.type === \"error\") {\n const taskId = response.taskId;\n const err = new Error(response.message);\n if (response.stack) err.stack = response.stack;\n // ReferenceError inside a worker almost always means the function captured\n // a variable from the enclosing scope. Surface a clear message rather than\n // a cryptic worker-internal stack trace.\n if (\n response.message.match(/^ReferenceError:/) ||\n response.message.match(/ is not defined$/)\n ) {\n err.message +=\n \"\\n Hint: functions passed to spawn() cannot access variables from the enclosing scope. \" +\n \"Inline all required values directly in the function body, or pass them via the channels option.\";\n }\n this.rejectTask(taskId, err);\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId);\n this.assignNextOrIdle(worker);\n } else {\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n taskSet.delete(taskId);\n this.assignNextConcurrentOrIdle(worker);\n }\n }\n }\n }\n\n private assignNextOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return;\n\n if (this.config.strategy === \"work-stealing\") {\n // 1. Check own deque (FIFO — pop from front)\n const own = this.dequeueFromOwn(worker);\n if (own) {\n this.cleanupDeque(worker);\n this.dispatch(worker, own);\n return;\n }\n\n // 2. Steal from the busiest worker (LIFO — pop from back, lowest priority first)\n const stolen = this.stealFromBusiest(worker);\n if (stolen) {\n this.dispatch(worker, stolen);\n return;\n }\n }\n\n // FIFO: try exclusive queue (also serves as fallback for work-stealing)\n const next = this.dequeue();\n if (next) {\n this.dispatch(worker, next);\n return;\n }\n\n // Then try concurrent queue\n const concurrentNext = this.dequeueConcurrent();\n if (concurrentNext) {\n this.dispatchConcurrent(worker, concurrentNext);\n return;\n }\n\n this.cleanupDeque(worker);\n this.makeIdle(worker);\n }\n\n private assignNextConcurrentOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return;\n\n const taskSet = this.sharedWorkers.get(worker);\n const currentCount = taskSet?.size ?? 0;\n\n // Fill up to concurrency limit from concurrent queue\n let filled = currentCount;\n while (filled < this.config.concurrency) {\n const next = this.dequeueConcurrent();\n if (!next) break;\n this.dispatchConcurrent(worker, next);\n filled++;\n }\n\n // If no tasks remain, transition back\n const updatedSet = this.sharedWorkers.get(worker);\n if (!updatedSet || updatedSet.size === 0) {\n this.sharedWorkers.delete(worker);\n // Try exclusive queue before going idle\n const exclusiveTask = this.dequeue();\n if (exclusiveTask) {\n this.dispatch(worker, exclusiveTask);\n } else if (this.config.strategy === \"work-stealing\") {\n // Try stealing from busy workers' deques\n const stolen = this.stealFromBusiest(worker);\n if (stolen) {\n this.dispatch(worker, stolen);\n } else {\n this.makeIdle(worker);\n }\n } else {\n this.makeIdle(worker);\n }\n }\n }\n\n private makeIdle(worker: ManagedWorker): void {\n worker.unref();\n this.idleWorkers.push(worker);\n\n if (this.config.idleTimeout > 0) {\n const timer = setTimeout(() => {\n this.idleTimers.delete(worker);\n const idx = this.idleWorkers.indexOf(worker);\n if (idx !== -1) {\n this.idleWorkers.splice(idx, 1);\n }\n this.allWorkers.delete(worker);\n worker.terminate();\n }, this.config.idleTimeout);\n\n // Don't let the idle timer prevent process exit\n if (timer.unref) timer.unref();\n this.idleTimers.set(worker, timer);\n }\n }\n\n // --- Channel RPC ---\n\n private async handleChannelOp(\n worker: ManagedWorker,\n msg: Extract<WorkerResponse, { type: \"channel-op\" }>,\n ): Promise<void> {\n const channel = getChannelById(msg.channelId);\n\n if (!channel) {\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n error: `Channel ${msg.channelId} not found`,\n });\n return;\n }\n\n try {\n if (msg.op === \"send\") {\n await channel.send(msg.value as ChannelValue);\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n });\n } else if (msg.op === \"recv\") {\n const value = await channel.recv();\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n value,\n });\n } else if (msg.op === \"close\") {\n channel.close();\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n });\n }\n } catch (err) {\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n // --- Task resolution ---\n\n private resolveTask(taskId: string, value: StructuredCloneValue): void {\n const task = this.taskMap.get(taskId);\n if (task) {\n this.taskMap.delete(taskId);\n this.totalCompleted++;\n task.resolve(value);\n }\n }\n\n private rejectTask(taskId: string, reason: TaskError): void {\n const task = this.taskMap.get(taskId);\n if (task) {\n this.taskMap.delete(taskId);\n this.totalFailed++;\n task.reject(reason);\n }\n }\n\n private rejectExclusiveTaskForWorker(worker: ManagedWorker, reason: TaskError): void {\n for (const [taskId, assignedWorker] of this.exclusiveWorkers) {\n if (assignedWorker === worker) {\n this.exclusiveWorkers.delete(taskId);\n this.rejectTask(taskId, reason);\n break;\n }\n }\n }\n\n // --- Cancellation ---\n\n cancelTask(taskId: string): void {\n // 1. Check exclusive queues\n const removed = this.removeFromQueue(taskId);\n if (removed) {\n removed.reject(new DOMException(\"Task was cancelled\", \"AbortError\"));\n return;\n }\n\n // 1b. Check per-worker deques (work-stealing)\n if (this.config.strategy === \"work-stealing\") {\n const removedFromDeque = this.removeFromDeques(taskId);\n if (removedFromDeque) {\n removedFromDeque.reject(new DOMException(\"Task was cancelled\", \"AbortError\"));\n return;\n }\n }\n\n // 2. Check concurrent queues\n const removedConcurrent = this.removeFromConcurrentQueue(taskId);\n if (removedConcurrent) {\n removedConcurrent.reject(new DOMException(\"Task was cancelled\", \"AbortError\"));\n return;\n }\n\n // 3. Check exclusive workers — terminate the worker (existing behavior)\n const exclusiveWorker = this.exclusiveWorkers.get(taskId);\n if (exclusiveWorker) {\n this.exclusiveWorkers.delete(taskId);\n this.allWorkers.delete(exclusiveWorker);\n this.taskMap.delete(taskId);\n // Redistribute deque tasks before terminating the worker\n this.flushDeque(exclusiveWorker);\n exclusiveWorker.terminate();\n return;\n }\n\n // 4. Check shared workers — send cancel message, do NOT terminate\n for (const [worker, taskSet] of this.sharedWorkers) {\n if (taskSet.has(taskId)) {\n taskSet.delete(taskId);\n this.taskMap.delete(taskId);\n worker.postMessage({ type: \"cancel\", taskId });\n if (taskSet.size === 0) {\n this.sharedWorkers.delete(worker);\n this.assignNextConcurrentOrIdle(worker);\n }\n return;\n }\n }\n }\n\n // --- Lifecycle ---\n\n async drain(): Promise<void> {\n this.draining = true;\n\n // Reject all queued exclusive tasks\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of this.queues[priority]) {\n task.reject(new Error(\"Pool is shutting down\"));\n }\n this.queues[priority] = [];\n }\n\n // Reject all queued concurrent tasks\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of this.concurrentQueues[priority]) {\n task.reject(new Error(\"Pool is shutting down\"));\n }\n this.concurrentQueues[priority] = [];\n }\n\n // Reject all tasks in per-worker deques (work-stealing)\n for (const [, deque] of this.workerDeques) {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of deque[priority]) {\n task.reject(new Error(\"Pool is shutting down\"));\n }\n }\n }\n this.workerDeques.clear();\n\n // Clear in-flight exclusive tasks — their workers are about to be terminated.\n // We don't reject them here because the caller may not be listening, which\n // would cause unhandled rejection errors. The promises will simply never settle.\n for (const [taskId] of this.exclusiveWorkers) {\n this.taskMap.delete(taskId);\n }\n this.exclusiveWorkers.clear();\n\n // Same for in-flight concurrent tasks.\n for (const [, taskSet] of this.sharedWorkers) {\n for (const taskId of taskSet) {\n this.taskMap.delete(taskId);\n }\n }\n\n // Terminate all workers\n const terminatePromises: Promise<number>[] = [];\n for (const worker of this.allWorkers) {\n const timer = this.idleTimers.get(worker);\n if (timer) clearTimeout(timer);\n terminatePromises.push(worker.terminate());\n }\n\n await Promise.all(terminatePromises);\n\n this.idleWorkers = [];\n this.exclusiveWorkers.clear();\n this.sharedWorkers.clear();\n this.allWorkers.clear();\n this.idleTimers.clear();\n }\n\n resize(maxThreads: number): void {\n this.config = { ...this.config, maxThreads };\n\n // If we now have capacity, dequeue tasks and spin up workers\n while (true) {\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount;\n if (totalWorkers >= maxThreads) break;\n // Try exclusive queue first, then steal from deques, then concurrent\n const task =\n this.dequeue() ??\n (this.config.strategy === \"work-stealing\" ? this.stealFromAny() : undefined) ??\n this.dequeueConcurrent();\n if (!task) break;\n this.pendingWorkerCount++;\n this.pendingTasksForWorkers.push(task);\n this.createAndReadyWorker();\n }\n\n // If pool is now oversized, terminate excess idle workers\n while (this.allWorkers.size > maxThreads && this.idleWorkers.length > 0) {\n const worker = this.idleWorkers.pop()!;\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n this.allWorkers.delete(worker);\n worker.terminate();\n }\n }\n\n // --- Worker creation ---\n\n private createAndReadyWorker(): void {\n const worker = this.adapter.createWorker();\n\n const onReady = () => {\n this.pendingWorkerCount--;\n this.allWorkers.add(worker);\n\n const task = this.pendingTasksForWorkers.shift();\n if (task) {\n if (task.concurrent) {\n this.dispatchConcurrent(worker, task);\n } else {\n this.dispatch(worker, task);\n }\n } else {\n this.makeIdle(worker);\n }\n };\n\n worker.on(\"message\", (response) => {\n if (response.type === \"ready\") {\n onReady();\n return;\n }\n this.handleWorkerMessage(worker, response);\n });\n\n worker.on(\"error\", (err: Error) => {\n this.rejectExclusiveTaskForWorker(worker, err);\n // Clean up concurrent tasks on this worker\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, err);\n }\n this.sharedWorkers.delete(worker);\n }\n });\n\n worker.on(\"exit\", (_code: number) => {\n this.allWorkers.delete(worker);\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n\n // Remove from idle if present\n const idleIdx = this.idleWorkers.indexOf(worker);\n if (idleIdx !== -1) {\n this.idleWorkers.splice(idleIdx, 1);\n }\n\n this.rejectExclusiveTaskForWorker(worker, new Error(\"Worker exited unexpectedly\"));\n\n // Redistribute deque tasks back to the global queue so other workers can pick them up\n this.flushDeque(worker);\n\n // Clean up concurrent tasks\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, new Error(\"Worker exited unexpectedly\"));\n }\n this.sharedWorkers.delete(worker);\n }\n });\n }\n\n // --- Stats ---\n\n stats(): PoolStats {\n let concurrentTasks = 0;\n for (const taskSet of this.sharedWorkers.values()) {\n concurrentTasks += taskSet.size;\n }\n\n // Include per-worker deque sizes in queued task counts\n let dequeHigh = 0;\n let dequeNormal = 0;\n let dequeLow = 0;\n for (const deque of this.workerDeques.values()) {\n dequeHigh += deque.high.length;\n dequeNormal += deque.normal.length;\n dequeLow += deque.low.length;\n }\n\n const queuedHigh = this.queues.high.length + dequeHigh;\n const queuedNormal = this.queues.normal.length + dequeNormal;\n const queuedLow = this.queues.low.length + dequeLow;\n\n return {\n totalWorkers: this.allWorkers.size,\n idleWorkers: this.idleWorkers.length,\n busyWorkers: this.exclusiveWorkers.size,\n sharedWorkers: this.sharedWorkers.size,\n concurrentTasks,\n pendingWorkers: this.pendingWorkerCount,\n queuedTasks: {\n high: queuedHigh,\n normal: queuedNormal,\n low: queuedLow,\n total: queuedHigh + queuedNormal + queuedLow,\n },\n queuedConcurrentTasks: {\n high: this.concurrentQueues.high.length,\n normal: this.concurrentQueues.normal.length,\n low: this.concurrentQueues.low.length,\n total:\n this.concurrentQueues.high.length +\n this.concurrentQueues.normal.length +\n this.concurrentQueues.low.length,\n },\n totalCompleted: this.totalCompleted,\n totalFailed: this.totalFailed,\n maxThreads: this.config.maxThreads,\n concurrency: this.config.concurrency,\n };\n }\n}\n\nexport interface PoolStats {\n totalWorkers: number;\n idleWorkers: number;\n busyWorkers: number;\n sharedWorkers: number;\n concurrentTasks: number;\n pendingWorkers: number;\n queuedTasks: {\n high: number;\n normal: number;\n low: number;\n total: number;\n };\n queuedConcurrentTasks: {\n high: number;\n normal: number;\n low: number;\n total: number;\n };\n totalCompleted: number;\n totalFailed: number;\n maxThreads: number;\n concurrency: number;\n}\n\n// Pool singleton\nlet poolInstance: WorkerPool | null = null;\n\nfunction createAdapter(adapterConfig: string): WorkerAdapter {\n if (adapterConfig === \"inline\") return new InlineAdapter();\n if (adapterConfig === \"node\") return new NodeWorkerAdapter();\n if (adapterConfig === \"bun\") return new BunWorkerAdapter();\n\n // auto — detect runtime\n const capability = detectCapability();\n if (capability === \"single-thread\") {\n throw new Error(\n \"puru requires a runtime with thread support (Node.js or Bun). \" +\n \"Current runtime does not support worker threads.\",\n );\n }\n const runtime = detectRuntime();\n if (runtime === \"bun\") return new BunWorkerAdapter();\n return new NodeWorkerAdapter();\n}\n\nexport function getPool(): WorkerPool {\n if (!poolInstance) {\n const config = getConfig();\n poolInstance = new WorkerPool(config, createAdapter(config.adapter));\n }\n return poolInstance;\n}\n\nexport function stats(): PoolStats {\n return getPool().stats();\n}\n\nexport function resize(maxThreads: number): void {\n getPool().resize(maxThreads);\n}\n\n/**\n * Gracefully shut down the thread pool.\n *\n * Rejects all queued tasks, waits for all workers to terminate, then clears\n * the pool. Safe to call at process exit or at the end of a test suite.\n *\n * ```ts\n * process.on('SIGTERM', async () => {\n * await shutdown()\n * process.exit(0)\n * })\n * ```\n */\nexport async function shutdown(): Promise<void> {\n if (poolInstance) {\n await poolInstance.drain();\n poolInstance = null;\n }\n}\n\n/** @internal For testing only */\nexport async function resetPool(): Promise<void> {\n await shutdown();\n}\n","import { serializeFunction } from \"./serialize.js\";\nimport { getPool } from \"./pool.js\";\nimport type { Channel } from \"./channel.js\";\nimport { getChannelId } from \"./channel.js\";\nimport type { Context } from \"./context.js\";\nimport type {\n ChannelMap,\n ChannelValue,\n SpawnResult,\n StructuredCloneValue,\n Task,\n TaskError,\n} from \"./types.js\";\n\nlet taskCounter = 0;\n\n/**\n * Run a function in a worker thread. Returns a handle with the result promise and a cancel function.\n *\n * **Functions must be self-contained** — they are serialized via `.toString()` and sent to a\n * worker thread, so they cannot capture variables from the enclosing scope. Define everything\n * you need inside the function body, or use `task()` to pass arguments.\n *\n * **Two modes:**\n * - Default (exclusive): the function gets a dedicated thread. Best for CPU-bound work (> 5ms).\n * - `{ concurrent: true }`: many tasks share a thread's event loop. Best for async/I/O work.\n *\n * @example\n * // CPU-bound work — define helpers inside the function body\n * const { result } = spawn(() => {\n * function fibonacci(n: number): number {\n * if (n <= 1) return n\n * return fibonacci(n - 1) + fibonacci(n - 2)\n * }\n * return fibonacci(40)\n * })\n * console.log(await result)\n *\n * @example\n * // I/O-bound work — concurrent mode shares threads efficiently\n * const { result } = spawn(() => fetch('https://api.example.com').then(r => r.json()), {\n * concurrent: true,\n * })\n *\n * @example\n * // Cancel a long-running task\n * const { result, cancel } = spawn(() => longRunningTask())\n * setTimeout(cancel, 5000)\n *\n * @example\n * // Cross-thread channels — pass channels via opts.channels\n * const ch = chan<number>(10)\n * spawn(async ({ ch }) => {\n * for (let i = 0; i < 100; i++) await ch.send(i)\n * ch.close()\n * }, { channels: { ch } })\n */\nexport function spawn<\n T extends StructuredCloneValue,\n TChannels extends Record<string, Channel<ChannelValue>> = Record<never, never>,\n>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: {\n priority?: \"low\" | \"normal\" | \"high\";\n concurrent?: boolean;\n channels?: TChannels;\n ctx?: Context;\n },\n): SpawnResult<T> {\n const fnStr = serializeFunction(fn);\n const taskId = String(++taskCounter);\n\n // Capture the call site for better error reporting.\n // Creating the Error is cheap; accessing .stack (which triggers V8's\n // stack formatting) is deferred to the reject path so the happy path\n // pays no cost.\n const spawnError = new Error();\n\n let resolveFn!: (value: T) => void;\n let rejectFn!: (reason: TaskError) => void;\n let settled = false;\n\n const result = new Promise<T>((resolve, reject) => {\n resolveFn = resolve;\n rejectFn = reject;\n });\n\n // Extract channel IDs if channels are provided\n let channelMap: ChannelMap | undefined;\n if (opts?.channels) {\n channelMap = {};\n for (const [name, ch] of Object.entries(opts.channels)) {\n channelMap[name] = getChannelId(ch);\n }\n }\n\n const task: Task = {\n id: taskId,\n fnStr,\n priority: opts?.priority ?? \"normal\",\n concurrent: opts?.concurrent ?? false,\n channels: channelMap,\n resolve: (value) => {\n if (!settled) {\n settled = true;\n resolveFn(value as T);\n }\n },\n reject: (reason) => {\n if (!settled) {\n settled = true;\n // Enrich worker errors with the spawn() call site\n if (reason instanceof Error) {\n const spawnStack = spawnError.stack;\n if (spawnStack) {\n const callerLine = spawnStack.split(\"\\n\").slice(2).join(\"\\n\");\n reason.stack =\n (reason.stack ?? reason.message) + \"\\n --- spawned at ---\\n\" + callerLine;\n }\n }\n rejectFn(reason);\n }\n },\n };\n\n // Context integration: cancel the task when the context is cancelled\n const ctx = opts?.ctx;\n if (ctx) {\n if (ctx.signal.aborted) {\n settled = true;\n rejectFn(ctx.err ?? new DOMException(\"Task was cancelled\", \"AbortError\"));\n return {\n result,\n cancel: () => {},\n };\n }\n }\n\n getPool().submit(task);\n\n const cancel = () => {\n if (settled) return;\n settled = true;\n getPool().cancelTask(taskId);\n rejectFn(new DOMException(\"Task was cancelled\", \"AbortError\"));\n };\n\n // Wire up context cancellation to task cancellation\n if (ctx) {\n const onAbort = () => cancel();\n ctx.signal.addEventListener(\"abort\", onAbort, { once: true });\n // Clean up listener when task settles to avoid leaks\n result.then(\n () => ctx.signal.removeEventListener(\"abort\", onAbort),\n () => ctx.signal.removeEventListener(\"abort\", onAbort),\n );\n }\n\n return { result, cancel };\n}\n\n/** @internal For testing only */\nexport function resetTaskCounter(): void {\n taskCounter = 0;\n}\n","import { spawn as spawnTask } from \"./spawn.js\";\nimport type { ChannelValue, SpawnResult, StructuredCloneValue } from \"./types.js\";\nimport type { Channel } from \"./channel.js\";\nimport type { Context } from \"./context.js\";\n\ntype SpawnChannels = Record<string, Channel<ChannelValue>>;\n\n/**\n * Structured concurrency: spawn multiple tasks and wait for all to complete.\n *\n * Like `Promise.all`, but tasks run in worker threads across CPU cores. Results are\n * returned in the order tasks were spawned. A shared `AbortSignal` lets long-running\n * tasks observe cooperative cancellation via `cancel()`.\n *\n * For fail-fast behavior (cancel all on first error), use `ErrGroup` instead.\n *\n * @example\n * // CPU-bound parallel work\n * const wg = new WaitGroup()\n * wg.spawn(() => { /* define helpers inside — no closure captures *\\/ })\n * wg.spawn(() => { /* another CPU task *\\/ })\n * const [r1, r2] = await wg.wait()\n *\n * @example\n * // Mixed CPU + I/O\n * wg.spawn(() => crunchNumbers(), )\n * wg.spawn(() => fetch('https://api.example.com').then(r => r.json()), { concurrent: true })\n * const results = await wg.wait()\n *\n * @example\n * // Tolerate partial failures with waitSettled\n * const settled = await wg.waitSettled()\n * for (const r of settled) {\n * if (r.status === 'fulfilled') use(r.value)\n * else console.error(r.reason)\n * }\n */\nexport class WaitGroup<T extends StructuredCloneValue = StructuredCloneValue> {\n private tasks: SpawnResult<T>[] = [];\n private controller = new AbortController();\n private ctx?: Context;\n\n constructor(ctx?: Context) {\n this.ctx = ctx;\n if (ctx) {\n if (ctx.signal.aborted) {\n this.controller.abort();\n } else {\n ctx.signal.addEventListener(\"abort\", () => this.cancel(), { once: true });\n }\n }\n }\n\n /**\n * An `AbortSignal` shared across all tasks in this group.\n * Pass it into spawned functions so they can stop early when `cancel()` is called.\n */\n get signal(): AbortSignal {\n return this.controller.signal;\n }\n\n /**\n * Spawns a function on a worker thread and adds it to the group.\n *\n * @throws If the group has already been cancelled.\n */\n spawn<TChannels extends SpawnChannels = Record<never, never>>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: { concurrent?: boolean; channels?: TChannels },\n ): void {\n if (this.controller.signal.aborted) {\n throw new Error(\"WaitGroup has been cancelled\");\n }\n const handle = spawnTask<T, TChannels>(fn, { ...opts, ctx: this.ctx });\n this.tasks.push(handle);\n }\n\n /**\n * Waits for all tasks to complete successfully.\n * Rejects as soon as any task throws.\n */\n async wait(): Promise<T[]> {\n return Promise.all(this.tasks.map((t) => t.result));\n }\n\n /**\n * Waits for all tasks to settle (fulfilled or rejected) and returns each outcome.\n * Never rejects — inspect each `PromiseSettledResult` to handle failures individually.\n */\n async waitSettled(): Promise<PromiseSettledResult<T>[]> {\n return Promise.allSettled(this.tasks.map((t) => t.result));\n }\n\n /**\n * Cancels all tasks in the group and signals the shared `AbortSignal`.\n * Already-settled tasks are unaffected.\n */\n cancel(): void {\n this.controller.abort();\n for (const task of this.tasks) {\n task.cancel();\n }\n }\n}\n","import { spawn as spawnTask } from \"./spawn.js\";\nimport type { ChannelValue, SpawnResult, StructuredCloneValue, TaskError } from \"./types.js\";\nimport type { Channel } from \"./channel.js\";\nimport type { Context } from \"./context.js\";\n\ntype SpawnChannels = Record<string, Channel<ChannelValue>>;\n\n/**\n * Like `WaitGroup`, but cancels all remaining tasks on the first error.\n *\n * Modeled after Go's `golang.org/x/sync/errgroup`. Use when partial results are useless —\n * if any task fails, there is no point waiting for the rest. Benchmarks show ~3.7x faster\n * failure handling than waiting for all tasks to settle.\n *\n * For \"wait for everything regardless of failures\", use `WaitGroup` with `waitSettled()`.\n *\n * @example\n * const eg = new ErrGroup()\n * eg.spawn(() => run('fetchUser', userId))\n * eg.spawn(() => run('fetchOrders', userId))\n * eg.spawn(() => run('fetchAnalytics', userId))\n *\n * try {\n * const [user, orders, analytics] = await eg.wait()\n * } catch (err) {\n * // First failure cancelled the rest — no partial data to clean up\n * }\n *\n * @example\n * // Observe cancellation inside a task via the shared signal\n * const eg = new ErrGroup()\n * eg.spawn(() => {\n * // eg.signal is not directly available inside the worker —\n * // use task() with register() and check a channel or AbortSignal instead\n * })\n */\nexport class ErrGroup<T extends StructuredCloneValue = StructuredCloneValue> {\n private tasks: SpawnResult<T>[] = [];\n private controller = new AbortController();\n private firstError: TaskError | null = null;\n private hasError = false;\n private ctx?: Context;\n private limit = 0; // 0 = unlimited\n private inFlight = 0;\n private waiting: (() => void)[] = [];\n\n constructor(ctx?: Context) {\n this.ctx = ctx;\n if (ctx) {\n if (ctx.signal.aborted) {\n this.controller.abort();\n } else {\n ctx.signal.addEventListener(\"abort\", () => this.cancel(), { once: true });\n }\n }\n }\n\n get signal(): AbortSignal {\n return this.controller.signal;\n }\n\n /**\n * Set the maximum number of tasks that can run concurrently.\n * Like Go's `errgroup.SetLimit()`. Must be called before any `spawn()`.\n * A value of 0 (default) means unlimited.\n */\n setLimit(n: number): void {\n if (this.tasks.length > 0) {\n throw new Error(\"SetLimit must be called before any spawn()\");\n }\n if (n < 0 || !Number.isInteger(n)) {\n throw new RangeError(\"Limit must be a non-negative integer\");\n }\n this.limit = n;\n }\n\n spawn<TChannels extends SpawnChannels = Record<never, never>>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: { concurrent?: boolean; channels?: TChannels },\n ): void {\n if (this.controller.signal.aborted) {\n throw new Error(\"ErrGroup has been cancelled\");\n }\n\n if (this.limit > 0 && this.inFlight >= this.limit) {\n // Queue the spawn until a slot opens\n let innerCancel: () => void = () => {};\n let cancelled = false;\n const cancel = () => {\n cancelled = true;\n innerCancel();\n };\n const result = new Promise<void>((resolve) => {\n this.waiting.push(resolve);\n }).then(() => {\n if (cancelled) throw new DOMException(\"Task was cancelled\", \"AbortError\");\n const handle = this.doSpawn(fn, opts);\n innerCancel = handle.cancel;\n return handle.result;\n });\n this.tasks.push({ result, cancel });\n return;\n }\n\n const handle = this.doSpawn(fn, opts);\n this.tasks.push(handle);\n }\n\n private doSpawn<TChannels extends SpawnChannels = Record<never, never>>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: { concurrent?: boolean; channels?: TChannels },\n ): SpawnResult<T> {\n this.inFlight++;\n const handle = spawnTask<T, TChannels>(fn, { ...opts, ctx: this.ctx });\n\n // When task settles, release the semaphore slot\n const onSettle = () => {\n this.inFlight--;\n const next = this.waiting.shift();\n if (next) next();\n };\n\n // Watch for errors and cancel all tasks on first failure\n handle.result.then(onSettle, (err) => {\n onSettle();\n if (!this.hasError) {\n this.hasError = true;\n this.firstError = err;\n this.cancel();\n }\n });\n\n return handle;\n }\n\n async wait(): Promise<T[]> {\n const settled = await Promise.allSettled(this.tasks.map((t) => t.result));\n\n if (this.hasError && this.firstError) {\n throw this.firstError;\n }\n\n return settled.map((r) => {\n if (r.status === \"fulfilled\") return r.value;\n throw r.reason;\n });\n }\n\n cancel(): void {\n this.controller.abort();\n for (const task of this.tasks) {\n task.cancel();\n }\n }\n}\n","/**\n * Async mutual exclusion. Serializes access to shared state under concurrency.\n *\n * Prefer `withLock()` over manual `lock()`/`unlock()` — it automatically releases\n * the lock even if the callback throws.\n *\n * Note: `Mutex` operates on the main thread (or whichever thread creates it).\n * Worker threads do not share memory, so this is not useful for cross-thread locking.\n * For cross-thread coordination, use channels instead.\n *\n * @example\n * const mu = new Mutex()\n *\n * // withLock — recommended (auto-unlocks on error)\n * const result = await mu.withLock(async () => {\n * const current = await db.get('counter')\n * await db.set('counter', current + 1)\n * return current + 1\n * })\n *\n * @example\n * // Manual lock/unlock (use withLock instead when possible)\n * await mu.lock()\n * try {\n * // critical section\n * } finally {\n * mu.unlock()\n * }\n */\nexport class Mutex {\n private queue: (() => void)[] = [];\n private locked = false;\n\n async lock(): Promise<void> {\n if (!this.locked) {\n this.locked = true;\n return;\n }\n return new Promise<void>((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n unlock(): void {\n if (!this.locked) {\n throw new Error(\"Cannot unlock a mutex that is not locked\");\n }\n const next = this.queue.shift();\n if (next) {\n next();\n } else {\n this.locked = false;\n }\n }\n\n async withLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.lock();\n try {\n return await fn();\n } finally {\n this.unlock();\n }\n }\n\n get isLocked(): boolean {\n return this.locked;\n }\n}\n\n/**\n * Async read-write mutex. Multiple readers can hold the lock simultaneously,\n * but writers get exclusive access. Modeled after Go's `sync.RWMutex`.\n *\n * Use this instead of `Mutex` when reads vastly outnumber writes — concurrent\n * readers improve throughput without sacrificing write safety.\n *\n * Like `Mutex`, this operates on the main thread only. For cross-thread\n * coordination, use channels instead.\n *\n * @example\n * const rw = new RWMutex()\n *\n * // Multiple readers can run concurrently\n * const data = await rw.withRLock(async () => {\n * return await db.get('config')\n * })\n *\n * // Writers get exclusive access\n * await rw.withLock(async () => {\n * await db.set('config', newValue)\n * })\n */\nexport class RWMutex {\n private readers = 0;\n private writing = false;\n private readQueue: (() => void)[] = [];\n private writeQueue: (() => void)[] = [];\n\n async rLock(): Promise<void> {\n if (!this.writing && this.writeQueue.length === 0) {\n this.readers++;\n return;\n }\n return new Promise<void>((resolve) => {\n this.readQueue.push(() => {\n this.readers++;\n resolve();\n });\n });\n }\n\n rUnlock(): void {\n if (this.readers <= 0) {\n throw new Error(\"Cannot rUnlock a RWMutex that is not read-locked\");\n }\n this.readers--;\n if (this.readers === 0) {\n this.wakeWriter();\n }\n }\n\n async lock(): Promise<void> {\n if (!this.writing && this.readers === 0) {\n this.writing = true;\n return;\n }\n return new Promise<void>((resolve) => {\n this.writeQueue.push(() => {\n this.writing = true;\n resolve();\n });\n });\n }\n\n unlock(): void {\n if (!this.writing) {\n throw new Error(\"Cannot unlock a RWMutex that is not write-locked\");\n }\n this.writing = false;\n // Prefer waking readers first (many can run); fall back to a writer\n if (this.readQueue.length > 0) {\n this.wakeReaders();\n } else {\n this.wakeWriter();\n }\n }\n\n async withRLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.rLock();\n try {\n return await fn();\n } finally {\n this.rUnlock();\n }\n }\n\n async withLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.lock();\n try {\n return await fn();\n } finally {\n this.unlock();\n }\n }\n\n get isLocked(): boolean {\n return this.writing || this.readers > 0;\n }\n\n private wakeReaders(): void {\n const queue = this.readQueue;\n this.readQueue = [];\n for (const wake of queue) {\n wake();\n }\n }\n\n private wakeWriter(): void {\n const next = this.writeQueue.shift();\n if (next) next();\n }\n}\n","/**\n * Weighted counting semaphore. Limits concurrent access to a resource where\n * each acquisition can have a different cost. Modeled after Go's\n * `golang.org/x/sync/semaphore.Weighted`.\n *\n * A `Mutex` is equivalent to `new Semaphore(1)` — one holder at a time.\n * A `Semaphore` generalizes this to N units, with variable-weight acquisitions.\n *\n * Like `Mutex`, this operates on the main thread only. For cross-thread\n * coordination, use channels instead.\n *\n * @example\n * // Limit to 10 concurrent DB connections\n * const sem = new Semaphore(10)\n *\n * await sem.acquire() // take 1 slot\n * try {\n * await db.query(...)\n * } finally {\n * sem.release()\n * }\n *\n * @example\n * // Weighted: heavy queries cost more\n * const sem = new Semaphore(10)\n *\n * await sem.acquire(5) // heavy query takes 5 slots\n * sem.release(5)\n *\n * @example\n * // withAcquire — recommended (auto-releases on error)\n * const result = await sem.withAcquire(async () => {\n * return await fetch(url)\n * })\n *\n * @example\n * // Non-blocking check\n * if (sem.tryAcquire(3)) {\n * try { ... } finally { sem.release(3) }\n * }\n */\nexport class Semaphore {\n private max: number;\n private cur: number;\n private queue: { n: number; resolve: () => void }[] = [];\n\n constructor(n: number) {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Semaphore capacity must be a positive integer\");\n }\n this.max = n;\n this.cur = 0;\n }\n\n /**\n * Acquire `n` permits, waiting if necessary until they are available.\n * Acquires are served in FIFO order.\n */\n async acquire(n = 1): Promise<void> {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Acquire count must be a positive integer\");\n }\n if (n > this.max) {\n throw new Error(`Acquire count ${n} exceeds semaphore capacity ${this.max}`);\n }\n if (this.cur + n <= this.max && this.queue.length === 0) {\n this.cur += n;\n return;\n }\n return new Promise<void>((resolve) => {\n this.queue.push({ n, resolve });\n });\n }\n\n /**\n * Try to acquire `n` permits without blocking.\n * Returns `true` if successful, `false` if not enough permits are available.\n */\n tryAcquire(n = 1): boolean {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Acquire count must be a positive integer\");\n }\n if (n > this.max) {\n throw new Error(`Acquire count ${n} exceeds semaphore capacity ${this.max}`);\n }\n if (this.cur + n <= this.max && this.queue.length === 0) {\n this.cur += n;\n return true;\n }\n return false;\n }\n\n /**\n * Release `n` permits, potentially waking queued acquirers.\n */\n release(n = 1): void {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Release count must be a positive integer\");\n }\n if (this.cur - n < 0) {\n throw new Error(\"Released more permits than acquired\");\n }\n this.cur -= n;\n this.wake();\n }\n\n /**\n * Acquire `n` permits, run `fn`, then release automatically — even if `fn` throws.\n */\n async withAcquire<T>(fn: () => T | Promise<T>, n = 1): Promise<T> {\n await this.acquire(n);\n try {\n return await fn();\n } finally {\n this.release(n);\n }\n }\n\n /** Number of permits currently available. */\n get available(): number {\n return this.max - this.cur;\n }\n\n /** Total capacity of the semaphore. */\n get capacity(): number {\n return this.max;\n }\n\n private wake(): void {\n while (this.queue.length > 0) {\n const head = this.queue[0];\n if (this.cur + head.n > this.max) break;\n this.queue.shift();\n this.cur += head.n;\n head.resolve();\n }\n }\n}\n","import { Mutex } from \"./mutex.js\";\n\n/**\n * Condition variable for async coordination. Modeled after Go's `sync.Cond`.\n *\n * A `Cond` is associated with a `Mutex`. Goroutines (async tasks) can:\n * - `wait()` — atomically release the lock and suspend until signaled, then re-acquire the lock\n * - `signal()` — wake one waiting task\n * - `broadcast()` — wake all waiting tasks\n *\n * Always check the condition in a loop — spurious wakeups are possible if\n * multiple waiters compete for the lock after `broadcast()`.\n *\n * @example\n * const mu = new Mutex()\n * const cond = new Cond(mu)\n * let ready = false\n *\n * // Waiter\n * await mu.lock()\n * while (!ready) {\n * await cond.wait()\n * }\n * console.log('ready!')\n * mu.unlock()\n *\n * // Signaler (from another async context)\n * await mu.lock()\n * ready = true\n * cond.signal()\n * mu.unlock()\n *\n * @example\n * // Broadcast to wake all waiters\n * await mu.lock()\n * ready = true\n * cond.broadcast()\n * mu.unlock()\n */\nexport class Cond {\n private mu: Mutex;\n private waiters: (() => void)[] = [];\n\n constructor(mu: Mutex) {\n this.mu = mu;\n }\n\n /**\n * Atomically releases the mutex, suspends the caller until `signal()` or `broadcast()`\n * is called, then re-acquires the mutex before returning.\n *\n * Must be called while holding the mutex.\n */\n async wait(): Promise<void> {\n // Release the lock\n this.mu.unlock();\n\n // Wait for signal\n await new Promise<void>((resolve) => {\n this.waiters.push(resolve);\n });\n\n // Re-acquire the lock\n await this.mu.lock();\n }\n\n /** Wake one waiting task (if any). */\n signal(): void {\n const next = this.waiters.shift();\n if (next) next();\n }\n\n /** Wake all waiting tasks. */\n broadcast(): void {\n const queue = this.waiters;\n this.waiters = [];\n for (const wake of queue) {\n wake();\n }\n }\n}\n","/**\n * Run a function exactly once, even if called concurrently.\n * All callers await the same promise and receive the same result.\n *\n * Use for lazy, one-time initialization of expensive resources (DB pools, ML models,\n * config, etc.) that must be initialized at most once regardless of concurrent demand.\n *\n * @example\n * const initDB = new Once<DBPool>()\n *\n * async function getDB() {\n * return initDB.do(() => createPool({ max: 10 }))\n * }\n *\n * // Safe under concurrent load — pool is created exactly once\n * const [db1, db2] = await Promise.all([getDB(), getDB()])\n * // db1 === db2 (same pool instance)\n *\n * @example\n * // Check if initialization has already run\n * if (!initDB.done) {\n * console.log('not yet initialized')\n * }\n */\nexport class Once<T = void> {\n private promise: Promise<T> | null = null;\n private called = false;\n\n async do(fn: () => T | Promise<T>): Promise<T> {\n if (!this.called) {\n this.called = true;\n this.promise = Promise.resolve(fn());\n }\n return this.promise!;\n }\n\n get done(): boolean {\n return this.called;\n }\n\n reset(): void {\n this.called = false;\n this.promise = null;\n }\n}\n","import type { StructuredCloneValue } from \"./types.js\";\n\ntype RecvCase<T = StructuredCloneValue> = [Promise<T>, (value: T) => void];\ntype SendCase = [Promise<void>, () => void];\ntype SelectCase<T = StructuredCloneValue> = RecvCase<T> | SendCase;\n\n/**\n * Options for `select()`.\n *\n * `default` makes the call non-blocking: if no case is immediately ready,\n * the default handler runs instead of waiting. This mirrors Go's `select { default: ... }`.\n */\nexport interface SelectOptions {\n default?: () => void;\n}\n\n/**\n * Wait for the first of multiple promises to resolve, like Go's `select`.\n *\n * Each case is a `[promise, handler]` tuple. The handler for the first settled\n * promise is called with its value. All other handlers are ignored.\n *\n * **Recv cases:** `[ch.recv(), (value) => ...]` — handler receives the value.\n * **Send cases:** `[ch.send(value), () => ...]` — handler is called when the send completes.\n *\n * If `opts.default` is provided, `select` becomes non-blocking: if no promise\n * is already resolved, the default runs immediately (Go's `select { default: ... }`).\n *\n * Commonly used with `ch.recv()`, `ch.send()`, `after()`, and `spawn().result`.\n *\n * @example\n * // Block until a channel message arrives or timeout after 5s\n * await select([\n * [ch.recv(), (value) => console.log('received', value)],\n * [after(5000), () => console.log('timed out')],\n * ])\n *\n * @example\n * // Non-blocking: check a channel without waiting\n * await select(\n * [[ch.recv(), (value) => process(value)]],\n * { default: () => console.log('channel empty — doing other work') },\n * )\n *\n * @example\n * // Select with send case — try to send or timeout\n * await select([\n * [ch.send(value), () => console.log('sent!')],\n * [after(1000), () => console.log('send timed out')],\n * ])\n *\n * @example\n * // Race two worker results against a deadline\n * const { result: fast } = spawn(() => quickSearch(query))\n * const { result: deep } = spawn(() => deepSearch(query))\n *\n * let response: Result\n * await select([\n * [fast, (r) => { response = r }],\n * [after(200), () => { response = { partial: true } }],\n * ])\n */\nexport function select(cases: SelectCase[], opts?: SelectOptions): Promise<void> {\n if (cases.length === 0) {\n if (opts?.default) {\n opts.default();\n }\n return Promise.resolve();\n }\n\n // Non-blocking: if default is provided, check if any promise is already settled\n if (opts?.default) {\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n // Check all promises for immediate resolution\n for (const [promise, handler] of cases) {\n Promise.resolve(promise).then(\n (value) => {\n if (settled) return;\n settled = true;\n try {\n (handler as (value: unknown) => void)(value);\n resolve();\n } catch (err) {\n reject(err);\n }\n },\n (err) => {\n if (settled) return;\n settled = true;\n reject(err);\n },\n );\n }\n\n // Schedule default on the next microtask — if no promise resolved synchronously,\n // default wins\n queueMicrotask(() => {\n if (settled) return;\n settled = true;\n try {\n opts.default!();\n resolve();\n } catch (err) {\n reject(err);\n }\n });\n });\n }\n\n // Blocking: wait for the first promise to settle\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n cases.forEach(([promise, handler]) => {\n promise.then(\n (value) => {\n if (settled) return;\n settled = true;\n try {\n (handler as (value: unknown) => void)(value);\n resolve();\n } catch (err) {\n reject(err);\n }\n },\n (err) => {\n if (settled) return;\n settled = true;\n reject(err);\n },\n );\n });\n });\n}\n","/**\n * Returns a promise that resolves after `ms` milliseconds.\n *\n * Designed for use with `select()` to add timeouts to channel operations or\n * race a deadline against worker results. Also works as a simple async delay.\n *\n * @example\n * // Timeout a channel receive after 2 seconds\n * await select([\n * [ch.recv(), (value) => handle(value)],\n * [after(2000), () => handleTimeout()],\n * ])\n *\n * @example\n * // Simple delay\n * await after(500)\n * console.log('500ms later')\n */\nexport function after(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * A repeating timer that ticks at a fixed interval.\n *\n * Implements `AsyncIterable<void>` — use `for await...of` to run work on each tick.\n * Call `stop()` to cancel the ticker and end the iteration.\n *\n * Create with the `ticker(ms)` factory function.\n *\n * @example\n * const t = ticker(1000) // tick every second\n * for await (const _ of t) {\n * await doWork()\n * if (shouldStop) t.stop() // ends the for-await loop\n * }\n *\n * @example\n * // Use with select() to process work on each tick with a timeout\n * const t = ticker(5000)\n * for await (const _ of t) {\n * await select([\n * [spawn(() => checkHealth()).result, (ok) => report(ok)],\n * [after(4000), () => report('timeout')],\n * ])\n * }\n */\nexport class Ticker {\n private interval: ReturnType<typeof setInterval> | null = null;\n private resolve: ((value: boolean) => void) | null = null;\n private stopped = false;\n private ms: number;\n\n constructor(ms: number) {\n this.ms = ms;\n this.interval = setInterval(() => {\n if (this.resolve) {\n const r = this.resolve;\n this.resolve = null;\n r(true);\n }\n }, ms);\n if (this.interval.unref) this.interval.unref();\n }\n\n async tick(): Promise<boolean> {\n if (this.stopped) return false;\n return new Promise<boolean>((resolve) => {\n this.resolve = resolve;\n // Re-check after assignment: stop() may have been called between\n // the guard above and here, in which case this.resolve was never\n // seen by stop() and the promise would hang.\n if (this.stopped) {\n this.resolve = null;\n resolve(false);\n }\n });\n }\n\n stop(): void {\n this.stopped = true;\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n if (this.resolve) {\n const r = this.resolve;\n this.resolve = null;\n r(false); // resolve pending tick with false — the ticker has stopped\n }\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<void> {\n while (await this.tick()) {\n yield;\n }\n }\n}\n\n/**\n * Create a `Ticker` that fires every `ms` milliseconds.\n *\n * @example\n * const t = ticker(500)\n * for await (const _ of t) {\n * console.log('tick')\n * if (done) t.stop()\n * }\n */\nexport function ticker(ms: number): Ticker {\n return new Ticker(ms);\n}\n","/**\n * A one-shot timer that can be stopped and reset. Like Go's `time.Timer`.\n *\n * Unlike `after()` which is fire-and-forget, `Timer` gives you control:\n * - `stop()` cancels a pending timer\n * - `reset(ms)` reschedules without allocating a new object\n *\n * The `channel` property is a promise that resolves when the timer fires.\n * After `stop()`, the promise never resolves. After `reset()`, a new `channel`\n * promise is created.\n *\n * @example\n * // Basic timeout with ability to cancel\n * const t = new Timer(5000)\n * await select([\n * [ch.recv(), (v) => { t.stop(); handle(v) }],\n * [t.channel, () => console.log('timed out')],\n * ])\n *\n * @example\n * // Reset a timer (e.g., debounce pattern)\n * const t = new Timer(300)\n * onInput(() => t.reset(300))\n * await t.channel // fires 300ms after last input\n */\nexport class Timer {\n private timer: ReturnType<typeof setTimeout> | null = null;\n private _stopped = false;\n\n /** Promise that resolves when the timer fires. Replaced on `reset()`. */\n channel: Promise<void>;\n\n constructor(ms: number) {\n this.channel = this.schedule(ms);\n }\n\n private schedule(ms: number): Promise<void> {\n return new Promise<void>((resolve) => {\n this.timer = setTimeout(() => {\n this._stopped = true;\n this.timer = null;\n resolve();\n }, ms);\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n });\n }\n\n /**\n * Stop the timer. Returns `true` if the timer was pending (stopped before firing),\n * `false` if it had already fired or was already stopped.\n *\n * After stopping, the current `channel` promise will never resolve.\n */\n stop(): boolean {\n if (this.timer === null) return false;\n clearTimeout(this.timer);\n this.timer = null;\n this._stopped = true;\n return true;\n }\n\n /**\n * Reset the timer to fire after `ms` milliseconds.\n * If the timer was pending, it is stopped first. Creates a new `channel` promise.\n */\n reset(ms: number): void {\n this.stop();\n this._stopped = false;\n this.channel = this.schedule(ms);\n }\n\n /** Whether the timer has fired or been stopped. */\n get stopped(): boolean {\n return this._stopped;\n }\n}\n","import { getPool } from \"./pool.js\";\nimport { serializeFunction } from \"./serialize.js\";\nimport type { JsonValue, StructuredCloneValue, Task, TaskError } from \"./types.js\";\n\nlet taskCounter = 0;\n\n/**\n * Define a reusable task that runs in a worker thread.\n *\n * Returns a typed async function — call it like a regular async function,\n * and it dispatches to the thread pool each time.\n *\n * Use task() when you have the same function to call many times with\n * different arguments. For one-off work, use spawn() instead.\n *\n * Arguments must be JSON-serializable (no functions, symbols, undefined, or BigInt).\n * The function itself must be self-contained — it cannot capture enclosing scope variables.\n *\n * @example\n * const resizeImage = task((src: string, width: number, height: number) => {\n * // runs in a worker thread\n * return processPixels(src, width, height)\n * })\n *\n * const result = await resizeImage('photo.jpg', 800, 600)\n * const [a, b] = await Promise.all([resizeImage('a.jpg', 400, 300), resizeImage('b.jpg', 800, 600)])\n */\nexport function task<TArgs extends JsonValue[], TReturn extends StructuredCloneValue>(\n fn: (...args: TArgs) => TReturn | Promise<TReturn>,\n): (...args: TArgs) => Promise<TReturn> {\n const fnStr = serializeFunction(fn);\n return (...args: TArgs): Promise<TReturn> => {\n for (const a of args) {\n if (JSON.stringify(a) === undefined) {\n throw new TypeError(\n `Argument of type ${typeof a} is not JSON-serializable. ` +\n \"task() args must be JSON-serializable (no undefined, functions, symbols, or BigInt).\",\n );\n }\n }\n\n const taskId = `task_${++taskCounter}`;\n const spawnError = new Error();\n\n let resolveFn!: (value: TReturn) => void;\n let rejectFn!: (reason: TaskError) => void;\n\n const result = new Promise<TReturn>((resolve, reject) => {\n resolveFn = resolve;\n rejectFn = reject;\n });\n\n const taskObj: Task = {\n id: taskId,\n fnStr,\n args,\n priority: \"normal\",\n concurrent: false,\n resolve: (value) => resolveFn(value as TReturn),\n reject: (reason) => {\n if (reason instanceof Error) {\n const spawnStack = spawnError.stack;\n if (spawnStack) {\n const callerLine = spawnStack.split(\"\\n\").slice(2).join(\"\\n\");\n reason.stack =\n (reason.stack ?? reason.message) + \"\\n --- spawned at ---\\n\" + callerLine;\n }\n }\n rejectFn(reason);\n },\n };\n\n getPool().submit(taskObj);\n\n return result;\n };\n}\n\n/** @internal For testing only */\nexport function resetTaskCounter(): void {\n taskCounter = 0;\n}\n","/**\n * Hierarchical cancellation, deadlines, and request-scoped values — modeled after Go's `context` package.\n *\n * Context is the glue that makes cancellation and timeouts composable. Derive child\n * contexts from a parent: when the parent is cancelled, all children cancel automatically.\n *\n * @example\n * // Timeout a group of tasks\n * const [ctx, cancel] = withTimeout(background(), 5000)\n * const wg = new WaitGroup()\n * wg.spawn(() => longRunningWork())\n * ctx.done().then(() => wg.cancel())\n *\n * @example\n * // Nested deadlines\n * const [parent, cancelParent] = withCancel(background())\n * const [child, _] = withTimeout(parent, 1000)\n * // child cancels after 1s OR when cancelParent() is called — whichever comes first\n *\n * @example\n * // Request-scoped values\n * const reqCtx = withValue(background(), 'requestId', 'abc-123')\n * reqCtx.value('requestId') // 'abc-123'\n */\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/** Returned by `ctx.err` when the context was explicitly cancelled. */\nexport class CancelledError extends Error {\n constructor(message = \"context cancelled\") {\n super(message);\n this.name = \"CancelledError\";\n }\n}\n\n/** Returned by `ctx.err` when the context's deadline has passed. */\nexport class DeadlineExceededError extends Error {\n constructor() {\n super(\"context deadline exceeded\");\n this.name = \"DeadlineExceededError\";\n }\n}\n\nexport type ContextError = CancelledError | DeadlineExceededError;\n\n// ---------------------------------------------------------------------------\n// Context interface\n// ---------------------------------------------------------------------------\n\nexport interface Context {\n /** AbortSignal that fires when this context is cancelled or its deadline expires. */\n readonly signal: AbortSignal;\n /** The deadline for this context, or `null` if none was set. */\n readonly deadline: Date | null;\n /** The cancellation error, or `null` if the context is still active. */\n readonly err: ContextError | null;\n /** Retrieves a value stored in this context or any of its ancestors. */\n value<T = unknown>(key: symbol | string): T | undefined;\n /** Returns a promise that resolves when the context is cancelled. */\n done(): Promise<void>;\n}\n\nexport type CancelFunc = (reason?: string) => void;\n\n// ---------------------------------------------------------------------------\n// Internal base\n// ---------------------------------------------------------------------------\n\nclass BaseContext implements Context {\n protected _err: ContextError | null = null;\n protected controller: AbortController;\n protected parent: Context | null;\n\n constructor(parent: Context | null) {\n this.parent = parent;\n this.controller = new AbortController();\n\n // Propagate parent cancellation\n if (parent) {\n if (parent.signal.aborted) {\n // Parent already cancelled — cancel immediately\n this._err = parent.err ?? new CancelledError();\n this.controller.abort();\n } else {\n parent.signal.addEventListener(\n \"abort\",\n () => {\n if (!this.controller.signal.aborted) {\n this._err = parent.err ?? new CancelledError();\n this.controller.abort();\n }\n },\n { once: true },\n );\n }\n }\n }\n\n get signal(): AbortSignal {\n return this.controller.signal;\n }\n\n get deadline(): Date | null {\n return this.parent?.deadline ?? null;\n }\n\n get err(): ContextError | null {\n return this._err;\n }\n\n value<T = unknown>(_key: symbol | string): T | undefined {\n return this.parent?.value<T>(_key);\n }\n\n done(): Promise<void> {\n if (this.controller.signal.aborted) return Promise.resolve();\n return new Promise((resolve) => {\n this.controller.signal.addEventListener(\"abort\", () => resolve(), { once: true });\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Background context (root, never cancelled)\n// ---------------------------------------------------------------------------\n\nclass BackgroundContext implements Context {\n private _signal = new AbortController().signal;\n\n get signal(): AbortSignal {\n return this._signal;\n }\n\n get deadline(): Date | null {\n return null;\n }\n\n get err(): ContextError | null {\n return null;\n }\n\n value<T = unknown>(_key: symbol | string): T | undefined {\n return undefined;\n }\n\n done(): Promise<void> {\n // Never resolves — background is never cancelled\n return new Promise(() => {});\n }\n}\n\nlet bg: BackgroundContext | null = null;\n\n/**\n * Returns the root context. It is never cancelled, has no deadline, and carries no values.\n * All other contexts should derive from this.\n */\nexport function background(): Context {\n if (!bg) bg = new BackgroundContext();\n return bg;\n}\n\n// ---------------------------------------------------------------------------\n// withCancel\n// ---------------------------------------------------------------------------\n\nclass CancelContext extends BaseContext {\n cancel(reason?: string): void {\n if (!this.controller.signal.aborted) {\n this._err = new CancelledError(reason ?? \"context cancelled\");\n this.controller.abort();\n }\n }\n}\n\n/**\n * Returns a child context and a cancel function. Calling `cancel()` cancels the child\n * and all contexts derived from it. The child also cancels when the parent does.\n */\nexport function withCancel(parent: Context): [Context, CancelFunc] {\n const ctx = new CancelContext(parent);\n return [ctx, (reason?: string) => ctx.cancel(reason)];\n}\n\n// ---------------------------------------------------------------------------\n// withDeadline / withTimeout\n// ---------------------------------------------------------------------------\n\nclass DeadlineContext extends BaseContext {\n private _deadline: Date;\n private timer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(parent: Context, deadline: Date) {\n super(parent);\n this._deadline = deadline;\n\n // Inherit the earlier deadline if the parent has one\n if (parent.deadline && parent.deadline < deadline) {\n this._deadline = parent.deadline;\n }\n\n if (this.controller.signal.aborted) {\n // Already cancelled by parent propagation\n return;\n }\n\n const ms = this._deadline.getTime() - Date.now();\n if (ms <= 0) {\n // Deadline already passed\n this._err = new DeadlineExceededError();\n this.controller.abort();\n } else {\n this.timer = setTimeout(() => {\n if (!this.controller.signal.aborted) {\n this._err = new DeadlineExceededError();\n this.controller.abort();\n }\n }, ms);\n // Don't keep the process alive just for this timer\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n }\n }\n\n override get deadline(): Date {\n return this._deadline;\n }\n\n cancel(reason?: string): void {\n if (this.timer !== null) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (!this.controller.signal.aborted) {\n this._err = new CancelledError(reason ?? \"context cancelled\");\n this.controller.abort();\n }\n }\n}\n\n/**\n * Returns a child context that automatically cancels at the given `deadline`.\n * If the parent has an earlier deadline, that deadline is inherited.\n * The returned cancel function can cancel early and clears the timer.\n */\nexport function withDeadline(parent: Context, deadline: Date): [Context, CancelFunc] {\n const ctx = new DeadlineContext(parent, deadline);\n return [ctx, (reason?: string) => ctx.cancel(reason)];\n}\n\n/**\n * Returns a child context that automatically cancels after `ms` milliseconds.\n * Equivalent to `withDeadline(parent, new Date(Date.now() + ms))`.\n */\nexport function withTimeout(parent: Context, ms: number): [Context, CancelFunc] {\n return withDeadline(parent, new Date(Date.now() + ms));\n}\n\n// ---------------------------------------------------------------------------\n// withValue\n// ---------------------------------------------------------------------------\n\nclass ValueContext extends BaseContext {\n private key: symbol | string;\n private val: unknown;\n\n constructor(parent: Context, key: symbol | string, val: unknown) {\n super(parent);\n this.key = key;\n this.val = val;\n }\n\n override value<T = unknown>(key: symbol | string): T | undefined {\n if (key === this.key) return this.val as T;\n return this.parent?.value<T>(key);\n }\n}\n\n/**\n * Returns a child context carrying a key-value pair.\n * Values are retrieved with `ctx.value(key)` and looked up through the ancestor chain.\n */\nexport function withValue<T = unknown>(parent: Context, key: symbol | string, value: T): Context {\n return new ValueContext(parent, key, value);\n}\n"],"mappings":"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","names":["import_node_os","sender","task","task","task","handle","task","taskCounter"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/serialize.ts","../src/configure.ts","../src/runtime.ts","../src/adapters/node.ts","../src/bootstrap.ts","../src/adapters/bun.ts","../src/queue.ts","../src/channel.ts","../src/adapters/inline.ts","../src/pool.ts","../src/spawn.ts","../src/waitgroup.ts","../src/errgroup.ts","../src/mutex.ts","../src/semaphore.ts","../src/cond.ts","../src/once.ts","../src/select.ts","../src/after.ts","../src/ticker.ts","../src/timer.ts","../src/registry.ts","../src/context.ts"],"sourcesContent":["export { spawn } from \"./spawn.js\";\nexport { chan } from \"./channel.js\";\nexport type { Channel, SendOnly, RecvOnly } from \"./channel.js\";\nexport { WaitGroup } from \"./waitgroup.js\";\nexport { ErrGroup } from \"./errgroup.js\";\nexport { Mutex, RWMutex } from \"./mutex.js\";\nexport { Semaphore } from \"./semaphore.js\";\nexport { Cond } from \"./cond.js\";\nexport { Once } from \"./once.js\";\nexport { select } from \"./select.js\";\nexport type { SelectOptions } from \"./select.js\";\nexport { after } from \"./after.js\";\nexport { Ticker, ticker } from \"./ticker.js\";\nexport { Timer } from \"./timer.js\";\nexport { task } from \"./registry.js\";\nexport {\n background,\n withCancel,\n withTimeout,\n withDeadline,\n withValue,\n CancelledError,\n DeadlineExceededError,\n} from \"./context.js\";\nexport type { Context, CancelFunc, ContextError } from \"./context.js\";\nexport { configure } from \"./configure.js\";\nexport { stats, resize, shutdown } from \"./pool.js\";\nexport type { PoolStats } from \"./pool.js\";\nexport { detectRuntime, detectCapability } from \"./runtime.js\";\nexport type { Runtime, Capability } from \"./runtime.js\";\nexport type { SpawnResult, PuruConfig } from \"./types.js\";\n","const NATIVE_CODE_RE = /\\[native code\\]/;\nconst METHOD_RE = /^[a-zA-Z_$][a-zA-Z0-9_$]*\\s*\\(/;\n\n// A valid serialized function must start with one of these patterns.\n// This guards against prototype pollution on Function.prototype.toString\n// returning arbitrary strings.\nconst VALID_FN_START_RE =\n /^(?:function\\b|async\\s+function\\b|async\\s*\\(|\\(|[a-zA-Z_$][a-zA-Z0-9_$]*\\s*=>|async\\s+[a-zA-Z_$])/;\n\nconst serializeCache = new WeakMap<Function, string>();\nconst functionRefCache = new WeakMap<Function, SerializedFunctionRef>();\nconst functionIdCache = new Map<string, string>();\nconst FUNCTION_ID_CACHE_MAX = 512;\nlet functionIdCounter = 0;\n\nexport interface SerializedFunctionRef {\n fnId: string;\n fnStr: string;\n}\n\nexport function serializeFunction(fn: Function): string {\n if (typeof fn !== \"function\") {\n throw new TypeError(\"Expected a function\");\n }\n\n const cached = serializeCache.get(fn);\n if (cached) return cached;\n\n const str = fn.toString();\n\n if (typeof str !== \"string\" || str.length === 0) {\n throw new TypeError(\n \"Function serialization returned an invalid result. \" +\n \"This may indicate Function.prototype.toString has been tampered with.\",\n );\n }\n\n if (NATIVE_CODE_RE.test(str)) {\n throw new TypeError(\n \"Native functions cannot be serialized. Use an arrow function wrapper instead.\",\n );\n }\n\n if (!VALID_FN_START_RE.test(str)) {\n throw new TypeError(\n \"Function serialization produced unexpected output. \" +\n \"Only arrow functions, function expressions, and async functions are supported.\",\n );\n }\n\n // Detect class methods like \"method() { ... }\" — not valid standalone functions\n if (\n METHOD_RE.test(str) &&\n !str.startsWith(\"function\") &&\n !str.startsWith(\"async function\") &&\n !str.startsWith(\"async (\") &&\n !str.startsWith(\"async=\") &&\n !str.startsWith(\"(\") &&\n !str.includes(\"=>\")\n ) {\n throw new TypeError(\n \"Class methods cannot be serialized. Use an arrow function wrapper instead.\",\n );\n }\n\n serializeCache.set(fn, str);\n return str;\n}\n\nexport function getSerializedFunctionRef(fn: Function): SerializedFunctionRef {\n const cached = functionRefCache.get(fn);\n if (cached) return cached;\n\n const fnStr = serializeFunction(fn);\n let fnId = functionIdCache.get(fnStr);\n\n if (fnId) {\n // Refresh insertion order to keep recent functions hot.\n functionIdCache.delete(fnStr);\n } else {\n fnId = `fn_${++functionIdCounter}`;\n }\n\n functionIdCache.set(fnStr, fnId);\n if (functionIdCache.size > FUNCTION_ID_CACHE_MAX) {\n const oldestFnStr = functionIdCache.keys().next().value;\n if (oldestFnStr !== undefined) functionIdCache.delete(oldestFnStr);\n }\n\n const ref = { fnId, fnStr };\n functionRefCache.set(fn, ref);\n return ref;\n}\n","import { availableParallelism } from \"node:os\";\nimport type { PuruConfig } from \"./types.js\";\n\nconst DEFAULT_CONFIG: PuruConfig = {\n maxThreads: availableParallelism?.() ?? 4,\n strategy: \"fifo\",\n idleTimeout: 30_000,\n adapter: \"auto\",\n concurrency: 64,\n};\n\nlet currentConfig: PuruConfig = { ...DEFAULT_CONFIG };\nlet configLocked = false;\n\n/**\n * Configure the global thread pool. **Must be called before the first `spawn()`.**\n *\n * After the pool is initialized, calling `configure()` throws. Call it once at\n * application startup or in test setup.\n *\n * @example\n * configure({\n * maxThreads: 4, // default: os.availableParallelism()\n * concurrency: 64, // max concurrent tasks per shared worker (default: 64)\n * idleTimeout: 30_000, // kill idle workers after 30s (default: 30_000)\n * adapter: 'auto', // 'auto' | 'node' | 'bun' | 'inline' (default: 'auto')\n * })\n *\n * @example\n * // In tests: run tasks on the main thread with no real workers\n * configure({ adapter: 'inline' })\n */\nexport function configure(opts: Partial<PuruConfig>): void {\n if (configLocked) {\n throw new Error(\n \"configure() must be called before the first spawn(). The worker pool has already been initialized.\",\n );\n }\n currentConfig = { ...currentConfig, ...opts };\n}\n\nexport function getConfig(): PuruConfig {\n configLocked = true;\n return { ...currentConfig };\n}\n\n/** @internal For testing only */\nexport function resetConfig(): void {\n currentConfig = { ...DEFAULT_CONFIG };\n configLocked = false;\n}\n","export type Runtime = \"node\" | \"deno\" | \"bun\" | \"browser\";\nexport type Capability = \"full-threads\" | \"single-thread\";\n\nexport function detectRuntime(): Runtime {\n if (\"Bun\" in globalThis) return \"bun\";\n if (\"Deno\" in globalThis) return \"deno\";\n if (typeof globalThis.process !== \"undefined\" && globalThis.process.versions?.node) return \"node\";\n return \"browser\";\n}\n\nexport function detectCapability(): Capability {\n const runtime = detectRuntime();\n if (runtime === \"node\" || runtime === \"bun\") return \"full-threads\";\n if (\"Worker\" in globalThis) return \"full-threads\";\n return \"single-thread\";\n}\n","import { Worker } from \"node:worker_threads\";\nimport { NODE_BOOTSTRAP_CODE } from \"../bootstrap.js\";\nimport type { ManagedWorker, WorkerAdapter } from \"./base.js\";\nimport type { WorkerMessage, WorkerResponse } from \"../types.js\";\n\nclass NodeManagedWorker implements ManagedWorker {\n private worker: Worker;\n\n constructor() {\n this.worker = new Worker(NODE_BOOTSTRAP_CODE, { eval: true });\n }\n\n get id(): number {\n return this.worker.threadId;\n }\n\n postMessage(data: WorkerMessage): void {\n this.worker.postMessage(data);\n }\n\n terminate(): Promise<number> {\n return this.worker.terminate();\n }\n\n on(event: \"message\", handler: (data: WorkerResponse) => void): void;\n on(event: \"error\", handler: (err: Error) => void): void;\n on(event: \"exit\", handler: (code: number) => void): void;\n on(\n event: \"message\" | \"error\" | \"exit\",\n handler: ((data: WorkerResponse) => void) | ((err: Error) => void) | ((code: number) => void),\n ): void {\n this.worker.on(event, handler);\n }\n\n unref(): void {\n this.worker.unref();\n }\n\n ref(): void {\n this.worker.ref();\n }\n}\n\nexport class NodeWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new NodeManagedWorker();\n }\n}\n","/**\n * Channel proxy code shared between Node and Web bootstraps.\n * Injected at the top of the worker, inert unless channels are passed.\n */\nconst CHANNEL_PROXY_CODE = `\nconst __chCallbacks = new Map();\nlet __chRpcId = 0;\n\nclass __ChannelProxy {\n constructor(id) {\n this._id = id;\n }\n\n _rpc(op, value) {\n const correlationId = ++__chRpcId;\n return new Promise((resolve, reject) => {\n __chCallbacks.set(correlationId, { resolve, reject });\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op,\n correlationId,\n value\n });\n });\n }\n\n send(value) {\n return this._rpc('send', value);\n }\n\n recv() {\n return this._rpc('recv', undefined);\n }\n\n close() {\n __postMsg({\n type: 'channel-op',\n channelId: this._id,\n op: 'close',\n correlationId: ++__chRpcId\n });\n }\n\n [Symbol.asyncIterator]() {\n const proxy = this;\n return {\n async next() {\n const value = await proxy.recv();\n if (value === null) return { done: true, value: undefined };\n return { done: false, value };\n }\n };\n }\n}\n\nfunction __handleChannelResult(msg) {\n if (msg.type === 'channel-result') {\n const cb = __chCallbacks.get(msg.correlationId);\n if (cb) {\n __chCallbacks.delete(msg.correlationId);\n if (msg.error) {\n cb.reject(new Error(msg.error));\n } else {\n cb.resolve(msg.value);\n }\n }\n }\n}\n\nfunction __buildChannelProxies(channels) {\n if (!channels) return undefined;\n const proxies = {};\n for (const name of Object.keys(channels)) {\n proxies[name] = new __ChannelProxy(channels[name]);\n }\n return proxies;\n}\n\nconst __fnCache = new Map();\nconst __FN_CACHE_MAX = 1000;\n\nfunction __execFn(fnId, fnStr, channels, args) {\n let parsedFn = __fnCache.get(fnId);\n if (!parsedFn) {\n if (!fnStr) {\n throw new Error('Worker function was not registered on this worker');\n }\n parsedFn = (new Function('return (' + fnStr + ')'))();\n if (__fnCache.size >= __FN_CACHE_MAX) __fnCache.delete(__fnCache.keys().next().value);\n __fnCache.set(fnId, parsedFn);\n }\n if (args) {\n return parsedFn(...args);\n }\n if (channels) {\n return parsedFn(__buildChannelProxies(channels));\n }\n return parsedFn();\n}\n`;\n\n/** Bootstrap code for Node.js workers (eval: true, CJS context) */\nexport const NODE_BOOTSTRAP_CODE = `\n'use strict';\nconst { parentPort } = require('worker_threads');\n\nconst __postMsg = (d) => parentPort.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nparentPort.on('message', (msg) => {\n __handleChannelResult(msg);\n});\n\nparentPort.on('message', async (msg) => {\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnId, msg.fnStr, msg.channels, msg.args);\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnId, msg.fnStr, msg.channels, msg.args);\n parentPort.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n parentPort.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n process.exit(0);\n }\n});\n\nparentPort.postMessage({ type: 'ready' });\n`;\n\n/** Bootstrap code for Bun/Web Workers (file-based, Web Worker API) */\nexport const WEB_BOOTSTRAP_CODE = `\nconst __postMsg = (d) => self.postMessage(d);\n\n${CHANNEL_PROXY_CODE}\n\nconst cancelledTasks = new Set();\n\nself.addEventListener('message', (event) => {\n __handleChannelResult(event.data);\n});\n\nself.onmessage = async (event) => {\n const msg = event.data;\n if (msg.type === 'execute') {\n if (msg.concurrent) {\n (async () => {\n if (cancelledTasks.has(msg.taskId)) {\n cancelledTasks.delete(msg.taskId);\n return;\n }\n try {\n const result = await __execFn(msg.fnId, msg.fnStr, msg.channels, msg.args);\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n }\n } catch (error) {\n if (!cancelledTasks.has(msg.taskId)) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n } finally {\n cancelledTasks.delete(msg.taskId);\n }\n })();\n } else {\n try {\n const result = await __execFn(msg.fnId, msg.fnStr, msg.channels, msg.args);\n self.postMessage({ type: 'result', taskId: msg.taskId, value: result });\n } catch (error) {\n self.postMessage({\n type: 'error',\n taskId: msg.taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n }\n } else if (msg.type === 'cancel') {\n cancelledTasks.add(msg.taskId);\n } else if (msg.type === 'shutdown') {\n self.close();\n }\n};\n\nself.postMessage({ type: 'ready' });\n`;\n\n/** @deprecated Use NODE_BOOTSTRAP_CODE instead */\nexport const BOOTSTRAP_CODE = NODE_BOOTSTRAP_CODE;\n","import { WEB_BOOTSTRAP_CODE } from \"../bootstrap.js\";\nimport type { ManagedWorker, WorkerAdapter } from \"./base.js\";\nimport type { WorkerMessage, WorkerResponse } from \"../types.js\";\nimport { writeFileSync, unlinkSync, mkdtempSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\n\ninterface BunWorkerMessageEvent {\n data: WorkerResponse;\n}\n\ninterface BunWorkerErrorEvent {\n message: string;\n error?: Error;\n}\n\ninterface BunWorkerCloseEvent {\n code?: number;\n}\n\ninterface BunRuntimeWorker {\n postMessage(data: WorkerMessage): void;\n terminate(): void;\n addEventListener(type: \"message\", handler: (event: BunWorkerMessageEvent) => void): void;\n addEventListener(type: \"error\", handler: (event: BunWorkerErrorEvent) => void): void;\n addEventListener(type: \"close\", handler: (event: BunWorkerCloseEvent) => void): void;\n unref?(): void;\n ref?(): void;\n}\n\ntype BunWorkerConstructor = new (url: string | URL) => BunRuntimeWorker;\n\nlet workerIdCounter = 0;\nlet bootstrapFile: string | null = null;\n\n/**\n * Returns the path to a temporary JS file containing the bootstrap code.\n * Bun's Blob URL workers break when the URL is revoked before the worker\n * fully initializes its message handler, so we use a file-based worker instead.\n */\nfunction getBootstrapFile(): string {\n if (!bootstrapFile) {\n const dir = mkdtempSync(join(tmpdir(), \"puru-\"));\n bootstrapFile = join(dir, \"worker.js\");\n writeFileSync(bootstrapFile, WEB_BOOTSTRAP_CODE);\n }\n return bootstrapFile;\n}\n\nclass BunManagedWorker implements ManagedWorker {\n private worker: BunRuntimeWorker;\n readonly id: number;\n\n constructor() {\n this.id = ++workerIdCounter;\n const WorkerConstructor = (globalThis as { Worker?: BunWorkerConstructor }).Worker;\n if (!WorkerConstructor) {\n throw new Error(\"Bun Worker constructor is not available in this runtime\");\n }\n this.worker = new WorkerConstructor(getBootstrapFile());\n }\n\n postMessage(data: WorkerMessage): void {\n this.worker.postMessage(data);\n }\n\n terminate(): Promise<number> {\n this.worker.terminate();\n // Web Worker terminate() is synchronous and void; return resolved 0\n return Promise.resolve(0);\n }\n\n on(event: \"message\", handler: (data: WorkerResponse) => void): void;\n on(event: \"error\", handler: (err: Error) => void): void;\n on(event: \"exit\", handler: (code: number) => void): void;\n on(\n event: \"message\" | \"error\" | \"exit\",\n handler: ((data: WorkerResponse) => void) | ((err: Error) => void) | ((code: number) => void),\n ): void {\n if (event === \"message\") {\n this.worker.addEventListener(\"message\", (e) => {\n (handler as (data: WorkerResponse) => void)(e.data);\n });\n } else if (event === \"error\") {\n this.worker.addEventListener(\"error\", (e) => {\n (handler as (err: Error) => void)(e.error ?? new Error(e.message));\n });\n } else if (event === \"exit\") {\n // Bun emits 'close' on worker termination; the event carries a numeric exit code\n this.worker.addEventListener(\"close\", (e) => {\n (handler as (code: number) => void)(e.code ?? 0);\n });\n }\n }\n\n unref(): void {\n // Bun Workers support unref() — not in standard Web Worker types\n if (\n \"unref\" in this.worker &&\n typeof (this.worker as { unref?: () => void }).unref === \"function\"\n ) {\n (this.worker as { unref(): void }).unref();\n }\n }\n\n ref(): void {\n // Bun Workers support ref() — not in standard Web Worker types\n if (\"ref\" in this.worker && typeof (this.worker as { ref?: () => void }).ref === \"function\") {\n (this.worker as { ref(): void }).ref();\n }\n }\n}\n\nexport class BunWorkerAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new BunManagedWorker();\n }\n}\n\n/** Clean up the temporary bootstrap file. Called during pool drain. */\nexport function cleanupBootstrapFile(): void {\n if (bootstrapFile) {\n try {\n unlinkSync(bootstrapFile);\n } catch {}\n bootstrapFile = null;\n }\n}\n","/**\n * O(1) fixed-capacity circular buffer.\n * Used as the value buffer in buffered channels.\n * @internal\n */\nexport class RingBuffer<T> {\n private items: (T | undefined)[];\n private head = 0;\n private tail = 0;\n private size = 0;\n private cap: number;\n\n constructor(capacity: number) {\n this.cap = capacity;\n this.items = new Array<T | undefined>(capacity);\n }\n\n get length(): number {\n return this.size;\n }\n\n push(value: T): void {\n this.items[this.tail] = value;\n this.tail = (this.tail + 1) % this.cap;\n this.size++;\n }\n\n shift(): T | undefined {\n if (this.size === 0) return undefined;\n const value = this.items[this.head];\n this.items[this.head] = undefined; // release reference for GC\n this.head = (this.head + 1) % this.cap;\n this.size--;\n return value;\n }\n}\n\ninterface FifoNode<T> {\n value: T;\n next: FifoNode<T> | null;\n}\n\n/**\n * O(1) singly-linked FIFO queue.\n * Used for pending sender/receiver waiters in channels.\n * @internal\n */\nexport class FifoQueue<T> {\n private head: FifoNode<T> | null = null;\n private tail: FifoNode<T> | null = null;\n private size = 0;\n\n get length(): number {\n return this.size;\n }\n\n push(value: T): void {\n const node: FifoNode<T> = { value, next: null };\n if (this.tail) {\n this.tail.next = node;\n } else {\n this.head = node;\n }\n this.tail = node;\n this.size++;\n }\n\n shift(): T | undefined {\n if (!this.head) return undefined;\n const node = this.head;\n this.head = node.next;\n if (!this.head) this.tail = null;\n this.size--;\n const value = node.value;\n // Release references for GC\n node.value = undefined!;\n node.next = null;\n return value;\n }\n\n clear(): void {\n this.head = null;\n this.tail = null;\n this.size = 0;\n }\n\n *[Symbol.iterator](): Iterator<T> {\n let current = this.head;\n while (current) {\n yield current.value;\n current = current.next;\n }\n }\n}\n","import type { ChannelValue } from \"./types.js\";\nimport { RingBuffer, FifoQueue } from \"./queue.js\";\n\n// Internal sentinel used to signal channel closure.\n// Using a symbol instead of null means null is a valid value to send through a channel\n// at the implementation level, and avoids silent failures if someone attempts to send null.\n// The public recv() API still returns null for a closed channel — the symbol is not leaked.\nconst CLOSED = Symbol(\"puru.channel.closed\");\n\n// Cached promises to avoid allocations on hot paths\nconst RESOLVED_VOID: Promise<void> = Promise.resolve();\nconst RESOLVED_NULL: Promise<null> = Promise.resolve(null);\n\n/**\n * A Go-style channel for communicating between async tasks and across worker threads.\n *\n * Use `chan<T>(capacity?)` to create a channel. Values must be structured-cloneable\n * (no functions, symbols, or WeakRefs). `null` cannot be sent — `recv()` returns\n * `null` only when the channel is closed.\n *\n * @example\n * const ch = chan<number>(10)\n * await ch.send(42)\n * const value = await ch.recv() // 42\n * ch.close()\n * await ch.recv() // null — channel closed\n *\n * @example\n * // Async iteration ends automatically when the channel is closed\n * for await (const item of ch) {\n * process(item)\n * }\n */\nexport interface Channel<T extends ChannelValue> {\n send(value: T): Promise<void>;\n /** Resolves with the next value, or `null` if the channel is closed. */\n recv(): Promise<T | null>;\n close(): void;\n /** Number of values currently buffered. Like Go's `len(ch)`. */\n readonly len: number;\n /** Buffer capacity. Like Go's `cap(ch)`. */\n readonly cap: number;\n /** Returns a send-only view of this channel. Like Go's `chan<- T`. */\n sendOnly(): SendOnly<T>;\n /** Returns a receive-only view of this channel. Like Go's `<-chan T`. */\n recvOnly(): RecvOnly<T>;\n [Symbol.asyncIterator](): AsyncIterator<T>;\n}\n\n/** Send-only view of a channel. Like Go's `chan<- T`. */\nexport interface SendOnly<T extends ChannelValue> {\n send(value: T): Promise<void>;\n close(): void;\n readonly len: number;\n readonly cap: number;\n}\n\n/** Receive-only view of a channel. Like Go's `<-chan T`. */\nexport interface RecvOnly<T extends ChannelValue> {\n recv(): Promise<T | null>;\n readonly len: number;\n readonly cap: number;\n [Symbol.asyncIterator](): AsyncIterator<T>;\n}\n\ninterface ChannelHandle<T extends ChannelValue> extends Channel<T> {\n readonly _id: string;\n}\n\ninterface PendingRecv<T> {\n resolve: (value: T | typeof CLOSED) => void;\n}\n\ninterface PendingSend<T> {\n value: T;\n resolve: () => void;\n reject: (reason: Error) => void;\n}\n\nlet channelIdCounter = 0;\nconst channelRegistry = new Map<string, ChannelHandle<ChannelValue>>();\n\nclass ChannelImpl<T extends ChannelValue> implements ChannelHandle<T> {\n // constraint: can't create channels of nullable type\n /** @internal */\n readonly _id: string;\n /** @internal — true once the channel ID has been sent to a worker */\n _shared = false;\n private buffer: RingBuffer<T>;\n private capacity: number;\n private closed = false;\n private recvQueue = new FifoQueue<PendingRecv<T>>();\n private sendQueue = new FifoQueue<PendingSend<T>>();\n\n constructor(capacity: number) {\n this._id = `__ch_${++channelIdCounter}`;\n this.capacity = capacity;\n this.buffer = new RingBuffer<T>(capacity);\n channelRegistry.set(this._id, this as ChannelHandle<ChannelValue>);\n }\n\n get len(): number {\n return this.buffer.length;\n }\n\n get cap(): number {\n return this.capacity;\n }\n\n send(value: T): Promise<void> {\n if (this.closed) {\n return Promise.reject(new Error(\"send on closed channel\"));\n }\n\n // If there's a waiting receiver, deliver directly\n const receiver = this.recvQueue.shift();\n if (receiver) {\n receiver.resolve(value);\n return RESOLVED_VOID;\n }\n\n // If buffer has room, buffer it\n if (this.buffer.length < this.capacity) {\n this.buffer.push(value);\n return RESOLVED_VOID;\n }\n\n // Block until a receiver is ready\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push({ value, resolve, reject });\n });\n }\n\n recv(): Promise<T | null> {\n // If buffer has a value, take it and unblock a pending sender\n if (this.buffer.length > 0) {\n const value = this.buffer.shift()!;\n const sender = this.sendQueue.shift();\n if (sender) {\n this.buffer.push(sender.value);\n sender.resolve();\n }\n this.maybeUnregister();\n return Promise.resolve(value);\n }\n\n // If there's a pending sender (unbuffered or buffer was empty), take directly\n const sender = this.sendQueue.shift();\n if (sender) {\n sender.resolve();\n return Promise.resolve(sender.value);\n }\n\n // If closed, return null\n if (this.closed) {\n this.maybeUnregister();\n return RESOLVED_NULL as Promise<T | null>;\n }\n\n // Block until a sender provides a value or channel closes\n return new Promise<T | null>((resolve) => {\n this.recvQueue.push({\n resolve: (v) => resolve(v === CLOSED ? null : (v as T)),\n });\n });\n }\n\n close(): void {\n if (this.closed) return;\n this.closed = true;\n\n // Resolve all pending receivers with the CLOSED sentinel (converted to null at the public boundary)\n for (const receiver of this.recvQueue) {\n receiver.resolve(CLOSED);\n }\n this.recvQueue.clear();\n\n // Reject all pending senders\n for (const sender of this.sendQueue) {\n sender.reject(new Error(\"send on closed channel\"));\n }\n this.sendQueue.clear();\n }\n\n private maybeUnregister(): void {\n if (!this._shared && this.closed && this.buffer.length === 0 && this.recvQueue.length === 0) {\n channelRegistry.delete(this._id);\n }\n }\n\n sendOnly(): SendOnly<T> {\n const send = (value: T) => this.send(value);\n const close = () => this.close();\n const getLen = () => this.len;\n const getCap = () => this.cap;\n return {\n send,\n close,\n get len() {\n return getLen();\n },\n get cap() {\n return getCap();\n },\n };\n }\n\n recvOnly(): RecvOnly<T> {\n const recv = () => this.recv();\n const getLen = () => this.len;\n const getCap = () => this.cap;\n const getIter = () => this[Symbol.asyncIterator]();\n return {\n recv,\n get len() {\n return getLen();\n },\n get cap() {\n return getCap();\n },\n [Symbol.asyncIterator]() {\n return getIter();\n },\n };\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n while (true) {\n const value = await this.recv();\n if (value === null) return;\n yield value;\n }\n }\n}\n\n/**\n * Create a Go-style channel for communicating between tasks and across worker threads.\n *\n * Provides backpressure: `send()` blocks when the buffer is full,\n * `recv()` blocks when the buffer is empty. Channel values must be structured-cloneable\n * (no functions, symbols, or WeakRefs). `null` cannot be sent — it signals closure.\n *\n * @param capacity Buffer size. `0` (default) = unbuffered: each `send()` blocks until a `recv()` is ready.\n *\n * @example\n * const ch = chan<string>(5) // buffered channel, capacity 5\n * await ch.send('hello')\n * const msg = await ch.recv() // 'hello'\n * ch.close()\n *\n * @example\n * // Fan-out: multiple workers pulling from the same channel\n * const input = chan<Job>(50)\n * const output = chan<Result>(50)\n *\n * for (let i = 0; i < 4; i++) {\n * spawn(async ({ input, output }) => {\n * for await (const job of input) {\n * await output.send(processJob(job))\n * }\n * }, { channels: { input, output } })\n * }\n */\nexport function chan<T extends ChannelValue>(capacity: number = 0): Channel<T> {\n if (capacity < 0 || !Number.isInteger(capacity)) {\n throw new RangeError(\"Channel capacity must be a non-negative integer\");\n }\n return new ChannelImpl<T>(capacity);\n}\n\n/** @internal */\nexport function getChannelById(id: string): ChannelHandle<ChannelValue> | undefined {\n return channelRegistry.get(id);\n}\n\n/** @internal */\nexport function getChannelId<T extends ChannelValue>(channel: Channel<T>): string {\n const impl = channel as ChannelImpl<T>;\n impl._shared = true;\n return impl._id;\n}\n\n/** @internal */\nexport function resetChannelRegistry(): void {\n channelRegistry.clear();\n channelIdCounter = 0;\n}\n","import type { ManagedWorker, WorkerAdapter } from \"./base.js\";\nimport { getChannelById } from \"../channel.js\";\nimport type {\n ChannelMap,\n ChannelValue,\n JsonValue,\n StructuredCloneValue,\n WorkerMessage,\n WorkerResponse,\n} from \"../types.js\";\n\nlet inlineIdCounter = 0;\n\ninterface ChannelProxy {\n _id: string;\n send(value: ChannelValue): Promise<void>;\n recv(): Promise<ChannelValue | null>;\n close(): void;\n [Symbol.asyncIterator](): AsyncIterator<ChannelValue>;\n}\n\ntype MessageHandler = (data: WorkerResponse) => void;\ntype ErrorHandler = (err: Error) => void;\ntype ExitHandler = (code: number) => void;\n\nclass InlineManagedWorker implements ManagedWorker {\n readonly id: number;\n private messageHandlers: MessageHandler[] = [];\n private errorHandlers: ErrorHandler[] = [];\n private exitHandlers: ExitHandler[] = [];\n private terminated = false;\n private cancelledTasks = new Set<string>();\n private fnCache = new Map<\n string,\n (...args: JsonValue[]) => StructuredCloneValue | Promise<StructuredCloneValue>\n >();\n\n constructor() {\n this.id = ++inlineIdCounter;\n // Emit ready on next microtask (matches real worker timing)\n queueMicrotask(() => {\n this.emit(\"message\", { type: \"ready\" });\n });\n }\n\n postMessage(msg: WorkerMessage): void {\n if (this.terminated) return;\n\n if (msg.type === \"execute\") {\n this.executeTask(msg.taskId, msg.fnId, msg.fnStr, msg.concurrent, msg.channels, msg.args);\n } else if (msg.type === \"cancel\") {\n this.cancelledTasks.add(msg.taskId);\n } else if (msg.type === \"channel-result\") {\n // The inline adapter calls channels directly, so there is no worker-side RPC to route.\n return;\n } else if (msg.type === \"shutdown\") {\n this.terminated = true;\n this.emit(\"exit\", 0);\n }\n }\n\n terminate(): Promise<number> {\n this.terminated = true;\n this.emit(\"exit\", 1);\n return Promise.resolve(1);\n }\n\n on(event: \"message\", handler: (data: WorkerResponse) => void): void;\n on(event: \"error\", handler: ErrorHandler): void;\n on(event: \"exit\", handler: ExitHandler): void;\n on(\n event: \"message\" | \"error\" | \"exit\",\n handler: MessageHandler | ErrorHandler | ExitHandler,\n ): void {\n if (event === \"message\") this.messageHandlers.push(handler as MessageHandler);\n else if (event === \"error\") this.errorHandlers.push(handler as ErrorHandler);\n else if (event === \"exit\") this.exitHandlers.push(handler as ExitHandler);\n }\n\n unref(): void {}\n ref(): void {}\n\n private emit(event: \"message\", data: WorkerResponse): void;\n private emit(event: \"error\", err: Error): void;\n private emit(event: \"exit\", code: number): void;\n private emit(event: \"message\" | \"error\" | \"exit\", value: WorkerResponse | Error | number): void {\n if (event === \"message\") {\n for (const h of this.messageHandlers) h(value as WorkerResponse);\n } else if (event === \"error\") {\n for (const h of this.errorHandlers) h(value as Error);\n } else if (event === \"exit\") {\n for (const h of this.exitHandlers) h(value as number);\n }\n }\n\n private buildChannelProxies(channels: ChannelMap): Record<string, ChannelProxy> {\n const proxies: Record<string, ChannelProxy> = {};\n for (const [name, channelId] of Object.entries(channels)) {\n proxies[name] = {\n _id: channelId,\n async send(value: ChannelValue) {\n const ch = getChannelById(channelId);\n if (!ch) throw new Error(`Channel ${channelId} not found`);\n await ch.send(value);\n },\n async recv() {\n const ch = getChannelById(channelId);\n if (!ch) throw new Error(`Channel ${channelId} not found`);\n return ch.recv();\n },\n close() {\n const ch = getChannelById(channelId);\n if (ch) ch.close();\n },\n [Symbol.asyncIterator]() {\n const ch = getChannelById(channelId);\n if (!ch) throw new Error(`Channel ${channelId} not found`);\n return ch[Symbol.asyncIterator]();\n },\n };\n }\n return proxies;\n }\n\n private executeTask(\n taskId: string,\n fnId: string,\n fnStr: string | undefined,\n concurrent: boolean,\n channels?: ChannelMap,\n args?: JsonValue[],\n ): void {\n // Run on next microtask to simulate async worker behavior\n queueMicrotask(async () => {\n if (this.terminated) return;\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId);\n return;\n }\n try {\n let parsedFn = this.fnCache.get(fnId);\n if (!parsedFn) {\n if (!fnStr) {\n throw new Error(\"Worker function was not registered on this worker\");\n }\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n parsedFn = new Function(\"return (\" + fnStr + \")\")() as (\n ...args: JsonValue[]\n ) => StructuredCloneValue | Promise<StructuredCloneValue>;\n if (this.fnCache.size >= 1000) this.fnCache.clear();\n this.fnCache.set(fnId, parsedFn);\n }\n let result: StructuredCloneValue;\n if (args) {\n result = await parsedFn(...args);\n } else if (channels) {\n const proxies = this.buildChannelProxies(channels);\n result = await parsedFn(proxies as never);\n } else {\n result = await parsedFn();\n }\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId);\n return;\n }\n this.emit(\"message\", { type: \"result\", taskId, value: result });\n } catch (error) {\n if (concurrent && this.cancelledTasks.has(taskId)) {\n this.cancelledTasks.delete(taskId);\n return;\n }\n this.emit(\"message\", {\n type: \"error\",\n taskId,\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n });\n }\n}\n\nexport class InlineAdapter implements WorkerAdapter {\n createWorker(): ManagedWorker {\n return new InlineManagedWorker();\n }\n}\n","import type { ManagedWorker, WorkerAdapter } from \"./adapters/base.js\";\nimport type {\n ChannelValue,\n PuruConfig,\n StructuredCloneValue,\n Task,\n TaskError,\n WorkerMessage,\n WorkerResponse,\n} from \"./types.js\";\nimport { getConfig } from \"./configure.js\";\nimport { detectRuntime, detectCapability } from \"./runtime.js\";\nimport { NodeWorkerAdapter } from \"./adapters/node.js\";\nimport { BunWorkerAdapter } from \"./adapters/bun.js\";\nimport { InlineAdapter } from \"./adapters/inline.js\";\nimport { getChannelById } from \"./channel.js\";\n\ninterface PriorityQueues {\n high: Task[];\n normal: Task[];\n low: Task[];\n}\n\nexport class WorkerPool {\n private config: PuruConfig;\n private adapter: WorkerAdapter;\n private idleWorkers: ManagedWorker[] = [];\n private exclusiveWorkers = new Map<string, ManagedWorker>();\n private sharedWorkers = new Map<ManagedWorker, Set<string>>();\n private queues: PriorityQueues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n };\n private concurrentQueues: PriorityQueues = {\n high: [] as Task[],\n normal: [] as Task[],\n low: [] as Task[],\n };\n private allWorkers = new Set<ManagedWorker>();\n private idleTimers = new Map<ManagedWorker, ReturnType<typeof setTimeout>>();\n private pendingWorkerCount = 0;\n private pendingTasksForWorkers: Task[] = [];\n private draining = false;\n private totalCompleted = 0;\n private totalFailed = 0;\n private taskMap = new Map<string, Task>();\n private workerFunctionIds = new Map<ManagedWorker, Set<string>>();\n\n // Per-worker deques for work-stealing strategy\n private workerDeques = new Map<ManagedWorker, PriorityQueues>();\n\n constructor(config: PuruConfig, adapter: WorkerAdapter) {\n this.config = config;\n this.adapter = adapter;\n }\n\n // --- Queue helpers ---\n\n private enqueue(task: Task): void {\n this.queues[task.priority].push(task);\n }\n\n private dequeue(): Task | undefined {\n return this.queues.high.shift() ?? this.queues.normal.shift() ?? this.queues.low.shift();\n }\n\n private enqueueConcurrent(task: Task): void {\n this.concurrentQueues[task.priority].push(task);\n }\n\n private dequeueConcurrent(): Task | undefined {\n return (\n this.concurrentQueues.high.shift() ??\n this.concurrentQueues.normal.shift() ??\n this.concurrentQueues.low.shift()\n );\n }\n\n private removeFromQueue(taskId: string): Task | undefined {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n const queue = this.queues[priority];\n const idx = queue.findIndex((t) => t.id === taskId);\n if (idx !== -1) {\n return queue.splice(idx, 1)[0];\n }\n }\n return undefined;\n }\n\n private removeFromConcurrentQueue(taskId: string): Task | undefined {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n const queue = this.concurrentQueues[priority];\n const idx = queue.findIndex((t) => t.id === taskId);\n if (idx !== -1) {\n return queue.splice(idx, 1)[0];\n }\n }\n return undefined;\n }\n\n // --- Work-stealing helpers ---\n\n private getOrCreateDeque(worker: ManagedWorker): PriorityQueues {\n let deque = this.workerDeques.get(worker);\n if (!deque) {\n deque = { high: [], normal: [], low: [] };\n this.workerDeques.set(worker, deque);\n }\n return deque;\n }\n\n private dequeSize(worker: ManagedWorker): number {\n const deque = this.workerDeques.get(worker);\n if (!deque) return 0;\n return deque.high.length + deque.normal.length + deque.low.length;\n }\n\n private enqueueToWorker(worker: ManagedWorker, task: Task): void {\n this.getOrCreateDeque(worker)[task.priority].push(task);\n }\n\n /** Pop from own deque — FIFO within each priority level. */\n private dequeueFromOwn(worker: ManagedWorker): Task | undefined {\n const deque = this.workerDeques.get(worker);\n if (!deque) return undefined;\n return deque.high.shift() ?? deque.normal.shift() ?? deque.low.shift();\n }\n\n /** Steal from a victim's deque — takes lowest-priority work from the back. */\n private stealFrom(victim: ManagedWorker): Task | undefined {\n const deque = this.workerDeques.get(victim);\n if (!deque) return undefined;\n return deque.low.pop() ?? deque.normal.pop() ?? deque.high.pop();\n }\n\n /** Find the exclusive worker with the shortest deque to push a new task to. */\n private findShortestDequeWorker(): ManagedWorker | undefined {\n let best: ManagedWorker | undefined;\n let bestSize = Infinity;\n const seen = new Set<ManagedWorker>();\n for (const worker of this.exclusiveWorkers.values()) {\n if (seen.has(worker)) continue;\n seen.add(worker);\n const size = this.dequeSize(worker);\n if (size < bestSize) {\n bestSize = size;\n best = worker;\n }\n }\n return best;\n }\n\n /** Steal a task from the busiest worker's deque, excluding the thief. */\n private stealFromBusiest(thief: ManagedWorker): Task | undefined {\n let victim: ManagedWorker | undefined;\n let maxSize = 0;\n for (const [worker, deque] of this.workerDeques) {\n if (worker === thief) continue;\n const size = deque.high.length + deque.normal.length + deque.low.length;\n if (size > maxSize) {\n maxSize = size;\n victim = worker;\n }\n }\n if (!victim || maxSize === 0) return undefined;\n return this.stealFrom(victim);\n }\n\n /** Steal from any deque (no thief exclusion — used by resize). */\n private stealFromAny(): Task | undefined {\n let victim: ManagedWorker | undefined;\n let maxSize = 0;\n for (const [worker, deque] of this.workerDeques) {\n const size = deque.high.length + deque.normal.length + deque.low.length;\n if (size > maxSize) {\n maxSize = size;\n victim = worker;\n }\n }\n if (!victim || maxSize === 0) return undefined;\n return this.stealFrom(victim);\n }\n\n /** Remove a task by ID from any worker's deque. */\n private removeFromDeques(taskId: string): Task | undefined {\n for (const [, deque] of this.workerDeques) {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n const queue = deque[priority];\n const idx = queue.findIndex((t) => t.id === taskId);\n if (idx !== -1) {\n return queue.splice(idx, 1)[0];\n }\n }\n }\n return undefined;\n }\n\n /** Flush a worker's deque back to the global queue (for redistribution). */\n private flushDeque(worker: ManagedWorker): void {\n const deque = this.workerDeques.get(worker);\n if (!deque) return;\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of deque[priority]) {\n this.queues[priority].push(task);\n }\n }\n this.workerDeques.delete(worker);\n }\n\n /** Clean up a deque if it's empty. */\n private cleanupDeque(worker: ManagedWorker): void {\n if (this.dequeSize(worker) === 0) {\n this.workerDeques.delete(worker);\n }\n }\n\n // --- Submit ---\n\n submit(task: Task): void {\n if (this.draining) {\n task.reject(new Error(\"Pool is shutting down\"));\n return;\n }\n\n if (task.concurrent) {\n this.submitConcurrent(task);\n } else {\n this.submitExclusive(task);\n }\n }\n\n private submitExclusive(task: Task): void {\n // Try to assign to an idle worker\n const worker = this.idleWorkers.pop();\n if (worker) {\n this.dispatch(worker, task);\n return;\n }\n\n // Try to create a new worker\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount;\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++;\n this.pendingTasksForWorkers.push(task);\n this.createAndReadyWorker();\n return;\n }\n\n // Work-stealing: push to the busy worker with the shortest deque\n if (this.config.strategy === \"work-stealing\") {\n const target = this.findShortestDequeWorker();\n if (target) {\n this.enqueueToWorker(target, task);\n return;\n }\n }\n\n // FIFO fallback (or no exclusive workers for work-stealing)\n this.enqueue(task);\n }\n\n private submitConcurrent(task: Task): void {\n // 1. Find a shared worker under the concurrency limit\n for (const [worker, tasks] of this.sharedWorkers) {\n if (tasks.size < this.config.concurrency) {\n this.dispatchConcurrent(worker, task);\n return;\n }\n }\n\n // 2. Grab an idle worker and convert to shared mode\n const idleWorker = this.idleWorkers.pop();\n if (idleWorker) {\n this.dispatchConcurrent(idleWorker, task);\n return;\n }\n\n // 3. Spin up a new worker if under limit\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount;\n if (totalWorkers < this.config.maxThreads) {\n this.pendingWorkerCount++;\n this.pendingTasksForWorkers.push(task);\n this.createAndReadyWorker();\n return;\n }\n\n // 4. All workers busy/saturated — queue it\n this.enqueueConcurrent(task);\n }\n\n // --- Dispatch ---\n\n private dispatch(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n\n worker.ref();\n this.exclusiveWorkers.set(task.id, worker);\n this.taskMap.set(task.id, task);\n\n const msg: WorkerMessage = {\n type: \"execute\",\n taskId: task.id,\n fnId: task.fnId,\n fnStr: this.getWorkerFunctionString(worker, task),\n args: task.args,\n concurrent: false,\n channels: task.channels,\n };\n worker.postMessage(msg);\n }\n\n private dispatchConcurrent(worker: ManagedWorker, task: Task): void {\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n\n worker.ref();\n\n if (!this.sharedWorkers.has(worker)) {\n this.sharedWorkers.set(worker, new Set());\n }\n this.sharedWorkers.get(worker)!.add(task.id);\n this.taskMap.set(task.id, task);\n\n const msg: WorkerMessage = {\n type: \"execute\",\n taskId: task.id,\n fnId: task.fnId,\n fnStr: this.getWorkerFunctionString(worker, task),\n args: task.args,\n concurrent: true,\n channels: task.channels,\n };\n worker.postMessage(msg);\n }\n\n private getWorkerFunctionString(worker: ManagedWorker, task: Task): string | undefined {\n let knownFunctions = this.workerFunctionIds.get(worker);\n if (!knownFunctions) {\n knownFunctions = new Set<string>();\n this.workerFunctionIds.set(worker, knownFunctions);\n }\n\n if (knownFunctions.has(task.fnId)) return undefined;\n knownFunctions.add(task.fnId);\n return task.fnStr;\n }\n\n // --- Task completion ---\n\n private handleWorkerMessage(worker: ManagedWorker, response: WorkerResponse): void {\n if (response.type === \"channel-op\") {\n this.handleChannelOp(worker, response);\n return;\n }\n\n if (response.type === \"result\") {\n const taskId = response.taskId;\n this.resolveTask(taskId, response.value);\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId);\n this.assignNextOrIdle(worker);\n } else {\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n taskSet.delete(taskId);\n this.assignNextConcurrentOrIdle(worker);\n }\n }\n } else if (response.type === \"error\") {\n const taskId = response.taskId;\n const err = new Error(response.message);\n if (response.stack) err.stack = response.stack;\n // ReferenceError inside a worker almost always means the function captured\n // a variable from the enclosing scope. Surface a clear message rather than\n // a cryptic worker-internal stack trace.\n if (\n response.message.match(/^ReferenceError:/) ||\n response.message.match(/ is not defined$/)\n ) {\n err.message +=\n \"\\n Hint: functions passed to spawn() cannot access variables from the enclosing scope. \" +\n \"Inline all required values directly in the function body, or pass them via the channels option.\";\n }\n this.rejectTask(taskId, err);\n\n if (this.exclusiveWorkers.has(taskId)) {\n this.exclusiveWorkers.delete(taskId);\n this.assignNextOrIdle(worker);\n } else {\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n taskSet.delete(taskId);\n this.assignNextConcurrentOrIdle(worker);\n }\n }\n }\n }\n\n private assignNextOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return;\n\n if (this.config.strategy === \"work-stealing\") {\n // 1. Check own deque (FIFO — pop from front)\n const own = this.dequeueFromOwn(worker);\n if (own) {\n this.cleanupDeque(worker);\n this.dispatch(worker, own);\n return;\n }\n\n // 2. Steal from the busiest worker (LIFO — pop from back, lowest priority first)\n const stolen = this.stealFromBusiest(worker);\n if (stolen) {\n this.dispatch(worker, stolen);\n return;\n }\n }\n\n // FIFO: try exclusive queue (also serves as fallback for work-stealing)\n const next = this.dequeue();\n if (next) {\n this.dispatch(worker, next);\n return;\n }\n\n // Then try concurrent queue\n const concurrentNext = this.dequeueConcurrent();\n if (concurrentNext) {\n this.dispatchConcurrent(worker, concurrentNext);\n return;\n }\n\n this.cleanupDeque(worker);\n this.makeIdle(worker);\n }\n\n private assignNextConcurrentOrIdle(worker: ManagedWorker): void {\n if (!this.allWorkers.has(worker)) return;\n\n const taskSet = this.sharedWorkers.get(worker);\n const currentCount = taskSet?.size ?? 0;\n\n // Fill up to concurrency limit from concurrent queue\n let filled = currentCount;\n while (filled < this.config.concurrency) {\n const next = this.dequeueConcurrent();\n if (!next) break;\n this.dispatchConcurrent(worker, next);\n filled++;\n }\n\n // If no tasks remain, transition back\n const updatedSet = this.sharedWorkers.get(worker);\n if (!updatedSet || updatedSet.size === 0) {\n this.sharedWorkers.delete(worker);\n // Try exclusive queue before going idle\n const exclusiveTask = this.dequeue();\n if (exclusiveTask) {\n this.dispatch(worker, exclusiveTask);\n } else if (this.config.strategy === \"work-stealing\") {\n // Try stealing from busy workers' deques\n const stolen = this.stealFromBusiest(worker);\n if (stolen) {\n this.dispatch(worker, stolen);\n } else {\n this.makeIdle(worker);\n }\n } else {\n this.makeIdle(worker);\n }\n }\n }\n\n private makeIdle(worker: ManagedWorker): void {\n worker.unref();\n this.idleWorkers.push(worker);\n\n if (this.config.idleTimeout > 0) {\n const timer = setTimeout(() => {\n this.idleTimers.delete(worker);\n const idx = this.idleWorkers.indexOf(worker);\n if (idx !== -1) {\n this.idleWorkers.splice(idx, 1);\n }\n this.allWorkers.delete(worker);\n worker.terminate();\n }, this.config.idleTimeout);\n\n // Don't let the idle timer prevent process exit\n if (timer.unref) timer.unref();\n this.idleTimers.set(worker, timer);\n }\n }\n\n // --- Channel RPC ---\n\n private async handleChannelOp(\n worker: ManagedWorker,\n msg: Extract<WorkerResponse, { type: \"channel-op\" }>,\n ): Promise<void> {\n const channel = getChannelById(msg.channelId);\n\n if (!channel) {\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n error: `Channel ${msg.channelId} not found`,\n });\n return;\n }\n\n try {\n if (msg.op === \"send\") {\n await channel.send(msg.value as ChannelValue);\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n });\n } else if (msg.op === \"recv\") {\n const value = await channel.recv();\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n value,\n });\n } else if (msg.op === \"close\") {\n channel.close();\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n });\n }\n } catch (err) {\n worker.postMessage({\n type: \"channel-result\",\n correlationId: msg.correlationId,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n // --- Task resolution ---\n\n private resolveTask(taskId: string, value: StructuredCloneValue): void {\n const task = this.taskMap.get(taskId);\n if (task) {\n this.taskMap.delete(taskId);\n this.totalCompleted++;\n task.resolve(value);\n }\n }\n\n private rejectTask(taskId: string, reason: TaskError): void {\n const task = this.taskMap.get(taskId);\n if (task) {\n this.taskMap.delete(taskId);\n this.totalFailed++;\n task.reject(reason);\n }\n }\n\n private rejectExclusiveTaskForWorker(worker: ManagedWorker, reason: TaskError): void {\n for (const [taskId, assignedWorker] of this.exclusiveWorkers) {\n if (assignedWorker === worker) {\n this.exclusiveWorkers.delete(taskId);\n this.rejectTask(taskId, reason);\n break;\n }\n }\n }\n\n // --- Cancellation ---\n\n cancelTask(taskId: string): void {\n // 1. Check exclusive queues\n const removed = this.removeFromQueue(taskId);\n if (removed) {\n removed.reject(new DOMException(\"Task was cancelled\", \"AbortError\"));\n return;\n }\n\n // 1b. Check per-worker deques (work-stealing)\n if (this.config.strategy === \"work-stealing\") {\n const removedFromDeque = this.removeFromDeques(taskId);\n if (removedFromDeque) {\n removedFromDeque.reject(new DOMException(\"Task was cancelled\", \"AbortError\"));\n return;\n }\n }\n\n // 2. Check concurrent queues\n const removedConcurrent = this.removeFromConcurrentQueue(taskId);\n if (removedConcurrent) {\n removedConcurrent.reject(new DOMException(\"Task was cancelled\", \"AbortError\"));\n return;\n }\n\n // 3. Check exclusive workers — terminate the worker (existing behavior)\n const exclusiveWorker = this.exclusiveWorkers.get(taskId);\n if (exclusiveWorker) {\n this.exclusiveWorkers.delete(taskId);\n this.allWorkers.delete(exclusiveWorker);\n this.taskMap.delete(taskId);\n // Redistribute deque tasks before terminating the worker\n this.flushDeque(exclusiveWorker);\n exclusiveWorker.terminate();\n return;\n }\n\n // 4. Check shared workers — send cancel message, do NOT terminate\n for (const [worker, taskSet] of this.sharedWorkers) {\n if (taskSet.has(taskId)) {\n taskSet.delete(taskId);\n this.taskMap.delete(taskId);\n worker.postMessage({ type: \"cancel\", taskId });\n if (taskSet.size === 0) {\n this.sharedWorkers.delete(worker);\n this.assignNextConcurrentOrIdle(worker);\n }\n return;\n }\n }\n }\n\n // --- Lifecycle ---\n\n async drain(): Promise<void> {\n this.draining = true;\n\n // Reject all queued exclusive tasks\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of this.queues[priority]) {\n task.reject(new Error(\"Pool is shutting down\"));\n }\n this.queues[priority] = [];\n }\n\n // Reject all queued concurrent tasks\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of this.concurrentQueues[priority]) {\n task.reject(new Error(\"Pool is shutting down\"));\n }\n this.concurrentQueues[priority] = [];\n }\n\n // Reject all tasks in per-worker deques (work-stealing)\n for (const [, deque] of this.workerDeques) {\n for (const priority of [\"high\", \"normal\", \"low\"] as const) {\n for (const task of deque[priority]) {\n task.reject(new Error(\"Pool is shutting down\"));\n }\n }\n }\n this.workerDeques.clear();\n\n // Clear in-flight exclusive tasks — their workers are about to be terminated.\n // We don't reject them here because the caller may not be listening, which\n // would cause unhandled rejection errors. The promises will simply never settle.\n for (const [taskId] of this.exclusiveWorkers) {\n this.taskMap.delete(taskId);\n }\n this.exclusiveWorkers.clear();\n\n // Same for in-flight concurrent tasks.\n for (const [, taskSet] of this.sharedWorkers) {\n for (const taskId of taskSet) {\n this.taskMap.delete(taskId);\n }\n }\n\n // Terminate all workers\n const terminatePromises: Promise<number>[] = [];\n for (const worker of this.allWorkers) {\n const timer = this.idleTimers.get(worker);\n if (timer) clearTimeout(timer);\n terminatePromises.push(worker.terminate());\n }\n\n await Promise.all(terminatePromises);\n\n this.idleWorkers = [];\n this.exclusiveWorkers.clear();\n this.sharedWorkers.clear();\n this.allWorkers.clear();\n this.idleTimers.clear();\n this.workerFunctionIds.clear();\n }\n\n resize(maxThreads: number): void {\n this.config = { ...this.config, maxThreads };\n\n // If we now have capacity, dequeue tasks and spin up workers\n while (true) {\n const totalWorkers = this.allWorkers.size + this.pendingWorkerCount;\n if (totalWorkers >= maxThreads) break;\n // Try exclusive queue first, then steal from deques, then concurrent\n const task =\n this.dequeue() ??\n (this.config.strategy === \"work-stealing\" ? this.stealFromAny() : undefined) ??\n this.dequeueConcurrent();\n if (!task) break;\n this.pendingWorkerCount++;\n this.pendingTasksForWorkers.push(task);\n this.createAndReadyWorker();\n }\n\n // If pool is now oversized, terminate excess idle workers\n while (this.allWorkers.size > maxThreads && this.idleWorkers.length > 0) {\n const worker = this.idleWorkers.pop()!;\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n this.allWorkers.delete(worker);\n worker.terminate();\n }\n }\n\n // --- Worker creation ---\n\n private createAndReadyWorker(): void {\n const worker = this.adapter.createWorker();\n\n const onReady = () => {\n this.pendingWorkerCount--;\n this.allWorkers.add(worker);\n\n const task = this.pendingTasksForWorkers.shift();\n if (task) {\n if (task.concurrent) {\n this.dispatchConcurrent(worker, task);\n } else {\n this.dispatch(worker, task);\n }\n } else {\n this.makeIdle(worker);\n }\n };\n\n worker.on(\"message\", (response) => {\n if (response.type === \"ready\") {\n onReady();\n return;\n }\n this.handleWorkerMessage(worker, response);\n });\n\n worker.on(\"error\", (err: Error) => {\n this.rejectExclusiveTaskForWorker(worker, err);\n // Clean up concurrent tasks on this worker\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, err);\n }\n this.sharedWorkers.delete(worker);\n }\n });\n\n worker.on(\"exit\", (_code: number) => {\n this.allWorkers.delete(worker);\n this.workerFunctionIds.delete(worker);\n const timer = this.idleTimers.get(worker);\n if (timer) {\n clearTimeout(timer);\n this.idleTimers.delete(worker);\n }\n\n // Remove from idle if present\n const idleIdx = this.idleWorkers.indexOf(worker);\n if (idleIdx !== -1) {\n this.idleWorkers.splice(idleIdx, 1);\n }\n\n this.rejectExclusiveTaskForWorker(worker, new Error(\"Worker exited unexpectedly\"));\n\n // Redistribute deque tasks back to the global queue so other workers can pick them up\n this.flushDeque(worker);\n\n // Clean up concurrent tasks\n const taskSet = this.sharedWorkers.get(worker);\n if (taskSet) {\n for (const taskId of taskSet) {\n this.rejectTask(taskId, new Error(\"Worker exited unexpectedly\"));\n }\n this.sharedWorkers.delete(worker);\n }\n });\n }\n\n // --- Stats ---\n\n stats(): PoolStats {\n let concurrentTasks = 0;\n for (const taskSet of this.sharedWorkers.values()) {\n concurrentTasks += taskSet.size;\n }\n\n // Include per-worker deque sizes in queued task counts\n let dequeHigh = 0;\n let dequeNormal = 0;\n let dequeLow = 0;\n for (const deque of this.workerDeques.values()) {\n dequeHigh += deque.high.length;\n dequeNormal += deque.normal.length;\n dequeLow += deque.low.length;\n }\n\n const queuedHigh = this.queues.high.length + dequeHigh;\n const queuedNormal = this.queues.normal.length + dequeNormal;\n const queuedLow = this.queues.low.length + dequeLow;\n\n return {\n totalWorkers: this.allWorkers.size,\n idleWorkers: this.idleWorkers.length,\n busyWorkers: this.exclusiveWorkers.size,\n sharedWorkers: this.sharedWorkers.size,\n concurrentTasks,\n pendingWorkers: this.pendingWorkerCount,\n queuedTasks: {\n high: queuedHigh,\n normal: queuedNormal,\n low: queuedLow,\n total: queuedHigh + queuedNormal + queuedLow,\n },\n queuedConcurrentTasks: {\n high: this.concurrentQueues.high.length,\n normal: this.concurrentQueues.normal.length,\n low: this.concurrentQueues.low.length,\n total:\n this.concurrentQueues.high.length +\n this.concurrentQueues.normal.length +\n this.concurrentQueues.low.length,\n },\n totalCompleted: this.totalCompleted,\n totalFailed: this.totalFailed,\n maxThreads: this.config.maxThreads,\n concurrency: this.config.concurrency,\n };\n }\n}\n\nexport interface PoolStats {\n totalWorkers: number;\n idleWorkers: number;\n busyWorkers: number;\n sharedWorkers: number;\n concurrentTasks: number;\n pendingWorkers: number;\n queuedTasks: {\n high: number;\n normal: number;\n low: number;\n total: number;\n };\n queuedConcurrentTasks: {\n high: number;\n normal: number;\n low: number;\n total: number;\n };\n totalCompleted: number;\n totalFailed: number;\n maxThreads: number;\n concurrency: number;\n}\n\n// Pool singleton\nlet poolInstance: WorkerPool | null = null;\n\nfunction createAdapter(adapterConfig: string): WorkerAdapter {\n if (adapterConfig === \"inline\") return new InlineAdapter();\n if (adapterConfig === \"node\") return new NodeWorkerAdapter();\n if (adapterConfig === \"bun\") return new BunWorkerAdapter();\n\n // auto — detect runtime\n const capability = detectCapability();\n if (capability === \"single-thread\") {\n throw new Error(\n \"puru requires a runtime with thread support (Node.js or Bun). \" +\n \"Current runtime does not support worker threads.\",\n );\n }\n const runtime = detectRuntime();\n if (runtime === \"bun\") return new BunWorkerAdapter();\n return new NodeWorkerAdapter();\n}\n\nexport function getPool(): WorkerPool {\n if (!poolInstance) {\n const config = getConfig();\n poolInstance = new WorkerPool(config, createAdapter(config.adapter));\n }\n return poolInstance;\n}\n\nexport function stats(): PoolStats {\n return getPool().stats();\n}\n\nexport function resize(maxThreads: number): void {\n getPool().resize(maxThreads);\n}\n\n/**\n * Gracefully shut down the thread pool.\n *\n * Rejects all queued tasks, waits for all workers to terminate, then clears\n * the pool. Safe to call at process exit or at the end of a test suite.\n *\n * ```ts\n * process.on('SIGTERM', async () => {\n * await shutdown()\n * process.exit(0)\n * })\n * ```\n */\nexport async function shutdown(): Promise<void> {\n if (poolInstance) {\n await poolInstance.drain();\n poolInstance = null;\n }\n}\n\n/** @internal For testing only */\nexport async function resetPool(): Promise<void> {\n await shutdown();\n}\n","import { getSerializedFunctionRef } from \"./serialize.js\";\nimport { getPool } from \"./pool.js\";\nimport type { Channel } from \"./channel.js\";\nimport { getChannelId } from \"./channel.js\";\nimport type { Context } from \"./context.js\";\nimport type {\n ChannelMap,\n ChannelValue,\n SpawnResult,\n StructuredCloneValue,\n Task,\n TaskError,\n} from \"./types.js\";\n\nlet taskCounter = 0;\n\n/**\n * Run a function in a worker thread. Returns a handle with the result promise and a cancel function.\n *\n * **Functions must be self-contained** — they are serialized via `.toString()` and sent to a\n * worker thread, so they cannot capture variables from the enclosing scope. Define everything\n * you need inside the function body, or use `task()` to pass arguments.\n *\n * **Two modes:**\n * - Default (exclusive): the function gets a dedicated thread. Best for CPU-bound work (> 5ms).\n * - `{ concurrent: true }`: many tasks share a thread's event loop. Best for async/I/O work.\n *\n * @example\n * // CPU-bound work — define helpers inside the function body\n * const { result } = spawn(() => {\n * function fibonacci(n: number): number {\n * if (n <= 1) return n\n * return fibonacci(n - 1) + fibonacci(n - 2)\n * }\n * return fibonacci(40)\n * })\n * console.log(await result)\n *\n * @example\n * // I/O-bound work — concurrent mode shares threads efficiently\n * const { result } = spawn(() => fetch('https://api.example.com').then(r => r.json()), {\n * concurrent: true,\n * })\n *\n * @example\n * // Cancel a long-running task\n * const { result, cancel } = spawn(() => longRunningTask())\n * setTimeout(cancel, 5000)\n *\n * @example\n * // Cross-thread channels — pass channels via opts.channels\n * const ch = chan<number>(10)\n * spawn(async ({ ch }) => {\n * for (let i = 0; i < 100; i++) await ch.send(i)\n * ch.close()\n * }, { channels: { ch } })\n */\nexport function spawn<\n T extends StructuredCloneValue,\n TChannels extends Record<string, Channel<ChannelValue>> = Record<never, never>,\n>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: {\n priority?: \"low\" | \"normal\" | \"high\";\n concurrent?: boolean;\n channels?: TChannels;\n ctx?: Context;\n },\n): SpawnResult<T> {\n const { fnId, fnStr } = getSerializedFunctionRef(fn);\n const taskId = String(++taskCounter);\n\n // Capture the call site for better error reporting.\n // Creating the Error is cheap; accessing .stack (which triggers V8's\n // stack formatting) is deferred to the reject path so the happy path\n // pays no cost.\n const spawnError = new Error();\n\n let resolveFn!: (value: T) => void;\n let rejectFn!: (reason: TaskError) => void;\n let settled = false;\n\n const result = new Promise<T>((resolve, reject) => {\n resolveFn = resolve;\n rejectFn = reject;\n });\n\n // Extract channel IDs if channels are provided\n let channelMap: ChannelMap | undefined;\n if (opts?.channels) {\n channelMap = {};\n for (const [name, ch] of Object.entries(opts.channels)) {\n channelMap[name] = getChannelId(ch);\n }\n }\n\n const task: Task = {\n id: taskId,\n fnId,\n fnStr,\n priority: opts?.priority ?? \"normal\",\n concurrent: opts?.concurrent ?? false,\n channels: channelMap,\n resolve: (value) => {\n if (!settled) {\n settled = true;\n resolveFn(value as T);\n }\n },\n reject: (reason) => {\n if (!settled) {\n settled = true;\n // Enrich worker errors with the spawn() call site\n if (reason instanceof Error) {\n const spawnStack = spawnError.stack;\n if (spawnStack) {\n const callerLine = spawnStack.split(\"\\n\").slice(2).join(\"\\n\");\n reason.stack =\n (reason.stack ?? reason.message) + \"\\n --- spawned at ---\\n\" + callerLine;\n }\n }\n rejectFn(reason);\n }\n },\n };\n\n // Context integration: cancel the task when the context is cancelled\n const ctx = opts?.ctx;\n if (ctx) {\n if (ctx.signal.aborted) {\n settled = true;\n rejectFn(ctx.err ?? new DOMException(\"Task was cancelled\", \"AbortError\"));\n return {\n result,\n cancel: () => {},\n };\n }\n }\n\n getPool().submit(task);\n\n const cancel = () => {\n if (settled) return;\n settled = true;\n getPool().cancelTask(taskId);\n rejectFn(new DOMException(\"Task was cancelled\", \"AbortError\"));\n };\n\n // Wire up context cancellation to task cancellation\n if (ctx) {\n const onAbort = () => cancel();\n ctx.signal.addEventListener(\"abort\", onAbort, { once: true });\n // Clean up listener when task settles to avoid leaks\n result.then(\n () => ctx.signal.removeEventListener(\"abort\", onAbort),\n () => ctx.signal.removeEventListener(\"abort\", onAbort),\n );\n }\n\n return { result, cancel };\n}\n\n/** @internal For testing only */\nexport function resetTaskCounter(): void {\n taskCounter = 0;\n}\n","import { spawn as spawnTask } from \"./spawn.js\";\nimport type { ChannelValue, SpawnResult, StructuredCloneValue } from \"./types.js\";\nimport type { Channel } from \"./channel.js\";\nimport type { Context } from \"./context.js\";\n\ntype SpawnChannels = Record<string, Channel<ChannelValue>>;\n\n/**\n * Structured concurrency: spawn multiple tasks and wait for all to complete.\n *\n * Like `Promise.all`, but tasks run in worker threads across CPU cores. Results are\n * returned in the order tasks were spawned. A shared `AbortSignal` lets long-running\n * tasks observe cooperative cancellation via `cancel()`.\n *\n * For fail-fast behavior (cancel all on first error), use `ErrGroup` instead.\n *\n * @example\n * // CPU-bound parallel work\n * const wg = new WaitGroup()\n * wg.spawn(() => { /* define helpers inside — no closure captures *\\/ })\n * wg.spawn(() => { /* another CPU task *\\/ })\n * const [r1, r2] = await wg.wait()\n *\n * @example\n * // Mixed CPU + I/O\n * wg.spawn(() => crunchNumbers(), )\n * wg.spawn(() => fetch('https://api.example.com').then(r => r.json()), { concurrent: true })\n * const results = await wg.wait()\n *\n * @example\n * // Tolerate partial failures with waitSettled\n * const settled = await wg.waitSettled()\n * for (const r of settled) {\n * if (r.status === 'fulfilled') use(r.value)\n * else console.error(r.reason)\n * }\n */\nexport class WaitGroup<T extends StructuredCloneValue = StructuredCloneValue> {\n private tasks: SpawnResult<T>[] = [];\n private controller = new AbortController();\n private ctx?: Context;\n\n constructor(ctx?: Context) {\n this.ctx = ctx;\n if (ctx) {\n if (ctx.signal.aborted) {\n this.controller.abort();\n } else {\n ctx.signal.addEventListener(\"abort\", () => this.cancel(), { once: true });\n }\n }\n }\n\n /**\n * An `AbortSignal` shared across all tasks in this group.\n * Pass it into spawned functions so they can stop early when `cancel()` is called.\n */\n get signal(): AbortSignal {\n return this.controller.signal;\n }\n\n /**\n * Spawns a function on a worker thread and adds it to the group.\n *\n * @throws If the group has already been cancelled.\n */\n spawn<TChannels extends SpawnChannels = Record<never, never>>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: { concurrent?: boolean; channels?: TChannels },\n ): void {\n if (this.controller.signal.aborted) {\n throw new Error(\"WaitGroup has been cancelled\");\n }\n const handle = spawnTask<T, TChannels>(fn, { ...opts, ctx: this.ctx });\n this.tasks.push(handle);\n }\n\n /**\n * Waits for all tasks to complete successfully.\n * Rejects as soon as any task throws.\n */\n async wait(): Promise<T[]> {\n return Promise.all(this.tasks.map((t) => t.result));\n }\n\n /**\n * Waits for all tasks to settle (fulfilled or rejected) and returns each outcome.\n * Never rejects — inspect each `PromiseSettledResult` to handle failures individually.\n */\n async waitSettled(): Promise<PromiseSettledResult<T>[]> {\n return Promise.allSettled(this.tasks.map((t) => t.result));\n }\n\n /**\n * Cancels all tasks in the group and signals the shared `AbortSignal`.\n * Already-settled tasks are unaffected.\n */\n cancel(): void {\n this.controller.abort();\n for (const task of this.tasks) {\n task.cancel();\n }\n }\n}\n","import { spawn as spawnTask } from \"./spawn.js\";\nimport type { ChannelValue, SpawnResult, StructuredCloneValue, TaskError } from \"./types.js\";\nimport type { Channel } from \"./channel.js\";\nimport type { Context } from \"./context.js\";\n\ntype SpawnChannels = Record<string, Channel<ChannelValue>>;\n\n/**\n * Like `WaitGroup`, but cancels all remaining tasks on the first error.\n *\n * Modeled after Go's `golang.org/x/sync/errgroup`. Use when partial results are useless —\n * if any task fails, there is no point waiting for the rest. Benchmarks show ~3.7x faster\n * failure handling than waiting for all tasks to settle.\n *\n * For \"wait for everything regardless of failures\", use `WaitGroup` with `waitSettled()`.\n *\n * @example\n * const eg = new ErrGroup()\n * eg.spawn(() => run('fetchUser', userId))\n * eg.spawn(() => run('fetchOrders', userId))\n * eg.spawn(() => run('fetchAnalytics', userId))\n *\n * try {\n * const [user, orders, analytics] = await eg.wait()\n * } catch (err) {\n * // First failure cancelled the rest — no partial data to clean up\n * }\n *\n * @example\n * // Observe cancellation inside a task via the shared signal\n * const eg = new ErrGroup()\n * eg.spawn(() => {\n * // eg.signal is not directly available inside the worker —\n * // use task() with register() and check a channel or AbortSignal instead\n * })\n */\nexport class ErrGroup<T extends StructuredCloneValue = StructuredCloneValue> {\n private tasks: SpawnResult<T>[] = [];\n private controller = new AbortController();\n private firstError: TaskError | null = null;\n private hasError = false;\n private ctx?: Context;\n private limit = 0; // 0 = unlimited\n private inFlight = 0;\n private waiting: (() => void)[] = [];\n\n constructor(ctx?: Context) {\n this.ctx = ctx;\n if (ctx) {\n if (ctx.signal.aborted) {\n this.controller.abort();\n } else {\n ctx.signal.addEventListener(\"abort\", () => this.cancel(), { once: true });\n }\n }\n }\n\n get signal(): AbortSignal {\n return this.controller.signal;\n }\n\n /**\n * Set the maximum number of tasks that can run concurrently.\n * Like Go's `errgroup.SetLimit()`. Must be called before any `spawn()`.\n * A value of 0 (default) means unlimited.\n */\n setLimit(n: number): void {\n if (this.tasks.length > 0) {\n throw new Error(\"SetLimit must be called before any spawn()\");\n }\n if (n < 0 || !Number.isInteger(n)) {\n throw new RangeError(\"Limit must be a non-negative integer\");\n }\n this.limit = n;\n }\n\n spawn<TChannels extends SpawnChannels = Record<never, never>>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: { concurrent?: boolean; channels?: TChannels },\n ): void {\n if (this.controller.signal.aborted) {\n throw new Error(\"ErrGroup has been cancelled\");\n }\n\n if (this.limit > 0 && this.inFlight >= this.limit) {\n // Queue the spawn until a slot opens\n let innerCancel: () => void = () => {};\n let cancelled = false;\n const cancel = () => {\n cancelled = true;\n innerCancel();\n };\n const result = new Promise<void>((resolve) => {\n this.waiting.push(resolve);\n }).then(() => {\n if (cancelled) throw new DOMException(\"Task was cancelled\", \"AbortError\");\n const handle = this.doSpawn(fn, opts);\n innerCancel = handle.cancel;\n return handle.result;\n });\n this.tasks.push({ result, cancel });\n return;\n }\n\n const handle = this.doSpawn(fn, opts);\n this.tasks.push(handle);\n }\n\n private doSpawn<TChannels extends SpawnChannels = Record<never, never>>(\n fn: (() => T | Promise<T>) | ((channels: TChannels) => T | Promise<T>),\n opts?: { concurrent?: boolean; channels?: TChannels },\n ): SpawnResult<T> {\n this.inFlight++;\n const handle = spawnTask<T, TChannels>(fn, { ...opts, ctx: this.ctx });\n\n // When task settles, release the semaphore slot\n const onSettle = () => {\n this.inFlight--;\n const next = this.waiting.shift();\n if (next) next();\n };\n\n // Watch for errors and cancel all tasks on first failure\n handle.result.then(onSettle, (err) => {\n onSettle();\n if (!this.hasError) {\n this.hasError = true;\n this.firstError = err;\n this.cancel();\n }\n });\n\n return handle;\n }\n\n async wait(): Promise<T[]> {\n const settled = await Promise.allSettled(this.tasks.map((t) => t.result));\n\n if (this.hasError && this.firstError) {\n throw this.firstError;\n }\n\n return settled.map((r) => {\n if (r.status === \"fulfilled\") return r.value;\n throw r.reason;\n });\n }\n\n cancel(): void {\n this.controller.abort();\n for (const task of this.tasks) {\n task.cancel();\n }\n }\n}\n","/**\n * Async mutual exclusion. Serializes access to shared state under concurrency.\n *\n * Prefer `withLock()` over manual `lock()`/`unlock()` — it automatically releases\n * the lock even if the callback throws.\n *\n * Note: `Mutex` operates on the main thread (or whichever thread creates it).\n * Worker threads do not share memory, so this is not useful for cross-thread locking.\n * For cross-thread coordination, use channels instead.\n *\n * @example\n * const mu = new Mutex()\n *\n * // withLock — recommended (auto-unlocks on error)\n * const result = await mu.withLock(async () => {\n * const current = await db.get('counter')\n * await db.set('counter', current + 1)\n * return current + 1\n * })\n *\n * @example\n * // Manual lock/unlock (use withLock instead when possible)\n * await mu.lock()\n * try {\n * // critical section\n * } finally {\n * mu.unlock()\n * }\n */\nexport class Mutex {\n private queue: (() => void)[] = [];\n private locked = false;\n\n async lock(): Promise<void> {\n if (!this.locked) {\n this.locked = true;\n return;\n }\n return new Promise<void>((resolve) => {\n this.queue.push(resolve);\n });\n }\n\n unlock(): void {\n if (!this.locked) {\n throw new Error(\"Cannot unlock a mutex that is not locked\");\n }\n const next = this.queue.shift();\n if (next) {\n next();\n } else {\n this.locked = false;\n }\n }\n\n async withLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.lock();\n try {\n return await fn();\n } finally {\n this.unlock();\n }\n }\n\n get isLocked(): boolean {\n return this.locked;\n }\n}\n\n/**\n * Async read-write mutex. Multiple readers can hold the lock simultaneously,\n * but writers get exclusive access. Modeled after Go's `sync.RWMutex`.\n *\n * Use this instead of `Mutex` when reads vastly outnumber writes — concurrent\n * readers improve throughput without sacrificing write safety.\n *\n * Like `Mutex`, this operates on the main thread only. For cross-thread\n * coordination, use channels instead.\n *\n * @example\n * const rw = new RWMutex()\n *\n * // Multiple readers can run concurrently\n * const data = await rw.withRLock(async () => {\n * return await db.get('config')\n * })\n *\n * // Writers get exclusive access\n * await rw.withLock(async () => {\n * await db.set('config', newValue)\n * })\n */\nexport class RWMutex {\n private readers = 0;\n private writing = false;\n private readQueue: (() => void)[] = [];\n private writeQueue: (() => void)[] = [];\n\n async rLock(): Promise<void> {\n if (!this.writing && this.writeQueue.length === 0) {\n this.readers++;\n return;\n }\n return new Promise<void>((resolve) => {\n this.readQueue.push(() => {\n this.readers++;\n resolve();\n });\n });\n }\n\n rUnlock(): void {\n if (this.readers <= 0) {\n throw new Error(\"Cannot rUnlock a RWMutex that is not read-locked\");\n }\n this.readers--;\n if (this.readers === 0) {\n this.wakeWriter();\n }\n }\n\n async lock(): Promise<void> {\n if (!this.writing && this.readers === 0) {\n this.writing = true;\n return;\n }\n return new Promise<void>((resolve) => {\n this.writeQueue.push(() => {\n this.writing = true;\n resolve();\n });\n });\n }\n\n unlock(): void {\n if (!this.writing) {\n throw new Error(\"Cannot unlock a RWMutex that is not write-locked\");\n }\n this.writing = false;\n // Prefer waking readers first (many can run); fall back to a writer\n if (this.readQueue.length > 0) {\n this.wakeReaders();\n } else {\n this.wakeWriter();\n }\n }\n\n async withRLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.rLock();\n try {\n return await fn();\n } finally {\n this.rUnlock();\n }\n }\n\n async withLock<T>(fn: () => T | Promise<T>): Promise<T> {\n await this.lock();\n try {\n return await fn();\n } finally {\n this.unlock();\n }\n }\n\n get isLocked(): boolean {\n return this.writing || this.readers > 0;\n }\n\n private wakeReaders(): void {\n const queue = this.readQueue;\n this.readQueue = [];\n for (const wake of queue) {\n wake();\n }\n }\n\n private wakeWriter(): void {\n const next = this.writeQueue.shift();\n if (next) next();\n }\n}\n","/**\n * Weighted counting semaphore. Limits concurrent access to a resource where\n * each acquisition can have a different cost. Modeled after Go's\n * `golang.org/x/sync/semaphore.Weighted`.\n *\n * A `Mutex` is equivalent to `new Semaphore(1)` — one holder at a time.\n * A `Semaphore` generalizes this to N units, with variable-weight acquisitions.\n *\n * Like `Mutex`, this operates on the main thread only. For cross-thread\n * coordination, use channels instead.\n *\n * @example\n * // Limit to 10 concurrent DB connections\n * const sem = new Semaphore(10)\n *\n * await sem.acquire() // take 1 slot\n * try {\n * await db.query(...)\n * } finally {\n * sem.release()\n * }\n *\n * @example\n * // Weighted: heavy queries cost more\n * const sem = new Semaphore(10)\n *\n * await sem.acquire(5) // heavy query takes 5 slots\n * sem.release(5)\n *\n * @example\n * // withAcquire — recommended (auto-releases on error)\n * const result = await sem.withAcquire(async () => {\n * return await fetch(url)\n * })\n *\n * @example\n * // Non-blocking check\n * if (sem.tryAcquire(3)) {\n * try { ... } finally { sem.release(3) }\n * }\n */\nexport class Semaphore {\n private max: number;\n private cur: number;\n private queue: { n: number; resolve: () => void }[] = [];\n\n constructor(n: number) {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Semaphore capacity must be a positive integer\");\n }\n this.max = n;\n this.cur = 0;\n }\n\n /**\n * Acquire `n` permits, waiting if necessary until they are available.\n * Acquires are served in FIFO order.\n */\n async acquire(n = 1): Promise<void> {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Acquire count must be a positive integer\");\n }\n if (n > this.max) {\n throw new Error(`Acquire count ${n} exceeds semaphore capacity ${this.max}`);\n }\n if (this.cur + n <= this.max && this.queue.length === 0) {\n this.cur += n;\n return;\n }\n return new Promise<void>((resolve) => {\n this.queue.push({ n, resolve });\n });\n }\n\n /**\n * Try to acquire `n` permits without blocking.\n * Returns `true` if successful, `false` if not enough permits are available.\n */\n tryAcquire(n = 1): boolean {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Acquire count must be a positive integer\");\n }\n if (n > this.max) {\n throw new Error(`Acquire count ${n} exceeds semaphore capacity ${this.max}`);\n }\n if (this.cur + n <= this.max && this.queue.length === 0) {\n this.cur += n;\n return true;\n }\n return false;\n }\n\n /**\n * Release `n` permits, potentially waking queued acquirers.\n */\n release(n = 1): void {\n if (n <= 0 || !Number.isInteger(n)) {\n throw new Error(\"Release count must be a positive integer\");\n }\n if (this.cur - n < 0) {\n throw new Error(\"Released more permits than acquired\");\n }\n this.cur -= n;\n this.wake();\n }\n\n /**\n * Acquire `n` permits, run `fn`, then release automatically — even if `fn` throws.\n */\n async withAcquire<T>(fn: () => T | Promise<T>, n = 1): Promise<T> {\n await this.acquire(n);\n try {\n return await fn();\n } finally {\n this.release(n);\n }\n }\n\n /** Number of permits currently available. */\n get available(): number {\n return this.max - this.cur;\n }\n\n /** Total capacity of the semaphore. */\n get capacity(): number {\n return this.max;\n }\n\n private wake(): void {\n while (this.queue.length > 0) {\n const head = this.queue[0];\n if (this.cur + head.n > this.max) break;\n this.queue.shift();\n this.cur += head.n;\n head.resolve();\n }\n }\n}\n","import { Mutex } from \"./mutex.js\";\n\n/**\n * Condition variable for async coordination. Modeled after Go's `sync.Cond`.\n *\n * A `Cond` is associated with a `Mutex`. Goroutines (async tasks) can:\n * - `wait()` — atomically release the lock and suspend until signaled, then re-acquire the lock\n * - `signal()` — wake one waiting task\n * - `broadcast()` — wake all waiting tasks\n *\n * Always check the condition in a loop — spurious wakeups are possible if\n * multiple waiters compete for the lock after `broadcast()`.\n *\n * @example\n * const mu = new Mutex()\n * const cond = new Cond(mu)\n * let ready = false\n *\n * // Waiter\n * await mu.lock()\n * while (!ready) {\n * await cond.wait()\n * }\n * console.log('ready!')\n * mu.unlock()\n *\n * // Signaler (from another async context)\n * await mu.lock()\n * ready = true\n * cond.signal()\n * mu.unlock()\n *\n * @example\n * // Broadcast to wake all waiters\n * await mu.lock()\n * ready = true\n * cond.broadcast()\n * mu.unlock()\n */\nexport class Cond {\n private mu: Mutex;\n private waiters: (() => void)[] = [];\n\n constructor(mu: Mutex) {\n this.mu = mu;\n }\n\n /**\n * Atomically releases the mutex, suspends the caller until `signal()` or `broadcast()`\n * is called, then re-acquires the mutex before returning.\n *\n * Must be called while holding the mutex.\n */\n async wait(): Promise<void> {\n // Release the lock\n this.mu.unlock();\n\n // Wait for signal\n await new Promise<void>((resolve) => {\n this.waiters.push(resolve);\n });\n\n // Re-acquire the lock\n await this.mu.lock();\n }\n\n /** Wake one waiting task (if any). */\n signal(): void {\n const next = this.waiters.shift();\n if (next) next();\n }\n\n /** Wake all waiting tasks. */\n broadcast(): void {\n const queue = this.waiters;\n this.waiters = [];\n for (const wake of queue) {\n wake();\n }\n }\n}\n","/**\n * Run a function exactly once, even if called concurrently.\n * All callers await the same promise and receive the same result.\n *\n * Use for lazy, one-time initialization of expensive resources (DB pools, ML models,\n * config, etc.) that must be initialized at most once regardless of concurrent demand.\n *\n * @example\n * const initDB = new Once<DBPool>()\n *\n * async function getDB() {\n * return initDB.do(() => createPool({ max: 10 }))\n * }\n *\n * // Safe under concurrent load — pool is created exactly once\n * const [db1, db2] = await Promise.all([getDB(), getDB()])\n * // db1 === db2 (same pool instance)\n *\n * @example\n * // Check if initialization has already run\n * if (!initDB.done) {\n * console.log('not yet initialized')\n * }\n */\nexport class Once<T = void> {\n private promise: Promise<T> | null = null;\n private called = false;\n\n async do(fn: () => T | Promise<T>): Promise<T> {\n if (!this.called) {\n this.called = true;\n this.promise = Promise.resolve(fn());\n }\n return this.promise!;\n }\n\n get done(): boolean {\n return this.called;\n }\n\n reset(): void {\n this.called = false;\n this.promise = null;\n }\n}\n","import type { StructuredCloneValue } from \"./types.js\";\n\ntype RecvCase<T = StructuredCloneValue> = [Promise<T>, (value: T) => void];\ntype SendCase = [Promise<void>, () => void];\ntype SelectCase<T = StructuredCloneValue> = RecvCase<T> | SendCase;\n\n/**\n * Options for `select()`.\n *\n * `default` makes the call non-blocking: if no case is immediately ready,\n * the default handler runs instead of waiting. This mirrors Go's `select { default: ... }`.\n */\nexport interface SelectOptions {\n default?: () => void;\n}\n\n/**\n * Wait for the first of multiple promises to resolve, like Go's `select`.\n *\n * Each case is a `[promise, handler]` tuple. The handler for the first settled\n * promise is called with its value. All other handlers are ignored.\n *\n * **Recv cases:** `[ch.recv(), (value) => ...]` — handler receives the value.\n * **Send cases:** `[ch.send(value), () => ...]` — handler is called when the send completes.\n *\n * If `opts.default` is provided, `select` becomes non-blocking: if no promise\n * is already resolved, the default runs immediately (Go's `select { default: ... }`).\n *\n * Commonly used with `ch.recv()`, `ch.send()`, `after()`, and `spawn().result`.\n *\n * @example\n * // Block until a channel message arrives or timeout after 5s\n * await select([\n * [ch.recv(), (value) => console.log('received', value)],\n * [after(5000), () => console.log('timed out')],\n * ])\n *\n * @example\n * // Non-blocking: check a channel without waiting\n * await select(\n * [[ch.recv(), (value) => process(value)]],\n * { default: () => console.log('channel empty — doing other work') },\n * )\n *\n * @example\n * // Select with send case — try to send or timeout\n * await select([\n * [ch.send(value), () => console.log('sent!')],\n * [after(1000), () => console.log('send timed out')],\n * ])\n *\n * @example\n * // Race two worker results against a deadline\n * const { result: fast } = spawn(() => quickSearch(query))\n * const { result: deep } = spawn(() => deepSearch(query))\n *\n * let response: Result\n * await select([\n * [fast, (r) => { response = r }],\n * [after(200), () => { response = { partial: true } }],\n * ])\n */\nexport function select(cases: SelectCase[], opts?: SelectOptions): Promise<void> {\n if (cases.length === 0) {\n if (opts?.default) {\n opts.default();\n }\n return Promise.resolve();\n }\n\n // Non-blocking: if default is provided, check if any promise is already settled\n if (opts?.default) {\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n // Check all promises for immediate resolution\n for (const [promise, handler] of cases) {\n Promise.resolve(promise).then(\n (value) => {\n if (settled) return;\n settled = true;\n try {\n (handler as (value: unknown) => void)(value);\n resolve();\n } catch (err) {\n reject(err);\n }\n },\n (err) => {\n if (settled) return;\n settled = true;\n reject(err);\n },\n );\n }\n\n // Schedule default on the next microtask — if no promise resolved synchronously,\n // default wins\n queueMicrotask(() => {\n if (settled) return;\n settled = true;\n try {\n opts.default!();\n resolve();\n } catch (err) {\n reject(err);\n }\n });\n });\n }\n\n // Blocking: wait for the first promise to settle\n return new Promise<void>((resolve, reject) => {\n let settled = false;\n\n cases.forEach(([promise, handler]) => {\n promise.then(\n (value) => {\n if (settled) return;\n settled = true;\n try {\n (handler as (value: unknown) => void)(value);\n resolve();\n } catch (err) {\n reject(err);\n }\n },\n (err) => {\n if (settled) return;\n settled = true;\n reject(err);\n },\n );\n });\n });\n}\n","/**\n * Returns a promise that resolves after `ms` milliseconds.\n *\n * Designed for use with `select()` to add timeouts to channel operations or\n * race a deadline against worker results. Also works as a simple async delay.\n *\n * @example\n * // Timeout a channel receive after 2 seconds\n * await select([\n * [ch.recv(), (value) => handle(value)],\n * [after(2000), () => handleTimeout()],\n * ])\n *\n * @example\n * // Simple delay\n * await after(500)\n * console.log('500ms later')\n */\nexport function after(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * A repeating timer that ticks at a fixed interval.\n *\n * Implements `AsyncIterable<void>` — use `for await...of` to run work on each tick.\n * Call `stop()` to cancel the ticker and end the iteration.\n *\n * Create with the `ticker(ms)` factory function.\n *\n * @example\n * const t = ticker(1000) // tick every second\n * for await (const _ of t) {\n * await doWork()\n * if (shouldStop) t.stop() // ends the for-await loop\n * }\n *\n * @example\n * // Use with select() to process work on each tick with a timeout\n * const t = ticker(5000)\n * for await (const _ of t) {\n * await select([\n * [spawn(() => checkHealth()).result, (ok) => report(ok)],\n * [after(4000), () => report('timeout')],\n * ])\n * }\n */\nexport class Ticker {\n private interval: ReturnType<typeof setInterval> | null = null;\n private resolve: ((value: boolean) => void) | null = null;\n private stopped = false;\n private ms: number;\n\n constructor(ms: number) {\n this.ms = ms;\n this.interval = setInterval(() => {\n if (this.resolve) {\n const r = this.resolve;\n this.resolve = null;\n r(true);\n }\n }, ms);\n if (this.interval.unref) this.interval.unref();\n }\n\n async tick(): Promise<boolean> {\n if (this.stopped) return false;\n return new Promise<boolean>((resolve) => {\n this.resolve = resolve;\n // Re-check after assignment: stop() may have been called between\n // the guard above and here, in which case this.resolve was never\n // seen by stop() and the promise would hang.\n if (this.stopped) {\n this.resolve = null;\n resolve(false);\n }\n });\n }\n\n stop(): void {\n this.stopped = true;\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n if (this.resolve) {\n const r = this.resolve;\n this.resolve = null;\n r(false); // resolve pending tick with false — the ticker has stopped\n }\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<void> {\n while (await this.tick()) {\n yield;\n }\n }\n}\n\n/**\n * Create a `Ticker` that fires every `ms` milliseconds.\n *\n * @example\n * const t = ticker(500)\n * for await (const _ of t) {\n * console.log('tick')\n * if (done) t.stop()\n * }\n */\nexport function ticker(ms: number): Ticker {\n return new Ticker(ms);\n}\n","/**\n * A one-shot timer that can be stopped and reset. Like Go's `time.Timer`.\n *\n * Unlike `after()` which is fire-and-forget, `Timer` gives you control:\n * - `stop()` cancels a pending timer\n * - `reset(ms)` reschedules without allocating a new object\n *\n * The `channel` property is a promise that resolves when the timer fires.\n * After `stop()`, the promise never resolves. After `reset()`, a new `channel`\n * promise is created.\n *\n * @example\n * // Basic timeout with ability to cancel\n * const t = new Timer(5000)\n * await select([\n * [ch.recv(), (v) => { t.stop(); handle(v) }],\n * [t.channel, () => console.log('timed out')],\n * ])\n *\n * @example\n * // Reset a timer (e.g., debounce pattern)\n * const t = new Timer(300)\n * onInput(() => t.reset(300))\n * await t.channel // fires 300ms after last input\n */\nexport class Timer {\n private timer: ReturnType<typeof setTimeout> | null = null;\n private _stopped = false;\n\n /** Promise that resolves when the timer fires. Replaced on `reset()`. */\n channel: Promise<void>;\n\n constructor(ms: number) {\n this.channel = this.schedule(ms);\n }\n\n private schedule(ms: number): Promise<void> {\n return new Promise<void>((resolve) => {\n this.timer = setTimeout(() => {\n this._stopped = true;\n this.timer = null;\n resolve();\n }, ms);\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n });\n }\n\n /**\n * Stop the timer. Returns `true` if the timer was pending (stopped before firing),\n * `false` if it had already fired or was already stopped.\n *\n * After stopping, the current `channel` promise will never resolve.\n */\n stop(): boolean {\n if (this.timer === null) return false;\n clearTimeout(this.timer);\n this.timer = null;\n this._stopped = true;\n return true;\n }\n\n /**\n * Reset the timer to fire after `ms` milliseconds.\n * If the timer was pending, it is stopped first. Creates a new `channel` promise.\n */\n reset(ms: number): void {\n this.stop();\n this._stopped = false;\n this.channel = this.schedule(ms);\n }\n\n /** Whether the timer has fired or been stopped. */\n get stopped(): boolean {\n return this._stopped;\n }\n}\n","import { getPool } from \"./pool.js\";\nimport { getSerializedFunctionRef } from \"./serialize.js\";\nimport type { JsonValue, StructuredCloneValue, Task, TaskError } from \"./types.js\";\n\nlet taskCounter = 0;\n\n/**\n * Define a reusable task that runs in a worker thread.\n *\n * Returns a typed async function — call it like a regular async function,\n * and it dispatches to the thread pool each time.\n *\n * Use task() when you have the same function to call many times with\n * different arguments. For one-off work, use spawn() instead.\n *\n * Arguments must be JSON-serializable (no functions, symbols, undefined, or BigInt).\n * The function itself must be self-contained — it cannot capture enclosing scope variables.\n *\n * @example\n * const resizeImage = task((src: string, width: number, height: number) => {\n * // runs in a worker thread\n * return processPixels(src, width, height)\n * })\n *\n * const result = await resizeImage('photo.jpg', 800, 600)\n * const [a, b] = await Promise.all([resizeImage('a.jpg', 400, 300), resizeImage('b.jpg', 800, 600)])\n */\nexport function task<TArgs extends JsonValue[], TReturn extends StructuredCloneValue>(\n fn: (...args: TArgs) => TReturn | Promise<TReturn>,\n): (...args: TArgs) => Promise<TReturn> {\n const { fnId, fnStr } = getSerializedFunctionRef(fn);\n return (...args: TArgs): Promise<TReturn> => {\n for (const a of args) {\n if (JSON.stringify(a) === undefined) {\n throw new TypeError(\n `Argument of type ${typeof a} is not JSON-serializable. ` +\n \"task() args must be JSON-serializable (no undefined, functions, symbols, or BigInt).\",\n );\n }\n }\n\n const taskId = `task_${++taskCounter}`;\n const spawnError = new Error();\n\n let resolveFn!: (value: TReturn) => void;\n let rejectFn!: (reason: TaskError) => void;\n\n const result = new Promise<TReturn>((resolve, reject) => {\n resolveFn = resolve;\n rejectFn = reject;\n });\n\n const taskObj: Task = {\n id: taskId,\n fnId,\n fnStr,\n args,\n priority: \"normal\",\n concurrent: false,\n resolve: (value) => resolveFn(value as TReturn),\n reject: (reason) => {\n if (reason instanceof Error) {\n const spawnStack = spawnError.stack;\n if (spawnStack) {\n const callerLine = spawnStack.split(\"\\n\").slice(2).join(\"\\n\");\n reason.stack =\n (reason.stack ?? reason.message) + \"\\n --- spawned at ---\\n\" + callerLine;\n }\n }\n rejectFn(reason);\n },\n };\n\n getPool().submit(taskObj);\n\n return result;\n };\n}\n\n/** @internal For testing only */\nexport function resetTaskCounter(): void {\n taskCounter = 0;\n}\n","/**\n * Hierarchical cancellation, deadlines, and request-scoped values — modeled after Go's `context` package.\n *\n * Context is the glue that makes cancellation and timeouts composable. Derive child\n * contexts from a parent: when the parent is cancelled, all children cancel automatically.\n *\n * @example\n * // Timeout a group of tasks\n * const [ctx, cancel] = withTimeout(background(), 5000)\n * const wg = new WaitGroup()\n * wg.spawn(() => longRunningWork())\n * ctx.done().then(() => wg.cancel())\n *\n * @example\n * // Nested deadlines\n * const [parent, cancelParent] = withCancel(background())\n * const [child, _] = withTimeout(parent, 1000)\n * // child cancels after 1s OR when cancelParent() is called — whichever comes first\n *\n * @example\n * // Request-scoped values\n * const reqCtx = withValue(background(), 'requestId', 'abc-123')\n * reqCtx.value('requestId') // 'abc-123'\n */\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/** Returned by `ctx.err` when the context was explicitly cancelled. */\nexport class CancelledError extends Error {\n constructor(message = \"context cancelled\") {\n super(message);\n this.name = \"CancelledError\";\n }\n}\n\n/** Returned by `ctx.err` when the context's deadline has passed. */\nexport class DeadlineExceededError extends Error {\n constructor() {\n super(\"context deadline exceeded\");\n this.name = \"DeadlineExceededError\";\n }\n}\n\nexport type ContextError = CancelledError | DeadlineExceededError;\n\n// ---------------------------------------------------------------------------\n// Context interface\n// ---------------------------------------------------------------------------\n\nexport interface Context {\n /** AbortSignal that fires when this context is cancelled or its deadline expires. */\n readonly signal: AbortSignal;\n /** The deadline for this context, or `null` if none was set. */\n readonly deadline: Date | null;\n /** The cancellation error, or `null` if the context is still active. */\n readonly err: ContextError | null;\n /** Retrieves a value stored in this context or any of its ancestors. */\n value<T = unknown>(key: symbol | string): T | undefined;\n /** Returns a promise that resolves when the context is cancelled. */\n done(): Promise<void>;\n}\n\nexport type CancelFunc = (reason?: string) => void;\n\n// ---------------------------------------------------------------------------\n// Internal base\n// ---------------------------------------------------------------------------\n\nclass BaseContext implements Context {\n protected _err: ContextError | null = null;\n protected controller: AbortController;\n protected parent: Context | null;\n\n constructor(parent: Context | null) {\n this.parent = parent;\n this.controller = new AbortController();\n\n // Propagate parent cancellation\n if (parent) {\n if (parent.signal.aborted) {\n // Parent already cancelled — cancel immediately\n this._err = parent.err ?? new CancelledError();\n this.controller.abort();\n } else {\n parent.signal.addEventListener(\n \"abort\",\n () => {\n if (!this.controller.signal.aborted) {\n this._err = parent.err ?? new CancelledError();\n this.controller.abort();\n }\n },\n { once: true },\n );\n }\n }\n }\n\n get signal(): AbortSignal {\n return this.controller.signal;\n }\n\n get deadline(): Date | null {\n return this.parent?.deadline ?? null;\n }\n\n get err(): ContextError | null {\n return this._err;\n }\n\n value<T = unknown>(_key: symbol | string): T | undefined {\n return this.parent?.value<T>(_key);\n }\n\n done(): Promise<void> {\n if (this.controller.signal.aborted) return Promise.resolve();\n return new Promise((resolve) => {\n this.controller.signal.addEventListener(\"abort\", () => resolve(), { once: true });\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Background context (root, never cancelled)\n// ---------------------------------------------------------------------------\n\nclass BackgroundContext implements Context {\n private _signal = new AbortController().signal;\n\n get signal(): AbortSignal {\n return this._signal;\n }\n\n get deadline(): Date | null {\n return null;\n }\n\n get err(): ContextError | null {\n return null;\n }\n\n value<T = unknown>(_key: symbol | string): T | undefined {\n return undefined;\n }\n\n done(): Promise<void> {\n // Never resolves — background is never cancelled\n return new Promise(() => {});\n }\n}\n\nlet bg: BackgroundContext | null = null;\n\n/**\n * Returns the root context. It is never cancelled, has no deadline, and carries no values.\n * All other contexts should derive from this.\n */\nexport function background(): Context {\n if (!bg) bg = new BackgroundContext();\n return bg;\n}\n\n// ---------------------------------------------------------------------------\n// withCancel\n// ---------------------------------------------------------------------------\n\nclass CancelContext extends BaseContext {\n cancel(reason?: string): void {\n if (!this.controller.signal.aborted) {\n this._err = new CancelledError(reason ?? \"context cancelled\");\n this.controller.abort();\n }\n }\n}\n\n/**\n * Returns a child context and a cancel function. Calling `cancel()` cancels the child\n * and all contexts derived from it. The child also cancels when the parent does.\n */\nexport function withCancel(parent: Context): [Context, CancelFunc] {\n const ctx = new CancelContext(parent);\n return [ctx, (reason?: string) => ctx.cancel(reason)];\n}\n\n// ---------------------------------------------------------------------------\n// withDeadline / withTimeout\n// ---------------------------------------------------------------------------\n\nclass DeadlineContext extends BaseContext {\n private _deadline: Date;\n private timer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(parent: Context, deadline: Date) {\n super(parent);\n this._deadline = deadline;\n\n // Inherit the earlier deadline if the parent has one\n if (parent.deadline && parent.deadline < deadline) {\n this._deadline = parent.deadline;\n }\n\n if (this.controller.signal.aborted) {\n // Already cancelled by parent propagation\n return;\n }\n\n const ms = this._deadline.getTime() - Date.now();\n if (ms <= 0) {\n // Deadline already passed\n this._err = new DeadlineExceededError();\n this.controller.abort();\n } else {\n this.timer = setTimeout(() => {\n if (!this.controller.signal.aborted) {\n this._err = new DeadlineExceededError();\n this.controller.abort();\n }\n }, ms);\n // Don't keep the process alive just for this timer\n if (typeof this.timer === \"object\" && \"unref\" in this.timer) {\n this.timer.unref();\n }\n }\n }\n\n override get deadline(): Date {\n return this._deadline;\n }\n\n cancel(reason?: string): void {\n if (this.timer !== null) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (!this.controller.signal.aborted) {\n this._err = new CancelledError(reason ?? \"context cancelled\");\n this.controller.abort();\n }\n }\n}\n\n/**\n * Returns a child context that automatically cancels at the given `deadline`.\n * If the parent has an earlier deadline, that deadline is inherited.\n * The returned cancel function can cancel early and clears the timer.\n */\nexport function withDeadline(parent: Context, deadline: Date): [Context, CancelFunc] {\n const ctx = new DeadlineContext(parent, deadline);\n return [ctx, (reason?: string) => ctx.cancel(reason)];\n}\n\n/**\n * Returns a child context that automatically cancels after `ms` milliseconds.\n * Equivalent to `withDeadline(parent, new Date(Date.now() + ms))`.\n */\nexport function withTimeout(parent: Context, ms: number): [Context, CancelFunc] {\n return withDeadline(parent, new Date(Date.now() + ms));\n}\n\n// ---------------------------------------------------------------------------\n// withValue\n// ---------------------------------------------------------------------------\n\nclass ValueContext extends BaseContext {\n private key: symbol | string;\n private val: unknown;\n\n constructor(parent: Context, key: symbol | string, val: unknown) {\n super(parent);\n this.key = key;\n this.val = val;\n }\n\n override value<T = unknown>(key: symbol | string): T | undefined {\n if (key === this.key) return this.val as T;\n return this.parent?.value<T>(key);\n }\n}\n\n/**\n * Returns a child context carrying a key-value pair.\n * Values are retrieved with `ctx.value(key)` and looked up through the ancestor chain.\n */\nexport function withValue<T = unknown>(parent: Context, key: symbol | string, value: T): Context {\n return new ValueContext(parent, key, value);\n}\n"],"mappings":"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","names":["import_node_os","sender","task","task","task","handle","task","taskCounter"]}