From ede1d5f7c8636d728ede80049e5e7dfa7de3e722 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 21 Jun 2018 10:49:03 +1000 Subject: [PATCH] Correctly dispose of Renderer and ScreenDprMonitor --- src/Terminal.ts | 2 ++ src/renderer/Renderer.ts | 2 ++ src/renderer/Types.ts | 5 +++-- src/utils/ScreenDprMonitor.ts | 9 ++++++++- src/utils/TestUtils.test.ts | 3 +++ 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Terminal.ts b/src/Terminal.ts index ab703aa2..51c3f189 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -611,6 +611,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this._screenDprMonitor = new ScreenDprMonitor(); this._screenDprMonitor.setListener(() => this.emit('dprchange', window.devicePixelRatio)); + this.register(this._screenDprMonitor); // Create main element container this.element = this._document.createElement('div'); @@ -671,6 +672,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II case 'dom': this.renderer = new DomRenderer(this, this.options.theme); break; default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`); } + this.register(this.renderer); this.options.theme = null; this.viewport = new Viewport(this, this._viewportElement, this._viewportScrollArea, this.charMeasure); this.viewport.onThemeChanged(this.renderer.colorManager.colors); diff --git a/src/renderer/Renderer.ts b/src/renderer/Renderer.ts index c41dece5..b6f4f640 100644 --- a/src/renderer/Renderer.ts +++ b/src/renderer/Renderer.ts @@ -62,12 +62,14 @@ export class Renderer extends EventEmitter implements IRenderer { this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this)); this._screenDprMonitor = new ScreenDprMonitor(); this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio)); + this.register(this._screenDprMonitor); // Detect whether IntersectionObserver is detected and enable renderer pause // and resume based on terminal visibility if so if ('IntersectionObserver' in window) { const observer = new IntersectionObserver(e => this.onIntersectionChange(e[0]), {threshold: 0}); observer.observe(this._terminal.element); + this.register({ dispose: () => observer.disconnect() }); } } diff --git a/src/renderer/Types.ts b/src/renderer/Types.ts index bafc9ad4..e7054c13 100644 --- a/src/renderer/Types.ts +++ b/src/renderer/Types.ts @@ -4,7 +4,7 @@ */ import { ITerminal } from '../Types'; -import { IEventEmitter, ITheme } from 'xterm'; +import { IEventEmitter, ITheme, IDisposable } from 'xterm'; import { IColorSet } from '../shared/Types'; /** @@ -24,10 +24,11 @@ export const enum FLAGS { * Note that IRenderer implementations should emit the refresh event after * rendering rows to the screen. */ -export interface IRenderer extends IEventEmitter { +export interface IRenderer extends IEventEmitter, IDisposable { dimensions: IRenderDimensions; colorManager: IColorManager; + dispose(): void; setTheme(theme: ITheme): IColorSet; onWindowResize(devicePixelRatio: number): void; onResize(cols: number, rows: number): void; diff --git a/src/utils/ScreenDprMonitor.ts b/src/utils/ScreenDprMonitor.ts index 15f3ac00..9247a032 100644 --- a/src/utils/ScreenDprMonitor.ts +++ b/src/utils/ScreenDprMonitor.ts @@ -3,6 +3,8 @@ * @license MIT */ +import { Disposable } from '../common/Lifecycle'; + export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void; /** @@ -15,7 +17,7 @@ export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRat * The listener should fire on both window zoom changes and switching to a * monitor with a different DPI. */ -export class ScreenDprMonitor { +export class ScreenDprMonitor extends Disposable { private _currentDevicePixelRatio: number; private _outerListener: MediaQueryListListener; private _listener: ScreenDprListener; @@ -33,6 +35,11 @@ export class ScreenDprMonitor { this._updateDpr(); } + public dispose(): void { + super.dispose(); + this.clearListener(); + } + private _updateDpr(): void { // Clear listeners for old DPR if (this._resolutionMediaMatchList) { diff --git a/src/utils/TestUtils.test.ts b/src/utils/TestUtils.test.ts index f4bad717..589ddac8 100644 --- a/src/utils/TestUtils.test.ts +++ b/src/utils/TestUtils.test.ts @@ -315,6 +315,9 @@ export class MockBuffer implements IBuffer { } export class MockRenderer implements IRenderer { + dispose(): void { + throw new Error('Method not implemented.'); + } colorManager: IColorManager; on(type: string, listener: XtermListener): void { throw new Error('Method not implemented.');