diff --git a/src/Buffer.ts b/src/Buffer.ts index 5ac2a4f2..78bcae27 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -6,7 +6,7 @@ import { CircularList } from './utils/CircularList'; import { LineData, CharData, ITerminal, IBuffer } from './Types'; import { EventEmitter } from './EventEmitter'; -import { IDisposable, IMarker } from 'xterm'; +import { IMarker } from 'xterm'; export const DEFAULT_ATTR = (0 << 18) | (257 << 9) | (256 << 0); export const CHAR_DATA_ATTR_INDEX = 0; @@ -320,7 +320,7 @@ export class Buffer implements IBuffer { public addMarker(y: number): Marker { const marker = new Marker(y); this.markers.push(marker); - marker.disposables.push(this.lines.addDisposableListener('trim', amount => { + marker.register(this.lines.addDisposableListener('trim', amount => { marker.line -= amount; // The marker should be disposed when the line is trimmed from the buffer if (marker.line < 0) { @@ -342,7 +342,6 @@ export class Marker extends EventEmitter implements IMarker { private _id: number = Marker._nextId++; public isDisposed: boolean = false; - public disposables: IDisposable[] = []; public get id(): number { return this._id; } @@ -357,8 +356,7 @@ export class Marker extends EventEmitter implements IMarker { return; } this.isDisposed = true; - this.disposables.forEach(d => d.dispose()); - this.disposables.length = 0; + super.dispose(); this.emit('dispose'); } } diff --git a/src/EventEmitter.ts b/src/EventEmitter.ts index 9ce31bb5..1970f3e6 100644 --- a/src/EventEmitter.ts +++ b/src/EventEmitter.ts @@ -5,11 +5,13 @@ import { XtermListener } from './Types'; import { IEventEmitter, IDisposable } from 'xterm'; +import { Disposable } from './common/Lifecycle'; -export class EventEmitter implements IEventEmitter, IDisposable { +export class EventEmitter extends Disposable implements IEventEmitter, IDisposable { private _events: {[type: string]: XtermListener[]}; constructor() { + super(); // Restore the previous events if available, this will happen if the // constructor is called multiple times on the same object (terminal reset). this._events = this._events || {}; @@ -26,6 +28,7 @@ export class EventEmitter implements IEventEmitter, IDisposable { * @param handler The handler for the listener. */ public addDisposableListener(type: string, handler: XtermListener): IDisposable { + // TODO: Rename addDisposableEventListener to more easily disambiguate from Dom listener this.on(type, handler); return { dispose: () => { diff --git a/src/Terminal.ts b/src/Terminal.ts index 55f3b493..05f47de2 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -113,8 +113,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II public element: HTMLElement; public screenElement: HTMLElement; - private _disposables: IDisposable[]; - /** * The HTMLElement that the terminal is created in, set by Terminal.open. */ @@ -252,8 +250,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II } private _setup(): void { - this._disposables = []; - Object.keys(DEFAULT_OPTIONS).forEach((key) => { if (this.options[key] == null) { this.options[key] = DEFAULT_OPTIONS[key]; @@ -688,7 +684,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this.on('dprchange', () => this.renderer.onWindowResize(window.devicePixelRatio)); // dprchange should handle this case, we need this as well for browsers that don't support the // matchMedia query. - this._disposables.push(Dom.addDisposableDomListener(window, 'resize', () => this.renderer.onWindowResize(window.devicePixelRatio))); + this.register(Dom.addDisposableDomListener(window, 'resize', () => this.renderer.onWindowResize(window.devicePixelRatio))); this.charMeasure.on('charsizechanged', () => this.renderer.onCharSizeChanged()); this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea()); diff --git a/src/common/Lifecycle.ts b/src/common/Lifecycle.ts new file mode 100644 index 00000000..f83f09af --- /dev/null +++ b/src/common/Lifecycle.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2018 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import { IDisposable } from 'xterm'; + +export abstract class Disposable implements IDisposable { + protected _disposables: IDisposable[] = []; + + constructor() { + } + + public dispose(): void { + this._disposables.forEach(d => d.dispose()); + this._disposables.length = 0; + } + + public register(t: T): void { + this._disposables.push(t); + } +}