import { resolver } from '@rocicorp/resolver';
import { AbortError } from "./abort-error.js";
const promiseVoid = Promise.resolve();
const promiseNever = new Promise(() => undefined);
/**
 * Creates a promise that resolves after `ms` milliseconds. Note that if you
 * pass in `0` no `setTimeout` is used and the promise resolves immediately. In
 * other words no macro task is used in that case.
 *
 * Pass in an AbortSignal to clear the timeout.
 */
export function sleep(ms, signal) {
    const newAbortError = () => new AbortError('Aborted');
    if (signal?.aborted) {
        return Promise.reject(newAbortError());
    }
    if (ms === 0) {
        return promiseVoid;
    }
    return new Promise((resolve, reject) => {
        let handleAbort;
        if (signal) {
            handleAbort = () => {
                clearTimeout(id);
                reject(newAbortError());
            };
            signal.addEventListener('abort', handleAbort, { once: true });
        }
        const id = setTimeout(() => {
            resolve();
            signal?.removeEventListener('abort', handleAbort);
        }, ms);
    });
}
/**
 * Returns a pair of promises. The first promise resolves after `ms` milliseconds
 * unless the AbortSignal is aborted. The second promise resolves when the AbortSignal
 * is aborted.
 */
export function sleepWithAbort(ms, signal) {
    if (ms === 0) {
        return [promiseVoid, promiseNever];
    }
    const { promise: abortedPromise, resolve: abortedResolve } = resolver();
    const sleepPromise = new Promise(resolve => {
        const handleAbort = () => {
            clearTimeout(id);
            abortedResolve();
        };
        const id = setTimeout(() => {
            resolve();
            signal.removeEventListener('abort', handleAbort);
        }, ms);
        signal.addEventListener('abort', handleAbort, { once: true });
    });
    return [sleepPromise, abortedPromise];
}
//# sourceMappingURL=sleep.js.map