From 3a90f7e7c0a508aeed422173df89d6b9366be341 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sat, 1 Oct 2022 07:39:02 -0700 Subject: [PATCH] Inline dirty row service into input handler Fixes #4147 --- src/common/CoreTerminal.ts | 12 +-- src/common/InputHandler.test.ts | 18 ++-- src/common/InputHandler.ts | 123 ++++++++++++++++++------- src/common/TestUtils.test.ts | 12 +-- src/common/services/DirtyRowService.ts | 53 ----------- src/common/services/Services.ts | 13 --- 6 files changed, 102 insertions(+), 129 deletions(-) delete mode 100644 src/common/services/DirtyRowService.ts diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 02a9439276..fae3efa580 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -22,7 +22,7 @@ */ import { Disposable } from 'common/Lifecycle'; -import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, ICoreMouseService, IUnicodeService, IDirtyRowService, LogLevelEnum, ITerminalOptions, IOscLinkService } from 'common/services/Services'; +import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, ICoreMouseService, IUnicodeService, LogLevelEnum, ITerminalOptions, IOscLinkService } from 'common/services/Services'; import { InstantiationService } from 'common/services/InstantiationService'; import { LogService } from 'common/services/LogService'; import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService'; @@ -31,7 +31,6 @@ import { IDisposable, IAttributeData, ICoreTerminal, IScrollEvent, ScrollSource import { CoreService } from 'common/services/CoreService'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; -import { DirtyRowService } from 'common/services/DirtyRowService'; import { UnicodeService } from 'common/services/UnicodeService'; import { CharsetService } from 'common/services/CharsetService'; import { updateWindowsModeWrappedState } from 'common/WindowsMode'; @@ -49,7 +48,6 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { protected readonly _bufferService: IBufferService; protected readonly _logService: ILogService; protected readonly _charsetService: ICharsetService; - protected readonly _dirtyRowService: IDirtyRowService; protected readonly _oscLinkService: IOscLinkService; public readonly coreMouseService: ICoreMouseService; @@ -114,8 +112,6 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { this._instantiationService.setService(ICoreService, this.coreService); this.coreMouseService = this._instantiationService.createInstance(CoreMouseService); this._instantiationService.setService(ICoreMouseService, this.coreMouseService); - this._dirtyRowService = this._instantiationService.createInstance(DirtyRowService); - this._instantiationService.setService(IDirtyRowService, this._dirtyRowService); this.unicodeService = this._instantiationService.createInstance(UnicodeService); this._instantiationService.setService(IUnicodeService, this.unicodeService); this._charsetService = this._instantiationService.createInstance(CharsetService); @@ -124,7 +120,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { this._instantiationService.setService(IOscLinkService, this._oscLinkService); // Register input handler and handle/forward events - this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this.coreService, this._dirtyRowService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService); + this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService); this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); this.register(this._inputHandler); @@ -136,11 +132,11 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { this.register(this.optionsService.onOptionChange(key => this._updateOptions(key))); this.register(this._bufferService.onScroll(event => { this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL }); - this._dirtyRowService.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom); + this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom); })); this.register(this._inputHandler.onScroll(event => { this._onScroll.fire({ position: this._bufferService.buffer.ydisp, source: ScrollSource.TERMINAL }); - this._dirtyRowService.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom); + this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom); })); // Setup WriteBuffer diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index f734b002c2..d9127e7b20 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -11,7 +11,7 @@ import { CellData } from 'common/buffer/CellData'; import { Attributes, UnderlineStyle } from 'common/buffer/Constants'; import { AttributeData } from 'common/buffer/AttributeData'; import { Params } from 'common/parser/Params'; -import { MockCoreService, MockBufferService, MockDirtyRowService, MockOptionsService, MockLogService, MockCoreMouseService, MockCharsetService, MockUnicodeService, MockOscLinkService } from 'common/TestUtils.test'; +import { MockCoreService, MockBufferService, MockOptionsService, MockLogService, MockCoreMouseService, MockCharsetService, MockUnicodeService, MockOscLinkService } from 'common/TestUtils.test'; import { IBufferService, ICoreService } from 'common/services/Services'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { clone } from 'common/Clone'; @@ -67,7 +67,7 @@ describe('InputHandler', () => { bufferService.resize(80, 30); coreService = new CoreService(() => { }, bufferService, new MockLogService(), optionsService); - inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); + inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockLogService(), optionsService, new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); }); describe('SL/SR/DECIC/DECDC', () => { @@ -236,7 +236,7 @@ describe('InputHandler', () => { describe('setMode', () => { it('should toggle bracketedPasteMode', () => { const coreService = new MockCoreService(); - const inputHandler = new TestInputHandler(new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); + const inputHandler = new TestInputHandler(new MockBufferService(80, 30), new MockCharsetService(), coreService, new MockLogService(), new MockOptionsService(), new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); // Set bracketed paste mode inputHandler.setModePrivate(Params.fromArray([2004])); assert.equal(coreService.decPrivateModes.bracketedPasteMode, true); @@ -258,7 +258,6 @@ describe('InputHandler', () => { bufferService, new MockCharsetService(), new MockCoreService(), - new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), @@ -305,7 +304,6 @@ describe('InputHandler', () => { bufferService, new MockCharsetService(), new MockCoreService(), - new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), @@ -356,7 +354,6 @@ describe('InputHandler', () => { bufferService, new MockCharsetService(), new MockCoreService(), - new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), @@ -394,7 +391,6 @@ describe('InputHandler', () => { bufferService, new MockCharsetService(), new MockCoreService(), - new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), @@ -445,7 +441,6 @@ describe('InputHandler', () => { bufferService, new MockCharsetService(), new MockCoreService(), - new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), @@ -572,7 +567,6 @@ describe('InputHandler', () => { new MockBufferService(80, 30), new MockCharsetService(), new MockCoreService(), - new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), @@ -599,7 +593,7 @@ describe('InputHandler', () => { beforeEach(() => { bufferService = new MockBufferService(80, 30); - handler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockDirtyRowService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); + handler = new TestInputHandler(bufferService, new MockCharsetService(), new MockCoreService(), new MockLogService(), new MockOptionsService(), new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); }); it('should handle DECSET/DECRST 47 (alt screen buffer)', async () => { await handler.parseP('\x1b[?47h\r\n\x1b[31mJUNK\x1b[?47lTEST'); @@ -796,7 +790,7 @@ describe('InputHandler', () => { describe('colon notation', () => { let inputHandler2: TestInputHandler; beforeEach(() => { - inputHandler2 = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); + inputHandler2 = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockLogService(), optionsService, new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); }); describe('should equal to semicolon', () => { it('CSI 38:2::50:100:150 m', async () => { @@ -2278,7 +2272,7 @@ describe('InputHandler - async handlers', () => { coreService = new CoreService(() => { }, bufferService, new MockLogService(), optionsService); coreService.onData(data => { console.log(data); }); - inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockDirtyRowService(), new MockLogService(), optionsService, new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); + inputHandler = new TestInputHandler(bufferService, new MockCharsetService(), coreService, new MockLogService(), optionsService, new MockOscLinkService(), new MockCoreMouseService(), new MockUnicodeService()); }); it('async CUP with CPR check', async () => { diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index b599bb7e42..dd61cf3474 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -12,11 +12,11 @@ import { Disposable } from 'common/Lifecycle'; import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from 'common/input/TextDecoder'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { EventEmitter, IEvent } from 'common/EventEmitter'; -import { IParsingState, IDcsHandler, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types'; +import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types'; import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content, UnderlineStyle } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; import { AttributeData } from 'common/buffer/AttributeData'; -import { ICoreService, IBufferService, IOptionsService, ILogService, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService, LogLevelEnum, IOscLinkService } from 'common/services/Services'; +import { ICoreService, IBufferService, IOptionsService, ILogService, ICoreMouseService, ICharsetService, IUnicodeService, LogLevelEnum, IOscLinkService } from 'common/services/Services'; import { OscHandler } from 'common/parser/OscParser'; import { DcsHandler } from 'common/parser/DcsParser'; import { IBuffer } from 'common/buffer/Types'; @@ -104,6 +104,8 @@ export enum WindowsOptionsReportType { // create a warning log if an async handler takes longer than the limit (in ms) const SLOW_ASYNC_LIMIT = 5000; +// Work variables to avoid garbage collection +let $temp = 0; /** * The terminal's standard implementation of IInputHandler, this handles all @@ -120,6 +122,7 @@ export class InputHandler extends Disposable implements IInputHandler { private _windowTitle = ''; private _iconName = ''; private _currentLinkId?: number; + private _dirtyRowTracker: IDirtyRowTracker; protected _windowTitleStack: string[] = []; protected _iconNameStack: string[] = []; @@ -169,7 +172,6 @@ export class InputHandler extends Disposable implements IInputHandler { private readonly _bufferService: IBufferService, private readonly _charsetService: ICharsetService, private readonly _coreService: ICoreService, - private readonly _dirtyRowService: IDirtyRowService, private readonly _logService: ILogService, private readonly _optionsService: IOptionsService, private readonly _oscLinkService: IOscLinkService, @@ -179,6 +181,7 @@ export class InputHandler extends Disposable implements IInputHandler { ) { super(); this.register(this._parser); + this._dirtyRowTracker = new DirtyRowTracker(this._bufferService); // Track properties used in performance critical code manually to avoid using slow getters this._activeBuffer = this._bufferService.buffer; @@ -459,7 +462,7 @@ export class InputHandler extends Disposable implements IInputHandler { // Clear the dirty row service so we know which lines changed as a result of parsing // Important: do not clear between async calls, otherwise we lost pending update information. if (!wasPaused) { - this._dirtyRowService.clearRange(); + this._dirtyRowTracker.clearRange(); } // process big data in smaller chunks @@ -493,7 +496,7 @@ export class InputHandler extends Disposable implements IInputHandler { } // Refresh any dirty rows accumulated as part of parsing - this._onRequestRefreshRows.fire(this._dirtyRowService.start, this._dirtyRowService.end); + this._onRequestRefreshRows.fire(this._dirtyRowTracker.start, this._dirtyRowTracker.end); } public print(data: Uint32Array, start: number, end: number): void { @@ -507,7 +510,7 @@ export class InputHandler extends Disposable implements IInputHandler { const curAttr = this._curAttrData; let bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!; - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); // handle wide chars: reset start_cell-1 if we would overwrite the second cell of a wide char if (this._activeBuffer.x && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x - 1) === 2) { @@ -635,7 +638,7 @@ export class InputHandler extends Disposable implements IInputHandler { bufferRow.setCellFromCodePoint(this._activeBuffer.x, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended); } - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); } /** @@ -699,7 +702,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y C0 FF "Form Feed" "\f, \x0C" "Treated as LF." */ public lineFeed(): boolean { - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); if (this._optionsService.rawOptions.convertEol) { this._activeBuffer.x = 0; } @@ -714,7 +717,7 @@ export class InputHandler extends Disposable implements IInputHandler { if (this._activeBuffer.x >= this._bufferService.cols) { this._activeBuffer.x--; } - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); this._onLineFeed.fire(); return true; @@ -842,14 +845,14 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.y = this._coreService.decPrivateModes.origin ? Math.min(this._activeBuffer.scrollBottom, Math.max(this._activeBuffer.scrollTop, this._activeBuffer.y)) : Math.min(this._bufferService.rows - 1, Math.max(0, this._activeBuffer.y)); - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); } /** * Set absolute cursor position. */ private _setCursor(x: number, y: number): void { - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); if (this._coreService.decPrivateModes.origin) { this._activeBuffer.x = x; this._activeBuffer.y = this._activeBuffer.scrollTop + y; @@ -858,7 +861,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.y = y; } this._restrictCursor(); - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); } /** @@ -1178,16 +1181,16 @@ export class InputHandler extends Disposable implements IInputHandler { switch (params.params[0]) { case 0: j = this._activeBuffer.y; - this._dirtyRowService.markDirty(j); + this._dirtyRowTracker.markDirty(j); this._eraseInBufferLine(j++, this._activeBuffer.x, this._bufferService.cols, this._activeBuffer.x === 0, respectProtect); for (; j < this._bufferService.rows; j++) { this._resetBufferLine(j, respectProtect); } - this._dirtyRowService.markDirty(j); + this._dirtyRowTracker.markDirty(j); break; case 1: j = this._activeBuffer.y; - this._dirtyRowService.markDirty(j); + this._dirtyRowTracker.markDirty(j); // Deleted front part of line and everything before. This line will no longer be wrapped. this._eraseInBufferLine(j, 0, this._activeBuffer.x + 1, true, respectProtect); if (this._activeBuffer.x + 1 >= this._bufferService.cols) { @@ -1197,15 +1200,15 @@ export class InputHandler extends Disposable implements IInputHandler { while (j--) { this._resetBufferLine(j, respectProtect); } - this._dirtyRowService.markDirty(0); + this._dirtyRowTracker.markDirty(0); break; case 2: j = this._bufferService.rows; - this._dirtyRowService.markDirty(j - 1); + this._dirtyRowTracker.markDirty(j - 1); while (j--) { this._resetBufferLine(j, respectProtect); } - this._dirtyRowService.markDirty(0); + this._dirtyRowTracker.markDirty(0); break; case 3: // Clear scrollback (everything not in viewport) @@ -1257,7 +1260,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._eraseInBufferLine(this._activeBuffer.y, 0, this._bufferService.cols, true, respectProtect); break; } - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); return true; } @@ -1289,7 +1292,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.lines.splice(row, 0, this._activeBuffer.getBlankLine(this._eraseAttrData())); } - this._dirtyRowService.markRangeDirty(this._activeBuffer.y, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.y, this._activeBuffer.scrollBottom); this._activeBuffer.x = 0; // see https://vt100.net/docs/vt220-rm/chapter4.html - vt220 only? return true; } @@ -1323,7 +1326,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.lines.splice(j, 0, this._activeBuffer.getBlankLine(this._eraseAttrData())); } - this._dirtyRowService.markRangeDirty(this._activeBuffer.y, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.y, this._activeBuffer.scrollBottom); this._activeBuffer.x = 0; // see https://vt100.net/docs/vt220-rm/chapter4.html - vt220 only? return true; } @@ -1349,7 +1352,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData() ); - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); } return true; } @@ -1375,7 +1378,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData() ); - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); } return true; } @@ -1395,7 +1398,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.lines.splice(this._activeBuffer.ybase + this._activeBuffer.scrollTop, 1); this._activeBuffer.lines.splice(this._activeBuffer.ybase + this._activeBuffer.scrollBottom, 0, this._activeBuffer.getBlankLine(this._eraseAttrData())); } - this._dirtyRowService.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); return true; } @@ -1411,7 +1414,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.lines.splice(this._activeBuffer.ybase + this._activeBuffer.scrollBottom, 1); this._activeBuffer.lines.splice(this._activeBuffer.ybase + this._activeBuffer.scrollTop, 0, this._activeBuffer.getBlankLine(DEFAULT_ATTR_DATA)); } - this._dirtyRowService.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); return true; } @@ -1443,7 +1446,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } - this._dirtyRowService.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); return true; } @@ -1476,7 +1479,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } - this._dirtyRowService.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); return true; } @@ -1499,7 +1502,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } - this._dirtyRowService.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); return true; } @@ -1522,7 +1525,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData()); line.isWrapped = false; } - this._dirtyRowService.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); return true; } @@ -1544,7 +1547,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData() ); - this._dirtyRowService.markDirty(this._activeBuffer.y); + this._dirtyRowTracker.markDirty(this._activeBuffer.y); } return true; } @@ -3220,7 +3223,7 @@ export class InputHandler extends Disposable implements IInputHandler { const scrollRegionHeight = this._activeBuffer.scrollBottom - this._activeBuffer.scrollTop; this._activeBuffer.lines.shiftElements(this._activeBuffer.ybase + this._activeBuffer.y, scrollRegionHeight, 1); this._activeBuffer.lines.set(this._activeBuffer.ybase + this._activeBuffer.y, this._activeBuffer.getBlankLine(this._eraseAttrData())); - this._dirtyRowService.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); + this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom); } else { this._activeBuffer.y--; this._restrictCursor(); // quickfix to not run out of bounds @@ -3293,7 +3296,7 @@ export class InputHandler extends Disposable implements IInputHandler { line.isWrapped = false; } } - this._dirtyRowService.markAllDirty(); + this._dirtyRowTracker.markAllDirty(); this._setCursor(0, 0); return true; } @@ -3344,4 +3347,60 @@ export class InputHandler extends Disposable implements IInputHandler { if (data === ' q') return f(`P1$r${STYLES[opts.cursorStyle] - (opts.cursorBlink ? 1 : 0)} q`); return f(`P0$r`); } + + public markRangeDirty(y1: number, y2: number): void { + this._dirtyRowTracker.markRangeDirty(y1, y2); + } +} + +export interface IDirtyRowTracker { + readonly start: number; + readonly end: number; + + clearRange(): void; + markDirty(y: number): void; + markRangeDirty(y1: number, y2: number): void; + markAllDirty(): void; +} + +class DirtyRowTracker implements IDirtyRowTracker { + public start!: number; + public end!: number; + + constructor( + @IBufferService private readonly _bufferService: IBufferService + ) { + this.clearRange(); + } + + public clearRange(): void { + this.start = this._bufferService.buffer.y; + this.end = this._bufferService.buffer.y; + } + + public markDirty(y: number): void { + if (y < this.start) { + this.start = y; + } else if (y > this.end) { + this.end = y; + } + } + + public markRangeDirty(y1: number, y2: number): void { + if (y1 > y2) { + $temp = y1; + y1 = y2; + y2 = $temp; + } + if (y1 < this.start) { + this.start = y1; + } + if (y2 > this.end) { + this.end = y2; + } + } + + public markAllDirty(): void { + this.markRangeDirty(0, this._bufferService.rows - 1); + } } diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index 8fb71a5d53..e302d3e4bd 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, IDirtyRowService, ICoreMouseService, ICharsetService, IUnicodeService, IUnicodeVersionProvider, LogLevelEnum, IDecorationService, IInternalDecoration, IOscLinkService } from 'common/services/Services'; +import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, ICoreMouseService, ICharsetService, IUnicodeService, IUnicodeVersionProvider, LogLevelEnum, IDecorationService, IInternalDecoration, IOscLinkService } from 'common/services/Services'; import { IEvent, EventEmitter } from 'common/EventEmitter'; import { clone } from 'common/Clone'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; @@ -100,16 +100,6 @@ export class MockCoreService implements ICoreService { public triggerBinaryEvent(data: string): void { } } -export class MockDirtyRowService implements IDirtyRowService { - public serviceBrand: any; - public start: number = 0; - public end: number = 0; - public clearRange(): void { } - public markDirty(y: number): void { } - public markRangeDirty(y1: number, y2: number): void { } - public markAllDirty(): void { } -} - export class MockLogService implements ILogService { public serviceBrand: any; public logLevel = LogLevelEnum.DEBUG; diff --git a/src/common/services/DirtyRowService.ts b/src/common/services/DirtyRowService.ts deleted file mode 100644 index 1c43b67ef6..0000000000 --- a/src/common/services/DirtyRowService.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2019 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { IBufferService, IDirtyRowService } from 'common/services/Services'; - -export class DirtyRowService implements IDirtyRowService { - public serviceBrand: any; - - private _start!: number; - private _end!: number; - - public get start(): number { return this._start; } - public get end(): number { return this._end; } - - constructor( - @IBufferService private readonly _bufferService: IBufferService - ) { - this.clearRange(); - } - - public clearRange(): void { - this._start = this._bufferService.buffer.y; - this._end = this._bufferService.buffer.y; - } - - public markDirty(y: number): void { - if (y < this._start) { - this._start = y; - } else if (y > this._end) { - this._end = y; - } - } - - public markRangeDirty(y1: number, y2: number): void { - if (y1 > y2) { - const temp = y1; - y1 = y2; - y2 = temp; - } - if (y1 < this._start) { - this._start = y1; - } - if (y2 > this._end) { - this._end = y2; - } - } - - public markAllDirty(): void { - this.markRangeDirty(0, this._bufferService.rows - 1); - } -} diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index 22edad1dd0..e2b517cde3 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -122,19 +122,6 @@ export interface ICharsetService { setgCharset(g: number, charset: ICharset | undefined): void; } -export const IDirtyRowService = createDecorator('DirtyRowService'); -export interface IDirtyRowService { - serviceBrand: undefined; - - readonly start: number; - readonly end: number; - - clearRange(): void; - markDirty(y: number): void; - markRangeDirty(y1: number, y2: number): void; - markAllDirty(): void; -} - export interface IServiceIdentifier { (...args: any[]): void; type: T;