Add WindowIdleValue and GlobalIdleValue, likewise runWhenGlobalIdle and runWhenWindowIdle. (#197721)

* Add WindowIdleValue and GlobalIdleValue, likewise runWhenGlobalIdle and runWhenWindowIdle.

Define window things inside dom.ts for more clarity and more correct layering.

Duplicate API definition for idle so that things compile standalone

fixes https://github.com/microsoft/vscode/issues/197661

* fix compile errors

* make treeshaker happy, use correct types
This commit is contained in:
Johannes Rieken 2023-11-08 15:20:40 +01:00 committed by GitHub
parent 3f0f51bde0
commit dff4173df4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 143 additions and 93 deletions

20
src/typings/base-common.d.ts vendored Normal file
View file

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// Declare types that we probe for to implement util and/or polyfill functions
declare global {
interface IdleDeadline {
readonly didTimeout: boolean;
timeRemaining(): number;
}
function requestIdleCallback(callback: (args: IdleDeadline) => void, options?: { timeout: number }): number;
function cancelIdleCallback(handle: number): void;
}
export { }

View file

@ -7,7 +7,7 @@ import * as browser from 'vs/base/browser/browser';
import { BrowserFeatures } from 'vs/base/browser/canIUse';
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { TimeoutTimer } from 'vs/base/common/async';
import { AbstractIdleValue, TimeoutTimer, _runWhenIdle, IdleDeadline } from 'vs/base/common/async';
import { onUnexpectedError } from 'vs/base/common/errors';
import * as event from 'vs/base/common/event';
import * as dompurify from 'vs/base/browser/dompurify/dompurify';
@ -178,6 +178,41 @@ export function addDisposableGenericMouseUpListener(node: EventTarget, handler:
return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_UP : EventType.MOUSE_UP, handler, useCapture);
}
/**
* 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 targetWindow The window for which to run the idle callback
* @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
*/
export function runWhenWindowIdle(targetWindow: Window | typeof globalThis, callback: (idle: IdleDeadline) => void, timeout?: number): IDisposable {
return _runWhenIdle(targetWindow, callback, timeout);
}
/**
* An implementation of the "idle-until-urgent"-strategy as introduced
* here: https://philipwalton.com/articles/idle-until-urgent/
*/
export class WindowIdleValue<T> extends AbstractIdleValue<T> {
constructor(targetWindow: Window | typeof globalThis, executor: () => T) {
super(targetWindow, executor);
}
}
/**
* Schedule a callback to be run at the next animation frame.
* This allows multiple parties to register callbacks that should run at the next animation frame.

View file

@ -1219,6 +1219,9 @@ export interface IdleDeadline {
timeRemaining(): number;
}
type IdleApi = Pick<typeof globalThis, 'requestIdleCallback' | 'cancelIdleCallback'>;
/**
* Execute the callback the next time the browser is idle, returning an
* {@link IDisposable} that will cancel the callback when disposed. This wraps
@ -1236,31 +1239,29 @@ export interface IdleDeadline {
* [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 let runWhenIdle: (targetWindow: typeof globalThis, callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable;
export let runWhenGlobalIdle: (callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable;
/**
* @deprecated use `runWhenIdle` instead passing in the target window
*/
export let globalRunWhenIdle: (callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable;
declare function requestIdleCallback(callback: (args: IdleDeadline) => void, options?: { timeout: number }): number;
declare function cancelIdleCallback(handle: number): void;
export let _runWhenIdle: (targetWindow: IdleApi, callback: (idle: IdleDeadline) => void, timeout?: number) => IDisposable;
(function () {
if (typeof requestIdleCallback !== 'function' || typeof cancelIdleCallback !== 'function') {
runWhenIdle = (targetWindow, runner) => {
if (typeof globalThis.requestIdleCallback !== 'function' || typeof globalThis.cancelIdleCallback !== 'function') {
_runWhenIdle = (_targetWindow, runner) => {
setTimeout0(() => {
if (disposed) {
return;
}
const end = Date.now() + 15; // one frame at 64fps
runner(Object.freeze({
const deadline: IdleDeadline = {
didTimeout: true,
timeRemaining() {
return Math.max(0, end - Date.now());
}
}));
};
runner(Object.freeze(deadline));
});
let disposed = false;
return {
@ -1273,7 +1274,7 @@ declare function cancelIdleCallback(handle: number): void;
};
};
} else {
runWhenIdle = (targetWindow: any, runner, timeout?) => {
_runWhenIdle = (targetWindow: IdleApi, runner, timeout?) => {
const handle: number = targetWindow.requestIdleCallback(runner, typeof timeout === 'number' ? { timeout } : undefined);
let disposed = false;
return {
@ -1287,14 +1288,10 @@ declare function cancelIdleCallback(handle: number): void;
};
};
}
globalRunWhenIdle = (runner) => runWhenIdle(globalThis, runner);
runWhenGlobalIdle = (runner) => _runWhenIdle(globalThis, runner);
})();
/**
* An implementation of the "idle-until-urgent"-strategy as introduced
* here: https://philipwalton.com/articles/idle-until-urgent/
*/
export class IdleValue<T> {
export abstract class AbstractIdleValue<T> {
private readonly _executor: () => void;
private readonly _handle: IDisposable;
@ -1303,7 +1300,7 @@ export class IdleValue<T> {
private _value?: T;
private _error: unknown;
constructor(targetWindow: typeof globalThis, executor: () => T) {
constructor(targetWindow: IdleApi, executor: () => T) {
this._executor = () => {
try {
this._value = executor();
@ -1313,7 +1310,7 @@ export class IdleValue<T> {
this._didRun = true;
}
};
this._handle = runWhenIdle(targetWindow, () => this._executor());
this._handle = _runWhenIdle(targetWindow, () => this._executor());
}
dispose(): void {
@ -1337,9 +1334,12 @@ export class IdleValue<T> {
}
/**
* @deprecated use `IdleValue` instead passing in the target window
* 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 class GlobalIdleValue<T> extends IdleValue<T> {
export class GlobalIdleValue<T> extends AbstractIdleValue<T> {
constructor(executor: () => T) {
super(globalThis, executor);

View file

@ -104,7 +104,7 @@ import { IExtensionsScannerService } from 'vs/platform/extensionManagement/commo
import { ExtensionsScannerService } from 'vs/platform/extensionManagement/node/extensionsScannerService';
import { UserDataProfilesHandler } from 'vs/platform/userDataProfile/electron-main/userDataProfilesHandler';
import { ProfileStorageChangesListenerChannel } from 'vs/platform/userDataProfile/electron-main/userDataProfileStorageIpc';
import { Promises, RunOnceScheduler, runWhenIdle } from 'vs/base/common/async';
import { Promises, RunOnceScheduler, runWhenGlobalIdle } from 'vs/base/common/async';
import { resolveMachineId, resolveSqmId } from 'vs/platform/telemetry/electron-main/telemetryUtils';
import { ExtensionsProfileScannerService } from 'vs/platform/extensionManagement/node/extensionsProfileScannerService';
import { LoggerChannel } from 'vs/platform/log/electron-main/logIpc';
@ -624,7 +624,7 @@ export class CodeApplication extends Disposable {
// Set lifecycle phase to `Eventually` after a short delay and when idle (min 2.5sec, max 5sec)
const eventuallyPhaseScheduler = this._register(new RunOnceScheduler(() => {
this._register(runWhenIdle(globalThis, () => this.lifecycleMainService.phase = LifecycleMainPhase.Eventually, 2500));
this._register(runWhenGlobalIdle(() => this.lifecycleMainService.phase = LifecycleMainPhase.Eventually, 2500));
}, 2500));
eventuallyPhaseScheduler.schedule();
}

View file

@ -3,8 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { getWindow } from 'vs/base/browser/dom';
import { runWhenIdle } from 'vs/base/common/async';
import { getWindow, runWhenWindowIdle } from 'vs/base/browser/dom';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, DisposableMap } from 'vs/base/common/lifecycle';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
@ -58,21 +57,21 @@ export class CodeEditorContributions extends Disposable {
// AfterFirstRender
// - these extensions will be instantiated at the latest 50ms after the first render.
// - but if there is idle time, we will instantiate them sooner.
this._register(runWhenIdle(getWindow(this._editor.getDomNode()), () => {
this._register(runWhenWindowIdle(getWindow(this._editor.getDomNode()), () => {
this._instantiateSome(EditorContributionInstantiation.AfterFirstRender);
}));
// BeforeFirstInteraction
// - these extensions will be instantiated at the latest before a mouse or a keyboard event.
// - but if there is idle time, we will instantiate them sooner.
this._register(runWhenIdle(getWindow(this._editor.getDomNode()), () => {
this._register(runWhenWindowIdle(getWindow(this._editor.getDomNode()), () => {
this._instantiateSome(EditorContributionInstantiation.BeforeFirstInteraction);
}));
// Eventually
// - these extensions will only be instantiated when there is idle time.
// - since there is no guarantee that there will ever be idle time, we set a timeout of 5s here.
this._register(runWhenIdle(getWindow(this._editor.getDomNode()), () => {
this._register(runWhenWindowIdle(getWindow(this._editor.getDomNode()), () => {
this._instantiateSome(EditorContributionInstantiation.Eventually);
}, 5000));
}
@ -113,7 +112,7 @@ export class CodeEditorContributions extends Disposable {
}
public onAfterModelAttached(): void {
this._register(runWhenIdle(getWindow(this._editor?.getDomNode()), () => {
this._register(runWhenWindowIdle(getWindow(this._editor?.getDomNode()), () => {
this._instantiateSome(EditorContributionInstantiation.AfterFirstRender);
}, 50));
}

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IdleDeadline, globalRunWhenIdle } from 'vs/base/common/async';
import { IdleDeadline, runWhenGlobalIdle } from 'vs/base/common/async';
import { BugIndicatingError, onUnexpectedError } from 'vs/base/common/errors';
import { setTimeout0 } from 'vs/base/common/platform';
import { StopWatch } from 'vs/base/common/stopwatch';
@ -462,7 +462,7 @@ export class DefaultBackgroundTokenizer implements IBackgroundTokenizer {
}
this._isScheduled = true;
globalRunWhenIdle((deadline) => {
runWhenGlobalIdle((deadline) => {
this._isScheduled = false;
this._backgroundTokenizeWithDeadline(deadline);

View file

@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { runWhenIdle } from 'vs/base/common/async';
import { Event } from 'vs/base/common/event';
import { LRUCache } from 'vs/base/common/map';
import { Range } from 'vs/editor/common/core/range';
@ -14,6 +13,7 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService, StorageScope, StorageTarget, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { $window } from 'vs/base/browser/window';
import { runWhenWindowIdle } from 'vs/base/browser/dom';
export const ICodeLensCache = createDecorator<ICodeLensCache>('ICodeLensCache');
@ -53,7 +53,7 @@ export class CodeLensCache implements ICodeLensCache {
// remove old data
const oldkey = 'codelens/cache';
runWhenIdle($window, () => storageService.remove(oldkey, StorageScope.WORKSPACE));
runWhenWindowIdle($window, () => storageService.remove(oldkey, StorageScope.WORKSPACE));
// restore lens data on start
const key = 'codelens/cache2';

View file

@ -5,7 +5,6 @@
import { alert } from 'vs/base/browser/ui/aria/aria';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { IdleValue } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { onUnexpectedError, onUnexpectedExternalError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
@ -45,7 +44,7 @@ import { ISelectedSuggestion, SuggestWidget } from './suggestWidget';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { basename, extname } from 'vs/base/common/resources';
import { hash } from 'vs/base/common/hash';
import { getWindow } from 'vs/base/browser/dom';
import { WindowIdleValue, getWindow } from 'vs/base/browser/dom';
// sticky suggest widget which doesn't disappear on focus out and such
const _sticky = false
@ -112,12 +111,12 @@ export class SuggestController implements IEditorContribution {
readonly editor: ICodeEditor;
readonly model: SuggestModel;
readonly widget: IdleValue<SuggestWidget>;
readonly widget: WindowIdleValue<SuggestWidget>;
private readonly _alternatives: IdleValue<SuggestAlternatives>;
private readonly _alternatives: WindowIdleValue<SuggestAlternatives>;
private readonly _lineSuffix = new MutableDisposable<LineSuffix>();
private readonly _toDispose = new DisposableStore();
private readonly _overtypingCapturer: IdleValue<OvertypingCapturer>;
private readonly _overtypingCapturer: WindowIdleValue<OvertypingCapturer>;
private readonly _selectors = new PriorityRegistry<ISuggestItemPreselector>(s => s.priority);
private readonly _onWillInsertSuggestItem = new Emitter<{ item: CompletionItem }>();
@ -146,7 +145,7 @@ export class SuggestController implements IEditorContribution {
ctxInsertMode.set(editor.getOption(EditorOption.suggest).insertMode);
this._toDispose.add(this.model.onDidTrigger(() => ctxInsertMode.set(editor.getOption(EditorOption.suggest).insertMode)));
this.widget = this._toDispose.add(new IdleValue(getWindow(editor.getDomNode()), () => {
this.widget = this._toDispose.add(new WindowIdleValue(getWindow(editor.getDomNode()), () => {
const widget = this._instantiationService.createInstance(SuggestWidget, this.editor);
@ -219,11 +218,11 @@ export class SuggestController implements IEditorContribution {
}));
// Wire up text overtyping capture
this._overtypingCapturer = this._toDispose.add(new IdleValue(getWindow(editor.getDomNode()), () => {
this._overtypingCapturer = this._toDispose.add(new WindowIdleValue(getWindow(editor.getDomNode()), () => {
return this._toDispose.add(new OvertypingCapturer(this.editor, this.model));
}));
this._alternatives = this._toDispose.add(new IdleValue(getWindow(editor.getDomNode()), () => {
this._alternatives = this._toDispose.add(new WindowIdleValue(getWindow(editor.getDomNode()), () => {
return this._toDispose.add(new SuggestAlternatives(this.editor, this._contextKeyService));
}));

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Promises, RunOnceScheduler, globalRunWhenIdle } from 'vs/base/common/async';
import { Promises, RunOnceScheduler, runWhenGlobalIdle } from 'vs/base/common/async';
import { Emitter, Event, PauseableEmitter } from 'vs/base/common/event';
import { Disposable, DisposableStore, dispose, MutableDisposable } from 'vs/base/common/lifecycle';
import { mark } from 'vs/base/common/performance';
@ -343,7 +343,7 @@ export abstract class AbstractStorageService extends Disposable implements IStor
}
private doFlushWhenIdle(): void {
this.runFlushWhenIdle.value = globalRunWhenIdle(() => {
this.runFlushWhenIdle.value = runWhenGlobalIdle(() => {
if (this.shouldFlushWhenIdle()) {
this.flush();
}

View file

@ -32,14 +32,14 @@ import { ResourcesDropHandler, DraggedEditorIdentifier, DraggedEditorGroupIdenti
import { Color } from 'vs/base/common/color';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { MergeGroupMode, IMergeGroupOptions, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { addDisposableListener, EventType, EventHelper, Dimension, scheduleAtNextAnimationFrame, findParentWithClass, clearNode, DragAndDropObserver, isMouseEvent, getWindow } from 'vs/base/browser/dom';
import { addDisposableListener, EventType, EventHelper, Dimension, scheduleAtNextAnimationFrame, findParentWithClass, clearNode, DragAndDropObserver, isMouseEvent, getWindow, runWhenWindowIdle } from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import { IEditorGroupsView, EditorServiceImpl, IEditorGroupView, IInternalEditorOpenOptions, IEditorPartsView } from 'vs/workbench/browser/parts/editor/editor';
import { CloseOneEditorAction, UnpinEditorAction } from 'vs/workbench/browser/parts/editor/editorActions';
import { assertAllDefined, assertIsDefined } from 'vs/base/common/types';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { basenameOrAuthority } from 'vs/base/common/resources';
import { RunOnceScheduler, runWhenIdle } from 'vs/base/common/async';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { IPath, win32, posix } from 'vs/base/common/path';
import { coalesce, insert } from 'vs/base/common/arrays';
@ -1618,7 +1618,7 @@ export class MultiEditorTabsControl extends EditorTabsControl {
if (this.lifecycleService.phase >= LifecyclePhase.Restored) {
scheduledLayout = scheduleAtNextAnimationFrame(getWindow(this.tabsContainer), layoutFunction);
} else {
scheduledLayout = runWhenIdle(getWindow(this.tabsContainer), layoutFunction);
scheduledLayout = runWhenWindowIdle(getWindow(this.tabsContainer), layoutFunction);
}
this.layoutScheduler.value = { options, dispose: () => scheduledLayout.dispose() };

View file

@ -18,12 +18,11 @@ import { ThemeIcon } from 'vs/base/common/themables';
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
import { Action, IAction, Separator, SubmenuAction, toAction } from 'vs/base/common/actions';
import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { addDisposableListener, EventType, append, clearNode, hide, show, EventHelper, $ } from 'vs/base/browser/dom';
import { addDisposableListener, EventType, append, clearNode, hide, show, EventHelper, $, runWhenWindowIdle } from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
import { AnchorAlignment, AnchorAxisAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { runWhenIdle } from 'vs/base/common/async';
import { Lazy } from 'vs/base/common/lazy';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@ -355,7 +354,7 @@ export class AccountsActivityActionViewItem extends AbstractGlobalActivityAction
if (this._store.isDisposed) {
return;
}
const disposable = this._register(runWhenIdle($window, async () => {
const disposable = this._register(runWhenWindowIdle($window, async () => {
await this.doInitialize();
disposable.dispose();
}));

View file

@ -5,9 +5,9 @@
import 'vs/workbench/browser/style';
import { localize } from 'vs/nls';
import { addDisposableListener } from 'vs/base/browser/dom';
import { addDisposableListener, runWhenWindowIdle } from 'vs/base/browser/dom';
import { Event, Emitter, setGlobalLeakWarningThreshold } from 'vs/base/common/event';
import { RunOnceScheduler, runWhenIdle, timeout } from 'vs/base/common/async';
import { RunOnceScheduler, timeout } from 'vs/base/common/async';
import { isFirefox, isSafari, isChrome, PixelRatio } from 'vs/base/browser/browser';
import { mark } from 'vs/base/common/performance';
import { onUnexpectedError, setUnexpectedErrorHandler } from 'vs/base/common/errors';
@ -451,7 +451,7 @@ export class Workbench extends Layout {
// Set lifecycle phase to `Eventually` after a short delay and when idle (min 2.5sec, max 5sec)
const eventuallyPhaseScheduler = this._register(new RunOnceScheduler(() => {
this._register(runWhenIdle(mainWindow, () => lifecycleService.phase = LifecyclePhase.Eventually, 2500));
this._register(runWhenWindowIdle(mainWindow, () => lifecycleService.phase = LifecyclePhase.Eventually, 2500));
}, 2500));
eventuallyPhaseScheduler.schedule();
})

View file

@ -6,7 +6,7 @@
import { IInstantiationService, IConstructorSignature, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
import { globalRunWhenIdle, IdleDeadline, DeferredPromise } from 'vs/base/common/async';
import { IdleDeadline, DeferredPromise, runWhenGlobalIdle } from 'vs/base/common/async';
import { mark } from 'vs/base/common/performance';
import { ILogService } from 'vs/platform/log/common/log';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@ -155,7 +155,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
this.safeCreateContribution(instantiationService, logService, environmentService, contribution, phase);
if (idle.timeRemaining() < 1) {
// time is up -> reschedule
globalRunWhenIdle(instantiateSome, forcedTimeout);
runWhenGlobalIdle(instantiateSome, forcedTimeout);
break;
}
}
@ -169,7 +169,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
}
};
globalRunWhenIdle(instantiateSome, forcedTimeout);
runWhenGlobalIdle(instantiateSome, forcedTimeout);
}
private safeCreateContribution(instantiationService: IInstantiationService, logService: ILogService, environmentService: IEnvironmentService, contribution: IConstructorSignature<IWorkbenchContribution>, phase: LifecyclePhase): void {

View file

@ -19,7 +19,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { MarkerSeverity } from 'vs/platform/markers/common/markers';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { listErrorForeground, listWarningForeground } from 'vs/platform/theme/common/colorRegistry';
import { IdleValue } from 'vs/base/common/async';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration';
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IOutlineComparator, OutlineConfigKeys } from 'vs/workbench/services/outline/browser/outline';
@ -252,7 +251,7 @@ export class DocumentSymbolFilter implements ITreeFilter<DocumentSymbolItem> {
export class DocumentSymbolComparator implements IOutlineComparator<DocumentSymbolItem> {
private readonly _collator = new IdleValue<Intl.Collator>(mainWindow, () => new Intl.Collator(undefined, { numeric: true }));
private readonly _collator = new dom.WindowIdleValue<Intl.Collator>(mainWindow, () => new Intl.Collator(undefined, { numeric: true }));
compareByPosition(a: DocumentSymbolItem, b: DocumentSymbolItem): number {
if (a instanceof OutlineGroup && b instanceof OutlineGroup) {

View file

@ -8,7 +8,6 @@ import { IIconLabelValueOptions, IconLabel } from 'vs/base/browser/ui/iconLabel/
import { IKeyboardNavigationLabelProvider, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IDataSource, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree';
import { IdleValue } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { FuzzyScore, createMatches } from 'vs/base/common/filters';
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
@ -38,6 +37,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IModelDeltaDecoration } from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
import { mainWindow } from 'vs/base/browser/window';
import { WindowIdleValue } from 'vs/base/browser/dom';
class NotebookOutlineTemplate {
@ -178,7 +178,7 @@ class NotebookQuickPickProvider implements IQuickPickDataSource<OutlineEntry> {
class NotebookComparator implements IOutlineComparator<OutlineEntry> {
private readonly _collator = new IdleValue<Intl.Collator>(mainWindow, () => new Intl.Collator(undefined, { numeric: true }));
private readonly _collator = new WindowIdleValue<Intl.Collator>(mainWindow, () => new Intl.Collator(undefined, { numeric: true }));
compareByPosition(a: OutlineEntry, b: OutlineEntry): number {
return a.index - b.index;

View file

@ -21,7 +21,7 @@ import { PixelRatio } from 'vs/base/browser/browser';
import * as DOM from 'vs/base/browser/dom';
import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
import { DeferredPromise, runWhenIdle, SequencerByKey } from 'vs/base/common/async';
import { DeferredPromise, SequencerByKey } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Color, RGBA } from 'vs/base/common/color';
import { onUnexpectedError } from 'vs/base/common/errors';
@ -1154,7 +1154,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
}
this._backgroundMarkdownRenderRunning = true;
runWhenIdle(DOM.getWindow(this._body), (deadline) => {
DOM.runWhenWindowIdle(DOM.getWindow(this._body), (deadline) => {
this._backgroundMarkdownRenderingWithDeadline(deadline);
});
}

View file

@ -11,13 +11,13 @@ import { LRUCache, ResourceMap } from 'vs/base/common/map';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { URI } from 'vs/base/common/uri';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { runWhenIdle } from 'vs/base/common/async';
import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IAction } from 'vs/base/common/actions';
import { MarshalledId } from 'vs/base/common/marshallingIds';
import { Schemas } from 'vs/base/common/network';
import { $window } from 'vs/base/browser/window';
import { runWhenWindowIdle } from 'vs/base/browser/dom';
class KernelInfo {
@ -169,7 +169,7 @@ export class NotebookKernelService extends Disposable implements INotebookKernel
private _persistMementos(): void {
this._persistSoonHandle?.dispose();
this._persistSoonHandle = runWhenIdle($window, () => {
this._persistSoonHandle = runWhenWindowIdle($window, () => {
this._storageService.store(NotebookKernelService._storageNotebookBinding, JSON.stringify(this._notebookBindings), StorageScope.WORKSPACE, StorageTarget.MACHINE);
}, 100);
}

View file

@ -6,7 +6,7 @@
import * as osPath from 'vs/base/common/path';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { coalesce } from 'vs/base/common/arrays';
import { DeferredPromise, globalRunWhenIdle } from 'vs/base/common/async';
import { DeferredPromise, runWhenGlobalIdle } from 'vs/base/common/async';
import { decodeBase64 } from 'vs/base/common/buffer';
import { Emitter, Event } from 'vs/base/common/event';
import { getExtensionForMimeType } from 'vs/base/common/mime';
@ -1436,7 +1436,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
return;
}
this.pendingWebviewIdleCreationRequest.set(content.source, globalRunWhenIdle(() => {
this.pendingWebviewIdleCreationRequest.set(content.source, runWhenGlobalIdle(() => {
const { message, renderer, transfer: transferable } = this._createOutputCreationMessage(cellInfo, content, cellTop, offset, true, true);
this._sendMessageToWebview(message, transferable);
this.pendingWebviewIdleInsetMapping.set(content.source, { outputId: message.outputId, versionId: content.source.model.versionId, cellInfo: cellInfo, renderer, cachedCreation: message });

View file

@ -11,13 +11,13 @@ import { KnownSnippetVariableNames } from 'vs/editor/contrib/snippet/browser/sni
import { URI } from 'vs/base/common/uri';
import { IFileService } from 'vs/platform/files/common/files';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IdleValue } from 'vs/base/common/async';
import { IExtensionResourceLoaderService } from 'vs/platform/extensionResourceLoader/common/extensionResourceLoader';
import { relativePath } from 'vs/base/common/resources';
import { isObject } from 'vs/base/common/types';
import { tail } from 'vs/base/common/arrays';
import { Iterable } from 'vs/base/common/iterator';
import { $window } from 'vs/base/browser/window';
import { WindowIdleValue } from 'vs/base/browser/dom';
class SnippetBodyInsights {
@ -101,7 +101,7 @@ class SnippetBodyInsights {
export class Snippet {
private readonly _bodyInsights: IdleValue<SnippetBodyInsights>;
private readonly _bodyInsights: WindowIdleValue<SnippetBodyInsights>;
readonly prefixLow: string;
@ -118,7 +118,7 @@ export class Snippet {
readonly extensionId?: ExtensionIdentifier,
) {
this.prefixLow = prefix.toLowerCase();
this._bodyInsights = new IdleValue($window, () => new SnippetBodyInsights(this.body));
this._bodyInsights = new WindowIdleValue($window, () => new SnippetBodyInsights(this.body));
}
get codeSnippet(): string {

View file

@ -18,7 +18,6 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import * as perf from 'vs/base/common/performance';
import { assertIsDefined } from 'vs/base/common/types';
import { runWhenIdle } from 'vs/base/common/async';
import { ISplashStorageService } from 'vs/workbench/contrib/splash/browser/splash';
import { mainWindow } from 'vs/base/browser/window';
@ -46,7 +45,7 @@ export class PartsSplash {
let lastIdleSchedule: IDisposable | undefined;
Event.any(onDidChangeFullscreen, editorGroupsService.mainPart.onDidLayout, _themeService.onDidColorThemeChange)(() => {
lastIdleSchedule?.dispose();
lastIdleSchedule = runWhenIdle(mainWindow, () => this._savePartsSplash(), 800);
lastIdleSchedule = dom.runWhenWindowIdle(mainWindow, () => this._savePartsSplash(), 800);
}, undefined, this._disposables);
_configService.onDidChangeConfiguration(e => {

View file

@ -38,8 +38,8 @@ import Severity from 'vs/base/common/severity';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IEnvironmentVariableCollection, IMergedEnvironmentVariableCollection } from 'vs/platform/terminal/common/environmentVariable';
import { generateUuid } from 'vs/base/common/uuid';
import { runWhenIdle } from 'vs/base/common/async';
import { $window } from 'vs/base/browser/window';
import { runWhenWindowIdle } from 'vs/base/browser/dom';
const enum ProcessConstants {
/**
@ -395,7 +395,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
}
// Report the latency to the pty host when idle
runWhenIdle($window, () => {
runWhenWindowIdle($window, () => {
this.backend?.getLatency().then(measurements => {
this._logService.info(`Latency measurements for ${this.remoteAuthority ?? 'local'} backend\n${measurements.map(e => `${e.label}: ${e.latency.toFixed(2)}ms`).join('\n')}`);
});

View file

@ -18,18 +18,18 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IdleValue } from 'vs/base/common/async';
import { IAuthenticationService } from 'vs/workbench/services/authentication/common/authentication';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { testUrlMatchesGlob } from 'vs/workbench/contrib/url/common/urlGlob';
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { $window } from 'vs/base/browser/window';
import { WindowIdleValue } from 'vs/base/browser/dom';
export class OpenerValidatorContributions implements IWorkbenchContribution {
private _readWorkspaceTrustedDomainsResult: IdleValue<Promise<string[]>>;
private _readAuthenticationTrustedDomainsResult: IdleValue<Promise<string[]>>;
private _readWorkspaceTrustedDomainsResult: WindowIdleValue<Promise<string[]>>;
private _readAuthenticationTrustedDomainsResult: WindowIdleValue<Promise<string[]>>;
constructor(
@IOpenerService private readonly _openerService: IOpenerService,
@ -48,19 +48,19 @@ export class OpenerValidatorContributions implements IWorkbenchContribution {
) {
this._openerService.registerValidator({ shouldOpen: (uri, options) => this.validateLink(uri, options) });
this._readAuthenticationTrustedDomainsResult = new IdleValue($window, () =>
this._readAuthenticationTrustedDomainsResult = new WindowIdleValue($window, () =>
this._instantiationService.invokeFunction(readAuthenticationTrustedDomains));
this._authenticationService.onDidRegisterAuthenticationProvider(() => {
this._readAuthenticationTrustedDomainsResult?.dispose();
this._readAuthenticationTrustedDomainsResult = new IdleValue($window, () =>
this._readAuthenticationTrustedDomainsResult = new WindowIdleValue($window, () =>
this._instantiationService.invokeFunction(readAuthenticationTrustedDomains));
});
this._readWorkspaceTrustedDomainsResult = new IdleValue($window, () =>
this._readWorkspaceTrustedDomainsResult = new WindowIdleValue($window, () =>
this._instantiationService.invokeFunction(readWorkspaceTrustedDomains));
this._workspaceContextService.onDidChangeWorkspaceFolders(() => {
this._readWorkspaceTrustedDomainsResult?.dispose();
this._readWorkspaceTrustedDomainsResult = new IdleValue($window, () =>
this._readWorkspaceTrustedDomainsResult = new WindowIdleValue($window, () =>
this._instantiationService.invokeFunction(readWorkspaceTrustedDomains));
});
}

View file

@ -8,7 +8,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ResourceMap } from 'vs/base/common/map';
import { equals } from 'vs/base/common/objects';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Queue, Barrier, runWhenIdle, Promises, Delayer } from 'vs/base/common/async';
import { Queue, Barrier, Promises, Delayer } from 'vs/base/common/async';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { IWorkspaceContextService, Workspace as BaseWorkspace, WorkbenchState, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkspaceFolder, toWorkspaceFolder, isWorkspaceFolder, IWorkspaceFoldersWillChangeEvent, IEmptyWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceIdentifier, IAnyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
import { ConfigurationModel, ConfigurationChangeEvent, mergeChanges } from 'vs/platform/configuration/common/configurationModels';
@ -46,6 +46,7 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration';
import { $window } from 'vs/base/browser/window';
import { runWhenWindowIdle } from 'vs/base/browser/dom';
function getLocalUserConfigurationScopes(userDataProfile: IUserDataProfile, hasRemote: boolean): ConfigurationScope[] | undefined {
return (userDataProfile.isDefault || userDataProfile.useDefaultFlags?.settings)
@ -577,7 +578,7 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat
if (!this.localUserConfiguration.hasTasksLoaded) {
// Reload local user configuration again to load user tasks
this._register(runWhenIdle($window, () => this.reloadLocalUserConfiguration(false, this._configuration.localUserConfiguration)));
this._register(runWhenWindowIdle($window, () => this.reloadLocalUserConfiguration(false, this._configuration.localUserConfiguration)));
}
}

View file

@ -3,8 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { runWhenWindowIdle } from 'vs/base/browser/dom';
import { $window } from 'vs/base/browser/window';
import { runWhenIdle } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Schemas } from 'vs/base/common/network';
import * as performance from 'vs/base/common/performance';
@ -135,7 +135,7 @@ export class NativeExtensionService extends AbstractExtensionService implements
// see https://github.com/microsoft/vscode/issues/41322
lifecycleService.when(LifecyclePhase.Ready).then(() => {
// reschedule to ensure this runs after restoring viewlets, panels, and editors
runWhenIdle($window, () => {
runWhenWindowIdle($window, () => {
this._initialize();
}, 50 /*max delay*/);
});

View file

@ -24,11 +24,10 @@ import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/la
import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { coalesce, remove } from 'vs/base/common/arrays';
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { addDisposableListener, EventType, EventHelper } from 'vs/base/browser/dom';
import { addDisposableListener, EventType, EventHelper, WindowIdleValue } from 'vs/base/browser/dom';
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { Schemas } from 'vs/base/common/network';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IdleValue } from 'vs/base/common/async';
import { ResourceGlobMatcher } from 'vs/workbench/common/resources';
import { IPathService } from 'vs/workbench/services/path/common/pathService';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
@ -753,7 +752,7 @@ export class HistoryService extends Disposable implements IHistoryService {
private readonly editorHistoryListeners = new Map<EditorInput, DisposableStore>();
private readonly resourceExcludeMatcher = this._register(new IdleValue(mainWindow, () => {
private readonly resourceExcludeMatcher = this._register(new WindowIdleValue(mainWindow, () => {
const matcher = this._register(this.instantiationService.createInstance(
ResourceGlobMatcher,
root => getExcludes(root ? this.configurationService.getValue<ISearchConfiguration>({ resource: root }) : this.configurationService.getValue<ISearchConfiguration>()) || Object.create(null),

View file

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { RunOnceScheduler, globalRunWhenIdle } from 'vs/base/common/async';
import { RunOnceScheduler, runWhenGlobalIdle } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
@ -60,7 +60,7 @@ export class UserActivityService extends Disposable implements IUserActivityServ
constructor(@IInstantiationService instantiationService: IInstantiationService) {
super();
this._register(globalRunWhenIdle(() => userActivityRegistry.take(this, instantiationService)));
this._register(runWhenGlobalIdle(() => userActivityRegistry.take(this, instantiationService)));
}
/** @inheritdoc */

View file

@ -5,7 +5,7 @@
import { localize } from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { IdleValue, Limiter } from 'vs/base/common/async';
import { GlobalIdleValue, Limiter } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { Disposable } from 'vs/base/common/lifecycle';
import { ResourceMap } from 'vs/base/common/map';
@ -37,7 +37,7 @@ export class WorkingCopyHistoryTracker extends Disposable implements IWorkbenchC
private readonly limiter = this._register(new Limiter(MAX_PARALLEL_HISTORY_IO_OPS));
private readonly resourceExcludeMatcher = this._register(new IdleValue(globalThis, () => {
private readonly resourceExcludeMatcher = this._register(new GlobalIdleValue(() => {
const matcher = this._register(new ResourceGlobMatcher(
root => this.configurationService.getValue(WorkingCopyHistoryTracker.SETTINGS.EXCLUDES, { resource: root }),
event => event.affectsConfiguration(WorkingCopyHistoryTracker.SETTINGS.EXCLUDES),