From c668bb1243eb35008fe5f405537ef400caf69297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 3 Jan 2019 16:08:40 +0100 Subject: [PATCH] remove js array based buffer line --- demo/client.ts | 3 +- src/Buffer.ts | 36 ++----------- src/BufferLine.ts | 127 +-------------------------------------------- src/Terminal.ts | 35 ++++--------- src/Types.ts | 4 -- typings/xterm.d.ts | 11 ---- 6 files changed, 16 insertions(+), 200 deletions(-) diff --git a/demo/client.ts b/demo/client.ts index acc83cb86f..a3a912f630 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -205,8 +205,7 @@ function initOptions(term: TerminalType): void { fontFamily: null, fontWeight: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], fontWeightBold: ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'], - rendererType: ['dom', 'canvas'], - experimentalBufferLineImpl: ['JsArray', 'TypedArray'] + rendererType: ['dom', 'canvas'] }; const options = Object.keys((term)._core.options); const booleanOptions = []; diff --git a/src/Buffer.ts b/src/Buffer.ts index 74750a8b4e..625a2497e7 100644 --- a/src/Buffer.ts +++ b/src/Buffer.ts @@ -4,10 +4,10 @@ */ import { CircularList } from './common/CircularList'; -import { CharData, ITerminal, IBuffer, IBufferLine, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult, IBufferLineConstructor } from './Types'; +import { CharData, ITerminal, IBuffer, IBufferLine, BufferIndex, IBufferStringIterator, IBufferStringIteratorResult } from './Types'; import { EventEmitter } from './common/EventEmitter'; import { IMarker } from 'xterm'; -import { BufferLine, BufferLineJSArray } from './BufferLine'; +import { BufferLine } from './BufferLine'; import { DEFAULT_COLOR } from './renderer/atlas/Types'; export const DEFAULT_ATTR = (0 << 18) | (DEFAULT_COLOR << 9) | (256 << 0); @@ -45,7 +45,6 @@ export class Buffer implements IBuffer { public savedX: number; public savedCurAttr: number; public markers: Marker[] = []; - private _bufferLineConstructor: IBufferLineConstructor; /** * Create a new Buffer. @@ -60,35 +59,9 @@ export class Buffer implements IBuffer { this.clear(); } - public setBufferLineFactory(type: string): void { - if (type === 'JsArray') { - if (this._bufferLineConstructor !== BufferLineJSArray) { - this._bufferLineConstructor = BufferLineJSArray; - this._recreateLines(); - } - } else { - if (this._bufferLineConstructor !== BufferLine) { - this._bufferLineConstructor = BufferLine; - this._recreateLines(); - } - } - } - - private _recreateLines(): void { - if (!this.lines) return; - for (let i = 0; i < this.lines.length; ++i) { - const oldLine = this.lines.get(i); - const newLine = new this._bufferLineConstructor(oldLine.length); - for (let j = 0; j < oldLine.length; ++j) { - newLine.set(j, oldLine.get(j)); - } - this.lines.set(i, newLine); - } - } - public getBlankLine(attr: number, isWrapped?: boolean): IBufferLine { const fillCharData: CharData = [attr, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; - return new this._bufferLineConstructor(this._terminal.cols, fillCharData, isWrapped); + return new BufferLine(this._terminal.cols, fillCharData, isWrapped); } public get hasScrollback(): boolean { @@ -135,7 +108,6 @@ export class Buffer implements IBuffer { * Clears the buffer to it's initial state, discarding all previous data. */ public clear(): void { - this.setBufferLineFactory(this._terminal.options.experimentalBufferLineImpl); this.ydisp = 0; this.ybase = 0; this.y = 0; @@ -188,7 +160,7 @@ export class Buffer implements IBuffer { // Add a blank line if there is no buffer left at the top to scroll to, or if there // are blank lines after the cursor const fillCharData: CharData = [DEFAULT_ATTR, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; - this.lines.push(new this._bufferLineConstructor(newCols, fillCharData)); + this.lines.push(new BufferLine(newCols, fillCharData)); } } } diff --git a/src/BufferLine.ts b/src/BufferLine.ts index 3f93af626a..226c4a87eb 100644 --- a/src/BufferLine.ts +++ b/src/BufferLine.ts @@ -3,133 +3,8 @@ * @license MIT */ import { CharData, IBufferLine } from './Types'; -import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, WHITESPACE_CELL_CHAR } from './Buffer'; +import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, WHITESPACE_CELL_CHAR } from './Buffer'; -/** - * Class representing a terminal line. - * - * @deprecated to be removed with one of the next releases - */ -export class BufferLineJSArray implements IBufferLine { - protected _data: CharData[]; - public isWrapped = false; - public length: number; - - constructor(cols: number, fillCharData?: CharData, isWrapped?: boolean) { - this._data = []; - if (!fillCharData) { - fillCharData = [0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]; - } - for (let i = 0; i < cols; i++) { - this._push(fillCharData); // Note: the ctor ch is not cloned (resembles old behavior) - } - if (isWrapped) { - this.isWrapped = true; - } - this.length = this._data.length; - } - - private _pop(): CharData | undefined { - const data = this._data.pop(); - this.length = this._data.length; - return data; - } - - private _push(data: CharData): void { - this._data.push(data); - this.length = this._data.length; - } - - private _splice(start: number, deleteCount: number, ...items: CharData[]): CharData[] { - const removed = this._data.splice(start, deleteCount, ...items); - this.length = this._data.length; - return removed; - } - - public get(index: number): CharData { - return this._data[index]; - } - - public set(index: number, data: CharData): void { - this._data[index] = data; - } - - /** insert n cells ch at pos, right cells are lost (stable length) */ - public insertCells(pos: number, n: number, ch: CharData): void { - while (n--) { - this._splice(pos, 0, ch); - this._pop(); - } - } - - /** delete n cells at pos, right side is filled with fill (stable length) */ - public deleteCells(pos: number, n: number, fillCharData: CharData): void { - while (n--) { - this._splice(pos, 1); - this._push(fillCharData); - } - } - - /** replace cells from pos to pos + n - 1 with fill */ - public replaceCells(start: number, end: number, fillCharData: CharData): void { - while (start < end && start < this.length) { - this.set(start++, fillCharData); // Note: fill is not cloned (resembles old behavior) - } - } - - /** resize line to cols filling new cells with fill */ - public resize(cols: number, fillCharData: CharData, shrink: boolean = false): void { - while (this._data.length < cols) { - this._data.push(fillCharData); - } - if (shrink) { - while (this._data.length > cols) { - this._data.pop(); - } - } - this.length = this._data.length; - } - - public fill(fillCharData: CharData): void { - for (let i = 0; i < this.length; ++i) { - this.set(i, fillCharData); - } - } - - public copyFrom(line: BufferLineJSArray): void { - this._data = line._data.slice(0); - this.length = line.length; - this.isWrapped = line.isWrapped; - } - - public clone(): IBufferLine { - const newLine = new BufferLineJSArray(0); - newLine.copyFrom(this); - return newLine; - } - - public getTrimmedLength(): number { - for (let i = this.length - 1; i >= 0; --i) { - const ch = this.get(i); - if (ch[CHAR_DATA_CHAR_INDEX] !== '') { - return i + ch[CHAR_DATA_WIDTH_INDEX]; - } - } - return 0; - } - - public translateToString(trimRight: boolean = false, startCol: number = 0, endCol: number = this.length): string { - if (trimRight) { - endCol = Math.min(endCol, this.getTrimmedLength()); - } - let result = ''; - while (startCol < endCol) { - result += this.get(startCol)[CHAR_DATA_CHAR_INDEX] || WHITESPACE_CELL_CHAR; - startCol += this.get(startCol)[CHAR_DATA_WIDTH_INDEX] || 1; - } - return result; - } -} /** typed array slots taken by one cell */ const CELL_SIZE = 3; diff --git a/src/Terminal.ts b/src/Terminal.ts index bed45e46ec..bc97de29ff 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -105,8 +105,7 @@ const DEFAULT_OPTIONS: ITerminalOptions = { tabStopWidth: 8, theme: null, rightClickSelectsWord: Browser.isMac, - rendererType: 'canvas', - experimentalBufferLineImpl: 'TypedArray' + rendererType: 'canvas' }; export class Terminal extends EventEmitter implements ITerminal, IDisposable, IInputHandlingTerminal { @@ -497,11 +496,6 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II } break; case 'tabStopWidth': this.buffers.setupTabStops(); break; - case 'experimentalBufferLineImpl': - this.buffers.normal.setBufferLineFactory(value); - this.buffers.alt.setBufferLineFactory(value); - this._blankLine = null; - break; } // Inform renderer of changes if (this.renderer) { @@ -1180,17 +1174,12 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II */ public scroll(isWrapped: boolean = false): void { let newLine: IBufferLine; - const useRecycling = this.options.experimentalBufferLineImpl !== 'JsArray'; - if (useRecycling) { - newLine = this._blankLine; - if (!newLine || newLine.length !== this.cols || newLine.get(0)[CHAR_DATA_ATTR_INDEX] !== this.eraseAttr()) { - newLine = this.buffer.getBlankLine(this.eraseAttr(), isWrapped); - this._blankLine = newLine; - } - newLine.isWrapped = isWrapped; - } else { + newLine = this._blankLine; + if (!newLine || newLine.length !== this.cols || newLine.get(0)[CHAR_DATA_ATTR_INDEX] !== this.eraseAttr()) { newLine = this.buffer.getBlankLine(this.eraseAttr(), isWrapped); + this._blankLine = newLine; } + newLine.isWrapped = isWrapped; const topRow = this.buffer.ybase + this.buffer.scrollTop; const bottomRow = this.buffer.ybase + this.buffer.scrollBottom; @@ -1201,17 +1190,13 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // Insert the line using the fastest method if (bottomRow === this.buffer.lines.length - 1) { - if (useRecycling) { - if (willBufferBeTrimmed) { - this.buffer.lines.recycle().copyFrom(newLine); - } else { - this.buffer.lines.push(newLine.clone()); - } + if (willBufferBeTrimmed) { + this.buffer.lines.recycle().copyFrom(newLine); } else { - this.buffer.lines.push(newLine); + this.buffer.lines.push(newLine.clone()); } } else { - this.buffer.lines.splice(bottomRow + 1, 0, (useRecycling) ? newLine.clone() : newLine); + this.buffer.lines.splice(bottomRow + 1, 0, newLine.clone()); } // Only adjust ybase and ydisp when the buffer is not trimmed @@ -1233,7 +1218,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II // scrollback, instead we can just shift them in-place. const scrollRegionHeight = bottomRow - topRow + 1/*as it's zero-based*/; this.buffer.lines.shiftElements(topRow + 1, scrollRegionHeight - 1, -1); - this.buffer.lines.set(bottomRow, (useRecycling) ? newLine.clone() : newLine); + this.buffer.lines.set(bottomRow, newLine.clone()); } // Move the viewport to the bottom of the buffer unless the user is diff --git a/src/Types.ts b/src/Types.ts index b54b9d6610..c6395ea3ca 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -529,7 +529,3 @@ export interface IBufferLine { getTrimmedLength(): number; translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string; } - -export interface IBufferLineConstructor { - new(cols: number, fillCharData?: CharData, isWrapped?: boolean): IBufferLine; -} diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index 0ceab01dcc..c5d2b0204e 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -101,17 +101,6 @@ declare module 'xterm' { */ experimentalCharAtlas?: 'none' | 'static' | 'dynamic'; - /** - * (EXPERIMENTAL) Defines which implementation to use for buffer lines. - * - * - 'JsArray': The default/stable implementation. - * - 'TypedArray': The new experimental implementation based on TypedArrays that is expected to - * significantly boost performance and memory consumption. Use at your own risk. - * - * @deprecated This option will be removed in the future. - */ - experimentalBufferLineImpl?: 'JsArray' | 'TypedArray'; - /** * The font size used to render text. */