source dump of claude code
at main 47 lines 1.7 kB view raw
1import { createAbortController } from './abortController.js' 2 3/** 4 * Creates a combined AbortSignal that aborts when the input signal aborts, 5 * an optional second signal aborts, or an optional timeout elapses. 6 * Returns both the signal and a cleanup function that removes event listeners 7 * and clears the internal timeout timer. 8 * 9 * Use `timeoutMs` instead of passing `AbortSignal.timeout(ms)` as a signal — 10 * under Bun, `AbortSignal.timeout` timers are finalized lazily and accumulate 11 * in native memory until they fire (measured ~2.4KB/call held for the full 12 * timeout duration). This implementation uses `setTimeout` + `clearTimeout` 13 * so the timer is freed immediately on cleanup. 14 */ 15export function createCombinedAbortSignal( 16 signal: AbortSignal | undefined, 17 opts?: { signalB?: AbortSignal; timeoutMs?: number }, 18): { signal: AbortSignal; cleanup: () => void } { 19 const { signalB, timeoutMs } = opts ?? {} 20 const combined = createAbortController() 21 22 if (signal?.aborted || signalB?.aborted) { 23 combined.abort() 24 return { signal: combined.signal, cleanup: () => {} } 25 } 26 27 let timer: ReturnType<typeof setTimeout> | undefined 28 const abortCombined = () => { 29 if (timer !== undefined) clearTimeout(timer) 30 combined.abort() 31 } 32 33 if (timeoutMs !== undefined) { 34 timer = setTimeout(abortCombined, timeoutMs) 35 timer.unref?.() 36 } 37 signal?.addEventListener('abort', abortCombined) 38 signalB?.addEventListener('abort', abortCombined) 39 40 const cleanup = () => { 41 if (timer !== undefined) clearTimeout(timer) 42 signal?.removeEventListener('abort', abortCombined) 43 signalB?.removeEventListener('abort', abortCombined) 44 } 45 46 return { signal: combined.signal, cleanup } 47}