Files
xterm.js/src/common/base/Async.ts
T
Cursor AgentandDaniel Imms 1d125ac715 Restructure common into layered folders (issue #5963)
Reorganize src/common into platform (base, encoding, data, buffer,
parser, input), integration (services, terminal), and public API layers.

- Move core utilities to common/base/
- Move TextDecoder to common/encoding/
- Move Types, CircularList, Color, TaskQueue, SortedList to common/services/
- Move CoreTerminal, InputHandler, WindowsMode to common/terminal/
- Define ICharset in common/data/Charsets.ts (re-exported from Types)
- Update imports across src/, addons/, and test/
- Add per-layer tsconfig.json files and REARCHITECTURE.md
- Root common/tsconfig.json remains the composite build entry

Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
2026-05-30 16:12:18 +00:00

142 lines
3.5 KiB
TypeScript

/**
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
* @license MIT
*
* Minimal async helpers for xterm.js core.
*/
import { DisposableStore, IDisposable, toDisposable } from 'common/base/Lifecycle';
export function timeout(millis: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, millis));
}
/**
* 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.
*/
export function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {
const timer = setTimeout(() => {
handler();
if (store) {
disposable.dispose();
}
}, timeout);
const disposable = toDisposable(() => {
clearTimeout(timer);
});
store?.add(disposable);
return disposable;
}
export class TimeoutTimer implements IDisposable {
private _token: any = -1;
private _isDisposed = false;
public dispose(): void {
this.cancel();
this._isDisposed = true;
}
public cancel(): void {
if (this._token !== -1) {
clearTimeout(this._token);
this._token = -1;
}
}
public cancelAndSet(runner: () => void, timeout: number): void {
if (this._isDisposed) {
throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');
}
this.cancel();
this._token = setTimeout(() => {
this._token = -1;
runner();
}, timeout);
}
public setIfNotSet(runner: () => void, timeout: number): void {
if (this._isDisposed) {
throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');
}
if (this._token !== -1) {
return;
}
this._token = setTimeout(() => {
this._token = -1;
runner();
}, timeout);
}
}
/**
* Schedules a single runner on the microtask queue. Unlike {@link TimeoutTimer}, a scheduled
* microtask cannot be unqueued; {@link cancel} prevents the runner from executing if it has not
* run yet.
*/
export class MicrotaskTimer implements IDisposable {
private _isScheduled = false;
private _isDisposed = false;
public dispose(): void {
this.cancel();
this._isDisposed = true;
}
public cancel(): void {
this._isScheduled = false;
}
public set(runner: () => void): void {
if (this._isDisposed) {
throw new Error('Calling set on a disposed MicrotaskTimer');
}
if (this._isScheduled) {
return;
}
this._isScheduled = true;
queueMicrotask(() => {
if (!this._isScheduled) {
return;
}
this._isScheduled = false;
runner();
});
}
}
export class IntervalTimer implements IDisposable {
private _disposable: IDisposable | undefined;
private _isDisposed = false;
public cancel(): void {
this._disposable?.dispose();
this._disposable = undefined;
}
public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {
if (this._isDisposed) {
throw new Error('Calling cancelAndSet on a disposed IntervalTimer');
}
this.cancel();
const handle = context.setInterval(() => {
runner();
}, interval);
this._disposable = {
dispose: () => {
context.clearInterval(handle as any);
this._disposable = undefined;
}
};
}
public dispose(): void {
this.cancel();
this._isDisposed = true;
}
}