UNPKG

@theia/core

Version:

Theia is a cloud & desktop IDE framework implemented in TypeScript.

120 lines (114 loc) 5.61 kB
// ***************************************************************************** // Copyright (C) 2025 1C-Soft LLC and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // copied and modified from https://github.com/microsoft/vscode/blob/1.96.3/src/vs/base/common/observableInternal/utils.ts, // https://github.com/microsoft/vscode/blob/1.96.3/src/vs/base/common/observableInternal/utilsCancellation.ts import { CancellationError, CancellationToken } from '../cancellation'; import { Disposable, DisposableCollection } from '../disposable'; import { Observable } from './observable-base'; import { DerivedObservable } from './derived-observable'; import { Autorun } from './autorun'; export namespace ObservableUtils { /** * Creates an {@link Autorun.create autorun} that passes a collector for disposable objects to the {@link run} function. * The collected disposables are disposed before the next run or when the autorun is disposed. */ export function autorunWithDisposables<TChangeSummary = void>( run: (args: Autorun.Args<TChangeSummary> & { readonly toDispose: { push(disposable: Disposable): void } }) => void, options?: Autorun.Options<TChangeSummary> ): Disposable { let toDispose: DisposableCollection | undefined = undefined; return new class extends Autorun<TChangeSummary> { override dispose(): void { super.dispose(); toDispose?.dispose(); } }( ({ autorun, isFirstRun, changeSummary }) => { toDispose?.dispose(); toDispose = new DisposableCollection(); run({ toDispose, autorun, isFirstRun, changeSummary }); }, options ); } export function derivedObservableWithCache<T, TChangeSummary = void>( compute: (args: DerivedObservable.Args<TChangeSummary> & { readonly lastValue: T | undefined }) => T, options?: DerivedObservable.Options<T, TChangeSummary> ): Observable<T, void> { let value: T | undefined = undefined; return new DerivedObservable( ({ changeSummary }) => { value = compute({ lastValue: value, changeSummary }); return value; }, options ); } /** * Resolves the promise when the observable's state matches the predicate. */ export function waitForState<T>(observable: Observable<T | undefined>): Promise<T>; export function waitForState<T, TState extends T>(observable: Observable<T>, predicate: (state: T) => state is TState, isError?: (state: T) => boolean | unknown | undefined, cancellationToken?: CancellationToken ): Promise<TState>; export function waitForState<T>(observable: Observable<T>, predicate: (state: T) => boolean, isError?: (state: T) => boolean | unknown | undefined, cancellationToken?: CancellationToken ): Promise<T>; export function waitForState<T>(observable: Observable<T>, predicate?: (state: T) => boolean, isError?: (state: T) => boolean | unknown | undefined, cancellationToken?: CancellationToken ): Promise<T> { if (!predicate) { predicate = state => !!state; } return new Promise((resolve, reject) => { const stateObservable = DerivedObservable.create(() => { const state = observable.get(); return { isFinished: predicate(state), error: isError ? isError(state) : false, state }; }); const autorun_ = Autorun.create(({ autorun }) => { const { isFinished, error, state } = stateObservable.get(); if (isFinished || error) { autorun.dispose(); if (error) { reject(error === true ? state : error); } else { resolve(state); } } }); if (cancellationToken) { const subscription = cancellationToken.onCancellationRequested(() => { autorun_.dispose(); subscription.dispose(); reject(new CancellationError()); }); if (cancellationToken.isCancellationRequested) { autorun_.dispose(); subscription.dispose(); reject(new CancellationError()); } } }); } }