@hydranium/protocol 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 +81 -0
- package/lib/abstract-logger.d.ts +66 -0
- package/lib/abstract-logger.d.ts.map +1 -0
- package/lib/abstract-logger.js +110 -0
- package/lib/abstract-logger.js.map +1 -0
- package/lib/browser-runtime.d.ts +124 -0
- package/lib/browser-runtime.d.ts.map +1 -0
- package/lib/browser-runtime.js +11 -0
- package/lib/browser-runtime.js.map +1 -0
- package/lib/client/data-events.d.ts +49 -0
- package/lib/client/data-events.d.ts.map +1 -0
- package/lib/client/data-events.js +60 -0
- package/lib/client/data-events.js.map +1 -0
- package/lib/client/data-port.d.ts +95 -0
- package/lib/client/data-port.d.ts.map +1 -0
- package/lib/client/data-port.js +11 -0
- package/lib/client/data-port.js.map +1 -0
- package/lib/client/data-session.d.ts +129 -0
- package/lib/client/data-session.d.ts.map +1 -0
- package/lib/client/data-session.js +179 -0
- package/lib/client/data-session.js.map +1 -0
- package/lib/client/index.d.ts +39 -0
- package/lib/client/index.d.ts.map +1 -0
- package/lib/client/index.js +55 -0
- package/lib/client/index.js.map +1 -0
- package/lib/client/message-relay.d.ts +111 -0
- package/lib/client/message-relay.d.ts.map +1 -0
- package/lib/client/message-relay.js +139 -0
- package/lib/client/message-relay.js.map +1 -0
- package/lib/client/post-message-transport.d.ts +77 -0
- package/lib/client/post-message-transport.d.ts.map +1 -0
- package/lib/client/post-message-transport.js +95 -0
- package/lib/client/post-message-transport.js.map +1 -0
- package/lib/clock.d.ts +111 -0
- package/lib/clock.d.ts.map +1 -0
- package/lib/clock.js +74 -0
- package/lib/clock.js.map +1 -0
- package/lib/data/data-protocol-methods.d.ts +39 -0
- package/lib/data/data-protocol-methods.d.ts.map +1 -0
- package/lib/data/data-protocol-methods.js +61 -0
- package/lib/data/data-protocol-methods.js.map +1 -0
- package/lib/data/data-server-protocol.d.ts +264 -0
- package/lib/data/data-server-protocol.d.ts.map +1 -0
- package/lib/data/data-server-protocol.js +11 -0
- package/lib/data/data-server-protocol.js.map +1 -0
- package/lib/data/diagnostics.d.ts +97 -0
- package/lib/data/diagnostics.d.ts.map +1 -0
- package/lib/data/diagnostics.js +25 -0
- package/lib/data/diagnostics.js.map +1 -0
- package/lib/data/events.d.ts +107 -0
- package/lib/data/events.d.ts.map +1 -0
- package/lib/data/events.js +11 -0
- package/lib/data/events.js.map +1 -0
- package/lib/data/index.d.ts +15 -0
- package/lib/data/index.d.ts.map +1 -0
- package/lib/data/index.js +38 -0
- package/lib/data/index.js.map +1 -0
- package/lib/data/methods.d.ts +57 -0
- package/lib/data/methods.d.ts.map +1 -0
- package/lib/data/methods.js +60 -0
- package/lib/data/methods.js.map +1 -0
- package/lib/data/requests.d.ts +65 -0
- package/lib/data/requests.d.ts.map +1 -0
- package/lib/data/requests.js +11 -0
- package/lib/data/requests.js.map +1 -0
- package/lib/debouncer.d.ts +75 -0
- package/lib/debouncer.d.ts.map +1 -0
- package/lib/debouncer.js +91 -0
- package/lib/debouncer.js.map +1 -0
- package/lib/errors.d.ts +84 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +113 -0
- package/lib/errors.js.map +1 -0
- package/lib/host-diagnostics.d.ts +58 -0
- package/lib/host-diagnostics.d.ts.map +1 -0
- package/lib/host-diagnostics.js +18 -0
- package/lib/host-diagnostics.js.map +1 -0
- package/lib/index.d.ts +34 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +56 -0
- package/lib/index.js.map +1 -0
- package/lib/latency-collector.d.ts +126 -0
- package/lib/latency-collector.d.ts.map +1 -0
- package/lib/latency-collector.js +137 -0
- package/lib/latency-collector.js.map +1 -0
- package/lib/logger.d.ts +119 -0
- package/lib/logger.d.ts.map +1 -0
- package/lib/logger.js +126 -0
- package/lib/logger.js.map +1 -0
- package/lib/model-server.d.ts +352 -0
- package/lib/model-server.d.ts.map +1 -0
- package/lib/model-server.js +160 -0
- package/lib/model-server.js.map +1 -0
- package/lib/model-service/args.d.ts +64 -0
- package/lib/model-service/args.d.ts.map +1 -0
- package/lib/model-service/args.js +11 -0
- package/lib/model-service/args.js.map +1 -0
- package/lib/model-service/index.d.ts +11 -0
- package/lib/model-service/index.d.ts.map +1 -0
- package/lib/model-service/index.js +31 -0
- package/lib/model-service/index.js.map +1 -0
- package/lib/model-service/reference-candidate.d.ts +56 -0
- package/lib/model-service/reference-candidate.d.ts.map +1 -0
- package/lib/model-service/reference-candidate.js +11 -0
- package/lib/model-service/reference-candidate.js.map +1 -0
- package/lib/noop-logger.d.ts +25 -0
- package/lib/noop-logger.d.ts.map +1 -0
- package/lib/noop-logger.js +36 -0
- package/lib/noop-logger.js.map +1 -0
- package/lib/observable-value.d.ts +72 -0
- package/lib/observable-value.d.ts.map +1 -0
- package/lib/observable-value.js +52 -0
- package/lib/observable-value.js.map +1 -0
- package/lib/patch-merge.d.ts +123 -0
- package/lib/patch-merge.d.ts.map +1 -0
- package/lib/patch-merge.js +104 -0
- package/lib/patch-merge.js.map +1 -0
- package/lib/profile-session.d.ts +87 -0
- package/lib/profile-session.d.ts.map +1 -0
- package/lib/profile-session.js +98 -0
- package/lib/profile-session.js.map +1 -0
- package/lib/profiling.d.ts +83 -0
- package/lib/profiling.d.ts.map +1 -0
- package/lib/profiling.js +20 -0
- package/lib/profiling.js.map +1 -0
- package/lib/project.d.ts +121 -0
- package/lib/project.d.ts.map +1 -0
- package/lib/project.js +34 -0
- package/lib/project.js.map +1 -0
- package/lib/rpc/bind-rpc-methods.d.ts +100 -0
- package/lib/rpc/bind-rpc-methods.d.ts.map +1 -0
- package/lib/rpc/bind-rpc-methods.js +110 -0
- package/lib/rpc/bind-rpc-methods.js.map +1 -0
- package/lib/rpc/create-rpc-proxy.d.ts +188 -0
- package/lib/rpc/create-rpc-proxy.d.ts.map +1 -0
- package/lib/rpc/create-rpc-proxy.js +158 -0
- package/lib/rpc/create-rpc-proxy.js.map +1 -0
- package/lib/rpc/index.d.ts +12 -0
- package/lib/rpc/index.d.ts.map +1 -0
- package/lib/rpc/index.js +31 -0
- package/lib/rpc/index.js.map +1 -0
- package/lib/rpc/wire-prefix.d.ts +37 -0
- package/lib/rpc/wire-prefix.d.ts.map +1 -0
- package/lib/rpc/wire-prefix.js +49 -0
- package/lib/rpc/wire-prefix.js.map +1 -0
- package/lib/testing/data-doubles.d.ts +121 -0
- package/lib/testing/data-doubles.d.ts.map +1 -0
- package/lib/testing/data-doubles.js +102 -0
- package/lib/testing/data-doubles.js.map +1 -0
- package/lib/testing/fake-clock.d.ts +35 -0
- package/lib/testing/fake-clock.d.ts.map +1 -0
- package/lib/testing/fake-clock.js +86 -0
- package/lib/testing/fake-clock.js.map +1 -0
- package/lib/testing/harness.d.ts +24 -0
- package/lib/testing/harness.d.ts.map +1 -0
- package/lib/testing/harness.js +11 -0
- package/lib/testing/harness.js.map +1 -0
- package/lib/testing/index.d.ts +13 -0
- package/lib/testing/index.d.ts.map +1 -0
- package/lib/testing/index.js +41 -0
- package/lib/testing/index.js.map +1 -0
- package/lib/testing/node/duplex-connection.d.ts +25 -0
- package/lib/testing/node/duplex-connection.d.ts.map +1 -0
- package/lib/testing/node/duplex-connection.js +34 -0
- package/lib/testing/node/duplex-connection.js.map +1 -0
- package/lib/testing/node/duplex-stream.d.ts +32 -0
- package/lib/testing/node/duplex-stream.d.ts.map +1 -0
- package/lib/testing/node/duplex-stream.js +35 -0
- package/lib/testing/node/duplex-stream.js.map +1 -0
- package/lib/testing/node/index.d.ts +11 -0
- package/lib/testing/node/index.d.ts.map +1 -0
- package/lib/testing/node/index.js +37 -0
- package/lib/testing/node/index.js.map +1 -0
- package/lib/testing/wait-for.d.ts +69 -0
- package/lib/testing/wait-for.d.ts.map +1 -0
- package/lib/testing/wait-for.js +67 -0
- package/lib/testing/wait-for.js.map +1 -0
- package/lib/tracer.d.ts +115 -0
- package/lib/tracer.d.ts.map +1 -0
- package/lib/tracer.js +205 -0
- package/lib/tracer.js.map +1 -0
- package/lib/transfer-diagnostic.d.ts +73 -0
- package/lib/transfer-diagnostic.d.ts.map +1 -0
- package/lib/transfer-diagnostic.js +45 -0
- package/lib/transfer-diagnostic.js.map +1 -0
- package/lib/transfer-document.d.ts +73 -0
- package/lib/transfer-document.d.ts.map +1 -0
- package/lib/transfer-document.js +46 -0
- package/lib/transfer-document.js.map +1 -0
- package/lib/transfer-element.d.ts +39 -0
- package/lib/transfer-element.d.ts.map +1 -0
- package/lib/transfer-element.js +11 -0
- package/lib/transfer-element.js.map +1 -0
- package/lib/uri.d.ts +62 -0
- package/lib/uri.d.ts.map +1 -0
- package/lib/uri.js +28 -0
- package/lib/uri.js.map +1 -0
- package/lib/util.d.ts +147 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +211 -0
- package/lib/util.js.map +1 -0
- package/package.json +100 -0
- package/src/abstract-logger.ts +120 -0
- package/src/browser-runtime.ts +135 -0
- package/src/client/data-events.ts +71 -0
- package/src/client/data-port.ts +99 -0
- package/src/client/data-session.ts +209 -0
- package/src/client/index.ts +40 -0
- package/src/client/message-relay.ts +216 -0
- package/src/client/post-message-transport.ts +167 -0
- package/src/clock.ts +173 -0
- package/src/data/data-protocol-methods.ts +79 -0
- package/src/data/data-server-protocol.ts +296 -0
- package/src/data/diagnostics.ts +116 -0
- package/src/data/events.ts +127 -0
- package/src/data/index.ts +23 -0
- package/src/data/methods.ts +59 -0
- package/src/data/requests.ts +70 -0
- package/src/debouncer.ts +118 -0
- package/src/errors.ts +127 -0
- package/src/host-diagnostics.ts +63 -0
- package/src/index.ts +41 -0
- package/src/latency-collector.ts +231 -0
- package/src/logger.ts +172 -0
- package/src/model-server.ts +479 -0
- package/src/model-service/args.ts +67 -0
- package/src/model-service/index.ts +16 -0
- package/src/model-service/reference-candidate.ts +58 -0
- package/src/noop-logger.ts +36 -0
- package/src/observable-value.ts +92 -0
- package/src/patch-merge.ts +165 -0
- package/src/profile-session.ts +164 -0
- package/src/profiling.ts +113 -0
- package/src/project.ts +125 -0
- package/src/rpc/README.md +163 -0
- package/src/rpc/bind-rpc-methods.ts +180 -0
- package/src/rpc/create-rpc-proxy.ts +292 -0
- package/src/rpc/index.ts +16 -0
- package/src/rpc/wire-prefix.ts +48 -0
- package/src/testing/data-doubles.ts +178 -0
- package/src/testing/fake-clock.ts +106 -0
- package/src/testing/harness.ts +24 -0
- package/src/testing/index.ts +26 -0
- package/src/testing/node/duplex-connection.ts +50 -0
- package/src/testing/node/duplex-stream.ts +51 -0
- package/src/testing/node/index.ts +22 -0
- package/src/testing/wait-for.ts +94 -0
- package/src/tracer.ts +277 -0
- package/src/transfer-diagnostic.ts +92 -0
- package/src/transfer-document.ts +99 -0
- package/src/transfer-element.ts +43 -0
- package/src/uri.ts +61 -0
- package/src/util.ts +250 -0
|
@@ -0,0 +1,139 @@
|
|
|
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.relayToPostMessageChannel = relayToPostMessageChannel;
|
|
12
|
+
const vscode_jsonrpc_1 = require("vscode-jsonrpc");
|
|
13
|
+
/**
|
|
14
|
+
* Pump JSON-RPC messages between a framed transport and a structured-clone
|
|
15
|
+
* {@link PostMessageChannel}, decoding neither.
|
|
16
|
+
*
|
|
17
|
+
* This is the extension-host half of the hop whose webview half is
|
|
18
|
+
* `createPostMessageTransport`. A webview has no `net`, so the data-server
|
|
19
|
+
* socket can only be held by the extension host; the host therefore has to move
|
|
20
|
+
* whole messages between a Content-Length-framed socket and a pipe that carries
|
|
21
|
+
* objects. Both sides speak the same JSON-RPC, so this moves messages and adds
|
|
22
|
+
* no semantics — there is no re-proxy in between, and `createRpcProxy` on the far
|
|
23
|
+
* side is unaware the relay exists.
|
|
24
|
+
*
|
|
25
|
+
* **No `MessageConnection` is built here, and that is what keeps the module
|
|
26
|
+
* browser-neutral.** A relay is not a JSON-RPC endpoint: it has no requests of
|
|
27
|
+
* its own, so it needs no message queue, hence no vscode-jsonrpc runtime
|
|
28
|
+
* abstraction layer. `reader.listen` / `writer.write` are enough. The caller
|
|
29
|
+
* imports the entrypoint that frames its own transport (`vscode-jsonrpc/node`
|
|
30
|
+
* for a socket) and the RAL that comes with it; this tier stays neutral and is
|
|
31
|
+
* gated so by `npm run check:neutral`. Contrast
|
|
32
|
+
* `@hydranium/data-client-theia`'s `SocketChannelForwarder`, which does build a
|
|
33
|
+
* connection only to borrow its `onClose`, and pays a Theia dependency for the
|
|
34
|
+
* byte coding this shape does not need.
|
|
35
|
+
*
|
|
36
|
+
* **The race this exists to close.** `openTransport` is asynchronous — a real
|
|
37
|
+
* host discovers a port first, then connects — while the clone pipe is usable
|
|
38
|
+
* immediately. `PostMessageChannel.onMessage` is a plain emitter with no replay,
|
|
39
|
+
* so a message sent during the connect window is dropped outright.
|
|
40
|
+
*
|
|
41
|
+
* It is not enough that a disciplined client awaits its own connection before
|
|
42
|
+
* sending: a host builds the far-side connection and hands it back *without*
|
|
43
|
+
* waiting for the relay, so `DataSession`'s very first call — the readiness
|
|
44
|
+
* handshake — is already in flight while the socket is still opening. Dropping
|
|
45
|
+
* that first request presents as a client hanging forever on connect against a
|
|
46
|
+
* perfectly healthy server.
|
|
47
|
+
*
|
|
48
|
+
* So the subscription is taken **synchronously, before the first await**, and
|
|
49
|
+
* buffers; the hand-off then swaps listeners and replays within one turn of the
|
|
50
|
+
* event loop, which is what makes it impossible for a message to be both
|
|
51
|
+
* buffered and forwarded, or to arrive between the two. Replay is FIFO because
|
|
52
|
+
* order is load-bearing — a `getModelDocument` that overtook its own
|
|
53
|
+
* `openModelDocument` would answer against an unopened document.
|
|
54
|
+
* `@hydranium/client-theia`'s `AbstractSocketForwardingConnectionHandler` carries the
|
|
55
|
+
* same fix for the Theia channel transport.
|
|
56
|
+
*/
|
|
57
|
+
function relayToPostMessageChannel(channel, openTransport, options = {}) {
|
|
58
|
+
const closeEmitter = new vscode_jsonrpc_1.Emitter();
|
|
59
|
+
const subscriptions = [];
|
|
60
|
+
let transport;
|
|
61
|
+
let disposed = false;
|
|
62
|
+
// Taken before the first await, so nothing the far side sends during the
|
|
63
|
+
// connect window is lost. See the race note above.
|
|
64
|
+
const buffered = [];
|
|
65
|
+
let bufferSubscription = channel.onMessage(message => buffered.push(message));
|
|
66
|
+
const closeFramedSide = () => {
|
|
67
|
+
if (disposed) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
closeEmitter.fire();
|
|
71
|
+
};
|
|
72
|
+
const wired = (async () => {
|
|
73
|
+
let opened;
|
|
74
|
+
try {
|
|
75
|
+
opened = await openTransport();
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
bufferSubscription?.dispose();
|
|
79
|
+
bufferSubscription = undefined;
|
|
80
|
+
buffered.length = 0;
|
|
81
|
+
options.reportError?.(error, 'opening the transport to relay');
|
|
82
|
+
closeFramedSide();
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (disposed) {
|
|
86
|
+
// Disposed while connecting: the transport is ours now, so it is ours
|
|
87
|
+
// to release, or the socket outlives the relay that owns it.
|
|
88
|
+
opened.dispose?.();
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
transport = opened;
|
|
92
|
+
// Synchronous hand-off: drop the buffering listener, wire both
|
|
93
|
+
// directions, then replay. No await in between, so the event loop cannot
|
|
94
|
+
// interleave a message into the gap.
|
|
95
|
+
bufferSubscription?.dispose();
|
|
96
|
+
bufferSubscription = undefined;
|
|
97
|
+
subscriptions.push(opened.reader.listen(message => channel.post(message)), opened.reader.onClose(() => closeFramedSide()), opened.reader.onError(error => {
|
|
98
|
+
options.reportError?.(error, 'reading from the relayed transport');
|
|
99
|
+
closeFramedSide();
|
|
100
|
+
}), channel.onMessage(message => {
|
|
101
|
+
void opened.writer.write(message).catch((error) => {
|
|
102
|
+
options.reportError?.(error, 'writing to the relayed transport');
|
|
103
|
+
});
|
|
104
|
+
}));
|
|
105
|
+
const onChannelClose = channel.onClose?.(() => dispose());
|
|
106
|
+
if (onChannelClose) {
|
|
107
|
+
subscriptions.push(onChannelClose);
|
|
108
|
+
}
|
|
109
|
+
for (const message of buffered) {
|
|
110
|
+
void opened.writer.write(message).catch((error) => {
|
|
111
|
+
options.reportError?.(error, 'replaying a buffered message to the relayed transport');
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
buffered.length = 0;
|
|
115
|
+
return true;
|
|
116
|
+
})();
|
|
117
|
+
function dispose() {
|
|
118
|
+
if (disposed) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
disposed = true;
|
|
122
|
+
bufferSubscription?.dispose();
|
|
123
|
+
bufferSubscription = undefined;
|
|
124
|
+
buffered.length = 0;
|
|
125
|
+
for (const subscription of subscriptions) {
|
|
126
|
+
subscription.dispose();
|
|
127
|
+
}
|
|
128
|
+
subscriptions.length = 0;
|
|
129
|
+
transport?.dispose?.();
|
|
130
|
+
transport = undefined;
|
|
131
|
+
closeEmitter.dispose();
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
wired,
|
|
135
|
+
onClose: closeEmitter.event,
|
|
136
|
+
dispose
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=message-relay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-relay.js","sourceRoot":"","sources":["../../src/client/message-relay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
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 Disposable, type Message, type MessageReader, type MessageWriter } from 'vscode-jsonrpc';
|
|
10
|
+
/**
|
|
11
|
+
* A `postMessage`-shaped pipe: fire-and-forget, structured-clone-only, no
|
|
12
|
+
* framing and no bytes.
|
|
13
|
+
*
|
|
14
|
+
* This is the shape every extension↔webview hop reduces to, and the reason the
|
|
15
|
+
* data head needs a port at all. A webview has no `net`, no reach into the
|
|
16
|
+
* extension host's connection, and nothing but structured clone — so a
|
|
17
|
+
* transport built on it can carry plain data and nothing else.
|
|
18
|
+
*
|
|
19
|
+
* Deliberately minimal, and deliberately not typed against any host's messaging
|
|
20
|
+
* library — a host adapter satisfies it in a few lines over whatever messenger
|
|
21
|
+
* it already has, so a diagram and a form can share one hop, one lifecycle and
|
|
22
|
+
* one dispose rather than opening a second channel for the form.
|
|
23
|
+
*/
|
|
24
|
+
export interface PostMessageChannel {
|
|
25
|
+
/**
|
|
26
|
+
* Hand one JSON-RPC message to the other side. Fire-and-forget: delivery
|
|
27
|
+
* failures surface through {@link onClose}, never as a rejection, because
|
|
28
|
+
* `postMessage` has no completion to report.
|
|
29
|
+
*/
|
|
30
|
+
post(message: Message): void;
|
|
31
|
+
/** Register for messages arriving from the other side. */
|
|
32
|
+
onMessage(listener: (message: Message) => void): Disposable;
|
|
33
|
+
/**
|
|
34
|
+
* Register for the pipe going away — the webview being disposed, the
|
|
35
|
+
* extension deactivating. Optional: a channel with no observable end simply
|
|
36
|
+
* never fires close, and the reader/writer then rely on their owner's
|
|
37
|
+
* dispose instead.
|
|
38
|
+
*/
|
|
39
|
+
onClose?(listener: () => void): Disposable;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A reader/writer pair over a {@link PostMessageChannel}, ready to be handed to
|
|
43
|
+
* `createMessageConnection`.
|
|
44
|
+
*
|
|
45
|
+
* The connection is NOT built here, and that omission is the point:
|
|
46
|
+
* `createMessageConnection`'s message queue needs a vscode-jsonrpc runtime
|
|
47
|
+
* abstraction layer, and only the `/node` and `/browser` entrypoints install
|
|
48
|
+
* one. vscode-jsonrpc 9's package ROOT resolves to the RAL-less common API and
|
|
49
|
+
* throws `No runtime abstraction layer installed` on the first message. Only
|
|
50
|
+
* the host knows which side it is on, so the host imports the matching entry
|
|
51
|
+
* (`/browser` in a webview, `/node` in an extension host) and builds the
|
|
52
|
+
* connection there.
|
|
53
|
+
*
|
|
54
|
+
* Keeping the factory out of this module is also what lets the module stay
|
|
55
|
+
* browser-neutral: it touches only `AbstractMessageReader` /
|
|
56
|
+
* `AbstractMessageWriter` / `Emitter`, none of which need a RAL.
|
|
57
|
+
*/
|
|
58
|
+
export interface PostMessageTransport {
|
|
59
|
+
readonly reader: MessageReader;
|
|
60
|
+
readonly writer: MessageWriter;
|
|
61
|
+
/** Release the channel subscriptions. */
|
|
62
|
+
dispose(): void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build the reader/writer pair for `channel`.
|
|
66
|
+
*
|
|
67
|
+
* What this buys, and why `DataPort` is shaped the way it is:
|
|
68
|
+
* `createRpcProxy` runs **unchanged** over the result. The typed surface, the
|
|
69
|
+
* `DATA_*_PROTOCOL_METHODS` allowlists and the whole open → watch → update →
|
|
70
|
+
* close sequence are identical in a webview and in a Node extension host,
|
|
71
|
+
* because only the `MessageConnection` the port hands back differs. Terminating
|
|
72
|
+
* JSON-RPC in the extension host and declaring one request type per data-head
|
|
73
|
+
* method is the wrong trade: it hand-maintains a per-method mapping and
|
|
74
|
+
* discards the `as const satisfies keyof` allowlists, which cannot drift.
|
|
75
|
+
*/
|
|
76
|
+
export declare function createPostMessageTransport(channel: PostMessageChannel): PostMessageTransport;
|
|
77
|
+
//# sourceMappingURL=post-message-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-message-transport.d.ts","sourceRoot":"","sources":["../../src/client/post-message-transport.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAKJ,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,aAAa,EAClB,KAAK,aAAa,EACpB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,kBAAkB;IAChC;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAE7B,0DAA0D;IAC1D,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,UAAU,CAAC;IAE5D;;;;;OAKG;IACH,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,UAAU,CAAC;CAC7C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,oBAAoB;IAClC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,yCAAyC;IACzC,OAAO,IAAI,IAAI,CAAC;CAClB;AAmED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,kBAAkB,GAAG,oBAAoB,CAW5F"}
|
|
@@ -0,0 +1,95 @@
|
|
|
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.createPostMessageTransport = createPostMessageTransport;
|
|
12
|
+
const vscode_jsonrpc_1 = require("vscode-jsonrpc");
|
|
13
|
+
/**
|
|
14
|
+
* A `MessageReader` over a {@link PostMessageChannel}.
|
|
15
|
+
*
|
|
16
|
+
* Structured clone moves objects, so there is nothing to frame and nothing to
|
|
17
|
+
* decode — the message arrives as the message.
|
|
18
|
+
*/
|
|
19
|
+
class PostMessageReader extends vscode_jsonrpc_1.AbstractMessageReader {
|
|
20
|
+
messageEmitter = new vscode_jsonrpc_1.Emitter();
|
|
21
|
+
subscriptions = [];
|
|
22
|
+
constructor(channel) {
|
|
23
|
+
super();
|
|
24
|
+
this.subscriptions.push(channel.onMessage(message => this.messageEmitter.fire(message)));
|
|
25
|
+
const onClose = channel.onClose?.(() => this.fireClose());
|
|
26
|
+
if (onClose) {
|
|
27
|
+
this.subscriptions.push(onClose);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
listen(callback) {
|
|
31
|
+
return this.messageEmitter.event(callback);
|
|
32
|
+
}
|
|
33
|
+
dispose() {
|
|
34
|
+
super.dispose();
|
|
35
|
+
for (const subscription of this.subscriptions) {
|
|
36
|
+
subscription.dispose();
|
|
37
|
+
}
|
|
38
|
+
this.subscriptions.length = 0;
|
|
39
|
+
this.messageEmitter.dispose();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** The dual of {@link PostMessageReader} — one `post` per JSON-RPC message. */
|
|
43
|
+
class PostMessageWriter extends vscode_jsonrpc_1.AbstractMessageWriter {
|
|
44
|
+
channel;
|
|
45
|
+
subscriptions = [];
|
|
46
|
+
constructor(channel) {
|
|
47
|
+
super();
|
|
48
|
+
this.channel = channel;
|
|
49
|
+
const onClose = channel.onClose?.(() => this.fireClose());
|
|
50
|
+
if (onClose) {
|
|
51
|
+
this.subscriptions.push(onClose);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
write(message) {
|
|
55
|
+
this.channel.post(message);
|
|
56
|
+
// `postMessage` reports no completion, so the resolved promise means
|
|
57
|
+
// "handed over", not "delivered". vscode-jsonrpc only needs the former.
|
|
58
|
+
return Promise.resolve();
|
|
59
|
+
}
|
|
60
|
+
end() {
|
|
61
|
+
this.dispose();
|
|
62
|
+
}
|
|
63
|
+
dispose() {
|
|
64
|
+
super.dispose();
|
|
65
|
+
for (const subscription of this.subscriptions) {
|
|
66
|
+
subscription.dispose();
|
|
67
|
+
}
|
|
68
|
+
this.subscriptions.length = 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Build the reader/writer pair for `channel`.
|
|
73
|
+
*
|
|
74
|
+
* What this buys, and why `DataPort` is shaped the way it is:
|
|
75
|
+
* `createRpcProxy` runs **unchanged** over the result. The typed surface, the
|
|
76
|
+
* `DATA_*_PROTOCOL_METHODS` allowlists and the whole open → watch → update →
|
|
77
|
+
* close sequence are identical in a webview and in a Node extension host,
|
|
78
|
+
* because only the `MessageConnection` the port hands back differs. Terminating
|
|
79
|
+
* JSON-RPC in the extension host and declaring one request type per data-head
|
|
80
|
+
* method is the wrong trade: it hand-maintains a per-method mapping and
|
|
81
|
+
* discards the `as const satisfies keyof` allowlists, which cannot drift.
|
|
82
|
+
*/
|
|
83
|
+
function createPostMessageTransport(channel) {
|
|
84
|
+
const reader = new PostMessageReader(channel);
|
|
85
|
+
const writer = new PostMessageWriter(channel);
|
|
86
|
+
return {
|
|
87
|
+
reader,
|
|
88
|
+
writer,
|
|
89
|
+
dispose() {
|
|
90
|
+
reader.dispose();
|
|
91
|
+
writer.dispose();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=post-message-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-message-transport.js","sourceRoot":"","sources":["../../src/client/post-message-transport.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAoJlF,gEAWC;AA7JD,mDASwB;AA4DxB;;;;;GAKG;AACH,MAAM,iBAAkB,SAAQ,sCAAqB;IAC/B,cAAc,GAAG,IAAI,wBAAO,EAAW,CAAC;IACxC,aAAa,GAAiB,EAAE,CAAC;IAEpD,YAAY,OAA2B;QACpC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACzF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1D,IAAI,OAAO,EAAE,CAAC;YACX,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,QAAsB;QAC1B,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAEQ,OAAO;QACb,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7C,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;CACH;AAED,+EAA+E;AAC/E,MAAM,iBAAkB,SAAQ,sCAAqB;IAGnB;IAFZ,aAAa,GAAiB,EAAE,CAAC;IAEpD,YAA+B,OAA2B;QACvD,KAAK,EAAE,CAAC;QADoB,YAAO,GAAP,OAAO,CAAoB;QAEvD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1D,IAAI,OAAO,EAAE,CAAC;YACX,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAgB;QACnB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,qEAAqE;QACrE,wEAAwE;QACxE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5B,CAAC;IAED,GAAG;QACA,IAAI,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC;IAEQ,OAAO;QACb,KAAK,CAAC,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7C,YAAY,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,CAAC;CACH;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,0BAA0B,CAAC,OAA2B;IACnE,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC9C,OAAO;QACJ,MAAM;QACN,MAAM;QACN,OAAO;YACJ,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,CAAC;KACH,CAAC;AACL,CAAC"}
|
package/lib/clock.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
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 { Disposable } from './util';
|
|
10
|
+
/**
|
|
11
|
+
* Measures how long something takes. Born running at {@link Clock.stopwatch};
|
|
12
|
+
* there is no `start` — you create it at the moment timing begins.
|
|
13
|
+
*
|
|
14
|
+
* Backed by a monotonic source (`performance.now`), so it is sub-millisecond
|
|
15
|
+
* precise and immune to wall-clock jumps (NTP/DST adjustments can make a
|
|
16
|
+
* `Date.now` delta go backwards; a stopwatch cannot). Use this for durations
|
|
17
|
+
* and {@link Clock.now} for "what time is it" (timestamps, TTLs).
|
|
18
|
+
*
|
|
19
|
+
* It holds no scheduled resource and is therefore NOT a {@link Disposable} —
|
|
20
|
+
* the disposable thing is a {@link Clock.setTimer}. Reads are lazy, so a fake
|
|
21
|
+
* clock just answers the current virtual time.
|
|
22
|
+
*/
|
|
23
|
+
export interface Stopwatch {
|
|
24
|
+
/** Total elapsed since creation; live while running, frozen after {@link stop}. */
|
|
25
|
+
readonly elapsedMs: number;
|
|
26
|
+
/**
|
|
27
|
+
* Split: the elapsed since the previous `lap` (or since creation for the
|
|
28
|
+
* first call), starting a new split. Non-destructive — the running total
|
|
29
|
+
* ({@link elapsedMs}) is unaffected, so `lap` is not a restart.
|
|
30
|
+
*/
|
|
31
|
+
lap(): number;
|
|
32
|
+
/**
|
|
33
|
+
* Freeze and return the grand total (the sum of every lap plus the tail
|
|
34
|
+
* since the last lap). Idempotent: further calls return the same value and
|
|
35
|
+
* {@link elapsedMs} stops advancing.
|
|
36
|
+
*/
|
|
37
|
+
stop(): number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Injectable time, so logic gated on time (debounce windows, slow-update
|
|
41
|
+
* warnings, request timeouts, the self-save TTL) is deterministically
|
|
42
|
+
* testable instead of waiting on real wall-clock. The {@link SystemClock}
|
|
43
|
+
* default delegates to the platform; tests bind `makeFakeClock`.
|
|
44
|
+
*
|
|
45
|
+
* Two distinct readings on purpose: {@link now} is wall-clock (for timestamps
|
|
46
|
+
* and TTLs that compare against a file's mtime), while {@link stopwatch}
|
|
47
|
+
* measures durations off a monotonic source. They are different clocks; do not
|
|
48
|
+
* subtract two {@link now} readings to measure a duration.
|
|
49
|
+
*
|
|
50
|
+
* A cross-head contract, so it carries no platform or DI-framework coupling.
|
|
51
|
+
*
|
|
52
|
+
* Note: the runtime health monitors (event-loop, memory) intentionally keep
|
|
53
|
+
* the real wall-clock rather than taking a `Clock` — faking the time they
|
|
54
|
+
* measure would invert their meaning.
|
|
55
|
+
*/
|
|
56
|
+
export interface Clock {
|
|
57
|
+
/** Current wall-clock time in milliseconds (the `Date.now` reading). */
|
|
58
|
+
now(): number;
|
|
59
|
+
/**
|
|
60
|
+
* Run `callback` after `ms` have elapsed; the returned {@link Disposable}
|
|
61
|
+
* cancels it if disposed before it fires. This is the testable
|
|
62
|
+
* `setTimeout` — debounce, deferred slow-warn, request timeouts.
|
|
63
|
+
*/
|
|
64
|
+
setTimer(callback: () => void, ms: number): Disposable;
|
|
65
|
+
/** Start measuring a duration. See {@link Stopwatch}. */
|
|
66
|
+
stopwatch(): Stopwatch;
|
|
67
|
+
/**
|
|
68
|
+
* Run `callback` and return its result together with how long it took.
|
|
69
|
+
* Sugar over {@link stopwatch} — pure measurement, no logging and no
|
|
70
|
+
* threshold gating (unlike `Tracer.time`). Use in
|
|
71
|
+
* measurement pipelines that consume `elapsedMs` directly. Async callbacks
|
|
72
|
+
* return a Promise of the same shape, timed across the full settle.
|
|
73
|
+
*/
|
|
74
|
+
measure<T>(callback: () => Promise<T>): Promise<Timed<T>>;
|
|
75
|
+
measure<T>(callback: () => T): Timed<T>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The result of {@link Clock.measure}: a callback's return value paired with
|
|
79
|
+
* its elapsed wall-time in milliseconds. A plain value object — no methods, no
|
|
80
|
+
* logging — deliberately distinct from `@theia/core`'s `Measurement` (a
|
|
81
|
+
* stateful self-logging handle), which would collide in a Theia process.
|
|
82
|
+
*/
|
|
83
|
+
export interface Timed<T> {
|
|
84
|
+
/**
|
|
85
|
+
* The callback's return value, unchanged. For an async callback this is the
|
|
86
|
+
* settled value rather than the promise — and a callback that REJECTS
|
|
87
|
+
* produces no `Timed` at all, because the rejection propagates, so a failed
|
|
88
|
+
* run cannot be timed through this shape.
|
|
89
|
+
*/
|
|
90
|
+
result: T;
|
|
91
|
+
/**
|
|
92
|
+
* Milliseconds off the monotonic source, so it is comparable with
|
|
93
|
+
* {@link Stopwatch.elapsedMs} and NOT with a difference of two
|
|
94
|
+
* {@link Clock.now} readings. For an async callback it spans the full settle,
|
|
95
|
+
* not just the synchronous prefix.
|
|
96
|
+
*/
|
|
97
|
+
elapsedMs: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Default {@link Clock}: delegates to the platform's `Date.now`,
|
|
101
|
+
* `performance.now`, and `setTimeout`/`clearTimeout`. Bound everywhere in
|
|
102
|
+
* production; swapped for `makeFakeClock` in tests.
|
|
103
|
+
*/
|
|
104
|
+
export declare class SystemClock implements Clock {
|
|
105
|
+
now(): number;
|
|
106
|
+
setTimer(callback: () => void, ms: number): Disposable;
|
|
107
|
+
stopwatch(): Stopwatch;
|
|
108
|
+
measure<T>(callback: () => Promise<T>): Promise<Timed<T>>;
|
|
109
|
+
measure<T>(callback: () => T): Timed<T>;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,SAAS;IACvB,mFAAmF;IACnF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,GAAG,IAAI,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,IAAI,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,KAAK;IACnB,wEAAwE;IACxE,GAAG,IAAI,MAAM,CAAC;IACd;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAAC;IACvD,yDAAyD;IACzD,SAAS,IAAI,SAAS,CAAC;IACvB;;;;;;OAMG;IACH,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;CAC1C;AAED;;;;;GAKG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC;IACrB;;;;;OAKG;IACH,MAAM,EAAE,CAAC,CAAC;IACV;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC;CACpB;AAyCD;;;;GAIG;AACH,qBAAa,WAAY,YAAW,KAAK;IACtC,GAAG,IAAI,MAAM;IAIb,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU;IAMtD,SAAS,IAAI,SAAS;IAItB,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;CASzC"}
|
package/lib/clock.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
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.SystemClock = void 0;
|
|
12
|
+
const util_1 = require("./util");
|
|
13
|
+
class SystemStopwatch {
|
|
14
|
+
start = performance.now();
|
|
15
|
+
lastLap = this.start;
|
|
16
|
+
stopped;
|
|
17
|
+
get elapsedMs() {
|
|
18
|
+
return (this.stopped ?? performance.now()) - this.start;
|
|
19
|
+
}
|
|
20
|
+
lap() {
|
|
21
|
+
const at = this.stopped ?? performance.now();
|
|
22
|
+
const split = at - this.lastLap;
|
|
23
|
+
this.lastLap = at;
|
|
24
|
+
return split;
|
|
25
|
+
}
|
|
26
|
+
stop() {
|
|
27
|
+
if (this.stopped === undefined) {
|
|
28
|
+
this.stopped = performance.now();
|
|
29
|
+
}
|
|
30
|
+
return this.stopped - this.start;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Detach a timer from the event loop so a single pending timer never keeps a
|
|
35
|
+
* Node process alive — a CLI run or test worker can exit cleanly while deferred
|
|
36
|
+
* work (debounce, slow-warn, idle CST eviction) is still scheduled; the
|
|
37
|
+
* persistent server connection keeps the loop alive in production regardless.
|
|
38
|
+
*
|
|
39
|
+
* `unref` is Node-only. {@link SystemClock} also runs in the browser, where
|
|
40
|
+
* `setTimeout` returns a bare numeric handle with no `unref` — the optional
|
|
41
|
+
* call is a no-op there, and declaring the parameter's `unref` optional accepts
|
|
42
|
+
* a Node `NodeJS.Timeout` structurally without a cast.
|
|
43
|
+
*/
|
|
44
|
+
function unrefTimer(handle) {
|
|
45
|
+
handle.unref?.();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Default {@link Clock}: delegates to the platform's `Date.now`,
|
|
49
|
+
* `performance.now`, and `setTimeout`/`clearTimeout`. Bound everywhere in
|
|
50
|
+
* production; swapped for `makeFakeClock` in tests.
|
|
51
|
+
*/
|
|
52
|
+
class SystemClock {
|
|
53
|
+
now() {
|
|
54
|
+
return Date.now();
|
|
55
|
+
}
|
|
56
|
+
setTimer(callback, ms) {
|
|
57
|
+
const handle = setTimeout(callback, ms);
|
|
58
|
+
unrefTimer(handle);
|
|
59
|
+
return util_1.Disposable.create(() => clearTimeout(handle));
|
|
60
|
+
}
|
|
61
|
+
stopwatch() {
|
|
62
|
+
return new SystemStopwatch();
|
|
63
|
+
}
|
|
64
|
+
measure(callback) {
|
|
65
|
+
const stopwatch = this.stopwatch();
|
|
66
|
+
const result = callback();
|
|
67
|
+
if (result instanceof Promise) {
|
|
68
|
+
return result.then(value => ({ result: value, elapsedMs: stopwatch.elapsedMs }));
|
|
69
|
+
}
|
|
70
|
+
return { result: result, elapsedMs: stopwatch.elapsedMs };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.SystemClock = SystemClock;
|
|
74
|
+
//# sourceMappingURL=clock.js.map
|
package/lib/clock.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,iCAAoC;AA8FpC,MAAM,eAAe;IACC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IACnC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;IACrB,OAAO,CAAqB;IAEtC,IAAI,SAAS;QACV,OAAO,CAAC,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;IAC3D,CAAC;IAED,GAAG;QACA,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC,GAAG,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,OAAO,KAAK,CAAC;IAChB,CAAC;IAED,IAAI;QACD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QACpC,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC;IACpC,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,SAAS,UAAU,CAAC,MAA8B;IAC/C,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAa,WAAW;IACrB,GAAG;QACA,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACrB,CAAC;IAED,QAAQ,CAAC,QAAoB,EAAE,EAAU;QACtC,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACxC,UAAU,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,iBAAU,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,SAAS;QACN,OAAO,IAAI,eAAe,EAAE,CAAC;IAChC,CAAC;IAID,OAAO,CAAI,QAA8B;QACtC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC1B,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;YAC7B,OAAQ,MAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACpG,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,MAAW,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC;IAClE,CAAC;CACH;AAzBD,kCAyBC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
/** Request-method names on {@link DocumentServerProtocol}. */
|
|
10
|
+
export declare const DOCUMENT_SERVER_PROTOCOL_METHODS: readonly ["openModelDocument", "closeModelDocument", "getModelDocument", "updateModelDocument", "saveModelDocument", "watchModelDocument", "unwatchModelDocument", "waitForReady"];
|
|
11
|
+
/** Request-method names on {@link ProjectServerProtocol}. */
|
|
12
|
+
export declare const PROJECT_SERVER_PROTOCOL_METHODS: readonly ["getProjects", "getProjectForUri"];
|
|
13
|
+
/**
|
|
14
|
+
* Request-method names on the composed {@link DataServerProtocol} — the
|
|
15
|
+
* document fragment followed by the project fragment. The `as const satisfies`
|
|
16
|
+
* constraint makes the array typed against the interface — stale names (typos,
|
|
17
|
+
* renamed methods) fail to typecheck.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DATA_SERVER_PROTOCOL_METHODS: readonly ["openModelDocument", "closeModelDocument", "getModelDocument", "updateModelDocument", "saveModelDocument", "watchModelDocument", "unwatchModelDocument", "waitForReady", "getProjects", "getProjectForUri"];
|
|
20
|
+
/**
|
|
21
|
+
* Request-method names on {@link ReferenceServerProtocol}. NOT part of
|
|
22
|
+
* {@link DATA_SERVER_PROTOCOL_METHODS} — adopters that compose the reference
|
|
23
|
+
* fragment register these alongside (e.g. via a `DataServer` subclass's
|
|
24
|
+
* `additionalMethods`).
|
|
25
|
+
*/
|
|
26
|
+
export declare const REFERENCE_SERVER_PROTOCOL_METHODS: readonly ["findReferenceCandidates", "resolveReference", "findNextName"];
|
|
27
|
+
/** Notification-method names on {@link DocumentClientProtocol}. */
|
|
28
|
+
export declare const DOCUMENT_CLIENT_PROTOCOL_METHODS: readonly ["onDocumentUpdated", "onDocumentSaved"];
|
|
29
|
+
/** Notification-method names on {@link ProjectClientProtocol}. */
|
|
30
|
+
export declare const PROJECT_CLIENT_PROTOCOL_METHODS: readonly ["onProjectsChanged"];
|
|
31
|
+
/**
|
|
32
|
+
* Notification-method names on the composed {@link DataClientProtocol}.
|
|
33
|
+
* Passed as the `localMethods` allowlist to `createRpcProxy` (frontend) /
|
|
34
|
+
* `bindRpcMethods` (backend) when binding inbound `on*` notifications — the
|
|
35
|
+
* data head's connection routes `<methodNamespace>onDocumentUpdated` etc. to
|
|
36
|
+
* the bound client target.
|
|
37
|
+
*/
|
|
38
|
+
export declare const DATA_CLIENT_PROTOCOL_METHODS: readonly ["onDocumentUpdated", "onDocumentSaved", "onProjectsChanged"];
|
|
39
|
+
//# sourceMappingURL=data-protocol-methods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-protocol-methods.d.ts","sourceRoot":"","sources":["../../src/data/data-protocol-methods.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAalF,8DAA8D;AAC9D,eAAO,MAAM,gCAAgC,oLAS6C,CAAC;AAE3F,6DAA6D;AAC7D,eAAO,MAAM,+BAA+B,8CAE3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,uNAG6C,CAAC;AAEvF;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,0EAI6C,CAAC;AAE5F,mEAAmE;AACnE,eAAO,MAAM,gCAAgC,mDAE5C,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,+BAA+B,gCAA+F,CAAC;AAE5I;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,wEAG6C,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
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.DATA_CLIENT_PROTOCOL_METHODS = exports.PROJECT_CLIENT_PROTOCOL_METHODS = exports.DOCUMENT_CLIENT_PROTOCOL_METHODS = exports.REFERENCE_SERVER_PROTOCOL_METHODS = exports.DATA_SERVER_PROTOCOL_METHODS = exports.PROJECT_SERVER_PROTOCOL_METHODS = exports.DOCUMENT_SERVER_PROTOCOL_METHODS = void 0;
|
|
12
|
+
/** Request-method names on {@link DocumentServerProtocol}. */
|
|
13
|
+
exports.DOCUMENT_SERVER_PROTOCOL_METHODS = [
|
|
14
|
+
'openModelDocument',
|
|
15
|
+
'closeModelDocument',
|
|
16
|
+
'getModelDocument',
|
|
17
|
+
'updateModelDocument',
|
|
18
|
+
'saveModelDocument',
|
|
19
|
+
'watchModelDocument',
|
|
20
|
+
'unwatchModelDocument',
|
|
21
|
+
'waitForReady'
|
|
22
|
+
];
|
|
23
|
+
/** Request-method names on {@link ProjectServerProtocol}. */
|
|
24
|
+
exports.PROJECT_SERVER_PROTOCOL_METHODS = ['getProjects', 'getProjectForUri'];
|
|
25
|
+
/**
|
|
26
|
+
* Request-method names on the composed {@link DataServerProtocol} — the
|
|
27
|
+
* document fragment followed by the project fragment. The `as const satisfies`
|
|
28
|
+
* constraint makes the array typed against the interface — stale names (typos,
|
|
29
|
+
* renamed methods) fail to typecheck.
|
|
30
|
+
*/
|
|
31
|
+
exports.DATA_SERVER_PROTOCOL_METHODS = [
|
|
32
|
+
...exports.DOCUMENT_SERVER_PROTOCOL_METHODS,
|
|
33
|
+
...exports.PROJECT_SERVER_PROTOCOL_METHODS
|
|
34
|
+
];
|
|
35
|
+
/**
|
|
36
|
+
* Request-method names on {@link ReferenceServerProtocol}. NOT part of
|
|
37
|
+
* {@link DATA_SERVER_PROTOCOL_METHODS} — adopters that compose the reference
|
|
38
|
+
* fragment register these alongside (e.g. via a `DataServer` subclass's
|
|
39
|
+
* `additionalMethods`).
|
|
40
|
+
*/
|
|
41
|
+
exports.REFERENCE_SERVER_PROTOCOL_METHODS = [
|
|
42
|
+
'findReferenceCandidates',
|
|
43
|
+
'resolveReference',
|
|
44
|
+
'findNextName'
|
|
45
|
+
];
|
|
46
|
+
/** Notification-method names on {@link DocumentClientProtocol}. */
|
|
47
|
+
exports.DOCUMENT_CLIENT_PROTOCOL_METHODS = ['onDocumentUpdated', 'onDocumentSaved'];
|
|
48
|
+
/** Notification-method names on {@link ProjectClientProtocol}. */
|
|
49
|
+
exports.PROJECT_CLIENT_PROTOCOL_METHODS = ['onProjectsChanged'];
|
|
50
|
+
/**
|
|
51
|
+
* Notification-method names on the composed {@link DataClientProtocol}.
|
|
52
|
+
* Passed as the `localMethods` allowlist to `createRpcProxy` (frontend) /
|
|
53
|
+
* `bindRpcMethods` (backend) when binding inbound `on*` notifications — the
|
|
54
|
+
* data head's connection routes `<methodNamespace>onDocumentUpdated` etc. to
|
|
55
|
+
* the bound client target.
|
|
56
|
+
*/
|
|
57
|
+
exports.DATA_CLIENT_PROTOCOL_METHODS = [
|
|
58
|
+
...exports.DOCUMENT_CLIENT_PROTOCOL_METHODS,
|
|
59
|
+
...exports.PROJECT_CLIENT_PROTOCOL_METHODS
|
|
60
|
+
];
|
|
61
|
+
//# sourceMappingURL=data-protocol-methods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-protocol-methods.js","sourceRoot":"","sources":["../../src/data/data-protocol-methods.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAalF,8DAA8D;AACjD,QAAA,gCAAgC,GAAG;IAC7C,mBAAmB;IACnB,oBAAoB;IACpB,kBAAkB;IAClB,qBAAqB;IACrB,mBAAmB;IACnB,oBAAoB;IACpB,sBAAsB;IACtB,cAAc;CACyE,CAAC;AAE3F,6DAA6D;AAChD,QAAA,+BAA+B,GAAG,CAAC,aAAa,EAAE,kBAAkB,CAEhF,CAAC;AAEF;;;;;GAKG;AACU,QAAA,4BAA4B,GAAG;IACzC,GAAG,wCAAgC;IACnC,GAAG,uCAA+B;CACiD,CAAC;AAEvF;;;;;GAKG;AACU,QAAA,iCAAiC,GAAG;IAC9C,yBAAyB;IACzB,kBAAkB;IAClB,cAAc;CAC0E,CAAC;AAE5F,mEAAmE;AACtD,QAAA,gCAAgC,GAAG,CAAC,mBAAmB,EAAE,iBAAiB,CAEtF,CAAC;AAEF,kEAAkE;AACrD,QAAA,+BAA+B,GAAG,CAAC,mBAAmB,CAAwE,CAAC;AAE5I;;;;;;GAMG;AACU,QAAA,4BAA4B,GAAG;IACzC,GAAG,wCAAgC;IACnC,GAAG,uCAA+B;CACiD,CAAC"}
|