@xterm/xterm 6.1.0-beta.28 → 6.1.0-beta.281
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/README.md +62 -38
- package/css/xterm.css +29 -22
- package/lib/xterm.js +1 -1
- package/lib/xterm.js.map +1 -1
- package/lib/xterm.mjs +8 -34
- package/lib/xterm.mjs.map +4 -4
- package/package.json +56 -45
- package/src/browser/AccessibilityManager.ts +18 -13
- package/src/browser/Clipboard.ts +8 -5
- package/src/browser/ColorContrastCache.ts +3 -3
- package/src/browser/CoreBrowserTerminal.ts +179 -348
- package/src/browser/Dom.ts +178 -0
- package/src/browser/Linkifier.ts +14 -14
- package/src/browser/OscLinkProvider.ts +86 -18
- package/src/browser/RenderDebouncer.ts +7 -9
- package/src/browser/TimeBasedDebouncer.ts +12 -5
- package/src/browser/Types.ts +16 -14
- package/src/browser/Viewport.ts +58 -23
- package/src/browser/decorations/BufferDecorationRenderer.ts +3 -3
- package/src/browser/decorations/ColorZoneStore.ts +1 -1
- package/src/browser/decorations/OverviewRulerRenderer.ts +36 -20
- package/src/browser/input/CompositionHelper.ts +47 -11
- package/src/browser/input/Mouse.ts +5 -9
- package/src/browser/input/MoveToCell.ts +3 -3
- package/src/browser/public/Terminal.ts +33 -36
- package/src/browser/renderer/dom/DomRenderer.ts +265 -89
- package/src/browser/renderer/dom/DomRendererRowFactory.ts +34 -27
- package/src/browser/renderer/dom/WidthCache.ts +57 -55
- package/src/browser/renderer/shared/Constants.ts +7 -0
- package/src/browser/renderer/shared/RendererUtils.ts +1 -1
- package/src/browser/renderer/shared/SelectionRenderModel.ts +2 -2
- package/src/browser/renderer/shared/TextBlinkStateManager.ts +97 -0
- package/src/browser/renderer/shared/Types.ts +10 -4
- package/src/browser/scrollable/abstractScrollbar.ts +300 -0
- package/src/browser/scrollable/fastDomNode.ts +126 -0
- package/src/browser/scrollable/globalPointerMoveMonitor.ts +90 -0
- package/src/browser/scrollable/horizontalScrollbar.ts +85 -0
- package/src/browser/scrollable/mouseEvent.ts +292 -0
- package/src/browser/scrollable/scrollable.ts +486 -0
- package/src/browser/scrollable/scrollableElement.ts +581 -0
- package/src/browser/scrollable/scrollableElementOptions.ts +161 -0
- package/src/browser/scrollable/scrollbarArrow.ts +110 -0
- package/src/browser/scrollable/scrollbarState.ts +246 -0
- package/src/browser/scrollable/scrollbarVisibilityController.ts +113 -0
- package/src/browser/scrollable/touch.ts +485 -0
- package/src/browser/scrollable/verticalScrollbar.ts +143 -0
- package/src/browser/scrollable/widget.ts +23 -0
- package/src/browser/selection/SelectionModel.ts +1 -1
- package/src/browser/services/CharSizeService.ts +4 -4
- package/src/browser/services/CharacterJoinerService.ts +13 -11
- package/src/browser/services/CoreBrowserService.ts +7 -5
- package/src/browser/services/KeyboardService.ts +67 -0
- package/src/browser/services/LinkProviderService.ts +3 -3
- package/src/browser/services/MouseCoordsService.ts +47 -0
- package/src/browser/services/MouseService.ts +619 -23
- package/src/browser/services/RenderService.ts +33 -21
- package/src/browser/services/SelectionService.ts +72 -54
- package/src/browser/services/Services.ts +44 -21
- package/src/browser/services/ThemeService.ts +9 -9
- package/src/common/Async.ts +141 -0
- package/src/common/CircularList.ts +24 -3
- package/src/common/Color.ts +13 -5
- package/src/common/CoreTerminal.ts +61 -35
- package/src/common/Event.ts +118 -0
- package/src/common/InputHandler.ts +286 -105
- package/src/common/Lifecycle.ts +113 -0
- package/src/common/Platform.ts +15 -5
- package/src/common/SortedList.ts +8 -4
- package/src/common/StringBuilder.ts +67 -0
- package/src/common/TaskQueue.ts +17 -8
- package/src/common/Types.ts +68 -206
- package/src/common/Version.ts +1 -1
- package/src/common/WindowsMode.ts +2 -2
- package/src/common/buffer/AttributeData.ts +3 -2
- package/src/common/buffer/Buffer.ts +47 -32
- package/src/common/buffer/BufferLine.ts +175 -100
- package/src/common/buffer/BufferLineStringCache.ts +69 -0
- package/src/common/buffer/BufferReflow.ts +7 -4
- package/src/common/buffer/BufferSet.ts +13 -9
- package/src/common/buffer/CellData.ts +61 -4
- package/src/common/buffer/Constants.ts +13 -13
- package/src/common/buffer/Marker.ts +4 -4
- package/src/common/buffer/Types.ts +153 -3
- package/src/common/data/Charsets.ts +4 -7
- package/src/common/data/EscapeSequences.ts +71 -70
- package/src/common/input/Keyboard.ts +17 -10
- package/src/common/input/KittyKeyboard.ts +526 -0
- package/src/common/input/TextDecoder.ts +3 -3
- package/src/common/input/UnicodeV6.ts +3 -2
- package/src/common/input/Win32InputMode.ts +297 -0
- package/src/common/input/WriteBuffer.ts +108 -39
- package/src/common/input/XParseColor.ts +2 -2
- package/src/common/parser/ApcParser.ts +196 -0
- package/src/common/parser/Constants.ts +14 -4
- package/src/common/parser/DcsParser.ts +15 -16
- package/src/common/parser/EscapeSequenceParser.ts +214 -72
- package/src/common/parser/OscParser.ts +14 -15
- package/src/common/parser/Params.ts +31 -12
- package/src/common/parser/Types.ts +40 -30
- package/src/common/public/BufferApiView.ts +3 -3
- package/src/common/public/BufferLineApiView.ts +4 -4
- package/src/common/public/BufferNamespaceApi.ts +5 -5
- package/src/common/public/ParserApi.ts +5 -2
- package/src/common/public/UnicodeApi.ts +1 -1
- package/src/common/services/BufferService.ts +17 -13
- package/src/common/services/CharsetService.ts +6 -2
- package/src/common/services/CoreService.ts +23 -10
- package/src/common/services/DecorationService.ts +260 -15
- package/src/common/services/InstantiationService.ts +2 -2
- package/src/common/services/LogService.ts +2 -32
- package/src/common/services/{CoreMouseService.ts → MouseStateService.ts} +22 -133
- package/src/common/services/OptionsService.ts +17 -7
- package/src/common/services/OscLinkService.ts +3 -2
- package/src/common/services/ServiceRegistry.ts +14 -8
- package/src/common/services/Services.ts +54 -50
- package/src/common/services/UnicodeService.ts +6 -11
- package/typings/xterm.d.ts +329 -34
- package/src/common/Clone.ts +0 -23
- package/src/common/TypedArrayUtils.ts +0 -17
- package/src/vs/base/browser/browser.ts +0 -141
- package/src/vs/base/browser/canIUse.ts +0 -49
- package/src/vs/base/browser/dom.ts +0 -2369
- package/src/vs/base/browser/fastDomNode.ts +0 -316
- package/src/vs/base/browser/globalPointerMoveMonitor.ts +0 -112
- package/src/vs/base/browser/iframe.ts +0 -135
- package/src/vs/base/browser/keyboardEvent.ts +0 -213
- package/src/vs/base/browser/mouseEvent.ts +0 -229
- package/src/vs/base/browser/touch.ts +0 -372
- package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +0 -303
- package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +0 -720
- package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +0 -165
- package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +0 -114
- package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +0 -243
- package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +0 -118
- package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +0 -116
- package/src/vs/base/browser/ui/widget.ts +0 -57
- package/src/vs/base/browser/window.ts +0 -14
- package/src/vs/base/common/arrays.ts +0 -887
- package/src/vs/base/common/arraysFind.ts +0 -202
- package/src/vs/base/common/assert.ts +0 -71
- package/src/vs/base/common/async.ts +0 -1992
- package/src/vs/base/common/cancellation.ts +0 -148
- package/src/vs/base/common/charCode.ts +0 -450
- package/src/vs/base/common/collections.ts +0 -140
- package/src/vs/base/common/decorators.ts +0 -130
- package/src/vs/base/common/equals.ts +0 -146
- package/src/vs/base/common/errors.ts +0 -303
- package/src/vs/base/common/event.ts +0 -1778
- package/src/vs/base/common/functional.ts +0 -32
- package/src/vs/base/common/hash.ts +0 -316
- package/src/vs/base/common/iterator.ts +0 -159
- package/src/vs/base/common/keyCodes.ts +0 -526
- package/src/vs/base/common/keybindings.ts +0 -284
- package/src/vs/base/common/lazy.ts +0 -47
- package/src/vs/base/common/lifecycle.ts +0 -801
- package/src/vs/base/common/linkedList.ts +0 -142
- package/src/vs/base/common/map.ts +0 -202
- package/src/vs/base/common/numbers.ts +0 -98
- package/src/vs/base/common/observable.ts +0 -76
- package/src/vs/base/common/observableInternal/api.ts +0 -31
- package/src/vs/base/common/observableInternal/autorun.ts +0 -281
- package/src/vs/base/common/observableInternal/base.ts +0 -489
- package/src/vs/base/common/observableInternal/debugName.ts +0 -145
- package/src/vs/base/common/observableInternal/derived.ts +0 -428
- package/src/vs/base/common/observableInternal/lazyObservableValue.ts +0 -146
- package/src/vs/base/common/observableInternal/logging.ts +0 -328
- package/src/vs/base/common/observableInternal/promise.ts +0 -209
- package/src/vs/base/common/observableInternal/utils.ts +0 -610
- package/src/vs/base/common/platform.ts +0 -281
- package/src/vs/base/common/scrollable.ts +0 -522
- package/src/vs/base/common/sequence.ts +0 -34
- package/src/vs/base/common/stopwatch.ts +0 -43
- package/src/vs/base/common/strings.ts +0 -557
- package/src/vs/base/common/symbols.ts +0 -9
- package/src/vs/base/common/uint.ts +0 -59
- package/src/vs/patches/nls.ts +0 -90
- package/src/vs/typings/base-common.d.ts +0 -20
- package/src/vs/typings/require.d.ts +0 -42
- package/src/vs/typings/vscode-globals-nls.d.ts +0 -36
- package/src/vs/typings/vscode-globals-product.d.ts +0 -33
|
@@ -3,31 +3,33 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { CharData, IAttributeData, IBufferLine, ICellData, IExtendedAttrs } from '
|
|
7
|
-
import { AttributeData } from '
|
|
8
|
-
import { CellData } from '
|
|
9
|
-
import { Attributes, BgFlags, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, Content, NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR } from '
|
|
10
|
-
import { stringFromCodePoint } from '
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
6
|
+
import { CharData, IAttributeData, IBufferLine, ICellData, IExtendedAttrs } from './Types';
|
|
7
|
+
import { AttributeData } from './AttributeData';
|
|
8
|
+
import { CellData } from './CellData';
|
|
9
|
+
import { Attributes, BgFlags, CHAR_DATA_ATTR_INDEX, CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, Content, NULL_CELL_CHAR, NULL_CELL_CODE, NULL_CELL_WIDTH, WHITESPACE_CELL_CHAR } from './Constants';
|
|
10
|
+
import { stringFromCodePoint } from '../input/TextDecoder';
|
|
11
|
+
import { StringBuilder } from '../StringBuilder';
|
|
12
|
+
|
|
13
|
+
// Buffer memory layout:
|
|
14
|
+
//
|
|
15
|
+
// [0]: content `uint32_t` - wcwidth(2) comb(1) codepoint(21)
|
|
16
|
+
// [1]: fg `uint32_t` - flags(8) r(8) g(8) b(8)
|
|
17
|
+
// [2]: bg `uint32_t` - flags(8) r(8) g(8) b(8)
|
|
18
|
+
|
|
19
|
+
const enum Constants {
|
|
20
|
+
/** The number of 32 bit array indices taken by one cell. */
|
|
21
|
+
CELL_INDICIES = 3,
|
|
22
|
+
/** Factor when to cleanup underlying array buffer after shrinking. */
|
|
23
|
+
CLEANUP_THRESHOLD = 2
|
|
24
|
+
}
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* Cell member indices.
|
|
26
28
|
*
|
|
27
29
|
* Direct access:
|
|
28
|
-
* `content = data[column *
|
|
29
|
-
* `fg = data[column *
|
|
30
|
-
* `bg = data[column *
|
|
30
|
+
* `content = data[column * Constants.CELL_INDICIES + Cell.CONTENT];`
|
|
31
|
+
* `fg = data[column * Constants.CELL_INDICIES + Cell.FG];`
|
|
32
|
+
* `bg = data[column * Constants.CELL_INDICIES + Cell.BG];`
|
|
31
33
|
*/
|
|
32
34
|
const enum Cell {
|
|
33
35
|
CONTENT = 0,
|
|
@@ -39,9 +41,20 @@ export const DEFAULT_ATTR_DATA = Object.freeze(new AttributeData());
|
|
|
39
41
|
|
|
40
42
|
// Work variables to avoid garbage collection
|
|
41
43
|
let $startIndex = 0;
|
|
44
|
+
const $workCell = new CellData();
|
|
45
|
+
const $translateToStringBuilder = new StringBuilder();
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
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
|
+
}
|
|
45
58
|
|
|
46
59
|
/**
|
|
47
60
|
* Typed array based bufferline implementation.
|
|
@@ -60,13 +73,21 @@ const CLEANUP_THRESHOLD = 2;
|
|
|
60
73
|
*/
|
|
61
74
|
export class BufferLine implements IBufferLine {
|
|
62
75
|
protected _data: Uint32Array;
|
|
76
|
+
/** Sparse cache; only read when `IS_COMBINED_MASK` is set in `_data`. */
|
|
63
77
|
protected _combined: {[index: number]: string} = {};
|
|
78
|
+
/** Sparse cache; only read when `HAS_EXTENDED` is set in `_data`. */
|
|
64
79
|
protected _extendedAttrs: {[index: number]: IExtendedAttrs | undefined} = {};
|
|
80
|
+
protected _stringCacheEntryRef: WeakRef<IBufferLineStringCacheEntry> | undefined;
|
|
65
81
|
public length: number;
|
|
66
82
|
|
|
67
|
-
constructor(
|
|
68
|
-
|
|
69
|
-
|
|
83
|
+
constructor(
|
|
84
|
+
protected readonly _stringCache: IBufferLineStringCache,
|
|
85
|
+
cols: number,
|
|
86
|
+
fillCellData?: ICellData,
|
|
87
|
+
public isWrapped: boolean = false
|
|
88
|
+
) {
|
|
89
|
+
this._data = new Uint32Array(cols * Constants.CELL_INDICIES);
|
|
90
|
+
const cell = fillCellData ?? CellData.fromCharData([0, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE]);
|
|
70
91
|
for (let i = 0; i < cols; ++i) {
|
|
71
92
|
this.setCell(i, cell);
|
|
72
93
|
}
|
|
@@ -78,10 +99,10 @@ export class BufferLine implements IBufferLine {
|
|
|
78
99
|
* @deprecated
|
|
79
100
|
*/
|
|
80
101
|
public get(index: number): CharData {
|
|
81
|
-
const content = this._data[index *
|
|
102
|
+
const content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
|
|
82
103
|
const cp = content & Content.CODEPOINT_MASK;
|
|
83
104
|
return [
|
|
84
|
-
this._data[index *
|
|
105
|
+
this._data[index * Constants.CELL_INDICIES + Cell.FG],
|
|
85
106
|
(content & Content.IS_COMBINED_MASK)
|
|
86
107
|
? this._combined[index]
|
|
87
108
|
: (cp) ? stringFromCodePoint(cp) : '',
|
|
@@ -97,12 +118,13 @@ export class BufferLine implements IBufferLine {
|
|
|
97
118
|
* @deprecated
|
|
98
119
|
*/
|
|
99
120
|
public set(index: number, value: CharData): void {
|
|
100
|
-
this.
|
|
121
|
+
this._invalidateStringCache();
|
|
122
|
+
this._data[index * Constants.CELL_INDICIES + Cell.FG] = value[CHAR_DATA_ATTR_INDEX];
|
|
101
123
|
if (value[CHAR_DATA_CHAR_INDEX].length > 1) {
|
|
102
124
|
this._combined[index] = value[1];
|
|
103
|
-
this._data[index *
|
|
125
|
+
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = index | Content.IS_COMBINED_MASK | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
|
|
104
126
|
} else {
|
|
105
|
-
this._data[index *
|
|
127
|
+
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = value[CHAR_DATA_CHAR_INDEX].charCodeAt(0) | (value[CHAR_DATA_WIDTH_INDEX] << Content.WIDTH_SHIFT);
|
|
106
128
|
}
|
|
107
129
|
}
|
|
108
130
|
|
|
@@ -111,22 +133,22 @@ export class BufferLine implements IBufferLine {
|
|
|
111
133
|
* use these when only one value is needed, otherwise use `loadCell`
|
|
112
134
|
*/
|
|
113
135
|
public getWidth(index: number): number {
|
|
114
|
-
return this._data[index *
|
|
136
|
+
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] >> Content.WIDTH_SHIFT;
|
|
115
137
|
}
|
|
116
138
|
|
|
117
139
|
/** Test whether content has width. */
|
|
118
140
|
public hasWidth(index: number): number {
|
|
119
|
-
return this._data[index *
|
|
141
|
+
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] & Content.WIDTH_MASK;
|
|
120
142
|
}
|
|
121
143
|
|
|
122
144
|
/** Get FG cell component. */
|
|
123
145
|
public getFg(index: number): number {
|
|
124
|
-
return this._data[index *
|
|
146
|
+
return this._data[index * Constants.CELL_INDICIES + Cell.FG];
|
|
125
147
|
}
|
|
126
148
|
|
|
127
149
|
/** Get BG cell component. */
|
|
128
150
|
public getBg(index: number): number {
|
|
129
|
-
return this._data[index *
|
|
151
|
+
return this._data[index * Constants.CELL_INDICIES + Cell.BG];
|
|
130
152
|
}
|
|
131
153
|
|
|
132
154
|
/**
|
|
@@ -135,7 +157,7 @@ export class BufferLine implements IBufferLine {
|
|
|
135
157
|
* from real empty cells.
|
|
136
158
|
*/
|
|
137
159
|
public hasContent(index: number): number {
|
|
138
|
-
return this._data[index *
|
|
160
|
+
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] & Content.HAS_CONTENT_MASK;
|
|
139
161
|
}
|
|
140
162
|
|
|
141
163
|
/**
|
|
@@ -144,7 +166,7 @@ export class BufferLine implements IBufferLine {
|
|
|
144
166
|
* a single UTF32 codepoint or the last codepoint of a combined string.
|
|
145
167
|
*/
|
|
146
168
|
public getCodePoint(index: number): number {
|
|
147
|
-
const content = this._data[index *
|
|
169
|
+
const content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
|
|
148
170
|
if (content & Content.IS_COMBINED_MASK) {
|
|
149
171
|
return this._combined[index].charCodeAt(this._combined[index].length - 1);
|
|
150
172
|
}
|
|
@@ -153,12 +175,12 @@ export class BufferLine implements IBufferLine {
|
|
|
153
175
|
|
|
154
176
|
/** Test whether the cell contains a combined string. */
|
|
155
177
|
public isCombined(index: number): number {
|
|
156
|
-
return this._data[index *
|
|
178
|
+
return this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] & Content.IS_COMBINED_MASK;
|
|
157
179
|
}
|
|
158
180
|
|
|
159
181
|
/** Returns the string content of the cell. */
|
|
160
182
|
public getString(index: number): string {
|
|
161
|
-
const content = this._data[index *
|
|
183
|
+
const content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
|
|
162
184
|
if (content & Content.IS_COMBINED_MASK) {
|
|
163
185
|
return this._combined[index];
|
|
164
186
|
}
|
|
@@ -171,7 +193,7 @@ export class BufferLine implements IBufferLine {
|
|
|
171
193
|
|
|
172
194
|
/** Get state of protected flag. */
|
|
173
195
|
public isProtected(index: number): number {
|
|
174
|
-
return this._data[index *
|
|
196
|
+
return this._data[index * Constants.CELL_INDICIES + Cell.BG] & BgFlags.PROTECTED;
|
|
175
197
|
}
|
|
176
198
|
|
|
177
199
|
/**
|
|
@@ -179,15 +201,21 @@ export class BufferLine implements IBufferLine {
|
|
|
179
201
|
* to GC as it significantly reduced the amount of new objects/references needed.
|
|
180
202
|
*/
|
|
181
203
|
public loadCell(index: number, cell: ICellData): ICellData {
|
|
182
|
-
$startIndex = index *
|
|
204
|
+
$startIndex = index * Constants.CELL_INDICIES;
|
|
183
205
|
cell.content = this._data[$startIndex + Cell.CONTENT];
|
|
184
206
|
cell.fg = this._data[$startIndex + Cell.FG];
|
|
185
207
|
cell.bg = this._data[$startIndex + Cell.BG];
|
|
186
208
|
if (cell.content & Content.IS_COMBINED_MASK) {
|
|
187
209
|
cell.combinedData = this._combined[index];
|
|
210
|
+
} else {
|
|
211
|
+
cell.combinedData = '';
|
|
188
212
|
}
|
|
189
213
|
if (cell.bg & BgFlags.HAS_EXTENDED) {
|
|
190
214
|
cell.extended = this._extendedAttrs[index]!;
|
|
215
|
+
} else {
|
|
216
|
+
// Do not mutate cell.extended in place: it may still reference this line's map entry from a
|
|
217
|
+
// prior loadCell into a reused CellData (e.g. $workCell during insert/delete).
|
|
218
|
+
cell.extended = DEFAULT_ATTR_DATA.extended.clone();
|
|
191
219
|
}
|
|
192
220
|
return cell;
|
|
193
221
|
}
|
|
@@ -196,15 +224,16 @@ export class BufferLine implements IBufferLine {
|
|
|
196
224
|
* Set data at `index` to `cell`.
|
|
197
225
|
*/
|
|
198
226
|
public setCell(index: number, cell: ICellData): void {
|
|
227
|
+
this._invalidateStringCache();
|
|
199
228
|
if (cell.content & Content.IS_COMBINED_MASK) {
|
|
200
229
|
this._combined[index] = cell.combinedData;
|
|
201
230
|
}
|
|
202
231
|
if (cell.bg & BgFlags.HAS_EXTENDED) {
|
|
203
232
|
this._extendedAttrs[index] = cell.extended;
|
|
204
233
|
}
|
|
205
|
-
this._data[index *
|
|
206
|
-
this._data[index *
|
|
207
|
-
this._data[index *
|
|
234
|
+
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = cell.content;
|
|
235
|
+
this._data[index * Constants.CELL_INDICIES + Cell.FG] = cell.fg;
|
|
236
|
+
this._data[index * Constants.CELL_INDICIES + Cell.BG] = cell.bg;
|
|
208
237
|
}
|
|
209
238
|
|
|
210
239
|
/**
|
|
@@ -213,12 +242,13 @@ export class BufferLine implements IBufferLine {
|
|
|
213
242
|
* it gets an optimized access method.
|
|
214
243
|
*/
|
|
215
244
|
public setCellFromCodepoint(index: number, codePoint: number, width: number, attrs: IAttributeData): void {
|
|
245
|
+
this._invalidateStringCache();
|
|
216
246
|
if (attrs.bg & BgFlags.HAS_EXTENDED) {
|
|
217
247
|
this._extendedAttrs[index] = attrs.extended;
|
|
218
248
|
}
|
|
219
|
-
this._data[index *
|
|
220
|
-
this._data[index *
|
|
221
|
-
this._data[index *
|
|
249
|
+
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = codePoint | (width << Content.WIDTH_SHIFT);
|
|
250
|
+
this._data[index * Constants.CELL_INDICIES + Cell.FG] = attrs.fg;
|
|
251
|
+
this._data[index * Constants.CELL_INDICIES + Cell.BG] = attrs.bg;
|
|
222
252
|
}
|
|
223
253
|
|
|
224
254
|
/**
|
|
@@ -228,7 +258,8 @@ export class BufferLine implements IBufferLine {
|
|
|
228
258
|
* by the previous `setDataFromCodePoint` call, we can omit it here.
|
|
229
259
|
*/
|
|
230
260
|
public addCodepointToCell(index: number, codePoint: number, width: number): void {
|
|
231
|
-
|
|
261
|
+
this._invalidateStringCache();
|
|
262
|
+
let content = this._data[index * Constants.CELL_INDICIES + Cell.CONTENT];
|
|
232
263
|
if (content & Content.IS_COMBINED_MASK) {
|
|
233
264
|
// we already have a combined string, simply add
|
|
234
265
|
this._combined[index] += stringFromCodePoint(codePoint);
|
|
@@ -250,10 +281,11 @@ export class BufferLine implements IBufferLine {
|
|
|
250
281
|
content &= ~Content.WIDTH_MASK;
|
|
251
282
|
content |= width << Content.WIDTH_SHIFT;
|
|
252
283
|
}
|
|
253
|
-
this._data[index *
|
|
284
|
+
this._data[index * Constants.CELL_INDICIES + Cell.CONTENT] = content;
|
|
254
285
|
}
|
|
255
286
|
|
|
256
287
|
public insertCells(pos: number, n: number, fillCellData: ICellData): void {
|
|
288
|
+
this._invalidateStringCache();
|
|
257
289
|
pos %= this.length;
|
|
258
290
|
|
|
259
291
|
// handle fullwidth at pos: reset cell one to the left if pos is second cell of a wide char
|
|
@@ -262,9 +294,8 @@ export class BufferLine implements IBufferLine {
|
|
|
262
294
|
}
|
|
263
295
|
|
|
264
296
|
if (n < this.length - pos) {
|
|
265
|
-
const cell = new CellData();
|
|
266
297
|
for (let i = this.length - pos - n - 1; i >= 0; --i) {
|
|
267
|
-
this.setCell(pos + n + i, this.loadCell(pos + i,
|
|
298
|
+
this.setCell(pos + n + i, this.loadCell(pos + i, $workCell));
|
|
268
299
|
}
|
|
269
300
|
for (let i = 0; i < n; ++i) {
|
|
270
301
|
this.setCell(pos + i, fillCellData);
|
|
@@ -282,11 +313,11 @@ export class BufferLine implements IBufferLine {
|
|
|
282
313
|
}
|
|
283
314
|
|
|
284
315
|
public deleteCells(pos: number, n: number, fillCellData: ICellData): void {
|
|
316
|
+
this._invalidateStringCache();
|
|
285
317
|
pos %= this.length;
|
|
286
318
|
if (n < this.length - pos) {
|
|
287
|
-
const cell = new CellData();
|
|
288
319
|
for (let i = 0; i < this.length - pos - n; ++i) {
|
|
289
|
-
this.setCell(pos + i, this.loadCell(pos + n + i,
|
|
320
|
+
this.setCell(pos + i, this.loadCell(pos + n + i, $workCell));
|
|
290
321
|
}
|
|
291
322
|
for (let i = this.length - n; i < this.length; ++i) {
|
|
292
323
|
this.setCell(i, fillCellData);
|
|
@@ -309,6 +340,7 @@ export class BufferLine implements IBufferLine {
|
|
|
309
340
|
}
|
|
310
341
|
|
|
311
342
|
public replaceCells(start: number, end: number, fillCellData: ICellData, respectProtect: boolean = false): void {
|
|
343
|
+
this._invalidateStringCache();
|
|
312
344
|
// full branching on respectProtect==true, hopefully getting fast JIT for standard case
|
|
313
345
|
if (respectProtect) {
|
|
314
346
|
if (start && this.getWidth(start - 1) === 2 && !this.isProtected(start - 1)) {
|
|
@@ -345,13 +377,14 @@ export class BufferLine implements IBufferLine {
|
|
|
345
377
|
* The underlying array buffer will not change if there is still enough space
|
|
346
378
|
* to hold the new buffer line data.
|
|
347
379
|
* Returns a boolean indicating, whether a `cleanupMemory` call would free
|
|
348
|
-
* excess memory (true after shrinking > CLEANUP_THRESHOLD).
|
|
380
|
+
* excess memory (true after shrinking > Constants.CLEANUP_THRESHOLD).
|
|
349
381
|
*/
|
|
350
382
|
public resize(cols: number, fillCellData: ICellData): boolean {
|
|
383
|
+
this._invalidateStringCache();
|
|
351
384
|
if (cols === this.length) {
|
|
352
|
-
return this._data.length * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength;
|
|
385
|
+
return this._data.length * 4 * Constants.CLEANUP_THRESHOLD < this._data.buffer.byteLength;
|
|
353
386
|
}
|
|
354
|
-
const uint32Cells = cols *
|
|
387
|
+
const uint32Cells = cols * Constants.CELL_INDICIES;
|
|
355
388
|
if (cols > this.length) {
|
|
356
389
|
if (this._data.buffer.byteLength >= uint32Cells * 4) {
|
|
357
390
|
// optimization: avoid alloc and data copy if buffer has enough room
|
|
@@ -386,17 +419,17 @@ export class BufferLine implements IBufferLine {
|
|
|
386
419
|
}
|
|
387
420
|
}
|
|
388
421
|
this.length = cols;
|
|
389
|
-
return uint32Cells * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength;
|
|
422
|
+
return uint32Cells * 4 * Constants.CLEANUP_THRESHOLD < this._data.buffer.byteLength;
|
|
390
423
|
}
|
|
391
424
|
|
|
392
425
|
/**
|
|
393
426
|
* Cleanup underlying array buffer.
|
|
394
427
|
* A cleanup will be triggered if the array buffer exceeds the actual used
|
|
395
|
-
* memory by a factor of CLEANUP_THRESHOLD.
|
|
428
|
+
* memory by a factor of Constants.CLEANUP_THRESHOLD.
|
|
396
429
|
* Returns 0 or 1 indicating whether a cleanup happened.
|
|
397
430
|
*/
|
|
398
431
|
public cleanupMemory(): number {
|
|
399
|
-
if (this._data.length * 4 * CLEANUP_THRESHOLD < this._data.buffer.byteLength) {
|
|
432
|
+
if (this._data.length * 4 * Constants.CLEANUP_THRESHOLD < this._data.buffer.byteLength) {
|
|
400
433
|
const data = new Uint32Array(this._data.length);
|
|
401
434
|
data.set(this._data);
|
|
402
435
|
this._data = data;
|
|
@@ -407,6 +440,7 @@ export class BufferLine implements IBufferLine {
|
|
|
407
440
|
|
|
408
441
|
/** fill a line with fillCharData */
|
|
409
442
|
public fill(fillCellData: ICellData, respectProtect: boolean = false): void {
|
|
443
|
+
this._invalidateStringCache();
|
|
410
444
|
// full branching on respectProtect==true, hopefully getting fast JIT for standard case
|
|
411
445
|
if (respectProtect) {
|
|
412
446
|
for (let i = 0; i < this.length; ++i) {
|
|
@@ -425,6 +459,7 @@ export class BufferLine implements IBufferLine {
|
|
|
425
459
|
|
|
426
460
|
/** alter to a full copy of line */
|
|
427
461
|
public copyFrom(line: BufferLine): void {
|
|
462
|
+
this._invalidateStringCache();
|
|
428
463
|
if (this.length !== line.length) {
|
|
429
464
|
this._data = new Uint32Array(line._data);
|
|
430
465
|
} else {
|
|
@@ -432,36 +467,24 @@ export class BufferLine implements IBufferLine {
|
|
|
432
467
|
this._data.set(line._data);
|
|
433
468
|
}
|
|
434
469
|
this.length = line.length;
|
|
435
|
-
this.
|
|
436
|
-
for (const el in line._combined) {
|
|
437
|
-
this._combined[el] = line._combined[el];
|
|
438
|
-
}
|
|
439
|
-
this._extendedAttrs = {};
|
|
440
|
-
for (const el in line._extendedAttrs) {
|
|
441
|
-
this._extendedAttrs[el] = line._extendedAttrs[el];
|
|
442
|
-
}
|
|
470
|
+
this._copySparseMapsFrom(line);
|
|
443
471
|
this.isWrapped = line.isWrapped;
|
|
444
472
|
}
|
|
445
473
|
|
|
446
474
|
/** create a new clone */
|
|
447
475
|
public clone(): IBufferLine {
|
|
448
|
-
const newLine = new BufferLine(0);
|
|
476
|
+
const newLine = new BufferLine(this._stringCache, 0, undefined, false);
|
|
449
477
|
newLine._data = new Uint32Array(this._data);
|
|
450
478
|
newLine.length = this.length;
|
|
451
|
-
|
|
452
|
-
newLine._combined[el] = this._combined[el];
|
|
453
|
-
}
|
|
454
|
-
for (const el in this._extendedAttrs) {
|
|
455
|
-
newLine._extendedAttrs[el] = this._extendedAttrs[el];
|
|
456
|
-
}
|
|
479
|
+
newLine._copySparseMapsFrom(this);
|
|
457
480
|
newLine.isWrapped = this.isWrapped;
|
|
458
481
|
return newLine;
|
|
459
482
|
}
|
|
460
483
|
|
|
461
484
|
public getTrimmedLength(): number {
|
|
462
485
|
for (let i = this.length - 1; i >= 0; --i) {
|
|
463
|
-
if ((this._data[i *
|
|
464
|
-
return i + (this._data[i *
|
|
486
|
+
if ((this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] & Content.HAS_CONTENT_MASK)) {
|
|
487
|
+
return i + (this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] >> Content.WIDTH_SHIFT);
|
|
465
488
|
}
|
|
466
489
|
}
|
|
467
490
|
return 0;
|
|
@@ -469,47 +492,36 @@ export class BufferLine implements IBufferLine {
|
|
|
469
492
|
|
|
470
493
|
public getNoBgTrimmedLength(): number {
|
|
471
494
|
for (let i = this.length - 1; i >= 0; --i) {
|
|
472
|
-
if ((this._data[i *
|
|
473
|
-
return i + (this._data[i *
|
|
495
|
+
if ((this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] & Content.HAS_CONTENT_MASK) || (this._data[i * Constants.CELL_INDICIES + Cell.BG] & Attributes.CM_MASK)) {
|
|
496
|
+
return i + (this._data[i * Constants.CELL_INDICIES + Cell.CONTENT] >> Content.WIDTH_SHIFT);
|
|
474
497
|
}
|
|
475
498
|
}
|
|
476
499
|
return 0;
|
|
477
500
|
}
|
|
478
501
|
|
|
479
502
|
public copyCellsFrom(src: BufferLine, srcCol: number, destCol: number, length: number, applyInReverse: boolean): void {
|
|
503
|
+
this._invalidateStringCache();
|
|
480
504
|
const srcData = src._data;
|
|
481
505
|
if (applyInReverse) {
|
|
482
506
|
for (let cell = length - 1; cell >= 0; cell--) {
|
|
483
|
-
for (let i = 0; i <
|
|
484
|
-
this._data[(destCol + cell) *
|
|
485
|
-
}
|
|
486
|
-
if (srcData[(srcCol + cell) * CELL_SIZE + Cell.BG] & BgFlags.HAS_EXTENDED) {
|
|
487
|
-
this._extendedAttrs[destCol + cell] = src._extendedAttrs[srcCol + cell];
|
|
507
|
+
for (let i = 0; i < Constants.CELL_INDICIES; i++) {
|
|
508
|
+
this._data[(destCol + cell) * Constants.CELL_INDICIES + i] = srcData[(srcCol + cell) * Constants.CELL_INDICIES + i];
|
|
488
509
|
}
|
|
510
|
+
this._copyCellMapsFrom(src, srcCol + cell, destCol + cell);
|
|
489
511
|
}
|
|
490
512
|
} else {
|
|
491
513
|
for (let cell = 0; cell < length; cell++) {
|
|
492
|
-
for (let i = 0; i <
|
|
493
|
-
this._data[(destCol + cell) *
|
|
494
|
-
}
|
|
495
|
-
if (srcData[(srcCol + cell) * CELL_SIZE + Cell.BG] & BgFlags.HAS_EXTENDED) {
|
|
496
|
-
this._extendedAttrs[destCol + cell] = src._extendedAttrs[srcCol + cell];
|
|
514
|
+
for (let i = 0; i < Constants.CELL_INDICIES; i++) {
|
|
515
|
+
this._data[(destCol + cell) * Constants.CELL_INDICIES + i] = srcData[(srcCol + cell) * Constants.CELL_INDICIES + i];
|
|
497
516
|
}
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// Move any combined data over as needed, FIXME: repeat for extended attrs
|
|
502
|
-
const srcCombinedKeys = Object.keys(src._combined);
|
|
503
|
-
for (let i = 0; i < srcCombinedKeys.length; i++) {
|
|
504
|
-
const key = parseInt(srcCombinedKeys[i], 10);
|
|
505
|
-
if (key >= srcCol) {
|
|
506
|
-
this._combined[key - srcCol + destCol] = src._combined[key];
|
|
517
|
+
this._copyCellMapsFrom(src, srcCol + cell, destCol + cell);
|
|
507
518
|
}
|
|
508
519
|
}
|
|
509
520
|
}
|
|
510
521
|
|
|
511
522
|
/**
|
|
512
|
-
* Translates the buffer line to a string.
|
|
523
|
+
* Translates the buffer line to a string. Caching only applies to canonical full-line translation
|
|
524
|
+
* requests (regardless of `trimRight` value).
|
|
513
525
|
*
|
|
514
526
|
* @param trimRight Whether to trim any empty cells on the right.
|
|
515
527
|
* @param startCol The column to start the string (0-based inclusive).
|
|
@@ -522,6 +534,19 @@ export class BufferLine implements IBufferLine {
|
|
|
522
534
|
* returned string, the corresponding entries in `outColumns` will have the same column number.
|
|
523
535
|
*/
|
|
524
536
|
public translateToString(trimRight?: boolean, startCol?: number, endCol?: number, outColumns?: number[]): string {
|
|
537
|
+
const isCanonicalRequest = (startCol === undefined || startCol === 0) && endCol === undefined && outColumns === undefined;
|
|
538
|
+
if (isCanonicalRequest) {
|
|
539
|
+
this._stringCache.touch?.();
|
|
540
|
+
}
|
|
541
|
+
const stringCacheEntry = isCanonicalRequest ? this._getStringCacheEntry(false) : undefined;
|
|
542
|
+
if (isCanonicalRequest && stringCacheEntry?.value !== undefined) {
|
|
543
|
+
if (trimRight) {
|
|
544
|
+
return stringCacheEntry.isTrimmed ? stringCacheEntry.value : stringCacheEntry.value.trimEnd();
|
|
545
|
+
}
|
|
546
|
+
if (!stringCacheEntry.isTrimmed) {
|
|
547
|
+
return stringCacheEntry.value;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
525
550
|
startCol = startCol ?? 0;
|
|
526
551
|
endCol = endCol ?? this.length;
|
|
527
552
|
if (trimRight) {
|
|
@@ -530,12 +555,12 @@ export class BufferLine implements IBufferLine {
|
|
|
530
555
|
if (outColumns) {
|
|
531
556
|
outColumns.length = 0;
|
|
532
557
|
}
|
|
533
|
-
|
|
558
|
+
$translateToStringBuilder.reset();
|
|
534
559
|
while (startCol < endCol) {
|
|
535
|
-
const content = this._data[startCol *
|
|
560
|
+
const content = this._data[startCol * Constants.CELL_INDICIES + Cell.CONTENT];
|
|
536
561
|
const cp = content & Content.CODEPOINT_MASK;
|
|
537
562
|
const chars = (content & Content.IS_COMBINED_MASK) ? this._combined[startCol] : (cp) ? stringFromCodePoint(cp) : WHITESPACE_CELL_CHAR;
|
|
538
|
-
|
|
563
|
+
$translateToStringBuilder.append(chars);
|
|
539
564
|
if (outColumns) {
|
|
540
565
|
for (let i = 0; i < chars.length; ++i) {
|
|
541
566
|
outColumns.push(startCol);
|
|
@@ -546,6 +571,56 @@ export class BufferLine implements IBufferLine {
|
|
|
546
571
|
if (outColumns) {
|
|
547
572
|
outColumns.push(startCol);
|
|
548
573
|
}
|
|
574
|
+
const result = $translateToStringBuilder.toString();
|
|
575
|
+
$translateToStringBuilder.reset();
|
|
576
|
+
if (isCanonicalRequest) {
|
|
577
|
+
const cacheEntry = this._getStringCacheEntry(true)!;
|
|
578
|
+
cacheEntry.value = result;
|
|
579
|
+
cacheEntry.isTrimmed = !!trimRight;
|
|
580
|
+
}
|
|
549
581
|
return result;
|
|
550
582
|
}
|
|
583
|
+
|
|
584
|
+
protected _getStringCacheEntry(createIfNeeded: boolean): IBufferLineStringCacheEntry | undefined {
|
|
585
|
+
const cachedEntry = this._stringCacheEntryRef?.deref();
|
|
586
|
+
if (cachedEntry) {
|
|
587
|
+
if (cachedEntry.generation === this._stringCache.generation) {
|
|
588
|
+
return cachedEntry;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (!createIfNeeded) {
|
|
592
|
+
return undefined;
|
|
593
|
+
}
|
|
594
|
+
const cacheEntry = this._stringCache.allocateEntry();
|
|
595
|
+
this._stringCacheEntryRef = new WeakRef(cacheEntry);
|
|
596
|
+
return cacheEntry;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
private _invalidateStringCache(): void {
|
|
600
|
+
const cacheEntry = this._getStringCacheEntry(false);
|
|
601
|
+
if (cacheEntry) {
|
|
602
|
+
cacheEntry.value = undefined;
|
|
603
|
+
cacheEntry.isTrimmed = false;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/** Copy sparse map entries for a single cell when `_data` flags require them. */
|
|
608
|
+
private _copyCellMapsFrom(src: BufferLine, srcCol: number, destCol: number): void {
|
|
609
|
+
const srcStart = srcCol * Constants.CELL_INDICIES;
|
|
610
|
+
if (src._data[srcStart + Cell.CONTENT] & Content.IS_COMBINED_MASK) {
|
|
611
|
+
this._combined[destCol] = src._combined[srcCol];
|
|
612
|
+
}
|
|
613
|
+
if (src._data[srcStart + Cell.BG] & BgFlags.HAS_EXTENDED) {
|
|
614
|
+
this._extendedAttrs[destCol] = src._extendedAttrs[srcCol];
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/** Rebuild sparse maps from another line, keyed only by `_data` flags. */
|
|
619
|
+
private _copySparseMapsFrom(line: BufferLine): void {
|
|
620
|
+
this._combined = {};
|
|
621
|
+
this._extendedAttrs = {};
|
|
622
|
+
for (let i = 0; i < line.length; i++) {
|
|
623
|
+
this._copyCellMapsFrom(line, i, i);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
551
626
|
}
|
|
@@ -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 './BufferLine';
|
|
7
|
+
import { disposableTimeout } from '../Async';
|
|
8
|
+
import { Disposable, MutableDisposable, toDisposable, type IDisposable } from '../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,9 +3,9 @@
|
|
|
3
3
|
* @license MIT
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { BufferLine } from '
|
|
7
|
-
import { CircularList } from '
|
|
8
|
-
import { IBufferLine, ICellData } from '
|
|
6
|
+
import { BufferLine } from './BufferLine';
|
|
7
|
+
import { CircularList } from '../CircularList';
|
|
8
|
+
import { IBufferLine, ICellData } from './Types';
|
|
9
9
|
|
|
10
10
|
export interface INewLayoutResult {
|
|
11
11
|
layout: number[];
|
|
@@ -178,7 +178,10 @@ export function reflowLargerApplyNewLayout(lines: CircularList<IBufferLine>, new
|
|
|
178
178
|
*/
|
|
179
179
|
export function reflowSmallerGetNewLineLengths(wrappedLines: BufferLine[], oldCols: number, newCols: number): number[] {
|
|
180
180
|
const newLineLengths: number[] = [];
|
|
181
|
-
|
|
181
|
+
let cellsNeeded = 0;
|
|
182
|
+
for (let i = 0; i < wrappedLines.length; i++) {
|
|
183
|
+
cellsNeeded += getWrappedLineTrimmedLength(wrappedLines, i, oldCols);
|
|
184
|
+
}
|
|
182
185
|
|
|
183
186
|
// Use srcCol and srcLine to find the new wrapping point, use that to get the cellsAvailable and
|
|
184
187
|
// linesNeeded
|