@theia/terminal 1.28.0-next.9 → 1.29.0-next.2
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/node/buffering-stream.d.ts +31 -0
- package/lib/node/buffering-stream.d.ts.map +1 -0
- package/lib/node/buffering-stream.js +61 -0
- package/lib/node/buffering-stream.js.map +1 -0
- package/lib/node/buffering-stream.spec.d.ts +2 -0
- package/lib/node/buffering-stream.spec.d.ts.map +1 -0
- package/lib/node/buffering-stream.spec.js +44 -0
- package/lib/node/buffering-stream.spec.js.map +1 -0
- package/lib/node/terminal-backend-contribution.d.ts.map +1 -1
- package/lib/node/terminal-backend-contribution.js +7 -3
- package/lib/node/terminal-backend-contribution.js.map +1 -1
- package/package.json +8 -8
- package/src/node/buffering-stream.spec.ts +46 -0
- package/src/node/buffering-stream.ts +78 -0
- package/src/node/terminal-backend-contribution.ts +7 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Emitter, Event } from '@theia/core/lib/common/event';
|
|
3
|
+
export interface BufferingStreamOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Max size in bytes of the chunks being emitted.
|
|
6
|
+
*/
|
|
7
|
+
maxChunkSize?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Amount of time in milliseconds to wait between the moment we start
|
|
10
|
+
* buffering data and when we emit the buffered chunk.
|
|
11
|
+
*/
|
|
12
|
+
emitInterval?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* This component will buffer whatever is pushed to it and emit chunks back
|
|
16
|
+
* every {@link BufferingStreamOptions.emitInterval}. It will also ensure that
|
|
17
|
+
* the emitted chunks never exceed {@link BufferingStreamOptions.maxChunkSize}.
|
|
18
|
+
*/
|
|
19
|
+
export declare class BufferingStream {
|
|
20
|
+
protected buffer?: Buffer;
|
|
21
|
+
protected timeout?: NodeJS.Timeout;
|
|
22
|
+
protected maxChunkSize: number;
|
|
23
|
+
protected emitInterval: number;
|
|
24
|
+
protected onDataEmitter: Emitter<Buffer>;
|
|
25
|
+
constructor(options?: BufferingStreamOptions);
|
|
26
|
+
get onData(): Event<Buffer>;
|
|
27
|
+
push(chunk: Buffer): void;
|
|
28
|
+
dispose(): void;
|
|
29
|
+
protected emitBufferedChunk(): void;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=buffering-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffering-stream.d.ts","sourceRoot":"","sources":["../../src/node/buffering-stream.ts"],"names":[],"mappings":";AAgBA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACnC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;;GAIG;AACH,qBAAa,eAAe;IAExB,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;IACnC,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC;IAE/B,SAAS,CAAC,aAAa,kBAAyB;gBAEpC,OAAO,CAAC,EAAE,sBAAsB;IAK5C,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,CAE1B;IAED,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IASzB,OAAO,IAAI,IAAI;IAMf,SAAS,CAAC,iBAAiB,IAAI,IAAI;CAStC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2022 Ericsson and others.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.BufferingStream = void 0;
|
|
19
|
+
const event_1 = require("@theia/core/lib/common/event");
|
|
20
|
+
/**
|
|
21
|
+
* This component will buffer whatever is pushed to it and emit chunks back
|
|
22
|
+
* every {@link BufferingStreamOptions.emitInterval}. It will also ensure that
|
|
23
|
+
* the emitted chunks never exceed {@link BufferingStreamOptions.maxChunkSize}.
|
|
24
|
+
*/
|
|
25
|
+
class BufferingStream {
|
|
26
|
+
constructor(options) {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
this.onDataEmitter = new event_1.Emitter();
|
|
29
|
+
this.emitInterval = (_a = options === null || options === void 0 ? void 0 : options.emitInterval) !== null && _a !== void 0 ? _a : 16; // ms
|
|
30
|
+
this.maxChunkSize = (_b = options === null || options === void 0 ? void 0 : options.maxChunkSize) !== null && _b !== void 0 ? _b : (256 * 1024); // bytes
|
|
31
|
+
}
|
|
32
|
+
get onData() {
|
|
33
|
+
return this.onDataEmitter.event;
|
|
34
|
+
}
|
|
35
|
+
push(chunk) {
|
|
36
|
+
if (this.buffer) {
|
|
37
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.buffer = chunk;
|
|
41
|
+
this.timeout = setTimeout(() => this.emitBufferedChunk(), this.emitInterval);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
dispose() {
|
|
45
|
+
clearTimeout(this.timeout);
|
|
46
|
+
this.buffer = undefined;
|
|
47
|
+
this.onDataEmitter.dispose();
|
|
48
|
+
}
|
|
49
|
+
emitBufferedChunk() {
|
|
50
|
+
this.onDataEmitter.fire(this.buffer.slice(0, this.maxChunkSize));
|
|
51
|
+
if (this.buffer.byteLength <= this.maxChunkSize) {
|
|
52
|
+
this.buffer = undefined;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.buffer = this.buffer.slice(this.maxChunkSize);
|
|
56
|
+
this.timeout = setTimeout(() => this.emitBufferedChunk(), this.emitInterval);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.BufferingStream = BufferingStream;
|
|
61
|
+
//# sourceMappingURL=buffering-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffering-stream.js","sourceRoot":"","sources":["../../src/node/buffering-stream.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,0CAA0C;AAC1C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;;;AAEhF,wDAA8D;AAc9D;;;;GAIG;AACH,MAAa,eAAe;IASxB,YAAY,OAAgC;;QAFlC,kBAAa,GAAG,IAAI,eAAO,EAAU,CAAC;QAG5C,IAAI,CAAC,YAAY,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,mCAAI,EAAE,CAAC,CAAC,KAAK;QACtD,IAAI,CAAC,YAAY,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,mCAAI,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ;IACvE,CAAC;IAED,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,KAAa;QACd,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;SACrD;aAAM;YACH,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;SAChF;IACL,CAAC;IAED,OAAO;QACH,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;IAES,iBAAiB;QACvB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,MAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;QAClE,IAAI,IAAI,CAAC,MAAO,CAAC,UAAU,IAAI,IAAI,CAAC,YAAY,EAAE;YAC9C,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;SAC3B;aAAM;YACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAO,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACpD,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;SAChF;IACL,CAAC;CACJ;AA1CD,0CA0CC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffering-stream.spec.d.ts","sourceRoot":"","sources":["../../src/node/buffering-stream.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2022 Ericsson and others.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const promise_util_1 = require("@theia/core/lib/common/promise-util");
|
|
19
|
+
const chai_1 = require("chai");
|
|
20
|
+
const buffering_stream_1 = require("./buffering-stream");
|
|
21
|
+
describe('BufferringStream', () => {
|
|
22
|
+
it('should emit whatever data was buffered before the timeout', async () => {
|
|
23
|
+
const buffer = new buffering_stream_1.BufferingStream({ emitInterval: 1000 });
|
|
24
|
+
const chunkPromise = waitForChunk(buffer);
|
|
25
|
+
buffer.push(Buffer.from([0]));
|
|
26
|
+
await (0, promise_util_1.wait)(100);
|
|
27
|
+
buffer.push(Buffer.from([1]));
|
|
28
|
+
await (0, promise_util_1.wait)(100);
|
|
29
|
+
buffer.push(Buffer.from([2, 3, 4]));
|
|
30
|
+
const chunk = await chunkPromise;
|
|
31
|
+
(0, chai_1.expect)(chunk).deep.eq(Buffer.from([0, 1, 2, 3, 4]));
|
|
32
|
+
});
|
|
33
|
+
it('should not emit chunks bigger than maxChunkSize', async () => {
|
|
34
|
+
const buffer = new buffering_stream_1.BufferingStream({ maxChunkSize: 2 });
|
|
35
|
+
buffer.push(Buffer.from([0, 1, 2, 3, 4, 5]));
|
|
36
|
+
(0, chai_1.expect)(await waitForChunk(buffer)).deep.eq(Buffer.from([0, 1]));
|
|
37
|
+
(0, chai_1.expect)(await waitForChunk(buffer)).deep.eq(Buffer.from([2, 3]));
|
|
38
|
+
(0, chai_1.expect)(await waitForChunk(buffer)).deep.eq(Buffer.from([4, 5]));
|
|
39
|
+
});
|
|
40
|
+
function waitForChunk(buffer) {
|
|
41
|
+
return new Promise(resolve => buffer.onData(resolve));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=buffering-stream.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffering-stream.spec.js","sourceRoot":"","sources":["../../src/node/buffering-stream.spec.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,0CAA0C;AAC1C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;;AAEhF,sEAA2D;AAC3D,+BAA8B;AAC9B,yDAAqD;AAErD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAE9B,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,MAAM,GAAG,IAAI,kCAAe,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,IAAA,mBAAI,EAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9B,MAAM,IAAA,mBAAI,EAAC,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC;QACjC,IAAA,aAAM,EAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,MAAM,GAAG,IAAI,kCAAe,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAA,aAAM,EAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,IAAA,aAAM,EAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,IAAA,aAAM,EAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY,CAAC,MAAuB;QACzC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-backend-contribution.d.ts","sourceRoot":"","sources":["../../src/node/terminal-backend-contribution.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAkB,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAmB,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;
|
|
1
|
+
{"version":3,"file":"terminal-backend-contribution.d.ts","sourceRoot":"","sources":["../../src/node/terminal-backend-contribution.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAkB,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAmB,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC;AAIpF,qBACa,2BAA4B,YAAW,gBAAgB,CAAC,YAAY;IAG7E,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAGlD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEnC,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;CA2B7C"}
|
|
@@ -30,6 +30,7 @@ const common_1 = require("@theia/core/lib/common");
|
|
|
30
30
|
const node_1 = require("@theia/process/lib/node");
|
|
31
31
|
const terminal_protocol_1 = require("../common/terminal-protocol");
|
|
32
32
|
const core_1 = require("@theia/core/");
|
|
33
|
+
const buffering_stream_1 = require("./buffering-stream");
|
|
33
34
|
let TerminalBackendContribution = class TerminalBackendContribution {
|
|
34
35
|
configure(service) {
|
|
35
36
|
service.wsChannel(`${terminal_protocol_1.terminalsPath}/:id`, (params, channel) => {
|
|
@@ -48,10 +49,13 @@ let TerminalBackendContribution = class TerminalBackendContribution {
|
|
|
48
49
|
}
|
|
49
50
|
};
|
|
50
51
|
const rpc = new core_1.RpcProtocol(channel, requestHandler);
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
const buffer = new buffering_stream_1.BufferingStream();
|
|
53
|
+
buffer.onData(chunk => rpc.sendNotification('onData', [chunk.toString('utf8')]));
|
|
54
|
+
output.on('data', chunk => buffer.push(Buffer.from(chunk, 'utf8')));
|
|
55
|
+
channel.onClose(() => {
|
|
56
|
+
buffer.dispose();
|
|
57
|
+
output.dispose();
|
|
53
58
|
});
|
|
54
|
-
channel.onClose(() => output.dispose());
|
|
55
59
|
}
|
|
56
60
|
});
|
|
57
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-backend-contribution.js","sourceRoot":"","sources":["../../src/node/terminal-backend-contribution.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;;;;;;;;;;;;AAEhF,4DAAyE;AACzE,mDAAiE;AACjE,kDAA0E;AAC1E,mEAA4D;AAE5D,uCAA2C;
|
|
1
|
+
{"version":3,"file":"terminal-backend-contribution.js","sourceRoot":"","sources":["../../src/node/terminal-backend-contribution.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;;;;;;;;;;;;AAEhF,4DAAyE;AACzE,mDAAiE;AACjE,kDAA0E;AAC1E,mEAA4D;AAE5D,uCAA2C;AAC3C,yDAAqD;AAGrD,IAAa,2BAA2B,GAAxC,MAAa,2BAA2B;IAQpC,SAAS,CAAC,OAAyB;QAC/B,OAAO,CAAC,SAAS,CAAC,GAAG,iCAAa,MAAM,EAAE,CAAC,MAAsB,EAAE,OAAO,EAAE,EAAE;YAC1E,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACnC,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChD,IAAI,WAAW,YAAY,sBAAe,EAAE;gBACxC,MAAM,MAAM,GAAG,WAAW,CAAC,kBAAkB,EAAE,CAAC;gBAChD,kDAAkD;gBAClD,8DAA8D;gBAC9D,MAAM,cAAc,GAAmB,KAAK,EAAE,MAAc,EAAE,IAAW,EAAE,EAAE;oBACzE,IAAI,MAAM,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE;wBAC/B,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;qBAC9B;yBAAM;wBACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4EAA4E,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;qBACpH;gBACL,CAAC,CAAC;gBAEF,MAAM,GAAG,GAAG,IAAI,kBAAW,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;gBACrD,MAAM,MAAM,GAAG,IAAI,kCAAe,EAAE,CAAC;gBACrC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;gBACpE,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;oBACjB,MAAM,CAAC,OAAO,EAAE,CAAC;oBACjB,MAAM,CAAC,OAAO,EAAE,CAAC;gBACrB,CAAC,CAAC,CAAC;aACN;QACL,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAA;AAhCG;IADC,IAAA,kBAAM,EAAC,qBAAc,CAAC;8BACY,qBAAc;mEAAC;AAGlD;IADC,IAAA,kBAAM,EAAC,gBAAO,CAAC;IAAE,IAAA,iBAAK,EAAC,UAAU,CAAC;;2DACA;AAN1B,2BAA2B;IADvC,IAAA,sBAAU,GAAE;GACA,2BAA2B,CAmCvC;AAnCY,kEAA2B"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/terminal",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0-next.2+d9715208c9f",
|
|
4
4
|
"description": "Theia - Terminal Extension",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/core": "1.
|
|
7
|
-
"@theia/editor": "1.
|
|
8
|
-
"@theia/filesystem": "1.
|
|
9
|
-
"@theia/process": "1.
|
|
10
|
-
"@theia/workspace": "1.
|
|
6
|
+
"@theia/core": "1.29.0-next.2+d9715208c9f",
|
|
7
|
+
"@theia/editor": "1.29.0-next.2+d9715208c9f",
|
|
8
|
+
"@theia/filesystem": "1.29.0-next.2+d9715208c9f",
|
|
9
|
+
"@theia/process": "1.29.0-next.2+d9715208c9f",
|
|
10
|
+
"@theia/workspace": "1.29.0-next.2+d9715208c9f",
|
|
11
11
|
"xterm": "^4.16.0",
|
|
12
12
|
"xterm-addon-fit": "^0.5.0",
|
|
13
13
|
"xterm-addon-search": "^0.8.2"
|
|
@@ -46,10 +46,10 @@
|
|
|
46
46
|
"watch": "theiaext watch"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@theia/ext-scripts": "1.
|
|
49
|
+
"@theia/ext-scripts": "1.28.0"
|
|
50
50
|
},
|
|
51
51
|
"nyc": {
|
|
52
52
|
"extends": "../../configs/nyc.json"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "d9715208c9fba269d79ff37e5d677864d40cd4cd"
|
|
55
55
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2022 Ericsson and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { wait } from '@theia/core/lib/common/promise-util';
|
|
18
|
+
import { expect } from 'chai';
|
|
19
|
+
import { BufferingStream } from './buffering-stream';
|
|
20
|
+
|
|
21
|
+
describe('BufferringStream', () => {
|
|
22
|
+
|
|
23
|
+
it('should emit whatever data was buffered before the timeout', async () => {
|
|
24
|
+
const buffer = new BufferingStream({ emitInterval: 1000 });
|
|
25
|
+
const chunkPromise = waitForChunk(buffer);
|
|
26
|
+
buffer.push(Buffer.from([0]));
|
|
27
|
+
await wait(100);
|
|
28
|
+
buffer.push(Buffer.from([1]));
|
|
29
|
+
await wait(100);
|
|
30
|
+
buffer.push(Buffer.from([2, 3, 4]));
|
|
31
|
+
const chunk = await chunkPromise;
|
|
32
|
+
expect(chunk).deep.eq(Buffer.from([0, 1, 2, 3, 4]));
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should not emit chunks bigger than maxChunkSize', async () => {
|
|
36
|
+
const buffer = new BufferingStream({ maxChunkSize: 2 });
|
|
37
|
+
buffer.push(Buffer.from([0, 1, 2, 3, 4, 5]));
|
|
38
|
+
expect(await waitForChunk(buffer)).deep.eq(Buffer.from([0, 1]));
|
|
39
|
+
expect(await waitForChunk(buffer)).deep.eq(Buffer.from([2, 3]));
|
|
40
|
+
expect(await waitForChunk(buffer)).deep.eq(Buffer.from([4, 5]));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
function waitForChunk(buffer: BufferingStream): Promise<Buffer> {
|
|
44
|
+
return new Promise(resolve => buffer.onData(resolve));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2022 Ericsson and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { Emitter, Event } from '@theia/core/lib/common/event';
|
|
18
|
+
|
|
19
|
+
export interface BufferingStreamOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Max size in bytes of the chunks being emitted.
|
|
22
|
+
*/
|
|
23
|
+
maxChunkSize?: number
|
|
24
|
+
/**
|
|
25
|
+
* Amount of time in milliseconds to wait between the moment we start
|
|
26
|
+
* buffering data and when we emit the buffered chunk.
|
|
27
|
+
*/
|
|
28
|
+
emitInterval?: number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* This component will buffer whatever is pushed to it and emit chunks back
|
|
33
|
+
* every {@link BufferingStreamOptions.emitInterval}. It will also ensure that
|
|
34
|
+
* the emitted chunks never exceed {@link BufferingStreamOptions.maxChunkSize}.
|
|
35
|
+
*/
|
|
36
|
+
export class BufferingStream {
|
|
37
|
+
|
|
38
|
+
protected buffer?: Buffer;
|
|
39
|
+
protected timeout?: NodeJS.Timeout;
|
|
40
|
+
protected maxChunkSize: number;
|
|
41
|
+
protected emitInterval: number;
|
|
42
|
+
|
|
43
|
+
protected onDataEmitter = new Emitter<Buffer>();
|
|
44
|
+
|
|
45
|
+
constructor(options?: BufferingStreamOptions) {
|
|
46
|
+
this.emitInterval = options?.emitInterval ?? 16; // ms
|
|
47
|
+
this.maxChunkSize = options?.maxChunkSize ?? (256 * 1024); // bytes
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get onData(): Event<Buffer> {
|
|
51
|
+
return this.onDataEmitter.event;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
push(chunk: Buffer): void {
|
|
55
|
+
if (this.buffer) {
|
|
56
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
57
|
+
} else {
|
|
58
|
+
this.buffer = chunk;
|
|
59
|
+
this.timeout = setTimeout(() => this.emitBufferedChunk(), this.emitInterval);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
dispose(): void {
|
|
64
|
+
clearTimeout(this.timeout);
|
|
65
|
+
this.buffer = undefined;
|
|
66
|
+
this.onDataEmitter.dispose();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
protected emitBufferedChunk(): void {
|
|
70
|
+
this.onDataEmitter.fire(this.buffer!.slice(0, this.maxChunkSize));
|
|
71
|
+
if (this.buffer!.byteLength <= this.maxChunkSize) {
|
|
72
|
+
this.buffer = undefined;
|
|
73
|
+
} else {
|
|
74
|
+
this.buffer = this.buffer!.slice(this.maxChunkSize);
|
|
75
|
+
this.timeout = setTimeout(() => this.emitBufferedChunk(), this.emitInterval);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -20,6 +20,7 @@ import { TerminalProcess, ProcessManager } from '@theia/process/lib/node';
|
|
|
20
20
|
import { terminalsPath } from '../common/terminal-protocol';
|
|
21
21
|
import { MessagingService } from '@theia/core/lib/node/messaging/messaging-service';
|
|
22
22
|
import { RpcProtocol } from '@theia/core/';
|
|
23
|
+
import { BufferingStream } from './buffering-stream';
|
|
23
24
|
|
|
24
25
|
@injectable()
|
|
25
26
|
export class TerminalBackendContribution implements MessagingService.Contribution {
|
|
@@ -47,10 +48,13 @@ export class TerminalBackendContribution implements MessagingService.Contributio
|
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
const rpc = new RpcProtocol(channel, requestHandler);
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
const buffer = new BufferingStream();
|
|
52
|
+
buffer.onData(chunk => rpc.sendNotification('onData', [chunk.toString('utf8')]));
|
|
53
|
+
output.on('data', chunk => buffer.push(Buffer.from(chunk, 'utf8')));
|
|
54
|
+
channel.onClose(() => {
|
|
55
|
+
buffer.dispose();
|
|
56
|
+
output.dispose();
|
|
52
57
|
});
|
|
53
|
-
channel.onClose(() => output.dispose());
|
|
54
58
|
}
|
|
55
59
|
});
|
|
56
60
|
}
|