mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-20 02:08:47 +00:00
Allow deleting from DisposableStore and add management to disposableTimeout
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { CancellationError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableMap, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableMap, DisposableStore, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { extUri as defaultExtUri, IExtUri } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { setTimeout0 } from 'vs/base/common/platform';
|
||||
@@ -490,9 +490,34 @@ export function timeout(millis: number, token?: CancellationToken): CancelablePr
|
||||
});
|
||||
}
|
||||
|
||||
export function disposableTimeout(handler: () => void, timeout = 0): IDisposable {
|
||||
const timer = setTimeout(handler, timeout);
|
||||
return toDisposable(() => clearTimeout(timer));
|
||||
/**
|
||||
* 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 function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {
|
||||
const timer = setTimeout(() => {
|
||||
handler();
|
||||
disposable.dispose();
|
||||
}, timeout);
|
||||
const disposable = toDisposable(() => {
|
||||
clearTimeout(timer);
|
||||
store?.deleteAndLeak(disposable);
|
||||
});
|
||||
store?.add(disposable);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -430,6 +430,28 @@ export class DisposableStore implements IDisposable {
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a disposable from store and disposes of it. This will not throw or warn and proceed to dispose the
|
||||
* disposable even when the disposable is not part in the store.
|
||||
*/
|
||||
public delete<T extends IDisposable>(o: T): void {
|
||||
if (!o) {
|
||||
return;
|
||||
}
|
||||
if ((o as unknown as DisposableStore) === this) {
|
||||
throw new Error('Cannot dispose a disposable on itself!');
|
||||
}
|
||||
this._toDispose.delete(o);
|
||||
o.dispose();
|
||||
}
|
||||
|
||||
public deleteAndLeak<T extends IDisposable>(o: T): void {
|
||||
if (!o) {
|
||||
return;
|
||||
}
|
||||
this._toDispose.delete(o);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ import { ErrorNoTelemetry, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ISeparator, template } from 'vs/base/common/labels';
|
||||
import { Disposable, DisposableMap, IDisposable, MutableDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, MutableDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { OS, OperatingSystem, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
@@ -87,7 +87,6 @@ import { importAMDNodeModule } from 'vs/amdX';
|
||||
import { ISimpleSelectedSuggestion } from 'vs/workbench/services/suggest/browser/simpleSuggestWidget';
|
||||
import type { IMarker, Terminal as XTermTerminal } from 'xterm';
|
||||
import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
|
||||
const enum Constants {
|
||||
/**
|
||||
@@ -122,52 +121,11 @@ const shellIntegrationSupportedShellTypes = [
|
||||
WindowsShellType.PowerShell
|
||||
];
|
||||
|
||||
/**
|
||||
* A wrapper around a {@link DisposableMap} that allows tracking transient disposables and then
|
||||
* freeing their memory when they are no longer needed. This can be thought of as an alternative to
|
||||
* a `IDisposable[]` for short lived disposables that allows declaring, initializing and registering
|
||||
* the disposable in a single line.
|
||||
*
|
||||
* Some other benefits:
|
||||
*
|
||||
* - Disposable tracking is integrated thanks to using {@link DisposableMap} internally.
|
||||
* - This is lighter weight and more concise than several {@link MutableDisposable}s.
|
||||
*
|
||||
* @example
|
||||
* class Foo {
|
||||
* private _transientDisposables = this._register(new TransientDisposableStore());
|
||||
*
|
||||
* constructor() {
|
||||
* // Cancel the callback if Foo is disposed
|
||||
* this._transientDisposables.addTimeout(() => { ... }, 1000);
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
class TransientDisposableStore implements IDisposable {
|
||||
private _map = new DisposableMap<string>();
|
||||
|
||||
addTimeout(handler: () => void, timeout = 0) {
|
||||
const idx = generateUuid();
|
||||
this._map.set(idx, disposableTimeout(() => {
|
||||
handler();
|
||||
this._map.deleteAndDispose(idx);
|
||||
}, timeout));
|
||||
}
|
||||
|
||||
// More functions can be added as needed
|
||||
|
||||
dispose() {
|
||||
this._map.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
private static _lastKnownCanvasDimensions: ICanvasDimensions | undefined;
|
||||
private static _lastKnownGridDimensions: IGridDimensions | undefined;
|
||||
private static _instanceIdCounter = 1;
|
||||
|
||||
private readonly _transientDisposables = this._register(new TransientDisposableStore());
|
||||
|
||||
private readonly _scopedInstantiationService: IInstantiationService;
|
||||
|
||||
private readonly _processManager: ITerminalProcessManager;
|
||||
@@ -801,7 +759,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._lineDataEventAddon = lineDataEventAddon;
|
||||
// Delay the creation of the bell listener to avoid showing the bell when the terminal
|
||||
// starts up or reconnects
|
||||
this._transientDisposables.addTimeout(() => {
|
||||
disposableTimeout(() => {
|
||||
this._register(xterm.raw.onBell(() => {
|
||||
if (this._configHelper.config.enableBell) {
|
||||
this.statusList.add({
|
||||
@@ -813,7 +771,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._audioCueService.playSound(AudioCue.terminalBell.sound.getSound());
|
||||
}
|
||||
}));
|
||||
}, 1000);
|
||||
}, 1000, this._store);
|
||||
this._register(xterm.raw.onSelectionChange(async () => this._onSelectionChange()));
|
||||
this._register(xterm.raw.buffer.onBufferChange(() => this._refreshAltBufferContextKey()));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user