posipaki 0.35.2 → 0.37.1

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.
Files changed (37) hide show
  1. package/dist/{client-C4LZE65N.d.ts → client-Cg_MlE0m.d.ts} +17 -4
  2. package/dist/client-Cg_MlE0m.d.ts.map +1 -0
  3. package/dist/{define-actor-DqOW2StX.js → define-actor-CZysIKH4.js} +18 -4
  4. package/dist/define-actor-CZysIKH4.js.map +1 -0
  5. package/dist/hooks-CgXhmY4r.js.map +1 -1
  6. package/dist/{hooks-Dj59y_jN.d.ts → hooks-gmAsdJBN.d.ts} +20 -4
  7. package/dist/hooks-gmAsdJBN.d.ts.map +1 -0
  8. package/dist/hooks.d.ts +1 -1
  9. package/dist/index.d.ts +4 -4
  10. package/dist/index.js +2 -2
  11. package/dist/json1-DYq9g7im.js +1124 -0
  12. package/dist/json1-DYq9g7im.js.map +1 -0
  13. package/dist/plugins/debug-logger.d.ts +2 -2
  14. package/dist/plugins/tree-introspection.d.ts +6 -6
  15. package/dist/plugins/tree-introspection.d.ts.map +1 -1
  16. package/dist/plugins/tree-introspection.js +5 -5
  17. package/dist/plugins/tree-introspection.js.map +1 -1
  18. package/dist/{process-pZDxIjLA.d.ts → process-DjRQSZef.d.ts} +2 -2
  19. package/dist/{process-pZDxIjLA.d.ts.map → process-DjRQSZef.d.ts.map} +1 -1
  20. package/dist/remote/index.d.ts +169 -8
  21. package/dist/remote/index.d.ts.map +1 -1
  22. package/dist/remote/index.js +2 -2
  23. package/dist/remote/node.d.ts +3 -3
  24. package/dist/remote/node.js +2 -2
  25. package/dist/testing/index.d.ts +2 -2
  26. package/dist/{types-CsE8xK3a.d.ts → types-DDc-stle.d.ts} +4 -2
  27. package/dist/types-DDc-stle.d.ts.map +1 -0
  28. package/dist/{version-0mlM8dbC.js → version-98a9sol-.js} +2 -2
  29. package/dist/{version-0mlM8dbC.js.map → version-98a9sol-.js.map} +1 -1
  30. package/dist/xfetch.d.ts +2 -2
  31. package/package.json +1 -1
  32. package/dist/client-C4LZE65N.d.ts.map +0 -1
  33. package/dist/define-actor-DqOW2StX.js.map +0 -1
  34. package/dist/hooks-Dj59y_jN.d.ts.map +0 -1
  35. package/dist/json1-DzPx9oX3.js +0 -200
  36. package/dist/json1-DzPx9oX3.js.map +0 -1
  37. package/dist/types-CsE8xK3a.d.ts.map +0 -1
@@ -0,0 +1,1124 @@
1
+ import { r as makeWaiter } from "./util-Brtfgv68.js";
2
+ import { i as isProcess, t as defineActor } from "./define-actor-CZysIKH4.js";
3
+ import { s as stopPropagation } from "./hooks-CgXhmY4r.js";
4
+ //#region src/remote/process-ref.ts
5
+ /** The key that marks a process reference inside an otherwise JSON value. */
6
+ const PROCESS_REF = "$p";
7
+ /**
8
+ * The id a side gives its own root: the first id of its parity. The two ends of a
9
+ * connection therefore number their roots differently, and an id says whose root it is
10
+ * as it says who holds every other process. A side hands out its next id from two
11
+ * steps further on, the one in between belonging to the root of the side it talks to.
12
+ */
13
+ function rootIdFor(parity) {
14
+ return parity === "odd" ? 1 : 0;
15
+ }
16
+ /** What a served root is called when the client states no name for it. A client that
17
+ * states one — and the library's own does, in `$init` — is served under that name instead:
18
+ * the process across the seam is the one its proxy was forked as, and it should be called
19
+ * the same on both sides. This is the name for a connection that says nothing. */
20
+ const SERVED_ROOT_NAME = "remote";
21
+ /**
22
+ * The processes one connection knows, by the ids that name them. One table per
23
+ * connection, because an id means nothing on any other one, and it lives exactly
24
+ * as long as the connection that owns it.
25
+ *
26
+ * It holds two sets, told apart by parity rather than kept apart by a rule: the
27
+ * processes this side holds — the root, and anything it hands over — and the ones
28
+ * the far side holds, which this side knows as handles. A frame's address is
29
+ * looked up in both, and exactly one can answer.
30
+ */
31
+ var ProcessTable = class {
32
+ constructor(parity, onCrossed) {
33
+ this.pvtMine = /* @__PURE__ */ new Map();
34
+ this.pvtMineIds = /* @__PURE__ */ new Map();
35
+ this.pvtTheirs = /* @__PURE__ */ new Map();
36
+ this.pvtRootId = rootIdFor(parity);
37
+ this.pvtFarRootId = rootIdFor(parity === "odd" ? "even" : "odd");
38
+ this.pvtNext = this.pvtRootId + 2;
39
+ this.pvtOnCrossed = onCrossed;
40
+ }
41
+ /** The id of this side's own end of the connection. */
42
+ rootId() {
43
+ return this.pvtRootId;
44
+ }
45
+ /** The id the far side knows its own end by: the root this side reaches as a handle,
46
+ * and the one it never hands out for anything of its own. */
47
+ farRootId() {
48
+ return this.pvtFarRootId;
49
+ }
50
+ /** Bind this side's own end of the connection — the root — to its id. */
51
+ bindRoot(proc) {
52
+ const bound = this.pvtMine.get(this.pvtRootId);
53
+ if (bound !== void 0 && bound !== proc) throw new Error("ProcessTable: the root is already bound");
54
+ this.pvtMine.set(this.pvtRootId, proc);
55
+ this.pvtMineIds.set(proc, this.pvtRootId);
56
+ }
57
+ /** The id this side gives a process it holds, allocating one the first time. */
58
+ handleFor(proc) {
59
+ const known = this.pvtMineIds.get(proc);
60
+ if (known !== void 0) return known;
61
+ const id = this.pvtNext;
62
+ this.pvtNext += 2;
63
+ this.pvtMine.set(id, proc);
64
+ this.pvtMineIds.set(proc, id);
65
+ this.pvtOnCrossed?.(proc, id);
66
+ return id;
67
+ }
68
+ /** A process this side holds, by the id it gave it. */
69
+ processFor(id) {
70
+ return this.pvtMine.get(id);
71
+ }
72
+ /**
73
+ * Register a process the far side holds — a handle — under the id it arrived
74
+ * with. A root is one of these as much as anything else: both ends hold one at 0,
75
+ * so the far side's root is a handle here, and the one this side has of itself
76
+ * stays what it was.
77
+ */
78
+ bindFar(id, proc) {
79
+ this.pvtTheirs.set(id, proc);
80
+ }
81
+ /** A process the far side holds, by the id it gave it. */
82
+ farHandleFor(id) {
83
+ return this.pvtTheirs.get(id);
84
+ }
85
+ /**
86
+ * Whatever this connection knows `id` to mean: a process this side holds, or a
87
+ * handle on one the far side holds. Only one of the two can answer, because
88
+ * the two sides take their ids from different halves of the space — so what
89
+ * comes back does not depend on which way the frame was going.
90
+ */
91
+ resolve(id) {
92
+ return this.pvtMine.get(id) ?? this.pvtTheirs.get(id);
93
+ }
94
+ /**
95
+ * Let go of an id: the process behind it is not this connection's business any
96
+ * more, so it is no longer known by it. Both sides' ids go the same way — the
97
+ * side that lets a handle go names the far side's id, the side that is asked to
98
+ * forget names its own — and an id let go is never handed out again, so nothing
99
+ * that still names it can come to mean another process.
100
+ *
101
+ * Neither root is let go of: one is this side's own end of the connection, and the
102
+ * other is what this side is talking to.
103
+ */
104
+ release(id) {
105
+ if (id === this.pvtRootId || id === this.pvtFarRootId) return void 0;
106
+ const mine = this.pvtMine.get(id);
107
+ if (mine !== void 0) {
108
+ this.pvtMine.delete(id);
109
+ this.pvtMineIds.delete(mine);
110
+ return mine;
111
+ }
112
+ const theirs = this.pvtTheirs.get(id);
113
+ if (theirs !== void 0) this.pvtTheirs.delete(id);
114
+ return theirs;
115
+ }
116
+ /** Every handle this side holds on a process of the far side. */
117
+ handles() {
118
+ return [...this.pvtTheirs.values()];
119
+ }
120
+ };
121
+ function isPlainObject(value) {
122
+ if (typeof value !== "object" || value === null) return false;
123
+ const proto = Object.getPrototypeOf(value);
124
+ return proto === Object.prototype || proto === null;
125
+ }
126
+ /** Whether `value` is the wire form of a reference. */
127
+ function asProcessRef(value) {
128
+ if (typeof value !== "object" || value === null) return null;
129
+ const ref = value["$p"];
130
+ if (typeof ref !== "object" || ref === null) return null;
131
+ const { id, pname } = ref;
132
+ if (typeof id !== "number" || typeof pname !== "string") return null;
133
+ return {
134
+ id,
135
+ pname
136
+ };
137
+ }
138
+ /** Whether `value` has the shape of a handle on a far-side process. Judged by
139
+ * what it holds rather than by `instanceof`, for the reason a process is: one
140
+ * build can hold two copies of the class. */
141
+ function isRemoteProcess(value) {
142
+ if (typeof value !== "object" || value === null) return false;
143
+ const candidate = value;
144
+ return typeof candidate.pname === "string" && typeof candidate.id === "symbol" && typeof candidate.send === "function" && asProcessRef({ ["$p"]: candidate.ref }) !== null;
145
+ }
146
+ /**
147
+ * Replace every process in `value` with the reference this connection uses for
148
+ * it, so what is left is JSON that says which processes the answer is about.
149
+ *
150
+ * A handle goes back as the reference it came with, id and all: that id is the
151
+ * far side's own, the one it will be read by.
152
+ *
153
+ * Containers are copied rather than rewritten: the objects belong to the actor
154
+ * that returned them, and a state it is still running on is not ours to edit. A
155
+ * node already seen is left where it is — a cycle is the encoder's to report, not
156
+ * something to walk forever.
157
+ */
158
+ function encodeProcessRefs(value, table, seen = /* @__PURE__ */ new Set()) {
159
+ if (isRemoteProcess(value)) return { ["$p"]: {
160
+ id: value.ref.id,
161
+ pname: value.ref.pname
162
+ } };
163
+ if (isProcess(value)) return { ["$p"]: {
164
+ id: table.handleFor(value),
165
+ pname: value.pname
166
+ } };
167
+ if (Array.isArray(value)) {
168
+ if (seen.has(value)) return value;
169
+ seen.add(value);
170
+ return value.map((item) => encodeProcessRefs(item, table, seen));
171
+ }
172
+ if (isPlainObject(value)) {
173
+ if (seen.has(value)) return value;
174
+ seen.add(value);
175
+ const copy = {};
176
+ for (const [key, item] of Object.entries(value)) copy[key] = encodeProcessRefs(item, table, seen);
177
+ return copy;
178
+ }
179
+ return value;
180
+ }
181
+ /** Replace every reference in `value` with what `resolve` makes of it. */
182
+ function decodeProcessRefs(value, resolve, seen = /* @__PURE__ */ new Set()) {
183
+ const ref = asProcessRef(value);
184
+ if (ref) return resolve(ref);
185
+ if (Array.isArray(value)) {
186
+ if (seen.has(value)) return value;
187
+ seen.add(value);
188
+ return value.map((item) => decodeProcessRefs(item, resolve, seen));
189
+ }
190
+ if (isPlainObject(value)) {
191
+ if (seen.has(value)) return value;
192
+ seen.add(value);
193
+ const copy = {};
194
+ for (const [key, item] of Object.entries(value)) copy[key] = decodeProcessRefs(item, resolve, seen);
195
+ return copy;
196
+ }
197
+ return value;
198
+ }
199
+ //#endregion
200
+ //#region src/remote/channel.ts
201
+ /** The id a frame addresses, or null when it names no process. */
202
+ function frameTo(frame) {
203
+ const to = frame.to;
204
+ return typeof to === "number" ? to : null;
205
+ }
206
+ /**
207
+ * A frame on its way out: every process in it becomes the reference this
208
+ * connection uses for that process, and the process the frame addresses is
209
+ * written down as `to`.
210
+ */
211
+ function encodeFrame(frame, table, to) {
212
+ return {
213
+ ...encodeProcessRefs(frame, table),
214
+ to
215
+ };
216
+ }
217
+ /**
218
+ * A frame just read: every reference in it becomes a handle on that process — or
219
+ * the handle this side already made for it, since the same process handed over
220
+ * twice is one process.
221
+ */
222
+ function decodeFrame(frame, resolve) {
223
+ return decodeProcessRefs(frame, resolve);
224
+ }
225
+ function isProto(msg) {
226
+ return "$proto" in msg;
227
+ }
228
+ function isInit(msg) {
229
+ return "$init" in msg;
230
+ }
231
+ function isState(msg) {
232
+ return "$state" in msg;
233
+ }
234
+ function isMsg(msg) {
235
+ return "$msg" in msg;
236
+ }
237
+ function isExit(msg) {
238
+ return "$exit" in msg;
239
+ }
240
+ /** The three, in the one order they are ever named in — the order a tune frame
241
+ * carries them in, so two ways of asking for the same thing look the same. */
242
+ const STREAM_KINDS = [
243
+ "message",
244
+ "state",
245
+ "exit"
246
+ ];
247
+ function isStreamKind(value) {
248
+ return typeof value === "string" && STREAM_KINDS.includes(value);
249
+ }
250
+ function isStop(msg) {
251
+ return "$stop" in msg;
252
+ }
253
+ function isPause(msg) {
254
+ return "$pause" in msg;
255
+ }
256
+ function isResume(msg) {
257
+ return "$resume" in msg;
258
+ }
259
+ function isRelease(msg) {
260
+ return "$release" in msg;
261
+ }
262
+ function isTune(msg) {
263
+ return "$tune" in msg;
264
+ }
265
+ /**
266
+ * The categories a tune frame asks for, in the order they are named in — or null
267
+ * when the frame says something this vocabulary has no word for, which is a frame
268
+ * to ignore rather than to guess at.
269
+ */
270
+ function tuneFrame(frame) {
271
+ const body = frame.$tune;
272
+ if (typeof body !== "object" || body === null) return null;
273
+ const streams = body.streams;
274
+ if (!Array.isArray(streams)) return null;
275
+ if (!streams.every(isStreamKind)) return null;
276
+ return STREAM_KINDS.filter((kind) => streams.includes(kind));
277
+ }
278
+ const REFLECT_METHODS = "$r.methods";
279
+ const REFLECT_CALL = "$r.call.";
280
+ const REFLECT_RESULT = "$r.result.";
281
+ function isReflectionMethods(msg) {
282
+ const names = msg[REFLECT_METHODS];
283
+ return Array.isArray(names) && names.every((name) => typeof name === "string");
284
+ }
285
+ function reflectionBody(frame, prefix) {
286
+ for (const key of Object.keys(frame)) {
287
+ if (!key.startsWith(prefix) || key.length === prefix.length) continue;
288
+ const body = frame[key];
289
+ if (typeof body !== "object" || body === null) return null;
290
+ return {
291
+ name: key.slice(prefix.length),
292
+ body
293
+ };
294
+ }
295
+ return null;
296
+ }
297
+ /** A call frame, or null — a malformed one is not worth an answer. */
298
+ function asReflectionCall(frame) {
299
+ const parsed = reflectionBody(frame, REFLECT_CALL);
300
+ if (!parsed || typeof parsed.body.seq !== "number") return null;
301
+ const args = parsed.body.args;
302
+ return {
303
+ name: parsed.name,
304
+ seq: parsed.body.seq,
305
+ args: Array.isArray(args) ? args : []
306
+ };
307
+ }
308
+ /** An answer frame, or null. `error` present means the call was refused. */
309
+ function asReflectionResult(frame) {
310
+ const parsed = reflectionBody(frame, REFLECT_RESULT);
311
+ if (!parsed || typeof parsed.body.seq !== "number") return null;
312
+ const { seq, value, error } = parsed.body;
313
+ return typeof error === "string" ? {
314
+ name: parsed.name,
315
+ seq,
316
+ error
317
+ } : {
318
+ name: parsed.name,
319
+ seq,
320
+ value
321
+ };
322
+ }
323
+ /**
324
+ * Why a value cannot cross a frame, or null when it can. Only JSON data
325
+ * crosses: a function, a symbol or a bigint cannot be written down at all, and
326
+ * a value with a cycle or a bigint inside it makes the encoder throw. What
327
+ * JSON itself would quietly drop — a function stored inside an object — is the
328
+ * caller's business, not something to invent a policy for here.
329
+ */
330
+ function jsonProblem(value) {
331
+ const kind = typeof value;
332
+ if (kind === "function" || kind === "symbol" || kind === "bigint") return `a ${kind}`;
333
+ if (kind !== "object" || value === null) return null;
334
+ try {
335
+ JSON.stringify(value);
336
+ } catch (err) {
337
+ return err instanceof Error ? err.message : String(err);
338
+ }
339
+ return null;
340
+ }
341
+ //#endregion
342
+ //#region src/remote/remote-process.ts
343
+ var RemoteProcess = class {
344
+ constructor(ref, send, fromName, letGo) {
345
+ this.state = null;
346
+ this.$reflection = {};
347
+ this.pvtConnected = true;
348
+ this.pvtReleased = false;
349
+ this.pvtExit = null;
350
+ this.pvtExitWaiter = null;
351
+ this.pvtMessageSubs = [];
352
+ this.pvtStateSubs = [];
353
+ this.pvtWanted = /* @__PURE__ */ new Set();
354
+ this.ref = ref;
355
+ this.pname = ref.pname;
356
+ this.id = Symbol(ref.pname);
357
+ this.pvtSend = send;
358
+ this.pvtFromName = fromName;
359
+ this.pvtLetGo = letGo;
360
+ }
361
+ /**
362
+ * Whether the process this handle names can still be reached: the wire is there, and
363
+ * this side has not let the handle go.
364
+ *
365
+ * Reaching it is not the same as it being alive. A process that has ended is still
366
+ * one this side has a handle on — it is what the handle points at, and what it left
367
+ * behind is here — so an end does not put it out of reach; `hasEnded()` is that
368
+ * answer, and the two are asked separately. From the two ways out there is no coming
369
+ * back: no reconnect, and no way to un-release.
370
+ */
371
+ isConnected() {
372
+ return this.pvtConnected && !this.pvtReleased;
373
+ }
374
+ /**
375
+ * The connection is gone. Every handle this side holds goes out of reach with it,
376
+ * and says so: there is no reconnect to wait for, so a send fails here and now
377
+ * rather than disappearing into nothing.
378
+ */
379
+ disconnect() {
380
+ if (!this.pvtConnected) return;
381
+ this.pvtConnected = false;
382
+ this.pvtStateSubs.forEach((fn) => fn());
383
+ this.pvtExitWaiter?.reject(/* @__PURE__ */ new Error(`${this.pname} cannot be reached: the connection is closed`));
384
+ }
385
+ /** Whether the process it names has ended, as far as this side has been told. */
386
+ hasEnded() {
387
+ return this.pvtExit !== null;
388
+ }
389
+ /** Why nothing can be asked *of the process* — let go, ended, or out of reach — or
390
+ * nothing when something can. Those are not one thing said three ways: an ended
391
+ * process is still reached, it simply has nothing left to receive. */
392
+ pvtWhyNotAskable() {
393
+ if (this.pvtReleased) return `${this.pname} was released`;
394
+ if (this.pvtExit !== null) return `${this.pname} has ended`;
395
+ if (!this.pvtConnected) return `${this.pname} cannot be reached: the connection is closed`;
396
+ return null;
397
+ }
398
+ pvtRequireAskable() {
399
+ const why = this.pvtWhyNotAskable();
400
+ if (why !== null) throw new Error(why);
401
+ }
402
+ /**
403
+ * Wait for the process to end. Its exit crosses back like everything else it
404
+ * does, and what it left behind is the answer.
405
+ *
406
+ * A handle whose connection is gone rejects instead: what is left to wait for
407
+ * after that is nothing, and a process that keeps running is not something this
408
+ * side can tell from one that died with the wire.
409
+ */
410
+ wait() {
411
+ if (this.pvtExit !== null) return Promise.resolve(this.pvtExit);
412
+ const why = this.pvtWhyNotAskable();
413
+ if (why !== null) return Promise.reject(new Error(why));
414
+ this.pvtWant("exit");
415
+ this.pvtExitWaiter ??= makeWaiter();
416
+ return this.pvtExitWaiter.promise;
417
+ }
418
+ /**
419
+ * Ask the far side to stop it. Stops the way it always does there, and this
420
+ * resolves when its exit has crossed back — which is all this side can know.
421
+ * There is no deadline, so a process that refuses to stop leaves this pending.
422
+ */
423
+ stop() {
424
+ this.pvtRequireAskable();
425
+ this.pvtWant("exit");
426
+ this.pvtSend({ $stop: {} }, this.ref.id);
427
+ return this.wait().then(() => void 0);
428
+ }
429
+ /**
430
+ * Let it go: the far side forgets this id and stops telling this side anything
431
+ * about the process behind it. The process itself is untouched — it runs on, it
432
+ * is simply nobody's here any more — and this handle is done: nothing reaches it,
433
+ * nothing is waited for, and what arrives for it later is not news.
434
+ */
435
+ release() {
436
+ this.pvtRequireAskable();
437
+ this.pvtReleased = true;
438
+ this.pvtLetGo?.(this.ref.id);
439
+ this.pvtSend({ $release: {} }, this.ref.id);
440
+ }
441
+ /** Stop feeding it messages. It is still there: `send` still reaches it. */
442
+ pause() {
443
+ this.pvtRequireAskable();
444
+ this.pvtSend({ $pause: {} }, this.ref.id);
445
+ }
446
+ /** Feed it messages again. */
447
+ resume() {
448
+ this.pvtRequireAskable();
449
+ this.pvtSend({ $resume: {} }, this.ref.id);
450
+ }
451
+ /**
452
+ * What to be told about it from now on: any of `message`, `state` and `exit`,
453
+ * or `"silent"` for none of it.
454
+ *
455
+ * A process that crossed is silent to begin with, so this is how a handle asks
456
+ * to hear anything at all — and what is heard is only ever what was asked for.
457
+ * An exit nobody asked for is not sent: silence is silence, which makes this the
458
+ * one way to leave a handle that will not answer a `wait()`, and the far side's
459
+ * books the one place an end can go unrecorded.
460
+ */
461
+ tune(kinds) {
462
+ this.pvtRequireAskable();
463
+ this.pvtTune(kinds === "silent" ? [] : kinds);
464
+ }
465
+ /** Ask the far side to say exactly this much, and nothing when it is already
466
+ * saying it. The list goes in the order the three are named in, so asking for
467
+ * the same thing twice sends the same frame twice. */
468
+ pvtTune(wanted) {
469
+ const kinds = STREAM_KINDS.filter((kind) => wanted.includes(kind));
470
+ if (kinds.length === this.pvtWanted.size && kinds.every((kind) => this.pvtWanted.has(kind))) return;
471
+ this.pvtWanted = new Set(kinds);
472
+ this.pvtSend({ $tune: { streams: kinds } }, this.ref.id);
473
+ }
474
+ /** Ask for one more category, because something here now wants it. A handle
475
+ * that is gone asks nothing: there is no far side left to hear it, and nothing
476
+ * was asked for, so what was wanted stays what it was. */
477
+ pvtWant(kind) {
478
+ if (this.pvtWanted.has(kind)) return;
479
+ if (!this.pvtConnected || this.pvtReleased) return;
480
+ this.pvtTune([...this.pvtWanted, kind]);
481
+ }
482
+ /** Hand the far process a message. */
483
+ send(msg) {
484
+ this.pvtRequireAskable();
485
+ this.pvtSend({ $msg: {
486
+ fromName: this.pvtFromName,
487
+ body: msg
488
+ } }, this.ref.id);
489
+ }
490
+ subscribe(channel, cb) {
491
+ if (channel === "message") {
492
+ const fn = cb;
493
+ this.pvtMessageSubs.push(fn);
494
+ this.pvtWant("message");
495
+ return () => this.pvtUnsubscribe(this.pvtMessageSubs, fn);
496
+ }
497
+ const fn = cb;
498
+ this.pvtStateSubs.push(fn);
499
+ this.pvtWant("state");
500
+ return () => this.pvtUnsubscribe(this.pvtStateSubs, fn);
501
+ }
502
+ pvtUnsubscribe(list, fn) {
503
+ const idx = list.indexOf(fn);
504
+ if (idx >= 0) list.splice(idx, 1);
505
+ }
506
+ /** Its state, as the far side just published it. */
507
+ receiveState(state) {
508
+ if (this.pvtReleased) return;
509
+ this.state = Object.assign(this.state ?? {}, state);
510
+ this.pvtStateSubs.forEach((fn) => fn());
511
+ }
512
+ /** A message it emitted. */
513
+ receiveMessage(msg, fromName) {
514
+ if (this.pvtReleased) return;
515
+ this.pvtMessageSubs.forEach((fn) => fn(msg, fromName));
516
+ }
517
+ /** It has ended, and this is what it left behind. The last thing said about a
518
+ * process: nothing crosses about it after its exit, though the handle still
519
+ * reaches it for what it left. */
520
+ receiveExit(exit) {
521
+ if (this.pvtExit !== null || this.pvtReleased) return;
522
+ this.pvtExit = exit;
523
+ this.pvtExitWaiter?.resolve(exit);
524
+ }
525
+ /** The methods it can answer, as functions that ask it for an answer. `call`
526
+ * is the connection's own: a handle knows what to ask for, not how a call is
527
+ * made or paired with its answer. */
528
+ receiveMethods(names, call) {
529
+ for (const name of names) this.$reflection[name] = (...args) => call(name, args);
530
+ }
531
+ };
532
+ //#endregion
533
+ //#region src/remote/process-streams.ts
534
+ /** What a process can be asked over the wire: the functions on its reflection
535
+ * surface, read once. On the side that serves it the list *is* the dispatch
536
+ * table, so a name that was never on it can never be reached. */
537
+ const pvtReflectionNames = /* @__PURE__ */ new WeakMap();
538
+ function reflectionNames(target) {
539
+ const known = pvtReflectionNames.get(target);
540
+ if (known) return known;
541
+ const surface = target.$reflection ?? {};
542
+ const names = Object.keys(surface).filter((name) => typeof surface[name] === "function");
543
+ pvtReflectionNames.set(target, names);
544
+ return names;
545
+ }
546
+ var ProcessStreams = class {
547
+ constructor(sink, rootId) {
548
+ this.pvtPending = [];
549
+ this.pvtRecords = /* @__PURE__ */ new Map();
550
+ this.pvtFlushing = false;
551
+ this.pvtSink = sink;
552
+ this.pvtRootId = rootId;
553
+ }
554
+ /** A process was numbered: it is about to cross. Anything that is not a
555
+ * process — a handle travelling back to the side that holds it — crosses as
556
+ * the reference it came with and is nobody's to stream. */
557
+ crossed(proc, id) {
558
+ if (!isProcess(proc)) return;
559
+ this.pvtPending.push([proc, id]);
560
+ }
561
+ /** Say what there is to say about whatever crossed while a frame was written. */
562
+ flush() {
563
+ if (this.pvtFlushing) return;
564
+ this.pvtFlushing = true;
565
+ try {
566
+ while (this.pvtPending.length > 0) {
567
+ const next = this.pvtPending.shift();
568
+ if (next) this.pvtStream(next[0], next[1]);
569
+ }
570
+ } finally {
571
+ this.pvtFlushing = false;
572
+ }
573
+ }
574
+ /**
575
+ * What to say about it from now on: the categories named, and none of the
576
+ * others. Asking for its state says it there and then — a handle that has just
577
+ * asked what it holds should not have to wait for it to change.
578
+ *
579
+ * An id with no stream here is not this side's to tune, and the frame is
580
+ * dropped: both sides tune only what they hold, so an id names a stream on the
581
+ * side that numbered it.
582
+ */
583
+ tune(id, kinds) {
584
+ const record = this.pvtRecords.get(id);
585
+ if (!record) return;
586
+ const wanted = new Set(kinds);
587
+ for (const kind of STREAM_KINDS) {
588
+ const isOn = record.kinds.has(kind);
589
+ const want = wanted.has(kind);
590
+ if (want === isOn) continue;
591
+ if (want) {
592
+ record.kinds.add(kind);
593
+ this.pvtArm(record, id, kind);
594
+ } else {
595
+ record.kinds.delete(kind);
596
+ this.pvtDisarm(record, kind);
597
+ }
598
+ }
599
+ }
600
+ /**
601
+ * Say nothing more about this one. It is not that the process ended — the far
602
+ * side asked to be left out of it, so its exit is nobody's news over here, and
603
+ * dropping the subscription is what keeps it from being sent.
604
+ */
605
+ stop(id) {
606
+ const record = this.pvtRecords.get(id);
607
+ if (!record) return;
608
+ for (const stop of record.stops.values()) stop();
609
+ this.pvtRecords.delete(id);
610
+ }
611
+ /** Nothing more is said about any of them: the connection is done. */
612
+ stopAll() {
613
+ for (const id of [...this.pvtRecords.keys()]) this.stop(id);
614
+ this.pvtPending.length = 0;
615
+ }
616
+ pvtStream(target, id) {
617
+ const record = {
618
+ target,
619
+ kinds: /* @__PURE__ */ new Set(),
620
+ stops: /* @__PURE__ */ new Map()
621
+ };
622
+ this.pvtRecords.set(id, record);
623
+ this.pvtSink({ [REFLECT_METHODS]: reflectionNames(target) }, id);
624
+ for (const kind of record.kinds) this.pvtArm(record, id, kind);
625
+ if (id !== this.pvtRootId) target.wait().then(() => void this.sayEnded(id, 0), () => void this.sayEnded(id, 1));
626
+ }
627
+ /** Start saying this much about it, and say what there is to say now. */
628
+ pvtArm(record, id, kind) {
629
+ if (kind === "message") {
630
+ record.stops.set("message", record.target.subscribe("message", (msg, sender) => {
631
+ this.pvtSink({ $msg: {
632
+ fromName: sender.fromName,
633
+ body: msg
634
+ } }, id);
635
+ }));
636
+ return;
637
+ }
638
+ if (kind === "state") {
639
+ record.stops.set("state", record.target.subscribe("state", () => {
640
+ this.pvtSink({ $state: record.target.state }, id);
641
+ }));
642
+ this.pvtSink({ $state: record.target.state }, id);
643
+ }
644
+ }
645
+ pvtDisarm(record, kind) {
646
+ const stop = record.stops.get(kind);
647
+ if (!stop) return;
648
+ stop();
649
+ record.stops.delete(kind);
650
+ }
651
+ /**
652
+ * It has ended: say so once, if that is among the categories asked for, and say
653
+ * nothing more about it either way. Awaited by whoever has to have the frame out
654
+ * before the wire closes, which is the root's end and nobody else's — no other
655
+ * process can end after this side has stopped saying anything about it.
656
+ */
657
+ async sayEnded(id, code) {
658
+ const record = this.pvtRecords.get(id);
659
+ if (!record) return;
660
+ const told = record.kinds.has("exit");
661
+ const state = record.target.state;
662
+ this.stop(id);
663
+ if (told) await this.pvtSink({ $exit: {
664
+ code,
665
+ state
666
+ } }, id);
667
+ }
668
+ };
669
+ //#endregion
670
+ //#region src/remote/sender.ts
671
+ function makeSender(fromName, parentName, parentId) {
672
+ if (parentId && fromName === parentName) return {
673
+ fromName,
674
+ fromId: parentId
675
+ };
676
+ return {
677
+ fromName,
678
+ fromId: Symbol()
679
+ };
680
+ }
681
+ //#endregion
682
+ //#region src/remote/call-side.ts
683
+ var CallSide = class {
684
+ constructor(write, table) {
685
+ this.pvtCalls = 0;
686
+ this.pvtWaiting = /* @__PURE__ */ new Map();
687
+ this.pvtWrite = write;
688
+ this.pvtTable = table;
689
+ }
690
+ /**
691
+ * Ask a process on the far side for one of its methods. Processes among the
692
+ * arguments become references first — this side's own, with ids from its table, or
693
+ * the far side's coming back — and what is left has to be JSON, or nothing is sent
694
+ * at all.
695
+ */
696
+ call(method, callArgs, to) {
697
+ return new Promise((resolve, reject) => {
698
+ const seq = ++this.pvtCalls;
699
+ const frame = encodeFrame({ [`${REFLECT_CALL}${method}`]: {
700
+ seq,
701
+ args: callArgs
702
+ } }, this.pvtTable, to);
703
+ const problem = jsonProblem(frame);
704
+ if (problem !== null) {
705
+ reject(/* @__PURE__ */ new Error(`cannot send ${problem} to ${method}`));
706
+ return;
707
+ }
708
+ this.pvtWaiting.set(seq, {
709
+ name: method,
710
+ resolve,
711
+ reject
712
+ });
713
+ this.pvtWrite(frame).catch((error) => {
714
+ this.pvtWaiting.delete(seq);
715
+ reject(error instanceof Error ? error : new Error(String(error)));
716
+ });
717
+ });
718
+ }
719
+ /** One function per announced name, on the surface whoever calls reads. */
720
+ install(surface, methods, to) {
721
+ for (const method of methods) surface[method] = (...callArgs) => this.call(method, callArgs, to);
722
+ }
723
+ /**
724
+ * An answer to a call this side made: the call waiting under that `seq` is settled
725
+ * by it, and the frame says whether it was one at all. An answer is about the call
726
+ * and not about a process, so a dispatcher reads it before it looks anything up.
727
+ */
728
+ settle(frame) {
729
+ const result = asReflectionResult(frame);
730
+ if (!result) return false;
731
+ const waiting = this.pvtWaiting.get(result.seq);
732
+ if (waiting) {
733
+ this.pvtWaiting.delete(result.seq);
734
+ if (result.error === void 0) waiting.resolve(result.value);
735
+ else waiting.reject(/* @__PURE__ */ new Error(`${waiting.name}: ${result.error}`));
736
+ }
737
+ return true;
738
+ }
739
+ /** A call that was in flight when the wire went has no answer coming; it fails
740
+ * here rather than hanging for ever. */
741
+ rejectAll() {
742
+ for (const waiting of this.pvtWaiting.values()) waiting.reject(/* @__PURE__ */ new Error(`connection closed before ${waiting.name} answered`));
743
+ this.pvtWaiting.clear();
744
+ }
745
+ };
746
+ /**
747
+ * Answer one call with what the process said, or why it could not. A method may be
748
+ * written for a call that answers later; the wire has no opinion about that, it just
749
+ * waits for the frame.
750
+ */
751
+ async function answerCall(call, target, write, table) {
752
+ const reply = (body) => write(encodeFrame({ [`${REFLECT_RESULT}${call.name}`]: body }, table, table.farRootId()));
753
+ if (!isProcess(target)) {
754
+ await reply({
755
+ seq: call.seq,
756
+ error: "no process with that id on this connection"
757
+ });
758
+ return;
759
+ }
760
+ const names = reflectionNames(target);
761
+ const surface = target.$reflection;
762
+ const method = names.includes(call.name) ? surface[call.name] : void 0;
763
+ if (typeof method !== "function") {
764
+ await reply({
765
+ seq: call.seq,
766
+ error: `no reflection method named ${call.name}`
767
+ });
768
+ return;
769
+ }
770
+ try {
771
+ const value = encodeProcessRefs(await method(...call.args), table);
772
+ const problem = jsonProblem(value);
773
+ if (problem !== null) {
774
+ await reply({
775
+ seq: call.seq,
776
+ error: `${call.name} returned ${problem}, which cannot cross a frame`
777
+ });
778
+ return;
779
+ }
780
+ await reply({
781
+ seq: call.seq,
782
+ value
783
+ });
784
+ } catch (err) {
785
+ await reply({
786
+ seq: call.seq,
787
+ error: err instanceof Error ? err.message : String(err)
788
+ });
789
+ }
790
+ }
791
+ //#endregion
792
+ //#region src/remote/server.ts
793
+ /** The name the served actor is spawned under, and the one it answers to as a sender when
794
+ * it talks to a process of the far side's: what the client states in `$init`, since the
795
+ * process being served is the one its proxy was forked as over there. The fallback is for
796
+ * a connection that states none — an older client, or a hand-written `$init` — where the
797
+ * far side's name for its own end is all there is to go on. */
798
+ let rootName = SERVED_ROOT_NAME;
799
+ async function serveRemoteActor(actor, spawner) {
800
+ const channel = await spawner();
801
+ const table = new ProcessTable("even", (proc, id) => streams.crossed(proc, id));
802
+ /** Put an encoded frame on the wire, and then say what it numbered. A frame that
803
+ * carried a reference has to be out before anything about that process is. */
804
+ const write = async (frame) => {
805
+ await channel.send(frame);
806
+ streams.flush();
807
+ };
808
+ const sendToFrame = (frame, to) => write(encodeFrame(frame, table, to));
809
+ /** Every frame leaves this way. The answer is handed back, since the one frame that
810
+ * has to be out before the wire closes is awaited by the side that owns the wire. */
811
+ const sendTo = (frame, to) => sendToFrame(frame, to).catch((e) => {
812
+ console.error("Error sending out the frame", e);
813
+ });
814
+ const streams = new ProcessStreams(sendTo, table.rootId());
815
+ const calls = new CallSide(write, table);
816
+ /** The handle for a reference that arrived: the same one every time, and the process
817
+ * itself when the reference names a process of this side's own. The roots are
818
+ * numbered apart, so a reference to the far side's root is a reference to a process
819
+ * of theirs, and a handle like any of those. */
820
+ const handleFor = (ref) => {
821
+ const held = table.processFor(ref.id);
822
+ if (held) return held;
823
+ const known = table.farHandleFor(ref.id);
824
+ if (isRemoteProcess(known)) return known;
825
+ const handle = new RemoteProcess(ref, sendTo, rootName, (id) => table.release(id));
826
+ table.bindFar(ref.id, handle);
827
+ return handle;
828
+ };
829
+ const waiting = [];
830
+ await new Promise((resolve) => {
831
+ channel.onMessage((frame) => {
832
+ waiting.push(frame);
833
+ resolve();
834
+ });
835
+ });
836
+ channel.removeHandler();
837
+ const initFrame = decodeFrame(waiting.shift(), handleFor);
838
+ if (!isInit(initFrame)) throw new Error("serveRemoteActor: expected $init");
839
+ const init = initFrame.$init;
840
+ const stated = init.rootName;
841
+ if (typeof stated === "string" && stated !== "") rootName = stated;
842
+ const parentName = init.parentName ?? null;
843
+ const parentIdName = init.parentIdName ?? null;
844
+ const parentId = parentIdName ? Symbol.for(parentIdName) : null;
845
+ const { parentName: _pn, parentIdName: _pid, ...initArgs } = init;
846
+ const proc = await actor.spawn(initArgs, {
847
+ name: rootName,
848
+ parentName,
849
+ parentId
850
+ });
851
+ table.bindRoot(proc);
852
+ await proc.ready();
853
+ streams.crossed(proc, table.rootId());
854
+ streams.flush();
855
+ function dispatch(raw) {
856
+ const frame = decodeFrame(raw, handleFor);
857
+ if (calls.settle(frame)) return;
858
+ const to = frameTo(frame);
859
+ if (to === null) return;
860
+ const news = table.farHandleFor(to);
861
+ const mine = table.processFor(to);
862
+ if (isRelease(frame)) {
863
+ if (mine !== void 0) {
864
+ streams.stop(to);
865
+ table.release(to);
866
+ }
867
+ return;
868
+ }
869
+ if (isTune(frame)) {
870
+ if (mine !== void 0) {
871
+ const kinds = tuneFrame(frame);
872
+ if (kinds !== null) streams.tune(to, kinds);
873
+ }
874
+ return;
875
+ }
876
+ if (isReflectionMethods(frame)) {
877
+ if (isRemoteProcess(news)) news.receiveMethods(frame[REFLECT_METHODS], (method, args) => calls.call(method, args, to));
878
+ return;
879
+ }
880
+ if (isState(frame)) {
881
+ if (isRemoteProcess(news)) news.receiveState(frame.$state);
882
+ return;
883
+ }
884
+ if (isExit(frame)) {
885
+ if (isRemoteProcess(news)) news.receiveExit(frame.$exit);
886
+ return;
887
+ }
888
+ if (isStop(frame) || isPause(frame) || isResume(frame)) {
889
+ if (isProcess(mine)) {
890
+ const sender = makeSender(rootName, parentName, parentId);
891
+ if (isStop(frame)) mine.stop({ from: sender });
892
+ else if (isPause(frame)) mine.pause();
893
+ else mine.resume();
894
+ }
895
+ return;
896
+ }
897
+ if (isMsg(frame)) {
898
+ const { fromName, body } = frame.$msg;
899
+ if (isProcess(mine)) mine.send(body, makeSender(fromName, parentName, parentId));
900
+ else if (isRemoteProcess(news)) news.receiveMessage(body, fromName);
901
+ return;
902
+ }
903
+ const call = asReflectionCall(frame);
904
+ if (call) answerCall(call, mine, write, table);
905
+ }
906
+ channel.removeHandler();
907
+ channel.onMessage(dispatch);
908
+ for (const frame of waiting.splice(0)) dispatch(frame);
909
+ let code = 0;
910
+ try {
911
+ await proc.wait();
912
+ } catch (err) {
913
+ console.error("server actor error:", err);
914
+ code = 1;
915
+ }
916
+ await streams.sayEnded(table.rootId(), code);
917
+ streams.stopAll();
918
+ calls.rejectAll();
919
+ await channel.close();
920
+ }
921
+ //#endregion
922
+ //#region src/remote/client.ts
923
+ function remoteClient(name, spawner) {
924
+ return defineActor({
925
+ name,
926
+ handlers: {},
927
+ async setup(args) {
928
+ const table = new ProcessTable("odd", (proc, id) => streams.crossed(proc, id));
929
+ const root = this.ctx;
930
+ table.bindRoot(root);
931
+ const channel = await spawner(args);
932
+ const fromName = this.ctx.pname;
933
+ const parentName = this.ctx.parentName ?? this.ctx.pname;
934
+ const streams = new ProcessStreams((frame, to) => sendTo(frame, to), table.rootId());
935
+ /** Put an encoded frame on the wire, and then say what it numbered. A frame that
936
+ * carried a reference has to be out first, or the far side hears about a process
937
+ * it cannot name yet. */
938
+ const write = (frame) => Promise.resolve(channel.send(frame)).then(() => streams.flush());
939
+ /** Every frame leaves this way: the processes in it become references, and
940
+ * what the frame is addressed to becomes the id the far side knows. */
941
+ const sendTo = (frame, to) => {
942
+ write(encodeFrame(frame, table, to)).catch((error) => {
943
+ console.error("Error sending out the frame", error);
944
+ });
945
+ };
946
+ sendTo({ $init: {
947
+ ...args,
948
+ rootName: fromName,
949
+ parentName,
950
+ parentIdName: parentName
951
+ } }, table.farRootId());
952
+ let currentState = {};
953
+ const calls = new CallSide(write, table);
954
+ /**
955
+ * The handle for a reference that arrived. A process handed over twice is one
956
+ * process, so a reference that names one this side already knows gives back the
957
+ * handle it gave last time, and one that names a process of this side's own —
958
+ * handed back to its owner — gives back that process.
959
+ *
960
+ * The roots are numbered apart, so the numbers say what belongs to whom: 1 is this
961
+ * side's own end, and 0 is the far side's root, which is a handle like any of the
962
+ * processes they hold.
963
+ */
964
+ const handleFor = (ref) => {
965
+ const held = table.processFor(ref.id);
966
+ if (held) return held;
967
+ const known = table.farHandleFor(ref.id);
968
+ if (isRemoteProcess(known)) return known;
969
+ const handle = new RemoteProcess(ref, sendTo, fromName, (id) => table.release(id));
970
+ table.bindFar(ref.id, handle);
971
+ return handle;
972
+ };
973
+ /**
974
+ * The far side's root, which is what this proxy stands in for. It is bound here
975
+ * like any other reference the far side sends: what it holds, what it says, when
976
+ * it is over and what it can answer reach it as they reach any handle.
977
+ */
978
+ const farRoot = new RemoteProcess({
979
+ id: table.farRootId(),
980
+ pname: fromName
981
+ }, sendTo, fromName, (id) => table.release(id));
982
+ table.bindFar(table.farRootId(), farRoot);
983
+ let started = null;
984
+ const start = new Promise((resolve) => {
985
+ started = resolve;
986
+ });
987
+ farRoot.tune([
988
+ "message",
989
+ "state",
990
+ "exit"
991
+ ]);
992
+ farRoot.subscribe("state", () => {
993
+ Object.assign(currentState, farRoot.state ?? {});
994
+ root.notify();
995
+ started?.();
996
+ started = null;
997
+ });
998
+ farRoot.subscribe("message", (msg) => {
999
+ this.emit(msg);
1000
+ });
1001
+ const exitPromise = farRoot.wait().then((exit) => ({
1002
+ code: exit.code,
1003
+ state: exit.state
1004
+ }), () => ({
1005
+ code: null,
1006
+ state: currentState
1007
+ }));
1008
+ channel.onMessage((raw) => {
1009
+ const frame = decodeFrame(raw, handleFor);
1010
+ if (calls.settle(frame)) return;
1011
+ const to = frameTo(frame);
1012
+ if (to === null) return;
1013
+ const news = table.farHandleFor(to);
1014
+ const mine = table.processFor(to);
1015
+ if (isRelease(frame)) {
1016
+ if (mine !== void 0) {
1017
+ streams.stop(to);
1018
+ table.release(to);
1019
+ }
1020
+ return;
1021
+ }
1022
+ if (isReflectionMethods(frame)) {
1023
+ if (isRemoteProcess(news)) {
1024
+ news.receiveMethods(frame[REFLECT_METHODS], (method, callArgs) => calls.call(method, callArgs, to));
1025
+ if (to === table.farRootId()) calls.install(this.reflection, frame[REFLECT_METHODS], table.farRootId());
1026
+ }
1027
+ return;
1028
+ }
1029
+ if (isState(frame)) {
1030
+ if (isRemoteProcess(news)) news.receiveState(frame.$state);
1031
+ return;
1032
+ }
1033
+ if (isExit(frame)) {
1034
+ if (isRemoteProcess(news)) news.receiveExit(frame.$exit);
1035
+ return;
1036
+ }
1037
+ if (isMsg(frame)) {
1038
+ if (isProcess(mine)) mine.send(frame.$msg.body, makeSender(frame.$msg.fromName, null, null));
1039
+ else if (isRemoteProcess(news)) news.receiveMessage(frame.$msg.body, frame.$msg.fromName);
1040
+ return;
1041
+ }
1042
+ if (isTune(frame)) {
1043
+ if (mine !== void 0) {
1044
+ const kinds = tuneFrame(frame);
1045
+ if (kinds !== null) streams.tune(to, kinds);
1046
+ }
1047
+ return;
1048
+ }
1049
+ if (isStop(frame) || isPause(frame) || isResume(frame)) {
1050
+ if (isProcess(mine)) {
1051
+ if (isStop(frame)) mine.stop({ from: makeSender(fromName, null, null) });
1052
+ else if (isPause(frame)) mine.pause();
1053
+ else mine.resume();
1054
+ }
1055
+ return;
1056
+ }
1057
+ const call = asReflectionCall(frame);
1058
+ if (call) answerCall(call, mine, write, table);
1059
+ });
1060
+ channel.onClose(() => {
1061
+ calls.rejectAll();
1062
+ for (const held of table.handles()) if (isRemoteProcess(held)) held.disconnect();
1063
+ streams.stopAll();
1064
+ });
1065
+ await start;
1066
+ return {
1067
+ public: currentState,
1068
+ private: {
1069
+ channel,
1070
+ farRoot,
1071
+ exitPromise
1072
+ }
1073
+ };
1074
+ },
1075
+ async onMessage(msg) {
1076
+ const { farRoot } = this.state.private;
1077
+ if (farRoot.isConnected()) farRoot.send(msg);
1078
+ return stopPropagation();
1079
+ },
1080
+ async onStopRequested() {
1081
+ const { channel, farRoot, exitPromise } = this.state.private;
1082
+ if (channel) {
1083
+ if (farRoot.isConnected() && !farRoot.hasEnded()) farRoot.stop().catch(() => void 0);
1084
+ await exitPromise;
1085
+ }
1086
+ this.agreeToStop();
1087
+ },
1088
+ async afterEnd() {
1089
+ if (this.state.private.channel) await this.state.private.channel.close();
1090
+ }
1091
+ });
1092
+ }
1093
+ //#endregion
1094
+ //#region src/remote/protocols/json1.ts
1095
+ const VERSION = "json.v1";
1096
+ function encode(frame) {
1097
+ return JSON.stringify(frame);
1098
+ }
1099
+ function decode(str) {
1100
+ return JSON.parse(str);
1101
+ }
1102
+ function json1Channel(transport) {
1103
+ return {
1104
+ send(frame) {
1105
+ return transport.send(encode(frame));
1106
+ },
1107
+ onMessage(handler) {
1108
+ transport.onMessage((str) => handler(decode(str)));
1109
+ },
1110
+ removeHandler() {
1111
+ transport.removeHandler();
1112
+ },
1113
+ onClose(handler) {
1114
+ transport.onClose(handler);
1115
+ },
1116
+ close() {
1117
+ return transport.close();
1118
+ }
1119
+ };
1120
+ }
1121
+ //#endregion
1122
+ export { isStop as _, remoteClient as a, rootIdFor as b, RemoteProcess as c, isMsg as d, isPause as f, isState as g, isResume as h, json1Channel as i, isExit as l, isRelease as m, decode as n, serveRemoteActor as o, isProto as p, encode as r, makeSender as s, VERSION as t, isInit as u, PROCESS_REF as v, isRemoteProcess as y };
1123
+
1124
+ //# sourceMappingURL=json1-DYq9g7im.js.map