@hydranium/client-browser 1.0.0-next.298 → 1.0.0-next.300
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -5
- package/lib/worker-heads.d.ts +10 -9
- package/lib/worker-heads.d.ts.map +1 -1
- package/lib/worker-heads.js +15 -9
- package/lib/worker-heads.js.map +1 -1
- package/package.json +3 -3
- package/src/worker-heads.ts +23 -15
package/README.md
CHANGED
|
@@ -56,11 +56,15 @@ const { capabilities } = await initializeLanguageClient(heads.lsp, {
|
|
|
56
56
|
const data = new DataConnectionWithEvents(heads.data);
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
In the worker,
|
|
60
|
-
`@hydranium/
|
|
61
|
-
global scope
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
In the worker, answer the bootstrap with `hostHeadsInWorker` from
|
|
60
|
+
`@hydranium/core/browser`, which starts each head on its port, never on the
|
|
61
|
+
worker's global scope, posts the ready message once they are up and reports
|
|
62
|
+
a failed start, build or rejection. A worker of your own reads the bootstrap
|
|
63
|
+
with `isWorkerBootstrapMessage` from `@hydranium/protocol`, posts a
|
|
64
|
+
`WorkerReadyMessage` once its heads are up and a `WorkerErrorMessage` for a
|
|
65
|
+
failure it catches; one under `WORKER_BOOTSTRAP_PHASE` ends the page's heads,
|
|
66
|
+
any other phase only reports. Until the worker has posted its ready message,
|
|
67
|
+
or anything on a head's port, the `Worker`'s `error` event ends the heads too.
|
|
64
68
|
|
|
65
69
|
Register the handler for the server's diagnostics in `beforeInitialized`,
|
|
66
70
|
which runs once `initialize` has answered and before `initialized` goes out.
|
package/lib/worker-heads.d.ts
CHANGED
|
@@ -48,12 +48,13 @@ export interface WorkerHeads {
|
|
|
48
48
|
readonly onWorkerError: Event<WorkerErrorMessage>;
|
|
49
49
|
/**
|
|
50
50
|
* Fires once when the heads end: on a failed bootstrap, on an `error` event
|
|
51
|
-
* before the worker
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
51
|
+
* before the worker is known to be up, or on {@link dispose}. What the heads
|
|
52
|
+
* had pending is rejected then rather than left waiting. The worker is up
|
|
53
|
+
* once it has posted its ready message, or anything on a head's port for a
|
|
54
|
+
* worker that posts no ready message. Any later report, and an `error`
|
|
55
|
+
* event once the worker is up, ends nothing: the worker runs on after an
|
|
56
|
+
* uncaught error, and the heads with it. Subscribe before the first
|
|
57
|
+
* `await`: the end fires once, and a subscriber after it hears nothing.
|
|
57
58
|
*/
|
|
58
59
|
readonly onDispose: Event<void>;
|
|
59
60
|
/** End every head. A head whose connection exists signals its close to the worker, which ends the head there. */
|
|
@@ -64,9 +65,9 @@ export interface WorkerHeads {
|
|
|
64
65
|
* each.
|
|
65
66
|
*
|
|
66
67
|
* The worker keeps `port2` of every pair and the page `port1`; neither end is
|
|
67
|
-
* given the worker global, which carries the bootstrap, the worker's
|
|
68
|
-
* reports and whatever the host adds for itself. See the
|
|
69
|
-
* `@hydranium/protocol` for why a head on the global is unusable.
|
|
68
|
+
* given the worker global, which carries the bootstrap, the worker's ready
|
|
69
|
+
* message and failure reports, and whatever the host adds for itself. See the
|
|
70
|
+
* handshake in `@hydranium/protocol` for why a head on the global is unusable.
|
|
70
71
|
*
|
|
71
72
|
* **A port reports nothing when its peer dies**, so a worker that fails to
|
|
72
73
|
* load, throws before its bootstrap or fails it would leave every request on
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-heads.d.ts","sourceRoot":"","sources":["../src/worker-heads.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,
|
|
1
|
+
{"version":3,"file":"worker-heads.d.ts","sourceRoot":"","sources":["../src/worker-heads.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAOJ,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,sBAAsB,EAE3B,KAAK,kBAAkB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAoC,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG/H,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,WAAW,CAAC;AAEjD,MAAM,WAAW,kBAAkB;IAChC,mHAAmH;IACnH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,sBAAsB,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,QAAQ,GAAG,UAAU,CAAC;CACrG;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IACzB;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC;IAChC,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAClD;;;;;;;;;OASG;IACH,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,iHAAiH;IACjH,OAAO,IAAI,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,WAAW,CA8EhG"}
|
package/lib/worker-heads.js
CHANGED
|
@@ -20,9 +20,9 @@ exports.WORKER_ERROR_EVENT_PHASE = 'worker';
|
|
|
20
20
|
* each.
|
|
21
21
|
*
|
|
22
22
|
* The worker keeps `port2` of every pair and the page `port1`; neither end is
|
|
23
|
-
* given the worker global, which carries the bootstrap, the worker's
|
|
24
|
-
* reports and whatever the host adds for itself. See the
|
|
25
|
-
* `@hydranium/protocol` for why a head on the global is unusable.
|
|
23
|
+
* given the worker global, which carries the bootstrap, the worker's ready
|
|
24
|
+
* message and failure reports, and whatever the host adds for itself. See the
|
|
25
|
+
* handshake in `@hydranium/protocol` for why a head on the global is unusable.
|
|
26
26
|
*
|
|
27
27
|
* **A port reports nothing when its peer dies**, so a worker that fails to
|
|
28
28
|
* load, throws before its bootstrap or fails it would leave every request on
|
|
@@ -49,12 +49,14 @@ function connectWorkerHeads(worker, options = {}) {
|
|
|
49
49
|
const glspConnection = (0, browser_1.createMessageConnection)(glspTransport.reader, glspTransport.writer, options.logger?.with('GLSP head'));
|
|
50
50
|
const errorEmitter = new browser_1.Emitter();
|
|
51
51
|
const disposeEmitter = new browser_1.Emitter();
|
|
52
|
-
// Whether the worker
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
|
|
52
|
+
// Whether the worker is past its bootstrap: it says so with its ready
|
|
53
|
+
// message, and a worker that posts none shows it by posting on a head's
|
|
54
|
+
// port, which only a running head does. An `error` event before that is a
|
|
55
|
+
// worker that never started; one after it is an uncaught error the worker
|
|
56
|
+
// survives.
|
|
57
|
+
let workerUp = false;
|
|
56
58
|
for (const port of [lsp.port1, data.port1, glsp.port1]) {
|
|
57
|
-
port.addEventListener('message', () => (
|
|
59
|
+
port.addEventListener('message', () => (workerUp = true), { once: true });
|
|
58
60
|
}
|
|
59
61
|
let disposed = false;
|
|
60
62
|
const dispose = () => {
|
|
@@ -77,11 +79,15 @@ function connectWorkerHeads(worker, options = {}) {
|
|
|
77
79
|
phase: exports.WORKER_ERROR_EVENT_PHASE,
|
|
78
80
|
message: event.message || 'no detail; check that the worker script loaded'
|
|
79
81
|
});
|
|
80
|
-
if (!
|
|
82
|
+
if (!workerUp) {
|
|
81
83
|
dispose();
|
|
82
84
|
}
|
|
83
85
|
});
|
|
84
86
|
worker.addEventListener('message', event => {
|
|
87
|
+
if ((0, protocol_1.isWorkerReadyMessage)(event.data)) {
|
|
88
|
+
workerUp = true;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
85
91
|
if (!(0, protocol_1.isWorkerErrorMessage)(event.data)) {
|
|
86
92
|
return;
|
|
87
93
|
}
|
package/lib/worker-heads.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-heads.js","sourceRoot":"","sources":["../src/worker-heads.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;AAElF,
|
|
1
|
+
{"version":3,"file":"worker-heads.js","sourceRoot":"","sources":["../src/worker-heads.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hydranium/client-browser",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.300",
|
|
4
4
|
"description": "The page side of a hydranium host that runs its heads in a web worker: the worker bootstrap that hands each head its own MessagePort, the page's LSP handshake, the data head's port, and the rejection of what is pending when the worker dies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"watch": "tsc -b -w --preserveWatchOutput"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
53
|
+
"@hydranium/protocol": "1.0.0-next.300",
|
|
54
54
|
"@types/node": "^22.0.0",
|
|
55
55
|
"rimraf": "^5.0.0",
|
|
56
56
|
"typescript": "^7.0.2",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"vscode-languageserver-protocol": "3.18.1"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
61
|
+
"@hydranium/protocol": "1.0.0-next.300",
|
|
62
62
|
"vscode-jsonrpc": "^9.0.0",
|
|
63
63
|
"vscode-languageserver-protocol": "~3.18.1"
|
|
64
64
|
},
|
package/src/worker-heads.ts
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import {
|
|
11
11
|
createMessagePortTransport,
|
|
12
12
|
isWorkerErrorMessage,
|
|
13
|
+
isWorkerReadyMessage,
|
|
13
14
|
WORKER_BOOTSTRAP_MESSAGE_TYPE,
|
|
14
15
|
WORKER_BOOTSTRAP_PHASE,
|
|
15
16
|
WORKER_ERROR_MESSAGE_TYPE,
|
|
@@ -64,12 +65,13 @@ export interface WorkerHeads {
|
|
|
64
65
|
readonly onWorkerError: Event<WorkerErrorMessage>;
|
|
65
66
|
/**
|
|
66
67
|
* Fires once when the heads end: on a failed bootstrap, on an `error` event
|
|
67
|
-
* before the worker
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
68
|
+
* before the worker is known to be up, or on {@link dispose}. What the heads
|
|
69
|
+
* had pending is rejected then rather than left waiting. The worker is up
|
|
70
|
+
* once it has posted its ready message, or anything on a head's port for a
|
|
71
|
+
* worker that posts no ready message. Any later report, and an `error`
|
|
72
|
+
* event once the worker is up, ends nothing: the worker runs on after an
|
|
73
|
+
* uncaught error, and the heads with it. Subscribe before the first
|
|
74
|
+
* `await`: the end fires once, and a subscriber after it hears nothing.
|
|
73
75
|
*/
|
|
74
76
|
readonly onDispose: Event<void>;
|
|
75
77
|
/** End every head. A head whose connection exists signals its close to the worker, which ends the head there. */
|
|
@@ -81,9 +83,9 @@ export interface WorkerHeads {
|
|
|
81
83
|
* each.
|
|
82
84
|
*
|
|
83
85
|
* The worker keeps `port2` of every pair and the page `port1`; neither end is
|
|
84
|
-
* given the worker global, which carries the bootstrap, the worker's
|
|
85
|
-
* reports and whatever the host adds for itself. See the
|
|
86
|
-
* `@hydranium/protocol` for why a head on the global is unusable.
|
|
86
|
+
* given the worker global, which carries the bootstrap, the worker's ready
|
|
87
|
+
* message and failure reports, and whatever the host adds for itself. See the
|
|
88
|
+
* handshake in `@hydranium/protocol` for why a head on the global is unusable.
|
|
87
89
|
*
|
|
88
90
|
* **A port reports nothing when its peer dies**, so a worker that fails to
|
|
89
91
|
* load, throws before its bootstrap or fails it would leave every request on
|
|
@@ -112,12 +114,14 @@ export function connectWorkerHeads(worker: Worker, options: WorkerHeadsOptions =
|
|
|
112
114
|
const errorEmitter = new Emitter<WorkerErrorMessage>();
|
|
113
115
|
const disposeEmitter = new Emitter<void>();
|
|
114
116
|
|
|
115
|
-
// Whether the worker
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
|
|
117
|
+
// Whether the worker is past its bootstrap: it says so with its ready
|
|
118
|
+
// message, and a worker that posts none shows it by posting on a head's
|
|
119
|
+
// port, which only a running head does. An `error` event before that is a
|
|
120
|
+
// worker that never started; one after it is an uncaught error the worker
|
|
121
|
+
// survives.
|
|
122
|
+
let workerUp = false;
|
|
119
123
|
for (const port of [lsp.port1, data.port1, glsp.port1]) {
|
|
120
|
-
port.addEventListener('message', () => (
|
|
124
|
+
port.addEventListener('message', () => (workerUp = true), { once: true });
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
let disposed = false;
|
|
@@ -142,11 +146,15 @@ export function connectWorkerHeads(worker: Worker, options: WorkerHeadsOptions =
|
|
|
142
146
|
phase: WORKER_ERROR_EVENT_PHASE,
|
|
143
147
|
message: event.message || 'no detail; check that the worker script loaded'
|
|
144
148
|
});
|
|
145
|
-
if (!
|
|
149
|
+
if (!workerUp) {
|
|
146
150
|
dispose();
|
|
147
151
|
}
|
|
148
152
|
});
|
|
149
153
|
worker.addEventListener('message', event => {
|
|
154
|
+
if (isWorkerReadyMessage(event.data)) {
|
|
155
|
+
workerUp = true;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
150
158
|
if (!isWorkerErrorMessage(event.data)) {
|
|
151
159
|
return;
|
|
152
160
|
}
|