import { defineInspectMethod } from '../../../debugging/inspect.js'; import { functionName, nameObject } from '../../../debugging/object-with-name.js'; import { dispose_name } from '../debug.js'; import type { IAsyncDisposable, IDisposable } from '../disposable.js'; /** * Convert "dispose function" to disposable object * @public */ export function functionToDisposable(fn: () => RT): RT extends Promise ? IAsyncDisposable : IDisposable { const r = { get displayName() { return `disposeFn(${functionName(fn)})`; }, disposed: false, disposing: false, dispose: async () => { if (r.disposing) return; r.disposing = true; try { await fn(); } finally { r.disposed = true; } }, }; return defineInspectMethod(r, (_depth, options) => { return options.stylize(`[FunctionDisposable ${functionName(fn)}]`, 'special'); }); } /** * convert disposable object to function * eg. * * useEffect(() => { * const disposable = new Xyz(); * return toFunction(disposable); * }, []) */ export function disposerFunction(obj: T): T extends IAsyncDisposable ? () => Promise : () => void { return nameObject(dispose_name(obj), () => { obj.dispose(); }) as any; }