import { CancellationToken, CancellationTokenSource } from "./cancellation.js"; import { Event } from "./event.js"; import { Disposable, DisposableStore, IDisposable } from "./lifecycle.js"; import { IExtUri } from "./resources.js"; import { URI } from "./uri.js"; import { MicrotaskDelay } from "./symbols.js"; export declare function isThenable(obj: unknown): obj is Promise; export interface CancelablePromise extends Promise { cancel(): void; } /** * Returns a promise that can be cancelled using the provided cancellation token. * * @remarks When cancellation is requested, the promise will be rejected with a {@link CancellationError}. * If the promise resolves to a disposable object, it will be automatically disposed when cancellation * is requested. * * @param callback A function that accepts a cancellation token and returns a promise * @returns A promise that can be cancelled */ export declare function createCancelablePromise(callback: (token: CancellationToken) => Promise): CancelablePromise; /** * Returns a promise that resolves with `undefined` as soon as the passed token is cancelled. * @see {@link raceCancellationError} */ export declare function raceCancellation(promise: Promise, token: CancellationToken): Promise; /** * Returns a promise that resolves with `defaultValue` as soon as the passed token is cancelled. * @see {@link raceCancellationError} */ export declare function raceCancellation(promise: Promise, token: CancellationToken, defaultValue: T): Promise; /** * Returns a promise that rejects with an {@CancellationError} as soon as the passed token is cancelled. * @see {@link raceCancellation} */ export declare function raceCancellationError(promise: Promise, token: CancellationToken): Promise; /** * Wraps a cancellable promise such that it is no cancellable. Can be used to * avoid issues with shared promises that would normally be returned as * cancellable to consumers. */ export declare function notCancellablePromise(promise: CancelablePromise): Promise; /** * Returns as soon as one of the promises resolves or rejects and cancels remaining promises */ export declare function raceCancellablePromises(cancellablePromises: (CancelablePromise | Promise)[]): CancelablePromise; export declare function raceTimeout(promise: Promise, timeout: number, onTimeout?: () => void): Promise; export declare function asPromise(callback: () => T | Thenable): Promise; /** * Creates and returns a new promise, plus its `resolve` and `reject` callbacks. * * Replace with standardized [`Promise.withResolvers`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers) once it is supported */ export declare function promiseWithResolvers(): { promise: Promise; resolve: (value: T | PromiseLike) => void; reject: (err?: any) => void; }; export interface ITask { (): T; } export interface ICancellableTask { (token: CancellationToken): T; } /** * A helper to prevent accumulation of sequential async tasks. * * Imagine a mail man with the sole task of delivering letters. As soon as * a letter submitted for delivery, he drives to the destination, delivers it * and returns to his base. Imagine that during the trip, N more letters were submitted. * When the mail man returns, he picks those N letters and delivers them all in a * single trip. Even though N+1 submissions occurred, only 2 deliveries were made. * * The throttler implements this via the queue() method, by providing it a task * factory. Following the example: * * const throttler = new Throttler(); * const letters = []; * * function deliver() { * const lettersToDeliver = letters; * letters = []; * return makeTheTrip(lettersToDeliver); * } * * function onLetterReceived(l) { * letters.push(l); * throttler.queue(deliver); * } */ export declare class Throttler implements IDisposable { private activePromise; private queuedPromise; private queuedPromiseFactory; private cancellationTokenSource; constructor(); queue(promiseFactory: ICancellableTask>): Promise; dispose(): void; } export declare class Sequencer { private current; queue(promiseTask: ITask>): Promise; } export declare class SequencerByKey { private promiseMap; queue(key: TKey, promiseTask: ITask>): Promise; peek(key: TKey): Promise | undefined; keys(): IterableIterator; } /** * A helper to delay (debounce) execution of a task that is being requested often. * * Following the throttler, now imagine the mail man wants to optimize the number of * trips proactively. The trip itself can be long, so he decides not to make the trip * as soon as a letter is submitted. Instead he waits a while, in case more * letters are submitted. After said waiting period, if no letters were submitted, he * decides to make the trip. Imagine that N more letters were submitted after the first * one, all within a short period of time between each other. Even though N+1 * submissions occurred, only 1 delivery was made. * * The delayer offers this behavior via the trigger() method, into which both the task * to be executed and the waiting period (delay) must be passed in as arguments. Following * the example: * * const delayer = new Delayer(WAITING_PERIOD); * const letters = []; * * function letterReceived(l) { * letters.push(l); * delayer.trigger(() => { return makeTheTrip(); }); * } */ export declare class Delayer implements IDisposable { defaultDelay: number | typeof MicrotaskDelay; private deferred; private completionPromise; private doResolve; private doReject; private task; constructor(defaultDelay: number | typeof MicrotaskDelay); trigger(task: ITask>, delay?: number | typeof MicrotaskDelay): Promise; isTriggered(): boolean; cancel(): void; private cancelTimeout; dispose(): void; } /** * A helper to delay execution of a task that is being requested often, while * preventing accumulation of consecutive executions, while the task runs. * * The mail man is clever and waits for a certain amount of time, before going * out to deliver letters. While the mail man is going out, more letters arrive * and can only be delivered once he is back. Once he is back the mail man will * do one more trip to deliver the letters that have accumulated while he was out. */ export declare class ThrottledDelayer { private delayer; private throttler; constructor(defaultDelay: number); trigger(promiseFactory: ICancellableTask>, delay?: number): Promise; isTriggered(): boolean; cancel(): void; dispose(): void; } /** * A barrier that is initially closed and then becomes opened permanently. */ export declare class Barrier { private _isOpen; private _promise; private _completePromise; constructor(); isOpen(): boolean; open(): void; wait(): Promise; } /** * A barrier that is initially closed and then becomes opened permanently after a certain period of * time or when open is called explicitly */ export declare class AutoOpenBarrier extends Barrier { private readonly _timeout; constructor(autoOpenTimeMs: number); open(): void; } export declare function timeout(millis: number): CancelablePromise; export declare function timeout(millis: number, token: CancellationToken): Promise; /** * Creates a timeout that can be disposed using its returned value. * @param handler The timeout handler. * @param timeout An optional timeout in milliseconds. * @param store An optional {@link DisposableStore} that will have the timeout disposable managed automatically. * * @example * const store = new DisposableStore; * // Call the timeout after 1000ms at which point it will be automatically * // evicted from the store. * const timeoutDisposable = disposableTimeout(() => {}, 1000, store); * * if (foo) { * // Cancel the timeout and evict it from store. * timeoutDisposable.dispose(); * } */ export declare function disposableTimeout(handler: () => void, timeout?: number, store?: DisposableStore): IDisposable; /** * Runs the provided list of promise factories in sequential order. The returned * promise will complete to an array of results from each promise. */ export declare function sequence(promiseFactories: ITask>[]): Promise; export declare function first(promiseFactories: ITask>[], shouldStop?: (t: T) => boolean, defaultValue?: T | null): Promise; /** * Returns the result of the first promise that matches the "shouldStop", * running all promises in parallel. Supports cancelable promises. */ export declare function firstParallel(promiseList: Promise[], shouldStop?: (t: T) => boolean, defaultValue?: T | null): Promise; export declare function firstParallel(promiseList: Promise[], shouldStop: (t: T) => t is R, defaultValue?: R | null): Promise; export interface ILimiter { readonly size: number; queue(factory: ITask>): Promise; clear(): void; } /** * A helper to queue N promises and run them all with a max degree of parallelism. The helper * ensures that at any time no more than M promises are running at the same time. */ export declare class Limiter implements ILimiter { private _size; private _isDisposed; private runningPromises; private readonly maxDegreeOfParalellism; private readonly outstandingPromises; private readonly _onDrained; constructor(maxDegreeOfParalellism: number); /** * * @returns A promise that resolved when all work is done (onDrained) or when * there is nothing to do */ whenIdle(): Promise; get onDrained(): Event; get size(): number; queue(factory: ITask>): Promise; private consume; private consumed; clear(): void; dispose(): void; } /** * A queue is handles one promise at a time and guarantees that at any time only one promise is executing. */ export declare class Queue extends Limiter { constructor(); } /** * Same as `Queue`, ensures that only 1 task is executed at the same time. The difference to `Queue` is that * there is only 1 task about to be scheduled next. As such, calling `queue` while a task is executing will * replace the currently queued task until it executes. * * As such, the returned promise may not be from the factory that is passed in but from the next factory that * is running after having called `queue`. */ export declare class LimitedQueue { private readonly sequentializer; private tasks; queue(factory: ITask>): Promise; } /** * A helper to organize queues per resource. The ResourceQueue makes sure to manage queues per resource * by disposing them once the queue is empty. */ export declare class ResourceQueue implements IDisposable { private readonly queues; private readonly drainers; private drainListeners; private drainListenerCount; whenDrained(): Promise; private isDrained; queueSize(resource: URI, extUri?: IExtUri): number; queueFor(resource: URI, factory: ITask>, extUri?: IExtUri): Promise; private onDidQueueDrain; private releaseDrainers; dispose(): void; } export type Task = () => (Promise | T); /** * Wrap a type in an optional promise. This can be useful to avoid the runtime * overhead of creating a promise. */ export type MaybePromise = Promise | T; /** * Processes tasks in the order they were scheduled. */ export declare class TaskQueue { private _runningTask; private _pendingTasks; /** * Waits for the current and pending tasks to finish, then runs and awaits the given task. * If the task is skipped because of clearPending, the promise is rejected with a CancellationError. */ schedule(task: Task): Promise; /** * Waits for the current and pending tasks to finish, then runs and awaits the given task. * If the task is skipped because of clearPending, the promise is resolved with undefined. */ scheduleSkipIfCleared(task: Task): Promise; private _runIfNotRunning; private _processQueue; /** * Clears all pending tasks. Does not cancel the currently running task. */ clearPending(): void; } export declare class TimeoutTimer implements IDisposable { private _token; private _isDisposed; constructor(); constructor(runner: () => void, timeout: number); dispose(): void; cancel(): void; cancelAndSet(runner: () => void, timeout: number): void; setIfNotSet(runner: () => void, timeout: number): void; } export declare class IntervalTimer implements IDisposable { private disposable; private isDisposed; cancel(): void; cancelAndSet(runner: () => void, interval: number, context?: typeof globalThis): void; dispose(): void; } export declare class RunOnceScheduler implements IDisposable { protected runner: ((...args: unknown[]) => void) | null; private timeoutToken; private timeout; private timeoutHandler; constructor(runner: (...args: any[]) => void, delay: number); /** * Dispose RunOnceScheduler */ dispose(): void; /** * Cancel current scheduled runner (if any). */ cancel(): void; /** * Cancel previous runner (if any) & schedule a new runner. */ schedule(delay?: number): void; get delay(): number; set delay(value: number); /** * Returns true if scheduled. */ isScheduled(): boolean; flush(): void; private onTimeout; protected doRun(): void; } /** * Same as `RunOnceScheduler`, but doesn't count the time spent in sleep mode. * > **NOTE**: Only offers 1s resolution. * * When calling `setTimeout` with 3hrs, and putting the computer immediately to sleep * for 8hrs, `setTimeout` will fire **as soon as the computer wakes from sleep**. But * this scheduler will execute 3hrs **after waking the computer from sleep**. */ export declare class ProcessTimeRunOnceScheduler { private runner; private timeout; private counter; private intervalToken; private intervalHandler; constructor(runner: () => void, delay: number); dispose(): void; cancel(): void; /** * Cancel previous runner (if any) & schedule a new runner. */ schedule(delay?: number): void; /** * Returns true if scheduled. */ isScheduled(): boolean; private onInterval; } export declare class RunOnceWorker extends RunOnceScheduler { private units; constructor(runner: (units: T[]) => void, timeout: number); work(unit: T): void; protected doRun(): void; dispose(): void; } export interface IThrottledWorkerOptions { /** * maximum of units the worker will pass onto handler at once */ maxWorkChunkSize: number; /** * maximum of units the worker will keep in memory for processing */ maxBufferedWork: number | undefined; /** * delay before processing the next round of chunks when chunk size exceeds limits */ throttleDelay: number; /** * When enabled will guarantee that two distinct calls to `work()` are not executed * without throttle delay between them. * Otherwise if the worker isn't currently throttling it will execute work immediately. */ waitThrottleDelayBetweenWorkUnits?: boolean; } /** * The `ThrottledWorker` will accept units of work `T` * to handle. The contract is: * * there is a maximum of units the worker can handle at once (via `maxWorkChunkSize`) * * there is a maximum of units the worker will keep in memory for processing (via `maxBufferedWork`) * * after having handled `maxWorkChunkSize` units, the worker needs to rest (via `throttleDelay`) */ export declare class ThrottledWorker extends Disposable { private options; private readonly handler; private readonly pendingWork; private readonly throttler; private disposed; private lastExecutionTime; constructor(options: IThrottledWorkerOptions, handler: (units: T[]) => void); /** * The number of work units that are pending to be processed. */ get pending(): number; /** * Add units to be worked on. Use `pending` to figure out * how many units are not yet processed after this method * was called. * * @returns whether the work was accepted or not. If the * worker is disposed, it will not accept any more work. * If the number of pending units would become larger * than `maxPendingWork`, more work will also not be accepted. */ work(units: readonly T[]): boolean; private doWork; private scheduleThrottler; dispose(): void; } export interface IdleDeadline { readonly didTimeout: boolean; timeRemaining(): number; } type IdleApi = Pick; /** * Execute the callback the next time the browser is idle, returning an * {@link IDisposable} that will cancel the callback when disposed. This wraps * [requestIdleCallback] so it will fallback to [setTimeout] if the environment * doesn't support it. * * @param callback The callback to run when idle, this includes an * [IdleDeadline] that provides the time alloted for the idle callback by the * browser. Not respecting this deadline will result in a degraded user * experience. * @param timeout A timeout at which point to queue no longer wait for an idle * callback but queue it on the regular event loop (like setTimeout). Typically * this should not be used. * * [IdleDeadline]: https://developer.mozilla.org/en-US/docs/Web/API/IdleDeadline * [requestIdleCallback]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback * [setTimeout]: https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout * * **Note** that there is `dom.ts#runWhenWindowIdle` which is better suited when running inside a browser * context */ export declare let runWhenGlobalIdle: (callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable; export declare let _runWhenIdle: (targetWindow: IdleApi, callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable; export declare abstract class AbstractIdleValue { private readonly _executor; private readonly _handle; private _didRun; private _value?; private _error; constructor(targetWindow: IdleApi, executor: () => T); dispose(): void; get value(): T; get isInitialized(): boolean; } /** * An `IdleValue` that always uses the current window (which might be throttled or inactive) * * **Note** that there is `dom.ts#WindowIdleValue` which is better suited when running inside a browser * context */ export declare class GlobalIdleValue extends AbstractIdleValue { constructor(executor: () => T); } export declare function retry(task: ITask>, delay: number, retries: number): Promise; interface IQueuedTask { readonly promise: Promise; readonly promiseResolve: () => void; readonly promiseReject: (error: Error) => void; run: ITask>; } export interface ITaskSequentializerWithRunningTask { readonly running: Promise; } export interface ITaskSequentializerWithQueuedTask { readonly queued: IQueuedTask; } /** * @deprecated use `LimitedQueue` instead for an easier to use API */ export declare class TaskSequentializer { private _running?; private _queued?; isRunning(taskId?: number): this is ITaskSequentializerWithRunningTask; get running(): Promise | undefined; cancelRunning(): void; run(taskId: number, promise: Promise, onCancel?: () => void): Promise; private doneRunning; private runQueued; /** * Note: the promise to schedule as next run MUST itself call `run`. * Otherwise, this sequentializer will report `false` for `isRunning` * even when this task is running. Missing this detail means that * suddenly multiple tasks will run in parallel. */ queue(run: ITask>): Promise; hasQueued(): this is ITaskSequentializerWithQueuedTask; join(): Promise; } /** * The `IntervalCounter` allows to count the number * of calls to `increment()` over a duration of * `interval`. This utility can be used to conditionally * throttle a frequent task when a certain threshold * is reached. */ export declare class IntervalCounter { private readonly interval; private readonly nowFn; private lastIncrementTime; private value; constructor(interval: number, nowFn?: () => number); increment(): number; } export type ValueCallback = (value: T | Promise) => void; /** * Creates a promise whose resolution or rejection can be controlled imperatively. */ export declare class DeferredPromise { static fromPromise(promise: Promise): DeferredPromise; private completeCallback; private errorCallback; private outcome?; get isRejected(): boolean; get isResolved(): boolean; get isSettled(): boolean; get value(): T | undefined; readonly p: Promise; constructor(); complete(value: T): Promise; error(err: unknown): Promise; settleWith(promise: Promise): Promise; cancel(): Promise; } export declare namespace Promises { /** * A drop-in replacement for `Promise.all` with the only difference * that the method awaits every promise to either fulfill or reject. * * Similar to `Promise.all`, only the first error will be returned * if any. */ function settled(promises: Promise[]): Promise; /** * A helper to create a new `Promise` with a body that is a promise * itself. By default, an error that raises from the async body will * end up as a unhandled rejection, so this utility properly awaits the * body and rejects the promise as a normal promise does without async * body. * * This method should only be used in rare cases where otherwise `async` * cannot be used (e.g. when callbacks are involved that require this). */ function withAsyncBody(bodyFn: (resolve: (value: T) => unknown, reject: (error: E) => unknown) => Promise): Promise; } export declare class StatefulPromise { private _value; get value(): T | undefined; private _error; get error(): unknown; private _isResolved; get isResolved(): boolean; readonly promise: Promise; constructor(promise: Promise); /** * Returns the resolved value. * Throws if the promise is not resolved yet. */ requireValue(): T; } export declare class LazyStatefulPromise { private readonly _compute; private readonly _promise; constructor(_compute: () => Promise); /** * Returns the resolved value. * Throws if the promise is not resolved yet. */ requireValue(): T; /** * Returns the promise (and triggers a computation of the promise if not yet done so). */ getPromise(): Promise; /** * Reads the current value without triggering a computation of the promise. */ get currentValue(): T | undefined; } /** * An object that allows to emit async values asynchronously or bring the iterable to an error state using `reject()`. * This emitter is valid only for the duration of the executor (until the promise returned by the executor settles). */ export interface AsyncIterableEmitter { /** * The value will be appended at the end. * * **NOTE** If `reject()` has already been called, this method has no effect. */ emitOne(value: T): void; /** * The values will be appended at the end. * * **NOTE** If `reject()` has already been called, this method has no effect. */ emitMany(values: T[]): void; /** * Writing an error will permanently invalidate this iterable. * The current users will receive an error thrown, as will all future users. * * **NOTE** If `reject()` have already been called, this method has no effect. */ reject(error: Error): void; } /** * An executor for the `AsyncIterableObject` that has access to an emitter. */ export interface AsyncIterableExecutor { /** * @param emitter An object that allows to emit async values valid only for the duration of the executor. */ (emitter: AsyncIterableEmitter): unknown | Promise; } /** * A rich implementation for an `AsyncIterable`. */ export declare class AsyncIterableObject implements AsyncIterable { static fromArray(items: T[]): AsyncIterableObject; static fromPromise(promise: Promise): AsyncIterableObject; static fromPromisesResolveOrder(promises: Promise[]): AsyncIterableObject; static merge(iterables: AsyncIterable[]): AsyncIterableObject; static EMPTY: AsyncIterableObject; private _state; private _results; private _error; private readonly _onReturn?; private readonly _onStateChanged; constructor(executor: AsyncIterableExecutor, onReturn?: () => void | Promise); [Symbol.asyncIterator](): AsyncIterator; static map(iterable: AsyncIterable, mapFn: (item: T) => R): AsyncIterableObject; map(mapFn: (item: T) => R): AsyncIterableObject; static filter(iterable: AsyncIterable, filterFn: (item: T) => boolean): AsyncIterableObject; filter(filterFn: (item: T) => item is T2): AsyncIterableObject; filter(filterFn: (item: T) => boolean): AsyncIterableObject; static coalesce(iterable: AsyncIterable): AsyncIterableObject; coalesce(): AsyncIterableObject>; static toPromise(iterable: AsyncIterable): Promise; toPromise(): Promise; /** * The value will be appended at the end. * * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect. */ private emitOne; /** * The values will be appended at the end. * * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect. */ private emitMany; /** * Calling `resolve()` will mark the result array as complete. * * **NOTE** `resolve()` must be called, otherwise all consumers of this iterable will hang indefinitely, similar to a non-resolved promise. * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect. */ private resolve; /** * Writing an error will permanently invalidate this iterable. * The current users will receive an error thrown, as will all future users. * * **NOTE** If `resolve()` or `reject()` have already been called, this method has no effect. */ private reject; } export declare function createCancelableAsyncIterableProducer(callback: (token: CancellationToken) => AsyncIterable): CancelableAsyncIterableProducer; export declare class AsyncIterableSource { private readonly _deferred; private readonly _asyncIterable; private _errorFn; private _emitOneFn; private _emitManyFn; /** * * @param onReturn A function that will be called when consuming the async iterable * has finished by the consumer, e.g the for-await-loop has be existed (break, return) early. * This is NOT called when resolving this source by its owner. */ constructor(onReturn?: () => Promise | void); get asyncIterable(): AsyncIterableObject; resolve(): void; reject(error: Error): void; emitOne(item: T): void; emitMany(items: T[]): void; } export declare function cancellableIterable(iterableOrIterator: AsyncIterator | AsyncIterable, token: CancellationToken): AsyncIterableIterator; /** * Important difference to AsyncIterableObject: * If it is iterated two times, the second iterator will not see the values emitted by the first iterator. */ export declare class AsyncIterableProducer implements AsyncIterable { private readonly _onReturn?; private readonly _producerConsumer; constructor(executor: AsyncIterableExecutor, _onReturn?: (() => void) | undefined); static fromArray(items: T[]): AsyncIterableProducer; static fromPromise(promise: Promise): AsyncIterableProducer; static fromPromisesResolveOrder(promises: Promise[]): AsyncIterableProducer; static merge(iterables: AsyncIterable[]): AsyncIterableProducer; static EMPTY: AsyncIterableProducer; static map(iterable: AsyncIterable, mapFn: (item: T) => R): AsyncIterableProducer; static tee(iterable: AsyncIterable): [ AsyncIterableProducer, AsyncIterableProducer ]; map(mapFn: (item: T) => R): AsyncIterableProducer; static coalesce(iterable: AsyncIterable): AsyncIterableProducer; coalesce(): AsyncIterableProducer>; static filter(iterable: AsyncIterable, filterFn: (item: T) => boolean): AsyncIterableProducer; filter(filterFn: (item: T) => item is T2): AsyncIterableProducer; filter(filterFn: (item: T) => boolean): AsyncIterableProducer; private _finishOk; private _finishError; private readonly _iterator; [Symbol.asyncIterator](): AsyncIterator; } export declare class CancelableAsyncIterableProducer extends AsyncIterableProducer { private readonly _source; constructor(_source: CancellationTokenSource, executor: AsyncIterableExecutor); cancel(): void; } export declare const AsyncReaderEndOfStream: unique symbol; export declare class AsyncReader { private readonly _source; private _buffer; private _atEnd; get endOfStream(): boolean; private _extendBufferPromise; constructor(_source: AsyncIterator); read(): Promise; readWhile(predicate: (value: T) => boolean, callback: (element: T) => unknown): Promise; readBufferedOrThrow(): T | typeof AsyncReaderEndOfStream; consumeToEnd(): Promise; peek(): Promise; peekBufferedOrThrow(): T | typeof AsyncReaderEndOfStream; peekTimeout(timeoutMs: number): Promise; private _extendBuffer; } export {};