@xterm/xterm 6.1.0-beta.213 → 6.1.0-beta.215
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -8
- package/lib/xterm.mjs.map +4 -4
- package/package.json +2 -2
- package/src/common/Version.ts +1 -1
- package/src/common/buffer/Buffer.ts +14 -5
- package/src/common/buffer/BufferLine.ts +74 -3
- package/src/common/buffer/BufferLineStringCache.ts +69 -0
- package/src/common/buffer/BufferSet.ts +5 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xterm/xterm",
|
|
3
3
|
"description": "Full xterm terminal, in your browser",
|
|
4
|
-
"version": "6.1.0-beta.
|
|
4
|
+
"version": "6.1.0-beta.215",
|
|
5
5
|
"main": "lib/xterm.js",
|
|
6
6
|
"module": "lib/xterm.mjs",
|
|
7
7
|
"style": "css/xterm.css",
|
|
@@ -119,5 +119,5 @@
|
|
|
119
119
|
"ws": "^8.2.3",
|
|
120
120
|
"xterm-benchmark": "^0.3.1"
|
|
121
121
|
},
|
|
122
|
-
"commit": "
|
|
122
|
+
"commit": "1023e404281ce625b469bd3614c38df26bcf885d"
|
|
123
123
|
}
|
package/src/common/Version.ts
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { CircularList, IInsertEvent } from 'common/CircularList';
|
|
7
|
+
import { Disposable, toDisposable } from 'common/Lifecycle';
|
|
7
8
|
import { IdleTaskQueue } from 'common/TaskQueue';
|
|
8
9
|
import { IAttributeData, IBufferLine, ICellData, ICharset } from 'common/Types';
|
|
9
10
|
import { ExtendedAttrs } from 'common/buffer/AttributeData';
|
|
10
11
|
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
|
|
12
|
+
import { BufferLineStringCache } from 'common/buffer/BufferLineStringCache';
|
|
11
13
|
import { getWrappedLineTrimmedLength, reflowLargerApplyNewLayout, reflowLargerCreateNewLayout, reflowLargerGetLinesToRemove, reflowSmallerGetNewLineLengths } from 'common/buffer/BufferReflow';
|
|
12
14
|
import { CellData } from 'common/buffer/CellData';
|
|
13
15
|
import { NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE, WHITESPACE_CELL_WIDTH } from 'common/buffer/Constants';
|
|
@@ -25,7 +27,7 @@ export const MAX_BUFFER_SIZE = 4294967295; // 2^32 - 1
|
|
|
25
27
|
* - cursor position
|
|
26
28
|
* - scroll position
|
|
27
29
|
*/
|
|
28
|
-
export class Buffer implements IBuffer {
|
|
30
|
+
export class Buffer extends Disposable implements IBuffer {
|
|
29
31
|
public lines: CircularList<IBufferLine>;
|
|
30
32
|
public ydisp: number = 0;
|
|
31
33
|
public ybase: number = 0;
|
|
@@ -50,6 +52,7 @@ export class Buffer implements IBuffer {
|
|
|
50
52
|
private _isClearing: boolean = false;
|
|
51
53
|
private _memoryCleanupQueue: InstanceType<typeof IdleTaskQueue>;
|
|
52
54
|
private _memoryCleanupPosition = 0;
|
|
55
|
+
private readonly _stringCache: BufferLineStringCache;
|
|
53
56
|
|
|
54
57
|
constructor(
|
|
55
58
|
private _hasScrollback: boolean,
|
|
@@ -57,6 +60,7 @@ export class Buffer implements IBuffer {
|
|
|
57
60
|
private _bufferService: IBufferService,
|
|
58
61
|
private readonly _logService: ILogService
|
|
59
62
|
) {
|
|
63
|
+
super();
|
|
60
64
|
this._cols = this._bufferService.cols;
|
|
61
65
|
this._rows = this._bufferService.rows;
|
|
62
66
|
this.lines = new CircularList<IBufferLine>(this._getCorrectBufferLength(this._rows));
|
|
@@ -64,6 +68,9 @@ export class Buffer implements IBuffer {
|
|
|
64
68
|
this.scrollBottom = this._rows - 1;
|
|
65
69
|
this.setupTabStops();
|
|
66
70
|
this._memoryCleanupQueue = new IdleTaskQueue(this._logService);
|
|
71
|
+
this._register(toDisposable(() => this._memoryCleanupQueue.clear()));
|
|
72
|
+
this._register(toDisposable(() => this.clearAllMarkers()));
|
|
73
|
+
this._stringCache = this._register(new BufferLineStringCache());
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
public getNullCell(attr?: IAttributeData): ICellData {
|
|
@@ -93,7 +100,7 @@ export class Buffer implements IBuffer {
|
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
public getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine {
|
|
96
|
-
return new BufferLine(this._bufferService.cols, this.getNullCell(attr), isWrapped);
|
|
103
|
+
return new BufferLine(this._stringCache, this._bufferService.cols, this.getNullCell(attr), isWrapped);
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
public get hasScrollback(): boolean {
|
|
@@ -138,6 +145,7 @@ export class Buffer implements IBuffer {
|
|
|
138
145
|
* Clears the buffer to it's initial state, discarding all previous data.
|
|
139
146
|
*/
|
|
140
147
|
public clear(): void {
|
|
148
|
+
this._stringCache.clear();
|
|
141
149
|
this.ydisp = 0;
|
|
142
150
|
this.ybase = 0;
|
|
143
151
|
this.y = 0;
|
|
@@ -156,6 +164,7 @@ export class Buffer implements IBuffer {
|
|
|
156
164
|
public resize(newCols: number, newRows: number): void {
|
|
157
165
|
// store reference to null cell with default attrs
|
|
158
166
|
const nullCell = this.getNullCell(DEFAULT_ATTR_DATA);
|
|
167
|
+
this._stringCache.clear();
|
|
159
168
|
|
|
160
169
|
// count bufferlines with overly big memory to be cleaned afterwards
|
|
161
170
|
let dirtyMemoryLines = 0;
|
|
@@ -190,7 +199,7 @@ export class Buffer implements IBuffer {
|
|
|
190
199
|
if (this._optionsService.rawOptions.windowsPty.backend !== undefined || this._optionsService.rawOptions.windowsPty.buildNumber !== undefined) {
|
|
191
200
|
// Just add the new missing rows on Windows as conpty reprints the screen with it's
|
|
192
201
|
// view of the world. Once a line enters scrollback for conpty it remains there
|
|
193
|
-
this.lines.push(new BufferLine(newCols, nullCell));
|
|
202
|
+
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
|
|
194
203
|
} else {
|
|
195
204
|
if (this.ybase > 0 && this.lines.length <= this.ybase + this.y + addToY + 1) {
|
|
196
205
|
// There is room above the buffer and there are no empty elements below the line,
|
|
@@ -204,7 +213,7 @@ export class Buffer implements IBuffer {
|
|
|
204
213
|
} else {
|
|
205
214
|
// Add a blank line if there is no buffer left at the top to scroll to, or if there
|
|
206
215
|
// are blank lines after the cursor
|
|
207
|
-
this.lines.push(new BufferLine(newCols, nullCell));
|
|
216
|
+
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
|
|
208
217
|
}
|
|
209
218
|
}
|
|
210
219
|
}
|
|
@@ -345,7 +354,7 @@ export class Buffer implements IBuffer {
|
|
|
345
354
|
}
|
|
346
355
|
if (this.lines.length < newRows) {
|
|
347
356
|
// Add an extra row at the bottom of the viewport
|
|
348
|
-
this.lines.push(new BufferLine(newCols, nullCell));
|
|
357
|
+
this.lines.push(new BufferLine(this._stringCache, newCols, nullCell, false));
|
|
349
358
|
}
|
|
350
359
|
} else {
|
|
351
360
|
if (this.ydisp === this.ybase) {
|
|
@@ -44,6 +44,18 @@ const $workCell = new CellData();
|
|
|
44
44
|
/** Factor when to cleanup underlying array buffer after shrinking. */
|
|
45
45
|
const CLEANUP_THRESHOLD = 2;
|
|
46
46
|
|
|
47
|
+
export interface IBufferLineStringCacheEntry {
|
|
48
|
+
value: string | undefined;
|
|
49
|
+
isTrimmed: boolean;
|
|
50
|
+
generation: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface IBufferLineStringCache {
|
|
54
|
+
generation: number;
|
|
55
|
+
allocateEntry(): IBufferLineStringCacheEntry;
|
|
56
|
+
touch?(): void;
|
|
57
|
+
}
|
|
58
|
+
|
|
47
59
|
/**
|
|
48
60
|
* Typed array based bufferline implementation.
|
|
49
61
|
*
|
|
@@ -63,9 +75,15 @@ export class BufferLine implements IBufferLine {
|
|
|
63
75
|
protected _data: Uint32Array;
|
|
64
76
|
protected _combined: {[index: number]: string} = {};
|
|
65
77
|
protected _extendedAttrs: {[index: number]: IExtendedAttrs | undefined} = {};
|
|
78
|
+
protected _stringCacheEntryRef: WeakRef<IBufferLineStringCacheEntry> | undefined;
|
|
66
79
|
public length: number;
|
|
67
80
|
|
|
68
|
-
constructor(
|
|
81
|
+
constructor(
|
|
82
|
+
protected readonly _stringCache: IBufferLineStringCache,
|
|
83
|
+
cols: number,
|
|
84
|
+
fillCellData?: ICellData,
|
|
85
|
+
public isWrapped: boolean = false
|
|
86
|
+
) {
|
|
69
87
|
this._data = new Uint32Array(cols * CELL_SIZE);
|
|
70
88
|
const cell = fillCellData ?? CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
|
71
89
|
for (let i = 0; i < cols; ++i) {
|
|
@@ -98,6 +116,7 @@ export class BufferLine implements IBufferLine {
|
|
|
98
116
|
* @deprecated
|
|
99
117
|
*/
|
|
100
118
|
public set(index: number, value: CharData): void {
|
|
119
|
+
this._invalidateStringCache();
|
|
101
120
|
this._data[index * CELL_SIZE + Cell.FG] = value[CHAR_DATA_ATTR_INDEX];
|
|
102
121
|
if (value[CHAR_DATA_CHAR_INDEX].length > 1) {
|
|
103
122
|
this._combined[index] = value[1];
|
|
@@ -197,6 +216,7 @@ export class BufferLine implements IBufferLine {
|
|
|
197
216
|
* Set data at `index` to `cell`.
|
|
198
217
|
*/
|
|
199
218
|
public setCell(index: number, cell: ICellData): void {
|
|
219
|
+
this._invalidateStringCache();
|
|
200
220
|
if (cell.content & Content.IS_COMBINED_MASK) {
|
|
201
221
|
this._combined[index] = cell.combinedData;
|
|
202
222
|
}
|
|
@@ -214,6 +234,7 @@ export class BufferLine implements IBufferLine {
|
|
|
214
234
|
* it gets an optimized access method.
|
|
215
235
|
*/
|
|
216
236
|
public setCellFromCodepoint(index: number, codePoint: number, width: number, attrs: IAttributeData): void {
|
|
237
|
+
this._invalidateStringCache();
|
|
217
238
|
if (attrs.bg & BgFlags.HAS_EXTENDED) {
|
|
218
239
|
this._extendedAttrs[index] = attrs.extended;
|
|
219
240
|
}
|
|
@@ -229,6 +250,7 @@ export class BufferLine implements IBufferLine {
|
|
|
229
250
|
* by the previous `setDataFromCodePoint` call, we can omit it here.
|
|
230
251
|
*/
|
|
231
252
|
public addCodepointToCell(index: number, codePoint: number, width: number): void {
|
|
253
|
+
this._invalidateStringCache();
|
|
232
254
|
let content = this._data[index * CELL_SIZE + Cell.CONTENT];
|
|
233
255
|
if (content & Content.IS_COMBINED_MASK) {
|
|
234
256
|
// we already have a combined string, simply add
|
|
@@ -255,6 +277,7 @@ export class BufferLine implements IBufferLine {
|
|
|
255
277
|
}
|
|
256
278
|
|
|
257
279
|
public insertCells(pos: number, n: number, fillCellData: ICellData): void {
|
|
280
|
+
this._invalidateStringCache();
|
|
258
281
|
pos %= this.length;
|
|
259
282
|
|
|
260
283
|
// handle fullwidth at pos: reset cell one to the left if pos is second cell of a wide char
|
|
@@ -282,6 +305,7 @@ export class BufferLine implements IBufferLine {
|
|
|
282
305
|
}
|
|
283
306
|
|
|
284
307
|
public deleteCells(pos: number, n: number, fillCellData: ICellData): void {
|
|
308
|
+
this._invalidateStringCache();
|
|
285
309
|
pos %= this.length;
|
|
286
310
|
if (n < this.length - pos) {
|
|
287
311
|
for (let i = 0; i < this.length - pos - n; ++i) {
|
|
@@ -308,6 +332,7 @@ export class BufferLine implements IBufferLine {
|
|
|
308
332
|
}
|
|
309
333
|
|
|
310
334
|
public replaceCells(start: number, end: number, fillCellData: ICellData, respectProtect: boolean = false): void {
|
|
335
|
+
this._invalidateStringCache();
|
|
311
336
|
// full branching on respectProtect==true, hopefully getting fast JIT for standard case
|
|
312
337
|
if (respectProtect) {
|
|
313
338
|
if (start && this.getWidth(start - 1) === 2 && !this.isProtected(start - 1)) {
|
|
@@ -347,6 +372,7 @@ export class BufferLine implements IBufferLine {
|
|
|
347
372
|
* excess memory (true after shrinking > CLEANUP_THRESHOLD).
|
|
348
373
|
*/
|
|
349
374
|
public resize(cols: number, fillCellData: ICellData): boolean {
|
|
375
|
+
this._invalidateStringCache();
|
|
350
376
|
if (cols === this.length) {
|
|
351
377
|
return this._data.length * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength;
|
|
352
378
|
}
|
|
@@ -406,6 +432,7 @@ export class BufferLine implements IBufferLine {
|
|
|
406
432
|
|
|
407
433
|
/** fill a line with fillCharData */
|
|
408
434
|
public fill(fillCellData: ICellData, respectProtect: boolean = false): void {
|
|
435
|
+
this._invalidateStringCache();
|
|
409
436
|
// full branching on respectProtect==true, hopefully getting fast JIT for standard case
|
|
410
437
|
if (respectProtect) {
|
|
411
438
|
for (let i = 0; i < this.length; ++i) {
|
|
@@ -424,6 +451,7 @@ export class BufferLine implements IBufferLine {
|
|
|
424
451
|
|
|
425
452
|
/** alter to a full copy of line */
|
|
426
453
|
public copyFrom(line: BufferLine): void {
|
|
454
|
+
this._invalidateStringCache();
|
|
427
455
|
if (this.length !== line.length) {
|
|
428
456
|
this._data = new Uint32Array(line._data);
|
|
429
457
|
} else {
|
|
@@ -444,7 +472,7 @@ export class BufferLine implements IBufferLine {
|
|
|
444
472
|
|
|
445
473
|
/** create a new clone */
|
|
446
474
|
public clone(): IBufferLine {
|
|
447
|
-
const newLine = new BufferLine(0);
|
|
475
|
+
const newLine = new BufferLine(this._stringCache, 0, undefined, false);
|
|
448
476
|
newLine._data = new Uint32Array(this._data);
|
|
449
477
|
newLine.length = this.length;
|
|
450
478
|
for (const el in this._combined) {
|
|
@@ -476,6 +504,7 @@ export class BufferLine implements IBufferLine {
|
|
|
476
504
|
}
|
|
477
505
|
|
|
478
506
|
public copyCellsFrom(src: BufferLine, srcCol: number, destCol: number, length: number, applyInReverse: boolean): void {
|
|
507
|
+
this._invalidateStringCache();
|
|
479
508
|
const srcData = src._data;
|
|
480
509
|
if (applyInReverse) {
|
|
481
510
|
for (let cell = length - 1; cell >= 0; cell--) {
|
|
@@ -508,7 +537,8 @@ export class BufferLine implements IBufferLine {
|
|
|
508
537
|
}
|
|
509
538
|
|
|
510
539
|
/**
|
|
511
|
-
* Translates the buffer line to a string.
|
|
540
|
+
* Translates the buffer line to a string. Caching only applies to canonical full-line translation
|
|
541
|
+
* requests (regardless of `trimRight` value).
|
|
512
542
|
*
|
|
513
543
|
* @param trimRight Whether to trim any empty cells on the right.
|
|
514
544
|
* @param startCol The column to start the string (0-based inclusive).
|
|
@@ -521,6 +551,19 @@ export class BufferLine implements IBufferLine {
|
|
|
521
551
|
* returned string, the corresponding entries in `outColumns` will have the same column number.
|
|
522
552
|
*/
|
|
523
553
|
public translateToString(trimRight?: boolean, startCol?: number, endCol?: number, outColumns?: number[]): string {
|
|
554
|
+
const isCanonicalRequest = (startCol === undefined || startCol === 0) && endCol === undefined && outColumns === undefined;
|
|
555
|
+
if (isCanonicalRequest) {
|
|
556
|
+
this._stringCache.touch?.();
|
|
557
|
+
}
|
|
558
|
+
const stringCacheEntry = isCanonicalRequest ? this._getStringCacheEntry(false) : undefined;
|
|
559
|
+
if (isCanonicalRequest && stringCacheEntry?.value !== undefined) {
|
|
560
|
+
if (trimRight) {
|
|
561
|
+
return stringCacheEntry.isTrimmed ? stringCacheEntry.value : stringCacheEntry.value.trimEnd();
|
|
562
|
+
}
|
|
563
|
+
if (!stringCacheEntry.isTrimmed) {
|
|
564
|
+
return stringCacheEntry.value;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
524
567
|
startCol = startCol ?? 0;
|
|
525
568
|
endCol = endCol ?? this.length;
|
|
526
569
|
if (trimRight) {
|
|
@@ -545,6 +588,34 @@ export class BufferLine implements IBufferLine {
|
|
|
545
588
|
if (outColumns) {
|
|
546
589
|
outColumns.push(startCol);
|
|
547
590
|
}
|
|
591
|
+
if (isCanonicalRequest) {
|
|
592
|
+
const cacheEntry = this._getStringCacheEntry(true)!;
|
|
593
|
+
cacheEntry.value = result;
|
|
594
|
+
cacheEntry.isTrimmed = !!trimRight;
|
|
595
|
+
}
|
|
548
596
|
return result;
|
|
549
597
|
}
|
|
598
|
+
|
|
599
|
+
protected _getStringCacheEntry(createIfNeeded: boolean): IBufferLineStringCacheEntry | undefined {
|
|
600
|
+
const cachedEntry = this._stringCacheEntryRef?.deref();
|
|
601
|
+
if (cachedEntry) {
|
|
602
|
+
if (cachedEntry.generation === this._stringCache.generation) {
|
|
603
|
+
return cachedEntry;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
if (!createIfNeeded) {
|
|
607
|
+
return undefined;
|
|
608
|
+
}
|
|
609
|
+
const cacheEntry = this._stringCache.allocateEntry();
|
|
610
|
+
this._stringCacheEntryRef = new WeakRef(cacheEntry);
|
|
611
|
+
return cacheEntry;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
private _invalidateStringCache(): void {
|
|
615
|
+
const cacheEntry = this._getStringCacheEntry(false);
|
|
616
|
+
if (cacheEntry) {
|
|
617
|
+
cacheEntry.value = undefined;
|
|
618
|
+
cacheEntry.isTrimmed = false;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
550
621
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { IBufferLineStringCache, IBufferLineStringCacheEntry } from 'common/buffer/BufferLine';
|
|
7
|
+
import { disposableTimeout } from 'common/Async';
|
|
8
|
+
import { Disposable, MutableDisposable, toDisposable, type IDisposable } from 'common/Lifecycle';
|
|
9
|
+
|
|
10
|
+
const enum Constants {
|
|
11
|
+
CACHE_TTL_MS = 15000
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class BufferLineStringCache extends Disposable implements IBufferLineStringCache {
|
|
15
|
+
public generation: number = 0;
|
|
16
|
+
public readonly entries: Set<IBufferLineStringCacheEntry> = new Set();
|
|
17
|
+
private readonly _clearTimeout = this._register(new MutableDisposable<IDisposable>());
|
|
18
|
+
private _lastAccessTimestamp: number = 0;
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
super();
|
|
22
|
+
this._register(toDisposable(() => this.entries.clear()));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public touch(): void {
|
|
26
|
+
this._scheduleClear();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public allocateEntry(): IBufferLineStringCacheEntry {
|
|
30
|
+
const entry: IBufferLineStringCacheEntry = {
|
|
31
|
+
value: undefined,
|
|
32
|
+
isTrimmed: false,
|
|
33
|
+
generation: this.generation
|
|
34
|
+
};
|
|
35
|
+
this.entries.add(entry);
|
|
36
|
+
this._scheduleClear();
|
|
37
|
+
return entry;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public clear(): void {
|
|
41
|
+
this._clearTimeout.clear();
|
|
42
|
+
this._lastAccessTimestamp = 0;
|
|
43
|
+
this.generation++;
|
|
44
|
+
for (const entry of this.entries) {
|
|
45
|
+
entry.value = undefined;
|
|
46
|
+
entry.isTrimmed = false;
|
|
47
|
+
}
|
|
48
|
+
this.entries.clear();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private _scheduleClear(): void {
|
|
52
|
+
this._lastAccessTimestamp = Date.now();
|
|
53
|
+
if (this._clearTimeout.value) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this._scheduleClearTimeout(Constants.CACHE_TTL_MS);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private _scheduleClearTimeout(timeoutMs: number): void {
|
|
60
|
+
this._clearTimeout.value = disposableTimeout(() => {
|
|
61
|
+
const elapsed = Date.now() - this._lastAccessTimestamp;
|
|
62
|
+
if (elapsed >= Constants.CACHE_TTL_MS) {
|
|
63
|
+
this.clear();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this._scheduleClearTimeout(Constants.CACHE_TTL_MS - elapsed);
|
|
67
|
+
}, timeoutMs);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { Disposable } from 'common/Lifecycle';
|
|
6
|
+
import { Disposable, MutableDisposable } from 'common/Lifecycle';
|
|
7
7
|
import { IAttributeData } from 'common/Types';
|
|
8
8
|
import { Buffer } from 'common/buffer/Buffer';
|
|
9
9
|
import { IBuffer, IBufferSet } from 'common/buffer/Types';
|
|
@@ -18,6 +18,8 @@ export class BufferSet extends Disposable implements IBufferSet {
|
|
|
18
18
|
private _normal!: Buffer;
|
|
19
19
|
private _alt!: Buffer;
|
|
20
20
|
private _activeBuffer!: Buffer;
|
|
21
|
+
private readonly _normalBuffer = this._register(new MutableDisposable<Buffer>());
|
|
22
|
+
private readonly _altBuffer = this._register(new MutableDisposable<Buffer>());
|
|
21
23
|
|
|
22
24
|
private readonly _onBufferActivate = this._register(new Emitter<{ activeBuffer: IBuffer, inactiveBuffer: IBuffer }>());
|
|
23
25
|
public readonly onBufferActivate = this._onBufferActivate.event;
|
|
@@ -38,11 +40,13 @@ export class BufferSet extends Disposable implements IBufferSet {
|
|
|
38
40
|
|
|
39
41
|
public reset(): void {
|
|
40
42
|
this._normal = new Buffer(true, this._optionsService, this._bufferService, this._logService);
|
|
43
|
+
this._normalBuffer.value = this._normal;
|
|
41
44
|
this._normal.fillViewportRows();
|
|
42
45
|
|
|
43
46
|
// The alt buffer should never have scrollback.
|
|
44
47
|
// See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer
|
|
45
48
|
this._alt = new Buffer(false, this._optionsService, this._bufferService, this._logService);
|
|
49
|
+
this._altBuffer.value = this._alt;
|
|
46
50
|
this._activeBuffer = this._normal;
|
|
47
51
|
this._onBufferActivate.fire({
|
|
48
52
|
activeBuffer: this._normal,
|