@hydranium/client-theia 1.0.0-next.10
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/LICENSE +21 -0
- package/README.md +113 -0
- package/lib/browser/browser-capture.d.ts +21 -0
- package/lib/browser/browser-capture.d.ts.map +1 -0
- package/lib/browser/browser-capture.js +61 -0
- package/lib/browser/browser-capture.js.map +1 -0
- package/lib/browser/channel-logger.d.ts +87 -0
- package/lib/browser/channel-logger.d.ts.map +1 -0
- package/lib/browser/channel-logger.js +149 -0
- package/lib/browser/channel-logger.js.map +1 -0
- package/lib/browser/index.d.ts +13 -0
- package/lib/browser/index.d.ts.map +1 -0
- package/lib/browser/index.js +30 -0
- package/lib/browser/index.js.map +1 -0
- package/lib/browser/log-level-preference.d.ts +82 -0
- package/lib/browser/log-level-preference.d.ts.map +1 -0
- package/lib/browser/log-level-preference.js +146 -0
- package/lib/browser/log-level-preference.js.map +1 -0
- package/lib/browser/memory-diagnostics-contribution.d.ts +105 -0
- package/lib/browser/memory-diagnostics-contribution.d.ts.map +1 -0
- package/lib/browser/memory-diagnostics-contribution.js +229 -0
- package/lib/browser/memory-diagnostics-contribution.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +11 -0
- package/lib/index.js.map +1 -0
- package/lib/node/abstract-socket-forwarding-connection-handler.d.ts +96 -0
- package/lib/node/abstract-socket-forwarding-connection-handler.d.ts.map +1 -0
- package/lib/node/abstract-socket-forwarding-connection-handler.js +224 -0
- package/lib/node/abstract-socket-forwarding-connection-handler.js.map +1 -0
- package/lib/node/index.d.ts +10 -0
- package/lib/node/index.d.ts.map +1 -0
- package/lib/node/index.js +26 -0
- package/lib/node/index.js.map +1 -0
- package/lib/testing/index.d.ts +11 -0
- package/lib/testing/index.d.ts.map +1 -0
- package/lib/testing/index.js +29 -0
- package/lib/testing/index.js.map +1 -0
- package/lib/testing/stub-inversify-context.d.ts +15 -0
- package/lib/testing/stub-inversify-context.d.ts.map +1 -0
- package/lib/testing/stub-inversify-context.js +32 -0
- package/lib/testing/stub-inversify-context.js.map +1 -0
- package/lib/testing/stub-output-channel.d.ts +25 -0
- package/lib/testing/stub-output-channel.d.ts.map +1 -0
- package/lib/testing/stub-output-channel.js +33 -0
- package/lib/testing/stub-output-channel.js.map +1 -0
- package/package.json +95 -0
- package/src/browser/browser-capture.ts +75 -0
- package/src/browser/channel-logger.ts +160 -0
- package/src/browser/index.ts +14 -0
- package/src/browser/log-level-preference.ts +127 -0
- package/src/browser/memory-diagnostics-contribution.ts +248 -0
- package/src/index.ts +19 -0
- package/src/node/abstract-socket-forwarding-connection-handler.ts +218 -0
- package/src/node/index.ts +10 -0
- package/src/testing/index.ts +14 -0
- package/src/testing/stub-inversify-context.ts +32 -0
- package/src/testing/stub-output-channel.ts +47 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
27
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
28
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
29
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
30
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
31
|
+
};
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
50
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.AbstractSocketForwardingConnectionHandler = void 0;
|
|
54
|
+
const core_1 = require("@theia/core");
|
|
55
|
+
const channel_1 = require("@theia/core/lib/common/message-rpc/channel");
|
|
56
|
+
const promise_util_1 = require("@theia/core/lib/common/promise-util");
|
|
57
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
58
|
+
const net = __importStar(require("node:net"));
|
|
59
|
+
/**
|
|
60
|
+
* Cross-head base for the Theia backend half of a protocol head's transport:
|
|
61
|
+
* it bridges a Theia browser-frontend {@link Channel} to a server's TCP socket
|
|
62
|
+
* by relaying bytes between the two.
|
|
63
|
+
*
|
|
64
|
+
* Theia delivers each frontend connection to a registered `ConnectionHandler`
|
|
65
|
+
* keyed by its `path`. The handler asks the language server (via a registered
|
|
66
|
+
* command) for the target server's listening port, opens a `net.Socket` to that
|
|
67
|
+
* port, and forwards the Theia channel onto the socket. The frontend terminates
|
|
68
|
+
* the same wire protocol the server speaks, so the backend performs no semantic
|
|
69
|
+
* re-proxy — it relays bytes only and stays oblivious to the server's method set.
|
|
70
|
+
*
|
|
71
|
+
* The single per-head variation — *which* byte forwarder bridges the channel and
|
|
72
|
+
* the socket — is the abstract {@link forwardToSocketConnection} hook: the GLSP
|
|
73
|
+
* head plugs in `@eclipse-glsp/theia-integration`'s `SocketConnectionForwarder`,
|
|
74
|
+
* the data-server head its own `SocketChannelForwarder`. Keeping the forwarder
|
|
75
|
+
* behind the hook is what lets the data head stay GLSP-free while sharing the
|
|
76
|
+
* port-discovery + buffer-and-replay race fix + connect orchestration here.
|
|
77
|
+
*/
|
|
78
|
+
let AbstractSocketForwardingConnectionHandler = class AbstractSocketForwardingConnectionHandler {
|
|
79
|
+
messageService;
|
|
80
|
+
commandService;
|
|
81
|
+
// Theia backend `ILogger` — this handler runs in the Theia backend process,
|
|
82
|
+
// not the spawned language-server process, so the framework `LspLogger`
|
|
83
|
+
// (which needs the Langium connection/services) is out of reach here.
|
|
84
|
+
logger;
|
|
85
|
+
path;
|
|
86
|
+
portCommand;
|
|
87
|
+
logComponent;
|
|
88
|
+
serverName;
|
|
89
|
+
findPortTimeout;
|
|
90
|
+
findPortAttempts;
|
|
91
|
+
connectTimeoutMs;
|
|
92
|
+
onSocketCreated;
|
|
93
|
+
constructor(options) {
|
|
94
|
+
this.path = options.path;
|
|
95
|
+
this.portCommand = options.portCommand;
|
|
96
|
+
this.logComponent = options.logComponent;
|
|
97
|
+
this.serverName = options.serverName;
|
|
98
|
+
this.findPortTimeout = options.findPortTimeout ?? 500;
|
|
99
|
+
this.findPortAttempts = options.findPortAttempts ?? -1;
|
|
100
|
+
this.connectTimeoutMs = options.connectTimeoutMs ?? 10000;
|
|
101
|
+
this.onSocketCreated = options.onSocketCreated;
|
|
102
|
+
}
|
|
103
|
+
onConnection(connection) {
|
|
104
|
+
this.initializeServerConnection(connection);
|
|
105
|
+
}
|
|
106
|
+
async initializeServerConnection(channel) {
|
|
107
|
+
// RACE FIX: subscribe to `channel.onMessage` synchronously and buffer
|
|
108
|
+
// every `MessageProvider` until the forwarder is wired. Theia's
|
|
109
|
+
// `ForwardingChannel.onMessage` is a plain `Emitter` — it does NOT replay
|
|
110
|
+
// to listeners that subscribe later. Without this buffer, frontend writes
|
|
111
|
+
// arriving between `onConnection` and the forwarder subscribing (worst
|
|
112
|
+
// case: the whole `findPort` delay plus the socket connect time) are
|
|
113
|
+
// dropped silently. A frontend builds its proxy synchronously on the
|
|
114
|
+
// channel and may send requests immediately, so it reliably hits this
|
|
115
|
+
// window.
|
|
116
|
+
const buffered = [];
|
|
117
|
+
const bufferSub = channel.onMessage(provider => buffered.push(provider));
|
|
118
|
+
try {
|
|
119
|
+
const port = await this.findPort();
|
|
120
|
+
this.logger.info(`[${this.logComponent}] Connecting to ${this.serverName} on port ${port}...`);
|
|
121
|
+
await this.connectToServer(channel, port, { bufferSub, buffered });
|
|
122
|
+
this.logger.info(`[${this.logComponent}] Connected to ${this.serverName} on port ${port}.`);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
bufferSub.dispose();
|
|
126
|
+
const message = error && typeof error === 'object' && 'message' in error ? String(error.message) : String(error);
|
|
127
|
+
this.logger.error(`[${this.logComponent}] Could not connect to ${this.serverName}: ${message}`);
|
|
128
|
+
this.messageService.error(`Could not connect to ${this.serverName}: ` + message);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async findPort() {
|
|
132
|
+
const pendingContent = new promise_util_1.Deferred();
|
|
133
|
+
let counter = 0;
|
|
134
|
+
const tryQueryingPort = () => {
|
|
135
|
+
setTimeout(async () => {
|
|
136
|
+
try {
|
|
137
|
+
const port = await this.commandService.executeCommand(this.portCommand);
|
|
138
|
+
if (port) {
|
|
139
|
+
pendingContent.resolve(port);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
counter++;
|
|
144
|
+
if (this.findPortAttempts >= 0 && counter > this.findPortAttempts) {
|
|
145
|
+
pendingContent.reject(error);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
tryQueryingPort();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}, this.findPortTimeout);
|
|
152
|
+
};
|
|
153
|
+
tryQueryingPort();
|
|
154
|
+
return pendingContent.promise;
|
|
155
|
+
}
|
|
156
|
+
async connectToServer(channel, port, preForwardBuffer) {
|
|
157
|
+
const connected = new promise_util_1.Deferred();
|
|
158
|
+
const socket = new net.Socket();
|
|
159
|
+
this.onSocketCreated?.(socket);
|
|
160
|
+
socket.on('ready', () => connected.resolve());
|
|
161
|
+
socket.on('close', () => connected.reject(`Socket to ${this.serverName} was closed.`));
|
|
162
|
+
socket.on('error', error => this.logger.error(`Error occurred with the ${this.serverName} socket: ${error.name}; ${error.message}`));
|
|
163
|
+
// Synchronous hand-off: dispose the pre-forward buffer FIRST, then wire the
|
|
164
|
+
// forwarder, then replay buffered messages. The event loop cannot
|
|
165
|
+
// interleave between these synchronous statements, so no message is both
|
|
166
|
+
// buffered AND forwarded (no double delivery), and none arriving this tick
|
|
167
|
+
// slips through without a subscriber.
|
|
168
|
+
preForwardBuffer?.bufferSub.dispose();
|
|
169
|
+
this.forwardToSocketConnection(channel, socket);
|
|
170
|
+
if (preForwardBuffer && preForwardBuffer.buffered.length > 0) {
|
|
171
|
+
this.replayBufferedMessages(channel, preForwardBuffer.buffered);
|
|
172
|
+
}
|
|
173
|
+
if (channel instanceof channel_1.ForwardingChannel) {
|
|
174
|
+
socket.on('error', error => channel.onErrorEmitter.fire(error));
|
|
175
|
+
}
|
|
176
|
+
socket.connect({ port });
|
|
177
|
+
setTimeout(() => connected.reject('Timeout reached.'), this.connectTimeoutMs);
|
|
178
|
+
return connected.promise;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Re-fire pre-forward buffered `MessageProvider`s on the channel's internal
|
|
182
|
+
* `onMessageEmitter` so the now-subscribed forwarder picks them up in arrival
|
|
183
|
+
* order. `MessageProvider` is a thunk (`() => ReadBuffer`) — buffering does
|
|
184
|
+
* not consume the read position, so replay produces the same bytes the
|
|
185
|
+
* forwarder would have seen if wired earlier.
|
|
186
|
+
*
|
|
187
|
+
* `AbstractChannel.onMessageEmitter` is `protected` in `@theia/core` but
|
|
188
|
+
* reachable at runtime; the cast is the workaround. A future Theia rename
|
|
189
|
+
* surfaces as a clear warning here.
|
|
190
|
+
*/
|
|
191
|
+
replayBufferedMessages(channel, buffered) {
|
|
192
|
+
if (!(channel instanceof channel_1.ForwardingChannel)) {
|
|
193
|
+
this.logger.warn(`[${this.logComponent}] dropping ${buffered.length} pre-forward message(s) — channel is not a ForwardingChannel`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const internals = channel;
|
|
197
|
+
if (!internals.onMessageEmitter) {
|
|
198
|
+
this.logger.warn(`[${this.logComponent}] dropping ${buffered.length} pre-forward message(s) — ForwardingChannel.onMessageEmitter not accessible`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
this.logger.info(`[${this.logComponent}] replaying ${buffered.length} pre-forward message(s) onto the wired socket forwarder`);
|
|
202
|
+
for (const provider of buffered) {
|
|
203
|
+
internals.onMessageEmitter.fire(provider);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
exports.AbstractSocketForwardingConnectionHandler = AbstractSocketForwardingConnectionHandler;
|
|
208
|
+
__decorate([
|
|
209
|
+
(0, inversify_1.inject)(core_1.MessageService),
|
|
210
|
+
__metadata("design:type", core_1.MessageService)
|
|
211
|
+
], AbstractSocketForwardingConnectionHandler.prototype, "messageService", void 0);
|
|
212
|
+
__decorate([
|
|
213
|
+
(0, inversify_1.inject)(core_1.CommandService),
|
|
214
|
+
__metadata("design:type", Object)
|
|
215
|
+
], AbstractSocketForwardingConnectionHandler.prototype, "commandService", void 0);
|
|
216
|
+
__decorate([
|
|
217
|
+
(0, inversify_1.inject)(core_1.ILogger),
|
|
218
|
+
__metadata("design:type", Object)
|
|
219
|
+
], AbstractSocketForwardingConnectionHandler.prototype, "logger", void 0);
|
|
220
|
+
exports.AbstractSocketForwardingConnectionHandler = AbstractSocketForwardingConnectionHandler = __decorate([
|
|
221
|
+
(0, inversify_1.injectable)(),
|
|
222
|
+
__metadata("design:paramtypes", [Object])
|
|
223
|
+
], AbstractSocketForwardingConnectionHandler);
|
|
224
|
+
//# sourceMappingURL=abstract-socket-forwarding-connection-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abstract-socket-forwarding-connection-handler.js","sourceRoot":"","sources":["../../src/node/abstract-socket-forwarding-connection-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
export * from './abstract-socket-forwarding-connection-handler';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,cAAc,iDAAiD,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
__exportStar(require("./abstract-socket-forwarding-connection-handler"), exports);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/node/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,kFAAgE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
export * from './stub-output-channel';
|
|
10
|
+
export * from './stub-inversify-context';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAKlF,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
// Subpath barrel for `@hydranium/client-theia/testing` — cross-head Theia
|
|
26
|
+
// test doubles (`makeStubOutputChannelManager`, `makeStubInversifyContext`).
|
|
27
|
+
__exportStar(require("./stub-output-channel"), exports);
|
|
28
|
+
__exportStar(require("./stub-inversify-context"), exports);
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,0EAA0E;AAC1E,6EAA6E;AAE7E,wDAAsC;AACtC,2DAAyC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
import { type interfaces } from '@theia/core/shared/inversify';
|
|
10
|
+
/** Builds the minimal slice of an Inversify Context needed by
|
|
11
|
+
* `getRequestParentName`: just the `currentRequest.parentRequest.bindings[0].implementationType.name`
|
|
12
|
+
* shape. Tests pass the desired parent class name (or undefined) and receive a
|
|
13
|
+
* cast context for the helper to walk. */
|
|
14
|
+
export declare function makeStubInversifyContext(parentClassName?: string): interfaces.Context;
|
|
15
|
+
//# sourceMappingURL=stub-inversify-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub-inversify-context.d.ts","sourceRoot":"","sources":["../../src/testing/stub-inversify-context.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D;;;2CAG2C;AAC3C,wBAAgB,wBAAwB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,CAgBrF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.makeStubInversifyContext = makeStubInversifyContext;
|
|
12
|
+
/** Builds the minimal slice of an Inversify Context needed by
|
|
13
|
+
* `getRequestParentName`: just the `currentRequest.parentRequest.bindings[0].implementationType.name`
|
|
14
|
+
* shape. Tests pass the desired parent class name (or undefined) and receive a
|
|
15
|
+
* cast context for the helper to walk. */
|
|
16
|
+
function makeStubInversifyContext(parentClassName) {
|
|
17
|
+
const parentRequest = parentClassName === undefined
|
|
18
|
+
? null
|
|
19
|
+
: {
|
|
20
|
+
bindings: [
|
|
21
|
+
{
|
|
22
|
+
implementationType: parentClassName === '' ? {} : { name: parentClassName }
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
currentRequest: {
|
|
28
|
+
parentRequest
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=stub-inversify-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub-inversify-context.js","sourceRoot":"","sources":["../../src/testing/stub-inversify-context.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAQlF,4DAgBC;AApBD;;;2CAG2C;AAC3C,SAAgB,wBAAwB,CAAC,eAAwB;IAC9D,MAAM,aAAa,GAChB,eAAe,KAAK,SAAS;QAC1B,CAAC,CAAC,IAAI;QACN,CAAC,CAAC;YACG,QAAQ,EAAE;gBACP;oBACG,kBAAkB,EAAE,eAAe,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE;iBAC7E;aACH;SACH,CAAC;IACV,OAAO;QACJ,cAAc,EAAE;YACb,aAAa;SACf;KAC8B,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
/** Minimal fake `OutputChannel` that captures appended lines into an array. */
|
|
10
|
+
export interface StubOutputChannel {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly lines: string[];
|
|
13
|
+
appendLine(line: string): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Minimal fake `OutputChannelManager` handing out {@link StubOutputChannel}s.
|
|
17
|
+
* Use in unit tests of `ChannelLogger` (and its subclasses) and of any consumer
|
|
18
|
+
* that injects an output channel.
|
|
19
|
+
*/
|
|
20
|
+
export interface StubOutputChannelManager {
|
|
21
|
+
readonly channels: ReadonlyMap<string, StubOutputChannel>;
|
|
22
|
+
getChannel(name: string): StubOutputChannel;
|
|
23
|
+
}
|
|
24
|
+
export declare function makeStubOutputChannelManager(): StubOutputChannelManager;
|
|
25
|
+
//# sourceMappingURL=stub-output-channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub-output-channel.d.ts","sourceRoot":"","sources":["../../src/testing/stub-output-channel.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACtC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC1D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC;CAC9C;AAED,wBAAgB,4BAA4B,IAAI,wBAAwB,CAoBvE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.makeStubOutputChannelManager = makeStubOutputChannelManager;
|
|
12
|
+
function makeStubOutputChannelManager() {
|
|
13
|
+
const channels = new Map();
|
|
14
|
+
return {
|
|
15
|
+
channels,
|
|
16
|
+
getChannel(name) {
|
|
17
|
+
let channel = channels.get(name);
|
|
18
|
+
if (!channel) {
|
|
19
|
+
const lines = [];
|
|
20
|
+
channel = {
|
|
21
|
+
name,
|
|
22
|
+
lines,
|
|
23
|
+
appendLine(line) {
|
|
24
|
+
lines.push(line);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
channels.set(name, channel);
|
|
28
|
+
}
|
|
29
|
+
return channel;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=stub-output-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub-output-channel.js","sourceRoot":"","sources":["../../src/testing/stub-output-channel.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAmBlF,oEAoBC;AApBD,SAAgB,4BAA4B;IACzC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;IACtD,OAAO;QACJ,QAAQ;QACR,UAAU,CAAC,IAAY;YACpB,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAa,EAAE,CAAC;gBAC3B,OAAO,GAAG;oBACP,IAAI;oBACJ,KAAK;oBACL,UAAU,CAAC,IAAY;wBACpB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACpB,CAAC;iBACH,CAAC;gBACF,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/B,CAAC;YACD,OAAO,OAAO,CAAC;QAClB,CAAC;KACH,CAAC;AACL,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hydranium/client-theia",
|
|
3
|
+
"version": "1.0.0-next.10",
|
|
4
|
+
"description": "Cross-head Theia client primitives shared by the hydranium protocol heads. Provides the socket-forwarding connection-handler base that the data-server and GLSP Theia integrations subclass, plus the preference-driven Output-channel logger; carries no head-specific dependency.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"hydranium",
|
|
7
|
+
"langium",
|
|
8
|
+
"language-server",
|
|
9
|
+
"lsp",
|
|
10
|
+
"theia"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/eclipse-emfcloud/hydranium/tree/main/packages/client-theia",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/eclipse-emfcloud/hydranium/issues"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/eclipse-emfcloud/hydranium.git",
|
|
19
|
+
"directory": "packages/client-theia"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": {
|
|
23
|
+
"name": "Hydranium Team"
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./lib/index.d.ts",
|
|
29
|
+
"default": "./lib/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./browser": {
|
|
32
|
+
"types": "./lib/browser/index.d.ts",
|
|
33
|
+
"default": "./lib/browser/index.js"
|
|
34
|
+
},
|
|
35
|
+
"./lib/browser": {
|
|
36
|
+
"types": "./lib/browser/index.d.ts",
|
|
37
|
+
"default": "./lib/browser/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./node": {
|
|
40
|
+
"types": "./lib/node/index.d.ts",
|
|
41
|
+
"default": "./lib/node/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./lib/node": {
|
|
44
|
+
"types": "./lib/node/index.d.ts",
|
|
45
|
+
"default": "./lib/node/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./testing": {
|
|
48
|
+
"types": "./lib/testing/index.d.ts",
|
|
49
|
+
"default": "./lib/testing/index.js"
|
|
50
|
+
},
|
|
51
|
+
"./lib/testing": {
|
|
52
|
+
"types": "./lib/testing/index.d.ts",
|
|
53
|
+
"default": "./lib/testing/index.js"
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"main": "lib/index.js",
|
|
57
|
+
"types": "lib/index.d.ts",
|
|
58
|
+
"files": [
|
|
59
|
+
"lib",
|
|
60
|
+
"src",
|
|
61
|
+
"!lib/**/*.tsbuildinfo"
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsc -b",
|
|
65
|
+
"clean": "rimraf lib tsconfig.tsbuildinfo",
|
|
66
|
+
"lint": "eslint src test --max-warnings 0",
|
|
67
|
+
"prepack": "node -e \"const m=require('./package.json'),fs=require('node:fs');const missing=[m.main,...Object.values(m.bin||{})].filter(entry=>entry&&!fs.existsSync(entry));if(missing.length){console.error('prepack '+m.name+': not built ('+missing.join(', ')+' missing). Run the build before packing: a files entry that matches nothing is skipped silently, so the tarball would ship src only.');process.exit(1);}\"",
|
|
68
|
+
"test": "npm run typecheck:test && vitest run",
|
|
69
|
+
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
|
|
70
|
+
"watch": "tsc -b -w --preserveWatchOutput"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@hydranium/protocol": "1.0.0-next.10",
|
|
74
|
+
"@theia/core": "^1.71.0",
|
|
75
|
+
"@theia/output": "^1.71.0",
|
|
76
|
+
"@types/node": "^22.0.0",
|
|
77
|
+
"inversify": "6.2.2",
|
|
78
|
+
"reflect-metadata": "0.2.2",
|
|
79
|
+
"rimraf": "^5.0.0",
|
|
80
|
+
"typescript": "^5.8.0"
|
|
81
|
+
},
|
|
82
|
+
"peerDependencies": {
|
|
83
|
+
"@hydranium/protocol": "1.0.0-next.10",
|
|
84
|
+
"@theia/core": "^1.71.0",
|
|
85
|
+
"@theia/output": "^1.71.0",
|
|
86
|
+
"inversify": "^6.0.0"
|
|
87
|
+
},
|
|
88
|
+
"engines": {
|
|
89
|
+
"node": ">=22.13"
|
|
90
|
+
},
|
|
91
|
+
"publishConfig": {
|
|
92
|
+
"access": "public"
|
|
93
|
+
},
|
|
94
|
+
"//prepack": "The publish guard, and it deliberately is NOT a `prepare`: npm runs a workspace `prepare` BEFORE the root `postinstall` that applies patches/vscode-jsonrpc+9.0.1.patch, so building there fails on a cold clone and npm rolls the entire install back. `prepack` runs only when a tarball is made (`npm pack`, `npm publish`) and never on install, so it cannot break the install it has no business touching. It FAILS rather than rebuilds, because the rebuild is exactly the part that ordering defeats. What it defends against: `files` lists `lib`, `lib` is gitignored, and a `files` entry matching nothing is skipped SILENTLY — so `npm publish` from an unbuilt tree emits a tarball of `src` and nothing else, with no error."
|
|
95
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* Browser-origin capture — what page JS can reach without DevTools attached (it
|
|
12
|
+
* cannot start a V8 CPU/heap profile). Produces a single-point renderer-runtime
|
|
13
|
+
* report (memory, source-graded). The shared report shape lives in
|
|
14
|
+
* `@hydranium/protocol` so this live capture and the Playwright CDP bridge produce
|
|
15
|
+
* the SAME `browser-runtime.json`. The main-thread timeline is an e2e-only signal,
|
|
16
|
+
* captured by the CDP bridge; deep renderer CPU/heap profiling stays a manual
|
|
17
|
+
* DevTools activity.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import type { BrowserRuntimeReport } from '@hydranium/protocol';
|
|
21
|
+
|
|
22
|
+
interface MemoryCapablePerformance {
|
|
23
|
+
measureUserAgentSpecificMemory?: () => Promise<{ bytes: number; breakdown: unknown }>;
|
|
24
|
+
memory?: { usedJSHeapSize: number; totalJSHeapSize: number; jsHeapSizeLimit: number };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Capture the renderer runtime as a single-point {@link BrowserRuntimeReport}
|
|
29
|
+
* (`after`-only — the live gauge read). Prefers the standardized
|
|
30
|
+
* `performance.measureUserAgentSpecificMemory()` (precise, by type + container, but
|
|
31
|
+
* requires cross-origin isolation and is rate-limited), falling back to Chrome's
|
|
32
|
+
* coarse `performance.memory` (JS-heap gauge), then to `unavailable`. The two-point
|
|
33
|
+
* CDP source (`nodes`/`jsEventListeners`/… + delta) is the e2e bridge's job.
|
|
34
|
+
*/
|
|
35
|
+
export async function captureBrowserRuntime(): Promise<BrowserRuntimeReport> {
|
|
36
|
+
const perf = globalThis.performance as (Performance & MemoryCapablePerformance) | undefined;
|
|
37
|
+
if (perf?.measureUserAgentSpecificMemory) {
|
|
38
|
+
try {
|
|
39
|
+
const result = await perf.measureUserAgentSpecificMemory();
|
|
40
|
+
return { source: 'measureUserAgentSpecificMemory', after: { totalBytes: result.bytes, breakdown: result.breakdown } };
|
|
41
|
+
} catch {
|
|
42
|
+
// COI missing or rate-limited — fall through to the coarse fallback.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (perf?.memory) {
|
|
46
|
+
return {
|
|
47
|
+
source: 'performance.memory',
|
|
48
|
+
after: {
|
|
49
|
+
jsHeapUsedBytes: perf.memory.usedJSHeapSize,
|
|
50
|
+
jsHeapTotalBytes: perf.memory.totalJSHeapSize,
|
|
51
|
+
jsHeapLimitBytes: perf.memory.jsHeapSizeLimit
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return { source: 'unavailable', after: {} };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function mb(bytes: number): string {
|
|
59
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Render a {@link BrowserRuntimeReport} as a one-line summary for a channel / toast. */
|
|
63
|
+
export function formatBrowserRuntime(report: BrowserRuntimeReport): string {
|
|
64
|
+
const { after } = report;
|
|
65
|
+
if (report.source === 'measureUserAgentSpecificMemory' && after.totalBytes !== undefined) {
|
|
66
|
+
return `Browser renderer memory (precise): ${mb(after.totalBytes)} total across JS/DOM/workers.`;
|
|
67
|
+
}
|
|
68
|
+
if (report.source === 'performance.memory' && after.jsHeapUsedBytes !== undefined) {
|
|
69
|
+
const used = after.jsHeapUsedBytes;
|
|
70
|
+
const total = after.jsHeapTotalBytes ?? 0;
|
|
71
|
+
const limit = after.jsHeapLimitBytes ?? 0;
|
|
72
|
+
return `Browser JS heap: ${mb(used)} used / ${mb(total)} total / ${mb(limit)} limit (JS heap only, not the full renderer).`;
|
|
73
|
+
}
|
|
74
|
+
return 'Browser memory info unavailable (non-Chromium, or performance.memory disabled / cross-origin isolation off).';
|
|
75
|
+
}
|