import { microTask } from './microTask' export function disposables() { let disposables: Function[] = [] let queue: Function[] = [] let api = { enqueue(fn: Function) { queue.push(fn) }, addEventListener( element: HTMLElement | Document, name: TEventName, listener: (event: WindowEventMap[TEventName]) => any, options?: boolean | AddEventListenerOptions ) { element.addEventListener(name, listener as any, options) return api.add(() => element.removeEventListener(name, listener as any, options)) }, requestAnimationFrame(...args: Parameters) { let raf = requestAnimationFrame(...args) return api.add(() => cancelAnimationFrame(raf)) }, nextFrame(...args: Parameters) { return api.requestAnimationFrame(() => { return api.requestAnimationFrame(...args) }) }, setTimeout(...args: Parameters) { let timer = setTimeout(...args) return api.add(() => clearTimeout(timer)) }, microTask(...args: Parameters) { let task = { current: true } microTask(() => { if (task.current) { args[0]() } }) return api.add(() => { task.current = false }) }, add(cb: () => void) { disposables.push(cb) return () => { let idx = disposables.indexOf(cb) if (idx >= 0) { let [dispose] = disposables.splice(idx, 1) dispose() } } }, dispose() { for (let dispose of disposables.splice(0)) { dispose() } }, async workQueue() { for (let handle of queue.splice(0)) { await handle() } }, } return api }