@xterm/xterm 6.1.0-beta.236 → 6.1.0-beta.238
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/StringBuilder.ts +67 -0
- package/src/common/Version.ts +1 -1
- package/src/common/parser/ApcParser.ts +7 -8
- package/src/common/parser/DcsParser.ts +7 -8
- package/src/common/parser/OscParser.ts +7 -8
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.238",
|
|
5
5
|
"main": "lib/xterm.js",
|
|
6
6
|
"module": "lib/xterm.mjs",
|
|
7
7
|
"style": "css/xterm.css",
|
|
@@ -111,5 +111,5 @@
|
|
|
111
111
|
"ws": "^8.2.3",
|
|
112
112
|
"xterm-benchmark": "^0.3.1"
|
|
113
113
|
},
|
|
114
|
-
"commit": "
|
|
114
|
+
"commit": "280dc0a36ad35eb28eee8a0822cc2cecac3a2e28"
|
|
115
115
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Accumulates string data from multiple chunks without O(n²) string concatenation.
|
|
8
|
+
*/
|
|
9
|
+
export class StringBuilder {
|
|
10
|
+
private _chunks: string[] = [];
|
|
11
|
+
private _length = 0;
|
|
12
|
+
|
|
13
|
+
public get length(): number {
|
|
14
|
+
return this._length;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public reset(): void {
|
|
18
|
+
this._chunks.length = 0;
|
|
19
|
+
this._length = 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public append(chunk: string): void {
|
|
23
|
+
this._chunks.push(chunk);
|
|
24
|
+
this._length += chunk.length;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public toString(): string {
|
|
28
|
+
return this._chunks.join('');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* String builder that rejects payloads larger than a fixed limit.
|
|
34
|
+
*/
|
|
35
|
+
export class LimitedStringBuilder {
|
|
36
|
+
private readonly _builder = new StringBuilder();
|
|
37
|
+
|
|
38
|
+
constructor(private readonly _limit: number) { }
|
|
39
|
+
|
|
40
|
+
public get length(): number {
|
|
41
|
+
return this._builder.length;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public get limit(): number {
|
|
45
|
+
return this._limit;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public reset(): void {
|
|
49
|
+
this._builder.reset();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @returns true if the limit was exceeded (buffer is cleared in that case)
|
|
54
|
+
*/
|
|
55
|
+
public append(chunk: string): boolean {
|
|
56
|
+
this._builder.append(chunk);
|
|
57
|
+
if (this._builder.length > this._limit) {
|
|
58
|
+
this._builder.reset();
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public toString(): string {
|
|
65
|
+
return this._builder.toString();
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/common/Version.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { IApcHandler, IHandlerCollection, ApcFallbackHandlerType, IApcParser, IS
|
|
|
7
7
|
import { ParserConstants } from 'common/parser/Constants';
|
|
8
8
|
import { utf32ToString } from 'common/input/TextDecoder';
|
|
9
9
|
import { IDisposable } from 'common/Types';
|
|
10
|
+
import { LimitedStringBuilder } from 'common/StringBuilder';
|
|
10
11
|
|
|
11
12
|
const EMPTY_HANDLERS: IApcHandler[] = [];
|
|
12
13
|
|
|
@@ -153,13 +154,13 @@ export class ApcParser implements IApcParser {
|
|
|
153
154
|
export class ApcHandler implements IApcHandler {
|
|
154
155
|
private static _payloadLimit = ParserConstants.PAYLOAD_LIMIT;
|
|
155
156
|
|
|
156
|
-
private _data =
|
|
157
|
+
private _data = new LimitedStringBuilder(ApcHandler._payloadLimit);
|
|
157
158
|
private _hitLimit: boolean = false;
|
|
158
159
|
|
|
159
160
|
constructor(private _handler: (data: string) => boolean | Promise<boolean>) { }
|
|
160
161
|
|
|
161
162
|
public start(): void {
|
|
162
|
-
this._data
|
|
163
|
+
this._data.reset();
|
|
163
164
|
this._hitLimit = false;
|
|
164
165
|
}
|
|
165
166
|
|
|
@@ -167,9 +168,7 @@ export class ApcHandler implements IApcHandler {
|
|
|
167
168
|
if (this._hitLimit) {
|
|
168
169
|
return;
|
|
169
170
|
}
|
|
170
|
-
this._data
|
|
171
|
-
if (this._data.length > ApcHandler._payloadLimit) {
|
|
172
|
-
this._data = '';
|
|
171
|
+
if (this._data.append(utf32ToString(data, start, end))) {
|
|
173
172
|
this._hitLimit = true;
|
|
174
173
|
}
|
|
175
174
|
}
|
|
@@ -179,18 +178,18 @@ export class ApcHandler implements IApcHandler {
|
|
|
179
178
|
if (this._hitLimit) {
|
|
180
179
|
ret = false;
|
|
181
180
|
} else if (success) {
|
|
182
|
-
ret = this._handler(this._data);
|
|
181
|
+
ret = this._handler(this._data.toString());
|
|
183
182
|
if (ret instanceof Promise) {
|
|
184
183
|
// need to hold data until `ret` got resolved
|
|
185
184
|
// dont care for errors, data will be freed anyway on next start
|
|
186
185
|
return ret.then(res => {
|
|
187
|
-
this._data
|
|
186
|
+
this._data.reset();
|
|
188
187
|
this._hitLimit = false;
|
|
189
188
|
return res;
|
|
190
189
|
});
|
|
191
190
|
}
|
|
192
191
|
}
|
|
193
|
-
this._data
|
|
192
|
+
this._data.reset();
|
|
194
193
|
this._hitLimit = false;
|
|
195
194
|
return ret;
|
|
196
195
|
}
|
|
@@ -8,6 +8,7 @@ import { IDcsHandler, IParams, IHandlerCollection, IDcsParser, DcsFallbackHandle
|
|
|
8
8
|
import { utf32ToString } from 'common/input/TextDecoder';
|
|
9
9
|
import { Params } from 'common/parser/Params';
|
|
10
10
|
import { ParserConstants } from 'common/parser/Constants';
|
|
11
|
+
import { LimitedStringBuilder } from 'common/StringBuilder';
|
|
11
12
|
|
|
12
13
|
const EMPTY_HANDLERS: IDcsHandler[] = [];
|
|
13
14
|
|
|
@@ -140,7 +141,7 @@ EMPTY_PARAMS.addParam(0);
|
|
|
140
141
|
export class DcsHandler implements IDcsHandler {
|
|
141
142
|
private static _payloadLimit = ParserConstants.PAYLOAD_LIMIT;
|
|
142
143
|
|
|
143
|
-
private _data =
|
|
144
|
+
private _data = new LimitedStringBuilder(DcsHandler._payloadLimit);
|
|
144
145
|
private _params: IParams = EMPTY_PARAMS;
|
|
145
146
|
private _hitLimit: boolean = false;
|
|
146
147
|
|
|
@@ -152,7 +153,7 @@ export class DcsHandler implements IDcsHandler {
|
|
|
152
153
|
// perf optimization:
|
|
153
154
|
// clone only, if we have non empty params, otherwise stick with default
|
|
154
155
|
this._params = (params.length > 1 || params.params[0]) ? params.clone() : EMPTY_PARAMS;
|
|
155
|
-
this._data
|
|
156
|
+
this._data.reset();
|
|
156
157
|
this._hitLimit = false;
|
|
157
158
|
}
|
|
158
159
|
|
|
@@ -160,9 +161,7 @@ export class DcsHandler implements IDcsHandler {
|
|
|
160
161
|
if (this._hitLimit) {
|
|
161
162
|
return;
|
|
162
163
|
}
|
|
163
|
-
this._data
|
|
164
|
-
if (this._data.length > DcsHandler._payloadLimit) {
|
|
165
|
-
this._data = '';
|
|
164
|
+
if (this._data.append(utf32ToString(data, start, end))) {
|
|
166
165
|
this._hitLimit = true;
|
|
167
166
|
}
|
|
168
167
|
}
|
|
@@ -172,20 +171,20 @@ export class DcsHandler implements IDcsHandler {
|
|
|
172
171
|
if (this._hitLimit) {
|
|
173
172
|
ret = false;
|
|
174
173
|
} else if (success) {
|
|
175
|
-
ret = this._handler(this._data, this._params);
|
|
174
|
+
ret = this._handler(this._data.toString(), this._params);
|
|
176
175
|
if (ret instanceof Promise) {
|
|
177
176
|
// need to hold data and params until `ret` got resolved
|
|
178
177
|
// dont care for errors, data will be freed anyway on next start
|
|
179
178
|
return ret.then(res => {
|
|
180
179
|
this._params = EMPTY_PARAMS;
|
|
181
|
-
this._data
|
|
180
|
+
this._data.reset();
|
|
182
181
|
this._hitLimit = false;
|
|
183
182
|
return res;
|
|
184
183
|
});
|
|
185
184
|
}
|
|
186
185
|
}
|
|
187
186
|
this._params = EMPTY_PARAMS;
|
|
188
|
-
this._data
|
|
187
|
+
this._data.reset();
|
|
189
188
|
this._hitLimit = false;
|
|
190
189
|
return ret;
|
|
191
190
|
}
|
|
@@ -7,6 +7,7 @@ import { IOscHandler, IHandlerCollection, OscFallbackHandlerType, IOscParser, IS
|
|
|
7
7
|
import { OscState, ParserConstants } from 'common/parser/Constants';
|
|
8
8
|
import { utf32ToString } from 'common/input/TextDecoder';
|
|
9
9
|
import { IDisposable } from 'common/Types';
|
|
10
|
+
import { LimitedStringBuilder } from 'common/StringBuilder';
|
|
10
11
|
|
|
11
12
|
const EMPTY_HANDLERS: IOscHandler[] = [];
|
|
12
13
|
|
|
@@ -194,13 +195,13 @@ export class OscParser implements IOscParser {
|
|
|
194
195
|
export class OscHandler implements IOscHandler {
|
|
195
196
|
private static _payloadLimit = ParserConstants.PAYLOAD_LIMIT;
|
|
196
197
|
|
|
197
|
-
private _data =
|
|
198
|
+
private _data = new LimitedStringBuilder(OscHandler._payloadLimit);
|
|
198
199
|
private _hitLimit: boolean = false;
|
|
199
200
|
|
|
200
201
|
constructor(private _handler: (data: string) => boolean | Promise<boolean>) { }
|
|
201
202
|
|
|
202
203
|
public start(): void {
|
|
203
|
-
this._data
|
|
204
|
+
this._data.reset();
|
|
204
205
|
this._hitLimit = false;
|
|
205
206
|
}
|
|
206
207
|
|
|
@@ -208,9 +209,7 @@ export class OscHandler implements IOscHandler {
|
|
|
208
209
|
if (this._hitLimit) {
|
|
209
210
|
return;
|
|
210
211
|
}
|
|
211
|
-
this._data
|
|
212
|
-
if (this._data.length > OscHandler._payloadLimit) {
|
|
213
|
-
this._data = '';
|
|
212
|
+
if (this._data.append(utf32ToString(data, start, end))) {
|
|
214
213
|
this._hitLimit = true;
|
|
215
214
|
}
|
|
216
215
|
}
|
|
@@ -220,18 +219,18 @@ export class OscHandler implements IOscHandler {
|
|
|
220
219
|
if (this._hitLimit) {
|
|
221
220
|
ret = false;
|
|
222
221
|
} else if (success) {
|
|
223
|
-
ret = this._handler(this._data);
|
|
222
|
+
ret = this._handler(this._data.toString());
|
|
224
223
|
if (ret instanceof Promise) {
|
|
225
224
|
// need to hold data until `ret` got resolved
|
|
226
225
|
// dont care for errors, data will be freed anyway on next start
|
|
227
226
|
return ret.then(res => {
|
|
228
|
-
this._data
|
|
227
|
+
this._data.reset();
|
|
229
228
|
this._hitLimit = false;
|
|
230
229
|
return res;
|
|
231
230
|
});
|
|
232
231
|
}
|
|
233
232
|
}
|
|
234
|
-
this._data
|
|
233
|
+
this._data.reset();
|
|
235
234
|
this._hitLimit = false;
|
|
236
235
|
return ret;
|
|
237
236
|
}
|