Skip to content

Commit 893d89a

Browse files
committed
cleanup
1 parent 543fefa commit 893d89a

File tree

10 files changed

+58
-43
lines changed

10 files changed

+58
-43
lines changed

addons/addon-image/src/ImageAddon.ts

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

6-
import type { ITerminalAddon, IDisposable } from '@xterm/xterm';
6+
import type { ITerminalAddon, IDisposable, ISharedExports } from '@xterm/xterm';
77
import type { ImageAddon as IImageApi } from '@xterm/addon-image';
88
import { IIPHandler } from './IIPHandler';
99
import { ImageRenderer } from './ImageRenderer';
@@ -57,7 +57,7 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
5757
private _terminal: ITerminalExt | undefined;
5858
private _handlers: Map<String, IResetHandler> = new Map();
5959

60-
constructor(opts?: Partial<IImageAddonOptions>) {
60+
constructor(private _sharedExports: ISharedExports, opts?: Partial<IImageAddonOptions>) {
6161
this._opts = Object.assign({}, DEFAULT_OPTIONS, opts);
6262
this._defaultOpts = Object.assign({}, DEFAULT_OPTIONS, opts);
6363
}
@@ -80,7 +80,7 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
8080
this._terminal = terminal;
8181

8282
// internal data structures
83-
this._renderer = new ImageRenderer(terminal);
83+
this._renderer = new ImageRenderer(this._sharedExports, terminal);
8484
this._storage = new ImageStorage(terminal, this._renderer, this._opts);
8585

8686
// enable size reports

addons/addon-image/src/ImageRenderer.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
*/
55

66
import { toRGBA8888 } from 'sixel/lib/Colors';
7-
import { IDisposable } from '@xterm/xterm';
7+
import { IDisposable, IMutableDisposable, ISharedExports } from '@xterm/xterm';
88
import { ICellSize, ITerminalExt, IImageSpec, IRenderDimensions, IRenderService } from './Types';
9-
import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
9+
import { AddonDisposable } from 'common/shared/AddonDisposable';
1010

1111
const PLACEHOLDER_LENGTH = 4096;
1212
const PLACEHOLDER_HEIGHT = 24;
@@ -17,12 +17,12 @@ const PLACEHOLDER_HEIGHT = 24;
1717
* - add canvas layer to DOM (browser only for now)
1818
* - draw image tiles onRender
1919
*/
20-
export class ImageRenderer extends Disposable implements IDisposable {
20+
export class ImageRenderer extends AddonDisposable implements IDisposable {
2121
public canvas: HTMLCanvasElement | undefined;
2222
private _ctx: CanvasRenderingContext2D | null | undefined;
2323
private _placeholder: HTMLCanvasElement | undefined;
2424
private _placeholderBitmap: ImageBitmap | undefined;
25-
private _optionsRefresh = this._register(new MutableDisposable());
25+
private _optionsRefresh: IMutableDisposable<IDisposable>;
2626
private _oldOpen: ((parent: HTMLElement) => void) | undefined;
2727
private _renderService: IRenderService | undefined;
2828
private _oldSetRenderer: ((renderer: any) => void) | undefined;
@@ -67,8 +67,8 @@ export class ImageRenderer extends Disposable implements IDisposable {
6767
}
6868

6969

70-
constructor(private _terminal: ITerminalExt) {
71-
super();
70+
constructor(sharedExports: ISharedExports, private _terminal: ITerminalExt) {
71+
super(sharedExports);
7272
this._oldOpen = this._terminal._core.open;
7373
this._terminal._core.open = (parent: HTMLElement): void => {
7474
this._oldOpen?.call(this._terminal._core, parent);
@@ -78,13 +78,14 @@ export class ImageRenderer extends Disposable implements IDisposable {
7878
this._open();
7979
}
8080
// hack to spot fontSize changes
81+
this._optionsRefresh = new sharedExports.MutableDisposable();
8182
this._optionsRefresh.value = this._terminal._core.optionsService.onOptionChange(option => {
8283
if (option === 'fontSize') {
8384
this.rescaleCanvas();
8485
this._renderService?.refreshRows(0, this._terminal.rows);
8586
}
8687
});
87-
this._register(toDisposable(() => {
88+
this._register(sharedExports.toDisposable(() => {
8889
this.removeLayerFromDom();
8990
if (this._terminal._core && this._oldOpen) {
9091
this._terminal._core.open = this._oldOpen;

addons/addon-image/test/ImageAddon.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { readFileSync } from 'fs';
88
import { FINALIZER, introducer, sixelEncode } from 'sixel';
99
import { ITestContext, createTestContext, openTerminal, pollFor, timeout } from '../../../test/playwright/TestUtils';
1010
import { deepStrictEqual, ok, strictEqual } from 'assert';
11+
import { ISharedExports } from '@xterm/xterm';
1112

1213
/**
1314
* Plugin ctor options.
@@ -27,7 +28,7 @@ export interface IImageAddonOptions {
2728

2829
// eslint-disable-next-line
2930
declare const ImageAddon: {
30-
new(options?: Partial<IImageAddonOptions>): any;
31+
new(sharedExports: ISharedExports, options?: Partial<IImageAddonOptions>): any;
3132
};
3233

3334
interface ITestData {
@@ -91,7 +92,7 @@ test.describe('ImageAddon', () => {
9192
await ctx.page.evaluate(`
9293
window.term.reset()
9394
window.imageAddon?.dispose();
94-
window.imageAddon = new ImageAddon({ sixelPaletteLimit: 512 });
95+
window.imageAddon = new ImageAddon(sharedExports, { sixelPaletteLimit: 512 });
9596
window.term.loadAddon(window.imageAddon);
9697
`);
9798
});
@@ -152,7 +153,7 @@ test.describe('ImageAddon', () => {
152153
iipSizeLimit: 1000
153154
};
154155
await ctx.page.evaluate(opts => {
155-
(window as any).imageAddonCustom = new ImageAddon(opts.opts);
156+
(window as any).imageAddonCustom = new ImageAddon((window as any).sharedExports, opts.opts);
156157
(window as any).term.loadAddon((window as any).imageAddonCustom);
157158
}, { opts: customSettings });
158159
deepStrictEqual(await ctx.page.evaluate(`window.imageAddonCustom._opts`), customSettings);

addons/addon-image/typings/addon-image.d.ts

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

6-
import { Terminal, ITerminalAddon } from '@xterm/xterm';
6+
import { Terminal, ITerminalAddon, ISharedExports } from '@xterm/xterm';
77

88
declare module '@xterm/addon-image' {
99
export interface IImageAddonOptions {
@@ -79,7 +79,7 @@ declare module '@xterm/addon-image' {
7979
}
8080

8181
export class ImageAddon implements ITerminalAddon {
82-
constructor(options?: IImageAddonOptions);
82+
constructor(sharedExports: ISharedExports, options?: IImageAddonOptions);
8383
public activate(terminal: Terminal): void;
8484
public dispose(): void;
8585

addons/addon-progress/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ module.exports = {
2727
alias: {
2828
common: path.resolve('../../out/common'),
2929
browser: path.resolve('../../out/browser'),
30-
vs: path.resolve('../../out/vs'),
30+
vs: path.resolve('../../out/vs')
3131
}
3232
},
3333
output: {

demo/client.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,7 @@ function createTerminal(): void {
280280
addons.search.instance = new SearchAddon();
281281
addons.serialize.instance = new SerializeAddon();
282282
addons.fit.instance = new FitAddon();
283-
addons.image.instance = new ImageAddon();
284-
//addons.progress.instance = new ProgressAddon(Terminal as unknown as IXtermSharedImports);
283+
addons.image.instance = new ImageAddon(sharedExports);
285284
addons.progress.instance = new ProgressAddon(sharedExports);
286285
addons.unicodeGraphemes.instance = new UnicodeGraphemesAddon();
287286
addons.clipboard.instance = new ClipboardAddon();
@@ -640,8 +639,8 @@ function initAddons(term: Terminal): void {
640639
if (checkbox.checked) {
641640
const ctorOptionsJson = document.querySelector<HTMLTextAreaElement>('#image-options').value;
642641
addon.instance = ctorOptionsJson
643-
? new addons[name].ctor(JSON.parse(ctorOptionsJson))
644-
: new addons[name].ctor();
642+
? new addons[name].ctor(sharedExports, JSON.parse(ctorOptionsJson))
643+
: new addons[name].ctor(sharedExports);
645644
term.loadAddon(addon.instance);
646645
} else {
647646
addon.instance!.dispose();

src/browser/public/Terminal.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import * as Strings from 'browser/LocalizableStrings';
77
import { CoreBrowserTerminal as TerminalCore } from 'browser/CoreBrowserTerminal';
88
import { IBufferRange, ITerminal } from 'browser/Types';
9-
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
9+
import { Disposable, DisposableStore, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
1010
import { ITerminalOptions } from 'common/Types';
1111
import { AddonManager } from 'common/public/AddonManager';
1212
import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi';
@@ -22,6 +22,7 @@ import { type Event, Emitter } from 'vs/base/common/event';
2222
*/
2323
export const sharedExports: ISharedExports = {
2424
DisposableStore,
25+
MutableDisposable,
2526
Emitter,
2627
toDisposable
2728
};

src/common/shared/AddonDisposable.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ export class AddonDisposable implements IDisposable {
1313
this._store = new sharedExports.DisposableStore();
1414
}
1515

16+
protected _register<T extends IDisposable>(o: T): T {
17+
if ((o as unknown as IDisposable) === this) {
18+
throw new Error('Cannot register a disposable on itself!');
19+
}
20+
return this._store.add(o);
21+
}
22+
1623
public dispose(): void {
1724
this._store.dispose();
1825
}

typings/xterm-headless.d.ts

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,26 +1363,26 @@ declare module '@xterm/headless' {
13631363
* EXPERIMENTAL:
13641364
* Module exposure of certain building blocks to be used at runtime in addons.
13651365
*/
1366-
export interface ISharedExports {
1367-
readonly DisposableStore: new() => IDisposableStore;
1368-
readonly Emitter: new<T>() => IEmitter<T>;
1369-
readonly toDisposable: (fn: () => void) => IDisposable;
1370-
}
1371-
1372-
export const sharedExports: ISharedExports;
1373-
1374-
// FIXME: @Tyriar - plz have a look at the following interfaces and
1375-
// to what degree those should be exposed or get stripped down
1376-
export interface IEmitter<T> extends IDisposable {
1377-
event: IEvent<T>;
1378-
fire(event: T): void;
1379-
hasListeners(): boolean;
1380-
}
1381-
export interface IDisposableStore extends IDisposable {
1382-
isDisposed: boolean;
1383-
clear(): void;
1384-
add<T extends IDisposable>(o: T): T;
1385-
delete<T extends IDisposable>(o: T): void;
1386-
deleteAndLeak<T extends IDisposable>(o: T): void;
1387-
}
1366+
export interface ISharedExports {
1367+
readonly DisposableStore: new() => IDisposableStore;
1368+
readonly Emitter: new<T>() => IEmitter<T>;
1369+
readonly toDisposable: (fn: () => void) => IDisposable;
1370+
}
1371+
1372+
export const sharedExports: ISharedExports;
1373+
1374+
// FIXME: @Tyriar - plz have a look at the following interfaces and
1375+
// to what degree those should be exposed or get stripped down
1376+
export interface IEmitter<T> extends IDisposable {
1377+
event: IEvent<T>;
1378+
fire(event: T): void;
1379+
hasListeners(): boolean;
1380+
}
1381+
export interface IDisposableStore extends IDisposable {
1382+
isDisposed: boolean;
1383+
clear(): void;
1384+
add<T extends IDisposable>(o: T): T;
1385+
delete<T extends IDisposable>(o: T): void;
1386+
deleteAndLeak<T extends IDisposable>(o: T): void;
1387+
}
13881388
}

typings/xterm.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,6 +1963,7 @@ declare module '@xterm/xterm' {
19631963
*/
19641964
export interface ISharedExports {
19651965
readonly DisposableStore: new() => IDisposableStore;
1966+
readonly MutableDisposable: new<T extends IDisposable>() => IMutableDisposable<T>;
19661967
readonly Emitter: new<T>() => IEmitter<T>;
19671968
readonly toDisposable: (fn: () => void) => IDisposable;
19681969
}
@@ -1983,4 +1984,9 @@ declare module '@xterm/xterm' {
19831984
delete<T extends IDisposable>(o: T): void;
19841985
deleteAndLeak<T extends IDisposable>(o: T): void;
19851986
}
1987+
export interface IMutableDisposable<T> extends IDisposable {
1988+
value: T | undefined;
1989+
clear(): void;
1990+
dispose(): void;
1991+
}
19861992
}

0 commit comments

Comments
 (0)