Skip to content

Commit abae7b6

Browse files
authored
Merge pull request #4733 from Tyriar/mutable
Adopt MutableDisposable for most usages of pattern `<var>?.dispose(); <var> = undefined`
2 parents a0d0c92 + 38c6af9 commit abae7b6

File tree

10 files changed

+114
-144
lines changed

10 files changed

+114
-144
lines changed

addons/xterm-addon-canvas/src/BaseRenderLayer.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
* @license MIT
44
*/
55

6+
import { ReadonlyColorSet } from 'browser/Types';
7+
import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver';
68
import { acquireTextureAtlas } from 'browser/renderer/shared/CharAtlasCache';
79
import { TEXT_BASELINE } from 'browser/renderer/shared/Constants';
810
import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs';
911
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
10-
import { IRasterizedGlyph, IRenderDimensions, ISelectionRenderModel, ITextureAtlas } from 'browser/renderer/shared/Types';
1112
import { createSelectionRenderModel } from 'browser/renderer/shared/SelectionRenderModel';
13+
import { IRasterizedGlyph, IRenderDimensions, ISelectionRenderModel, ITextureAtlas } from 'browser/renderer/shared/Types';
1214
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
13-
import { ReadonlyColorSet } from 'browser/Types';
15+
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
16+
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
17+
import { isSafari } from 'common/Platform';
18+
import { ICellData } from 'common/Types';
1419
import { CellData } from 'common/buffer/CellData';
1520
import { WHITESPACE_CELL_CODE } from 'common/buffer/Constants';
1621
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
17-
import { ICellData, IDisposable } from 'common/Types';
1822
import { Terminal } from 'xterm';
1923
import { IRenderLayer } from './Types';
20-
import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver';
21-
import { Disposable, toDisposable } from 'common/Lifecycle';
22-
import { isSafari } from 'common/Platform';
23-
import { EventEmitter, forwardEvent } from 'common/EventEmitter';
2424

2525
export abstract class BaseRenderLayer extends Disposable implements IRenderLayer {
2626
private _canvas: HTMLCanvasElement;
@@ -37,7 +37,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
3737
private _bitmapGenerator: (BitmapGenerator | undefined)[] = [];
3838

3939
protected _charAtlas!: ITextureAtlas;
40-
private _charAtlasDisposable?: IDisposable;
40+
protected _charAtlasDisposable = this.register(new MutableDisposable());
4141

4242
public get canvas(): HTMLCanvasElement { return this._canvas; }
4343
public get cacheCanvas(): HTMLCanvasElement { return this._charAtlas?.pages[0].canvas!; }
@@ -74,7 +74,6 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
7474

7575
this.register(toDisposable(() => {
7676
this._canvas.remove();
77-
this._charAtlas?.dispose();
7877
}));
7978
}
8079

@@ -122,9 +121,8 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
122121
if (this._deviceCharWidth <= 0 && this._deviceCharHeight <= 0) {
123122
return;
124123
}
125-
this._charAtlasDisposable?.dispose();
126124
this._charAtlas = acquireTextureAtlas(this._terminal, this._optionsService.rawOptions, colorSet, this._deviceCellWidth, this._deviceCellHeight, this._deviceCharWidth, this._deviceCharHeight, this._coreBrowserService.dpr);
127-
this._charAtlasDisposable = forwardEvent(this._charAtlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas);
125+
this._charAtlasDisposable.value = forwardEvent(this._charAtlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas);
128126
this._charAtlas.warmUp();
129127
for (let i = 0; i < this._charAtlas.pages.length; i++) {
130128
this._bitmapGenerator[i] = new BitmapGenerator(this._charAtlas.pages[i].canvas);

addons/xterm-addon-canvas/src/CursorRenderLayer.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { CursorBlinkStateManager } from 'browser/renderer/shared/CursorBlinkStat
77
import { IRenderDimensions, IRequestRedrawEvent } from 'browser/renderer/shared/Types';
88
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
99
import { IEventEmitter } from 'common/EventEmitter';
10-
import { toDisposable } from 'common/Lifecycle';
10+
import { MutableDisposable } from 'common/Lifecycle';
1111
import { isFirefox } from 'common/Platform';
1212
import { ICellData } from 'common/Types';
1313
import { CellData } from 'common/buffer/CellData';
@@ -26,7 +26,7 @@ interface ICursorState {
2626
export class CursorRenderLayer extends BaseRenderLayer {
2727
private _state: ICursorState;
2828
private _cursorRenderers: {[key: string]: (x: number, y: number, cell: ICellData) => void};
29-
private _cursorBlinkStateManager: CursorBlinkStateManager | undefined;
29+
private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = this.register(new MutableDisposable());
3030
private _cell: ICellData = new CellData();
3131

3232
constructor(
@@ -57,10 +57,6 @@ export class CursorRenderLayer extends BaseRenderLayer {
5757
};
5858
this.register(optionsService.onOptionChange(() => this._handleOptionsChanged()));
5959
this._handleOptionsChanged();
60-
this.register(toDisposable(() => {
61-
this._cursorBlinkStateManager?.dispose();
62-
this._cursorBlinkStateManager = undefined;
63-
}));
6460
}
6561

6662
public resize(dim: IRenderDimensions): void {
@@ -77,43 +73,42 @@ export class CursorRenderLayer extends BaseRenderLayer {
7773

7874
public reset(): void {
7975
this._clearCursor();
80-
this._cursorBlinkStateManager?.restartBlinkAnimation();
76+
this._cursorBlinkStateManager.value?.restartBlinkAnimation();
8177
this._handleOptionsChanged();
8278
}
8379

8480
public handleBlur(): void {
85-
this._cursorBlinkStateManager?.pause();
81+
this._cursorBlinkStateManager.value?.pause();
8682
this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });
8783
}
8884

8985
public handleFocus(): void {
90-
this._cursorBlinkStateManager?.resume();
86+
this._cursorBlinkStateManager.value?.resume();
9187
this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });
9288
}
9389

9490
private _handleOptionsChanged(): void {
9591
if (this._optionsService.rawOptions.cursorBlink) {
96-
if (!this._cursorBlinkStateManager) {
97-
this._cursorBlinkStateManager = new CursorBlinkStateManager(() => this._render(true), this._coreBrowserService);
92+
if (!this._cursorBlinkStateManager.value) {
93+
this._cursorBlinkStateManager.value = new CursorBlinkStateManager(() => this._render(true), this._coreBrowserService);
9894
}
9995
} else {
100-
this._cursorBlinkStateManager?.dispose();
101-
this._cursorBlinkStateManager = undefined;
96+
this._cursorBlinkStateManager.clear();
10297
}
10398
// Request a refresh from the terminal as management of rendering is being
10499
// moved back to the terminal
105100
this._onRequestRedraw.fire({ start: this._bufferService.buffer.y, end: this._bufferService.buffer.y });
106101
}
107102

108103
public handleCursorMove(): void {
109-
this._cursorBlinkStateManager?.restartBlinkAnimation();
104+
this._cursorBlinkStateManager.value?.restartBlinkAnimation();
110105
}
111106

112107
public handleGridChanged(startRow: number, endRow: number): void {
113-
if (!this._cursorBlinkStateManager || this._cursorBlinkStateManager.isPaused) {
108+
if (!this._cursorBlinkStateManager.value || this._cursorBlinkStateManager.value.isPaused) {
114109
this._render(false);
115110
} else {
116-
this._cursorBlinkStateManager.restartBlinkAnimation();
111+
this._cursorBlinkStateManager.value.restartBlinkAnimation();
117112
}
118113
}
119114

@@ -159,7 +154,7 @@ export class CursorRenderLayer extends BaseRenderLayer {
159154
}
160155

161156
// Don't draw the cursor if it's blinking
162-
if (this._cursorBlinkStateManager && !this._cursorBlinkStateManager.isCursorVisible) {
157+
if (this._cursorBlinkStateManager.value && !this._cursorBlinkStateManager.value.isCursorVisible) {
163158
this._clearCursor();
164159
return;
165160
}

addons/xterm-addon-image/src/ImageRenderer.ts

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { toRGBA8888 } from 'sixel/lib/Colors';
77
import { IDisposable } from 'xterm';
88
import { ICellSize, ITerminalExt, IImageSpec, IRenderDimensions, IRenderService } from './Types';
9+
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
910

1011

1112
const PLACEHOLDER_LENGTH = 4096;
@@ -17,12 +18,12 @@ const PLACEHOLDER_HEIGHT = 24;
1718
* - add canvas layer to DOM (browser only for now)
1819
* - draw image tiles onRender
1920
*/
20-
export class ImageRenderer implements IDisposable {
21+
export class ImageRenderer extends Disposable implements IDisposable {
2122
public canvas: HTMLCanvasElement | undefined;
2223
private _ctx: CanvasRenderingContext2D | null | undefined;
2324
private _placeholder: HTMLCanvasElement | undefined;
2425
private _placeholderBitmap: ImageBitmap | undefined;
25-
private _optionsRefresh: IDisposable | undefined;
26+
private _optionsRefresh = this.register(new MutableDisposable());
2627
private _oldOpen: ((parent: HTMLElement) => void) | undefined;
2728
private _renderService: IRenderService | undefined;
2829
private _oldSetRenderer: ((renderer: any) => void) | undefined;
@@ -68,6 +69,7 @@ export class ImageRenderer implements IDisposable {
6869

6970

7071
constructor(private _terminal: ITerminalExt) {
72+
super();
7173
this._oldOpen = this._terminal._core.open;
7274
this._terminal._core.open = (parent: HTMLElement): void => {
7375
this._oldOpen?.call(this._terminal._core, parent);
@@ -77,32 +79,29 @@ export class ImageRenderer implements IDisposable {
7779
this._open();
7880
}
7981
// hack to spot fontSize changes
80-
this._optionsRefresh = this._terminal._core.optionsService.onOptionChange(option => {
82+
this._optionsRefresh.value = this._terminal._core.optionsService.onOptionChange(option => {
8183
if (option === 'fontSize') {
8284
this.rescaleCanvas();
8385
this._renderService?.refreshRows(0, this._terminal.rows);
8486
}
8587
});
86-
}
87-
88-
89-
public dispose(): void {
90-
this._optionsRefresh?.dispose();
91-
this.removeLayerFromDom();
92-
if (this._terminal._core && this._oldOpen) {
93-
this._terminal._core.open = this._oldOpen;
94-
this._oldOpen = undefined;
95-
}
96-
if (this._renderService && this._oldSetRenderer) {
97-
this._renderService.setRenderer = this._oldSetRenderer;
98-
this._oldSetRenderer = undefined;
99-
}
100-
this._renderService = undefined;
101-
this.canvas = undefined;
102-
this._ctx = undefined;
103-
this._placeholderBitmap?.close();
104-
this._placeholderBitmap = undefined;
105-
this._placeholder = undefined;
88+
this.register(toDisposable(() => {
89+
this.removeLayerFromDom();
90+
if (this._terminal._core && this._oldOpen) {
91+
this._terminal._core.open = this._oldOpen;
92+
this._oldOpen = undefined;
93+
}
94+
if (this._renderService && this._oldSetRenderer) {
95+
this._renderService.setRenderer = this._oldSetRenderer;
96+
this._oldSetRenderer = undefined;
97+
}
98+
this._renderService = undefined;
99+
this.canvas = undefined;
100+
this._ctx = undefined;
101+
this._placeholderBitmap?.close();
102+
this._placeholderBitmap = undefined;
103+
this._placeholder = undefined;
104+
}));
106105
}
107106

108107
/**

addons/xterm-addon-search/src/SearchAddon.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { Terminal, IDisposable, ITerminalAddon, IDecoration } from 'xterm';
77
import { EventEmitter } from 'common/EventEmitter';
8-
import { Disposable, toDisposable, disposeArray } from 'common/Lifecycle';
8+
import { Disposable, toDisposable, disposeArray, MutableDisposable } from 'common/Lifecycle';
99

1010
export interface ISearchOptions {
1111
regex?: boolean;
@@ -66,7 +66,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
6666
private _cachedSearchTerm: string | undefined;
6767
private _highlightedLines: Set<number> = new Set();
6868
private _highlightDecorations: IHighlight[] = [];
69-
private _selectedDecoration: IHighlight | undefined;
69+
private _selectedDecoration: MutableDisposable<IHighlight> = this.register(new MutableDisposable());
7070
private _highlightLimit: number;
7171
private _lastSearchOptions: ISearchOptions | undefined;
7272
private _highlightTimeout: number | undefined;
@@ -110,7 +110,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
110110
}
111111

112112
public clearDecorations(retainCachedSearchTerm?: boolean): void {
113-
this.clearActiveDecoration();
113+
this._selectedDecoration.clear();
114114
disposeArray(this._highlightDecorations);
115115
this._highlightDecorations = [];
116116
this._highlightedLines.clear();
@@ -119,11 +119,6 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
119119
}
120120
}
121121

122-
public clearActiveDecoration(): void {
123-
this._selectedDecoration?.dispose();
124-
this._selectedDecoration = undefined;
125-
}
126-
127122
/**
128123
* Find the next instance of the term, then scroll to and select it. If it
129124
* doesn't exist, do nothing.
@@ -320,8 +315,8 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
320315
private _fireResults(searchOptions?: ISearchOptions): void {
321316
if (searchOptions?.decorations) {
322317
let resultIndex = -1;
323-
if (this._selectedDecoration) {
324-
const selectedMatch = this._selectedDecoration.match;
318+
if (this._selectedDecoration.value) {
319+
const selectedMatch = this._selectedDecoration.value.match;
325320
for (let i = 0; i < this._highlightDecorations.length; i++) {
326321
const match = this._highlightDecorations[i].match;
327322
if (match.row === selectedMatch.row && match.col === selectedMatch.col && match.size === selectedMatch.size) {
@@ -642,7 +637,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
642637
*/
643638
private _selectResult(result: ISearchResult | undefined, options?: ISearchDecorationOptions, noScroll?: boolean): boolean {
644639
const terminal = this._terminal!;
645-
this.clearActiveDecoration();
640+
this._selectedDecoration.clear();
646641
if (!result) {
647642
terminal.clearSelection();
648643
return false;
@@ -666,7 +661,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon {
666661
disposables.push(marker);
667662
disposables.push(decoration.onRender((e) => this._applyStyles(e, options.activeMatchBorder, true)));
668663
disposables.push(decoration.onDispose(() => disposeArray(disposables)));
669-
this._selectedDecoration = { decoration, match: result, dispose() { decoration.dispose(); } };
664+
this._selectedDecoration.value = { decoration, match: result, dispose() { decoration.dispose(); } };
670665
}
671666
}
672667
}

0 commit comments

Comments
 (0)