posipaki 0.37.0 → 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.
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{json1-CWWXL69y.js → json1-DYq9g7im.js} +23 -15
- package/dist/json1-DYq9g7im.js.map +1 -0
- package/dist/remote/index.d.ts.map +1 -1
- package/dist/remote/index.js +1 -1
- package/dist/remote/node.js +2 -2
- package/dist/{version-DTvG9uAx.js → version-98a9sol-.js} +2 -2
- package/dist/{version-DTvG9uAx.js.map → version-98a9sol-.js.map} +1 -1
- package/package.json +1 -1
- package/dist/json1-CWWXL69y.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ declare function defineActor<Args, InternalState, InMsg extends Message, OutMsg
|
|
|
20
20
|
//#endregion
|
|
21
21
|
//#region src/version.d.ts
|
|
22
22
|
/** posipaki's release version. Must equal package.json's `version`. */
|
|
23
|
-
declare const LIB_VERSION = "0.37.
|
|
23
|
+
declare const LIB_VERSION = "0.37.1";
|
|
24
24
|
//#endregion
|
|
25
25
|
export { type ActorConfig, type ActorContext, type ActorDecorated, type ActorDefinition, type ActorPlugin, type ActorReflection, type AnyProcess, AsyncProcess, type AsyncProcessFn, type ExitMessage, type HandlerFn, type HandlerOptions, type HookResult, LIB_VERSION, type Message, type MethodOptions, type PluginTransform, Process, type ProcessCtx, type ProcessFn, type SenderInfo, type SenderOrigin, type SpawnedFrom, type StopMessage, type WithSender, type WithoutSender, asyncify, callHook, chainHook, defineActor, defineMessages, mergeConfigs, propagateError, runDispatch, runDispatchAsync, spawn, spawnAsync, stopPropagation };
|
|
26
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as runDispatch } from "./util-Brtfgv68.js";
|
|
2
2
|
import { a as runDispatchAsync, n as defineMessages, o as spawnAsync, r as AsyncProcess, s as asyncify, t as defineActor } from "./define-actor-CZysIKH4.js";
|
|
3
3
|
import { n as chainHook, o as propagateError, r as mergeConfigs, s as stopPropagation, t as callHook } from "./hooks-CgXhmY4r.js";
|
|
4
|
-
import { t as LIB_VERSION } from "./version-
|
|
4
|
+
import { t as LIB_VERSION } from "./version-98a9sol-.js";
|
|
5
5
|
//#region src/process.ts
|
|
6
6
|
/** @deprecated Use {@link spawnAsync} instead. */
|
|
7
7
|
function spawn(fn, pname, tp) {
|
|
@@ -13,8 +13,10 @@ const PROCESS_REF = "$p";
|
|
|
13
13
|
function rootIdFor(parity) {
|
|
14
14
|
return parity === "odd" ? 1 : 0;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
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. */
|
|
18
20
|
const SERVED_ROOT_NAME = "remote";
|
|
19
21
|
/**
|
|
20
22
|
* The processes one connection knows, by the ids that name them. One table per
|
|
@@ -788,10 +790,12 @@ async function answerCall(call, target, write, table) {
|
|
|
788
790
|
}
|
|
789
791
|
//#endregion
|
|
790
792
|
//#region src/remote/server.ts
|
|
791
|
-
/** The name the served actor is spawned under, and the one it answers to as a
|
|
792
|
-
*
|
|
793
|
-
*
|
|
794
|
-
|
|
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;
|
|
795
799
|
async function serveRemoteActor(actor, spawner) {
|
|
796
800
|
const channel = await spawner();
|
|
797
801
|
const table = new ProcessTable("even", (proc, id) => streams.crossed(proc, id));
|
|
@@ -818,7 +822,7 @@ async function serveRemoteActor(actor, spawner) {
|
|
|
818
822
|
if (held) return held;
|
|
819
823
|
const known = table.farHandleFor(ref.id);
|
|
820
824
|
if (isRemoteProcess(known)) return known;
|
|
821
|
-
const handle = new RemoteProcess(ref, sendTo,
|
|
825
|
+
const handle = new RemoteProcess(ref, sendTo, rootName, (id) => table.release(id));
|
|
822
826
|
table.bindFar(ref.id, handle);
|
|
823
827
|
return handle;
|
|
824
828
|
};
|
|
@@ -833,12 +837,14 @@ async function serveRemoteActor(actor, spawner) {
|
|
|
833
837
|
const initFrame = decodeFrame(waiting.shift(), handleFor);
|
|
834
838
|
if (!isInit(initFrame)) throw new Error("serveRemoteActor: expected $init");
|
|
835
839
|
const init = initFrame.$init;
|
|
840
|
+
const stated = init.rootName;
|
|
841
|
+
if (typeof stated === "string" && stated !== "") rootName = stated;
|
|
836
842
|
const parentName = init.parentName ?? null;
|
|
837
843
|
const parentIdName = init.parentIdName ?? null;
|
|
838
844
|
const parentId = parentIdName ? Symbol.for(parentIdName) : null;
|
|
839
845
|
const { parentName: _pn, parentIdName: _pid, ...initArgs } = init;
|
|
840
846
|
const proc = await actor.spawn(initArgs, {
|
|
841
|
-
name:
|
|
847
|
+
name: rootName,
|
|
842
848
|
parentName,
|
|
843
849
|
parentId
|
|
844
850
|
});
|
|
@@ -881,7 +887,7 @@ async function serveRemoteActor(actor, spawner) {
|
|
|
881
887
|
}
|
|
882
888
|
if (isStop(frame) || isPause(frame) || isResume(frame)) {
|
|
883
889
|
if (isProcess(mine)) {
|
|
884
|
-
const sender = makeSender(
|
|
890
|
+
const sender = makeSender(rootName, parentName, parentId);
|
|
885
891
|
if (isStop(frame)) mine.stop({ from: sender });
|
|
886
892
|
else if (isPause(frame)) mine.pause();
|
|
887
893
|
else mine.resume();
|
|
@@ -923,7 +929,8 @@ function remoteClient(name, spawner) {
|
|
|
923
929
|
const root = this.ctx;
|
|
924
930
|
table.bindRoot(root);
|
|
925
931
|
const channel = await spawner(args);
|
|
926
|
-
const fromName =
|
|
932
|
+
const fromName = this.ctx.pname;
|
|
933
|
+
const parentName = this.ctx.parentName ?? this.ctx.pname;
|
|
927
934
|
const streams = new ProcessStreams((frame, to) => sendTo(frame, to), table.rootId());
|
|
928
935
|
/** Put an encoded frame on the wire, and then say what it numbered. A frame that
|
|
929
936
|
* carried a reference has to be out first, or the far side hears about a process
|
|
@@ -938,8 +945,9 @@ function remoteClient(name, spawner) {
|
|
|
938
945
|
};
|
|
939
946
|
sendTo({ $init: {
|
|
940
947
|
...args,
|
|
941
|
-
|
|
942
|
-
|
|
948
|
+
rootName: fromName,
|
|
949
|
+
parentName,
|
|
950
|
+
parentIdName: parentName
|
|
943
951
|
} }, table.farRootId());
|
|
944
952
|
let currentState = {};
|
|
945
953
|
const calls = new CallSide(write, table);
|
|
@@ -969,7 +977,7 @@ function remoteClient(name, spawner) {
|
|
|
969
977
|
*/
|
|
970
978
|
const farRoot = new RemoteProcess({
|
|
971
979
|
id: table.farRootId(),
|
|
972
|
-
pname:
|
|
980
|
+
pname: fromName
|
|
973
981
|
}, sendTo, fromName, (id) => table.release(id));
|
|
974
982
|
table.bindFar(table.farRootId(), farRoot);
|
|
975
983
|
let started = null;
|
|
@@ -1040,7 +1048,7 @@ function remoteClient(name, spawner) {
|
|
|
1040
1048
|
}
|
|
1041
1049
|
if (isStop(frame) || isPause(frame) || isResume(frame)) {
|
|
1042
1050
|
if (isProcess(mine)) {
|
|
1043
|
-
if (isStop(frame)) mine.stop({ from: makeSender(
|
|
1051
|
+
if (isStop(frame)) mine.stop({ from: makeSender(fromName, null, null) });
|
|
1044
1052
|
else if (isPause(frame)) mine.pause();
|
|
1045
1053
|
else mine.resume();
|
|
1046
1054
|
}
|
|
@@ -1113,4 +1121,4 @@ function json1Channel(transport) {
|
|
|
1113
1121
|
//#endregion
|
|
1114
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 };
|
|
1115
1123
|
|
|
1116
|
-
//# sourceMappingURL=json1-
|
|
1124
|
+
//# sourceMappingURL=json1-DYq9g7im.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json1-DYq9g7im.js","names":[],"sources":["../src/remote/process-ref.ts","../src/remote/channel.ts","../src/remote/remote-process.ts","../src/remote/process-streams.ts","../src/remote/sender.ts","../src/remote/call-side.ts","../src/remote/server.ts","../src/remote/client.ts","../src/remote/protocols/json1.ts"],"sourcesContent":["// ── Process references on the wire ─────────────────────────────────────────\n//\n// A process is not JSON: it holds state, children and methods. So a reflection\n// method that returns one cannot answer with the process itself — it answers\n// with a reference, and the caller is handed what it can read: a name, and an id\n// this connection uses for that process.\n//\n// The id belongs to the connection and to the side that holds the process: that\n// side allocates it, and both sides then know the process by it. Allocated once\n// per process — handed over twice, it is the same reference both times — and\n// never reused, so an id whose process is gone resolves to nothing rather than to\n// whatever came after it.\n//\n// The two sides allocate from one space, split by parity: the client takes the\n// odd ids, the server the even ones. Every connection also has a root, and a root is\n// numbered like anything else — the first id of the parity of the side that holds it:\n// 0 on the even side (the server), 1 on the odd one (the client). So an id says on\n// its own which side holds the process it names, the two roots included, and a frame's\n// address means the same thing whoever reads it.\n//\n// A side's own root is the process the connection is, and the far side's root is a\n// handle here like any of theirs. Neither end has to be told which number belongs to\n// whom: each root is the first id of its own parity.\n\nimport { isProcess } from \"../process.async.js\";\nimport type { RemoteProcess } from \"./remote-process.js\";\n\n/** The key that marks a process reference inside an otherwise JSON value. */\nexport const PROCESS_REF = \"$p\";\n\n/**\n * The id a side gives its own root: the first id of its parity. The two ends of a\n * connection therefore number their roots differently, and an id says whose root it is\n * as it says who holds every other process. A side hands out its next id from two\n * steps further on, the one in between belonging to the root of the side it talks to.\n */\nexport function rootIdFor(parity: IdParity): number {\n return parity === \"odd\" ? 1 : 0;\n}\n\n/** What a served root is called when the client states no name for it. A client that\n * states one — and the library's own does, in `$init` — is served under that name instead:\n * the process across the seam is the one its proxy was forked as, and it should be called\n * the same on both sides. This is the name for a connection that says nothing. */\nexport const SERVED_ROOT_NAME = \"remote\";\n\n/** What crosses the wire in place of a process. */\nexport interface ProcessRef {\n id: number;\n pname: string;\n}\n\n/** The little a table needs of what it holds to name it: what it is called, and\n * the symbol that identifies it in this build. */\nexport interface ProcessHandle {\n readonly pname: string;\n readonly id: symbol;\n}\n\n/** Which ids a side hands out: the client takes the odd ones, the server the\n * even ones, so one number can never name a process on both sides at once. */\nexport type IdParity = \"odd\" | \"even\";\n\n/**\n * The processes one connection knows, by the ids that name them. One table per\n * connection, because an id means nothing on any other one, and it lives exactly\n * as long as the connection that owns it.\n *\n * It holds two sets, told apart by parity rather than kept apart by a rule: the\n * processes this side holds — the root, and anything it hands over — and the ones\n * the far side holds, which this side knows as handles. A frame's address is\n * looked up in both, and exactly one can answer.\n */\nexport class ProcessTable<P extends ProcessHandle = ProcessHandle> {\n /** This side's own processes, by the ids it gave them. */\n private pvtMine = new Map<number, P>();\n private pvtMineIds = new Map<P, number>();\n /** The far side's processes, by the ids they came with. */\n private pvtTheirs = new Map<number, P>();\n /** The id of this side's own root: the first of its parity. */\n private pvtRootId: number;\n /** The id the far side gave its root: the first of its parity, and the number this\n * side's own numbering skips. */\n private pvtFarRootId: number;\n /** The next id this side may hand out: its own parity, from two steps past its own\n * root, the one in between belonging to the far side's root. */\n private pvtNext: number;\n /** Told the first time a process is numbered — the moment it is about to\n * cross the connection. */\n private pvtOnCrossed: ((proc: P, id: number) => void) | undefined;\n\n constructor(parity: IdParity, onCrossed?: (proc: P, id: number) => void) {\n this.pvtRootId = rootIdFor(parity);\n this.pvtFarRootId = rootIdFor(parity === \"odd\" ? \"even\" : \"odd\");\n this.pvtNext = this.pvtRootId + 2;\n this.pvtOnCrossed = onCrossed;\n }\n\n /** The id of this side's own end of the connection. */\n rootId(): number {\n return this.pvtRootId;\n }\n\n /** The id the far side knows its own end by: the root this side reaches as a handle,\n * and the one it never hands out for anything of its own. */\n farRootId(): number {\n return this.pvtFarRootId;\n }\n\n /** Bind this side's own end of the connection — the root — to its id. */\n bindRoot(proc: P): void {\n const bound = this.pvtMine.get(this.pvtRootId);\n if (bound !== undefined && bound !== proc) {\n throw new Error(\"ProcessTable: the root is already bound\");\n }\n this.pvtMine.set(this.pvtRootId, proc);\n this.pvtMineIds.set(proc, this.pvtRootId);\n }\n\n /** The id this side gives a process it holds, allocating one the first time. */\n handleFor(proc: P): number {\n const known = this.pvtMineIds.get(proc);\n if (known !== undefined) return known;\n const id = this.pvtNext;\n this.pvtNext += 2;\n this.pvtMine.set(id, proc);\n this.pvtMineIds.set(proc, id);\n this.pvtOnCrossed?.(proc, id);\n return id;\n }\n\n /** A process this side holds, by the id it gave it. */\n processFor(id: number): P | undefined {\n return this.pvtMine.get(id);\n }\n\n /**\n * Register a process the far side holds — a handle — under the id it arrived\n * with. A root is one of these as much as anything else: both ends hold one at 0,\n * so the far side's root is a handle here, and the one this side has of itself\n * stays what it was.\n */\n bindFar(id: number, proc: P): void {\n this.pvtTheirs.set(id, proc);\n }\n\n /** A process the far side holds, by the id it gave it. */\n farHandleFor(id: number): P | undefined {\n return this.pvtTheirs.get(id);\n }\n\n /**\n * Whatever this connection knows `id` to mean: a process this side holds, or a\n * handle on one the far side holds. Only one of the two can answer, because\n * the two sides take their ids from different halves of the space — so what\n * comes back does not depend on which way the frame was going.\n */\n resolve(id: number): P | undefined {\n return this.pvtMine.get(id) ?? this.pvtTheirs.get(id);\n }\n\n /**\n * Let go of an id: the process behind it is not this connection's business any\n * more, so it is no longer known by it. Both sides' ids go the same way — the\n * side that lets a handle go names the far side's id, the side that is asked to\n * forget names its own — and an id let go is never handed out again, so nothing\n * that still names it can come to mean another process.\n *\n * Neither root is let go of: one is this side's own end of the connection, and the\n * other is what this side is talking to.\n */\n release(id: number): P | undefined {\n if (id === this.pvtRootId || id === this.pvtFarRootId) return undefined;\n const mine = this.pvtMine.get(id);\n if (mine !== undefined) {\n this.pvtMine.delete(id);\n this.pvtMineIds.delete(mine);\n return mine;\n }\n const theirs = this.pvtTheirs.get(id);\n if (theirs !== undefined) this.pvtTheirs.delete(id);\n return theirs;\n }\n\n /** Every handle this side holds on a process of the far side. */\n handles(): P[] {\n return [...this.pvtTheirs.values()];\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as object | null;\n return proto === Object.prototype || proto === null;\n}\n\n/** Whether `value` is the wire form of a reference. */\nexport function asProcessRef(value: unknown): ProcessRef | null {\n if (typeof value !== \"object\" || value === null) return null;\n const ref = (value as Record<string, unknown>)[PROCESS_REF];\n if (typeof ref !== \"object\" || ref === null) return null;\n const { id, pname } = ref as Record<string, unknown>;\n if (typeof id !== \"number\" || typeof pname !== \"string\") return null;\n return { id, pname };\n}\n\n/** Whether `value` has the shape of a handle on a far-side process. Judged by\n * what it holds rather than by `instanceof`, for the reason a process is: one\n * build can hold two copies of the class. */\nexport function isRemoteProcess(value: unknown): value is RemoteProcess {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as { pname?: unknown; id?: unknown; ref?: unknown; send?: unknown };\n return (\n typeof candidate.pname === \"string\" &&\n typeof candidate.id === \"symbol\" &&\n typeof candidate.send === \"function\" &&\n asProcessRef({ [PROCESS_REF]: candidate.ref }) !== null\n );\n}\n\n/**\n * Replace every process in `value` with the reference this connection uses for\n * it, so what is left is JSON that says which processes the answer is about.\n *\n * A handle goes back as the reference it came with, id and all: that id is the\n * far side's own, the one it will be read by.\n *\n * Containers are copied rather than rewritten: the objects belong to the actor\n * that returned them, and a state it is still running on is not ours to edit. A\n * node already seen is left where it is — a cycle is the encoder's to report, not\n * something to walk forever.\n */\nexport function encodeProcessRefs(\n value: unknown,\n table: ProcessTable,\n seen: Set<unknown> = new Set(),\n): unknown {\n if (isRemoteProcess(value)) {\n return { [PROCESS_REF]: { id: value.ref.id, pname: value.ref.pname } };\n }\n if (isProcess(value)) {\n return { [PROCESS_REF]: { id: table.handleFor(value), pname: value.pname } };\n }\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n return value.map((item) => encodeProcessRefs(item, table, seen));\n }\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const copy: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n copy[key] = encodeProcessRefs(item, table, seen);\n }\n return copy;\n }\n return value;\n}\n\n/** How a side turns a reference into something it can hold: a handle. */\nexport type RefResolver = (ref: ProcessRef) => unknown;\n\n/** Replace every reference in `value` with what `resolve` makes of it. */\nexport function decodeProcessRefs(\n value: unknown,\n resolve: RefResolver,\n seen: Set<unknown> = new Set(),\n): unknown {\n const ref = asProcessRef(value);\n if (ref) return resolve(ref);\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n return value.map((item) => decodeProcessRefs(item, resolve, seen));\n }\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const copy: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n copy[key] = decodeProcessRefs(item, resolve, seen);\n }\n return copy;\n }\n return value;\n}\n","// ── Frame channel ──────────────────────────────────────────────────────────\n//\n// The seam's shared vocabulary. A StringTransport moves encoded frames\n// (strings); a Channel moves decoded frame objects. The frame guards narrow a\n// decoded frame to one of the `$`-key shapes. server.ts / client.ts speak only\n// in Channels and these guards — they never see a specific protocol or\n// transport.\n\nimport type { Message } from \"../types.js\";\nimport {\n decodeProcessRefs,\n encodeProcessRefs,\n type ProcessTable,\n type RefResolver,\n} from \"./process-ref.js\";\n\nexport interface StringTransport {\n send(frame: string): void | Promise<void>;\n onMessage(handler: (frame: string) => void): void;\n removeHandler(): void;\n /** Fires when the peer disconnects (transport closes from the other side). */\n onClose(handler: () => void): void;\n close(): Promise<void>;\n}\n\nexport interface Channel {\n send(frame: Record<string, unknown>): void | Promise<void>;\n onMessage(handler: (frame: Record<string, unknown>) => void): void;\n removeHandler(): void;\n /** Fires when the peer disconnects (transport closes from the other side). */\n onClose(handler: () => void): void;\n close(): Promise<void>;\n}\n\n// ── the address on a frame ─────────────────────────────────────────────────\n//\n// A frame that is about a process carries that process's id as `to`, at the top level\n// of the frame rather than inside its body: the frame is the envelope, and the address\n// says who it is for whatever kind it turns out to be. Every frame that is about a\n// process names it, the root of the connection included, since both ends number their\n// own root and neither has to be guessed at.\n\n/** The id a frame addresses, or null when it names no process. */\nexport function frameTo(frame: Record<string, unknown>): number | null {\n const to = frame.to;\n return typeof to === \"number\" ? to : null;\n}\n\n/**\n * A frame on its way out: every process in it becomes the reference this\n * connection uses for that process, and the process the frame addresses is\n * written down as `to`.\n */\nexport function encodeFrame(\n frame: Record<string, unknown>,\n table: ProcessTable,\n to: number,\n): Record<string, unknown> {\n const encoded = encodeProcessRefs(frame, table) as Record<string, unknown>;\n return { ...encoded, to };\n}\n\n/**\n * A frame just read: every reference in it becomes a handle on that process — or\n * the handle this side already made for it, since the same process handed over\n * twice is one process.\n */\nexport function decodeFrame(\n frame: Record<string, unknown>,\n resolve: RefResolver,\n): Record<string, unknown> {\n return decodeProcessRefs(frame, resolve) as Record<string, unknown>;\n}\n\n// ── frame guards ──────────────────────────────────────────────────────────\n\nexport function isProto(msg: Record<string, unknown>): msg is { $proto: string } {\n return \"$proto\" in msg;\n}\nexport function isInit(msg: Record<string, unknown>): msg is { $init: Record<string, unknown> } {\n return \"$init\" in msg;\n}\nexport function isState(msg: Record<string, unknown>): msg is { $state: Record<string, unknown> } {\n return \"$state\" in msg;\n}\nexport function isMsg(\n msg: Record<string, unknown>,\n): msg is { $msg: { fromName: string; body: Message } } {\n return \"$msg\" in msg;\n}\nexport function isExit(\n msg: Record<string, unknown>,\n): msg is { $exit: { code: number; state: unknown } } {\n return \"$exit\" in msg;\n}\n\n// ── what is said about a crossed process ────────────────────────────────────\n//\n// A process that crossed can be asked for less than everything, or for nothing at\n// all: what crosses about it is three categories, and only the ones asked for are\n// sent. Silence is the empty list, so a handle that asks for nothing hears\n// nothing — not its state, not its messages, and not that it is gone.\n//\n// {\"$tune\": {\"streams\": [\"state\"]}, \"to\": 3} this much about it, and no more\n\nexport type StreamKind = \"message\" | \"state\" | \"exit\";\n\n/** The three, in the one order they are ever named in — the order a tune frame\n * carries them in, so two ways of asking for the same thing look the same. */\nexport const STREAM_KINDS: StreamKind[] = [\"message\", \"state\", \"exit\"];\n\nexport function isStreamKind(value: unknown): value is StreamKind {\n return typeof value === \"string\" && (STREAM_KINDS as string[]).includes(value);\n}\n\n// ── control frames ─────────────────────────────────────────────────────────\n//\n// What the holder of a handle can ask of a process on the far side, beside\n// sending it a message. Each is a frame of its own rather than a message, so\n// nothing an actor reads is ever a control signal by accident:\n//\n// {\"$stop\": {}, \"to\": 3} stop it; it ends, and its `$exit` crosses back\n// {\"$pause\": {}, \"to\": 3} stop feeding it messages\n// {\"$resume\": {}, \"to\": 3} feed it again\n// {\"$release\": {}, \"to\": 3} let it go: forget this id, and stop telling me\n// about the process behind it\n// {\"$tune\": {\"streams\": [...]}, \"to\": 3}\n// say this much about it and no more: a subset of\n// message, state and exit, or the empty list for\n// silence\n//\n// They address the process they are about, so they are answered by whoever holds\n// that process — the side that can act on it. Stopping the *root* of a connection\n// is not one of these: that stays the STOP message it always was, since the root\n// is not a handle but the process this side is talking through.\n\nexport function isStop(msg: Record<string, unknown>): msg is { $stop: Record<string, unknown> } {\n return \"$stop\" in msg;\n}\nexport function isPause(msg: Record<string, unknown>): msg is { $pause: Record<string, unknown> } {\n return \"$pause\" in msg;\n}\nexport function isResume(msg: Record<string, unknown>): msg is { $resume: Record<string, unknown> } {\n return \"$resume\" in msg;\n}\nexport function isRelease(msg: Record<string, unknown>): msg is { $release: Record<string, unknown> } {\n return \"$release\" in msg;\n}\n\nexport function isTune(msg: Record<string, unknown>): msg is { $tune: Record<string, unknown> } {\n return \"$tune\" in msg;\n}\n\n/**\n * The categories a tune frame asks for, in the order they are named in — or null\n * when the frame says something this vocabulary has no word for, which is a frame\n * to ignore rather than to guess at.\n */\nexport function tuneFrame(frame: { $tune: unknown }): StreamKind[] | null {\n const body = frame.$tune;\n if (typeof body !== \"object\" || body === null) return null;\n const streams = (body as { streams?: unknown }).streams;\n if (!Array.isArray(streams)) return null;\n if (!streams.every(isStreamKind)) return null;\n return STREAM_KINDS.filter((kind) => (streams as StreamKind[]).includes(kind));\n}\n\n// ── reflection frames ──────────────────────────────────────────────────────\n//\n// A reflection call crosses the seam as one frame and its answer as another, and\n// both go both ways: whoever holds a process is the one that answers for it.\n//\n// {\"$r.methods\": [\"inspect.getTree\", …]} what a process can answer, once, when\n// it crosses (and, for the root, once\n// when the connection opens)\n// {\"$r.call.<name>\": {seq, args}} asking, addressed to the process\n// {\"$r.result.<name>\": {seq, value}} answered\n// {\"$r.result.<name>\": {seq, error}} refused\n//\n// The method name is in the frame key, so a frame says what it is without a\n// table, and `seq` — one connection's, never reused — tells two calls to the\n// same method apart while both are in flight. An answer is about the call and not\n// about a process, so it carries no address: it names the seq it settles.\n\nexport const REFLECT_METHODS = \"$r.methods\";\nexport const REFLECT_CALL = \"$r.call.\";\nexport const REFLECT_RESULT = \"$r.result.\";\n\nexport interface ReflectionCall {\n name: string;\n seq: number;\n args: unknown[];\n}\n\nexport interface ReflectionResult {\n name: string;\n seq: number;\n value?: unknown;\n error?: string;\n}\n\nexport function isReflectionMethods(\n msg: Record<string, unknown>,\n): msg is { \"$r.methods\": string[] } {\n const names = msg[REFLECT_METHODS];\n return Array.isArray(names) && names.every((name) => typeof name === \"string\");\n}\n\nfunction reflectionBody(\n frame: Record<string, unknown>,\n prefix: string,\n): { name: string; body: Record<string, unknown> } | null {\n for (const key of Object.keys(frame)) {\n if (!key.startsWith(prefix) || key.length === prefix.length) continue;\n const body = frame[key];\n if (typeof body !== \"object\" || body === null) return null;\n return { name: key.slice(prefix.length), body: body as Record<string, unknown> };\n }\n return null;\n}\n\n/** A call frame, or null — a malformed one is not worth an answer. */\nexport function asReflectionCall(frame: Record<string, unknown>): ReflectionCall | null {\n const parsed = reflectionBody(frame, REFLECT_CALL);\n if (!parsed || typeof parsed.body.seq !== \"number\") return null;\n const args = parsed.body.args;\n return {\n name: parsed.name,\n seq: parsed.body.seq,\n args: Array.isArray(args) ? args : [],\n };\n}\n\n/** An answer frame, or null. `error` present means the call was refused. */\nexport function asReflectionResult(frame: Record<string, unknown>): ReflectionResult | null {\n const parsed = reflectionBody(frame, REFLECT_RESULT);\n if (!parsed || typeof parsed.body.seq !== \"number\") return null;\n const { seq, value, error } = parsed.body;\n return typeof error === \"string\"\n ? { name: parsed.name, seq, error }\n : { name: parsed.name, seq, value };\n}\n\n/**\n * Why a value cannot cross a frame, or null when it can. Only JSON data\n * crosses: a function, a symbol or a bigint cannot be written down at all, and\n * a value with a cycle or a bigint inside it makes the encoder throw. What\n * JSON itself would quietly drop — a function stored inside an object — is the\n * caller's business, not something to invent a policy for here.\n */\nexport function jsonProblem(value: unknown): string | null {\n const kind = typeof value;\n if (kind === \"function\" || kind === \"symbol\" || kind === \"bigint\") return `a ${kind}`;\n if (kind !== \"object\" || value === null) return null;\n try {\n JSON.stringify(value);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n return null;\n}\n","// ── A process on the far side, as this side can use it ─────────────────────\n//\n// A handle. It knows the name the far side calls the process and the id this\n// connection knows it by, and one thing more than a bare reference has: a way to\n// put a frame on the wire with that id. Everything else it offers is what comes\n// back because of it — the state that streams for it, the messages it emits, the\n// methods it announced.\n//\n// A handle is not a process of this side's tree. Nothing has to make it one:\n// the far side's tree is already reachable through reflection, so asking the\n// proxy for it walks that side and gives that tree. A handle is how something\n// on the far side is talked to, not where it sits here.\n\nimport type { Message } from \"../types.js\";\nimport { makeWaiter, type Waiter } from \"../util.js\";\nimport { STREAM_KINDS, type StreamKind } from \"./channel.js\";\nimport type { ProcessRef } from \"./process-ref.js\";\n\n/** What a process left behind when it ended. */\nexport interface RemoteExit {\n code: number;\n state: unknown;\n}\n\n/** How a handle gets a frame onto the connection it belongs to, addressed to a\n * process the far side holds. The answer is handed back when a caller has to know\n * the frame is out — the root's end is said that way, just before the wire closes. */\nexport type FrameSink = (frame: Record<string, unknown>, to: number) => void | Promise<void>;\n\n/** What a side does when it lets go of a handle: stop knowing the id, so nothing\n * arriving for it can land here again. */\nexport type ReleaseHook = (id: number) => void;\n\n/** An out-message of the far process, and the name it came with. */\nexport type RemoteMessage<OutMsg extends Message = Message> = (msg: OutMsg, fromName: string) => void;\n\nexport class RemoteProcess<InMsg extends Message = Message, OutMsg extends Message = Message> {\n /** The name the far side knows it by. */\n readonly pname: string;\n /** The id this connection knows it by — the far side's own, since it is the\n * side that holds the process. */\n readonly ref: ProcessRef;\n /** A symbol of this side's own, so a handle can be told apart from any other\n * the way a process is: by holding one. */\n readonly id: symbol;\n /** What the far side has said about its state so far. */\n state: Record<string, unknown> | null = null;\n /** The methods the far side announced it can answer. */\n readonly $reflection: Record<string, (...args: unknown[]) => Promise<unknown>> = {};\n\n private pvtSend: FrameSink;\n private pvtFromName: string;\n private pvtConnected = true;\n /** This side let it go: nothing more is asked of it, and nothing arriving for it\n * is news any more. Not the same as ending, and not the same as the connection\n * going: in all three the handle is dead, and only the reason differs. */\n private pvtReleased = false;\n private pvtLetGo: ReleaseHook | undefined;\n /** What the far side said when it ended, or null while it is running. */\n private pvtExit: RemoteExit | null = null;\n private pvtExitWaiter: Waiter<RemoteExit> | null = null;\n private pvtMessageSubs: Array<RemoteMessage<OutMsg>> = [];\n private pvtStateSubs: Array<() => void> = [];\n /** What this side has asked to be told about it. A process that crosses is\n * silent, so a handle starts out having asked for nothing and hears nothing\n * until something here wants it — which is the same rule the far side holds,\n * written from the other end. */\n private pvtWanted: Set<StreamKind> = new Set();\n\n constructor(ref: ProcessRef, send: FrameSink, fromName: string, letGo?: ReleaseHook) {\n this.ref = ref;\n this.pname = ref.pname;\n this.id = Symbol(ref.pname);\n this.pvtSend = send;\n this.pvtFromName = fromName;\n this.pvtLetGo = letGo;\n }\n\n /**\n * Whether the process this handle names can still be reached: the wire is there, and\n * this side has not let the handle go.\n *\n * Reaching it is not the same as it being alive. A process that has ended is still\n * one this side has a handle on — it is what the handle points at, and what it left\n * behind is here — so an end does not put it out of reach; `hasEnded()` is that\n * answer, and the two are asked separately. From the two ways out there is no coming\n * back: no reconnect, and no way to un-release.\n */\n isConnected(): boolean {\n return this.pvtConnected && !this.pvtReleased;\n }\n\n /**\n * The connection is gone. Every handle this side holds goes out of reach with it,\n * and says so: there is no reconnect to wait for, so a send fails here and now\n * rather than disappearing into nothing.\n */\n disconnect(): void {\n if (!this.pvtConnected) return;\n this.pvtConnected = false;\n this.pvtStateSubs.forEach((fn) => fn());\n // Whoever is waiting for it to end is waiting for news that can no longer come.\n this.pvtExitWaiter?.reject(new Error(`${this.pname} cannot be reached: the connection is closed`));\n }\n\n /** Whether the process it names has ended, as far as this side has been told. */\n hasEnded(): boolean {\n return this.pvtExit !== null;\n }\n\n /** Why nothing can be asked *of the process* — let go, ended, or out of reach — or\n * nothing when something can. Those are not one thing said three ways: an ended\n * process is still reached, it simply has nothing left to receive. */\n private pvtWhyNotAskable(): string | null {\n if (this.pvtReleased) return `${this.pname} was released`;\n if (this.pvtExit !== null) return `${this.pname} has ended`;\n if (!this.pvtConnected) return `${this.pname} cannot be reached: the connection is closed`;\n return null;\n }\n\n private pvtRequireAskable(): void {\n const why = this.pvtWhyNotAskable();\n if (why !== null) throw new Error(why);\n }\n\n /**\n * Wait for the process to end. Its exit crosses back like everything else it\n * does, and what it left behind is the answer.\n *\n * A handle whose connection is gone rejects instead: what is left to wait for\n * after that is nothing, and a process that keeps running is not something this\n * side can tell from one that died with the wire.\n */\n wait(): Promise<RemoteExit> {\n if (this.pvtExit !== null) return Promise.resolve(this.pvtExit);\n const why = this.pvtWhyNotAskable();\n if (why !== null) return Promise.reject(new Error(why));\n // Waiting for it to end is a subscription to its end: nothing here hears an\n // exit that was never asked for, so asking to wait asks for it.\n this.pvtWant(\"exit\");\n this.pvtExitWaiter ??= makeWaiter<RemoteExit>();\n return this.pvtExitWaiter.promise;\n }\n\n /**\n * Ask the far side to stop it. Stops the way it always does there, and this\n * resolves when its exit has crossed back — which is all this side can know.\n * There is no deadline, so a process that refuses to stop leaves this pending.\n */\n stop(): Promise<void> {\n this.pvtRequireAskable();\n // Ask for the end before asking it to stop: whether an exit is sent is decided\n // by what the far side has been asked for when it comes, so a stop ordered ahead\n // of the asking could leave nothing to wait for.\n this.pvtWant(\"exit\");\n this.pvtSend({ $stop: {} }, this.ref.id);\n return this.wait().then(() => undefined);\n }\n\n /**\n * Let it go: the far side forgets this id and stops telling this side anything\n * about the process behind it. The process itself is untouched — it runs on, it\n * is simply nobody's here any more — and this handle is done: nothing reaches it,\n * nothing is waited for, and what arrives for it later is not news.\n */\n release(): void {\n this.pvtRequireAskable();\n this.pvtReleased = true;\n this.pvtLetGo?.(this.ref.id);\n this.pvtSend({ $release: {} }, this.ref.id);\n }\n\n /** Stop feeding it messages. It is still there: `send` still reaches it. */\n pause(): void {\n this.pvtRequireAskable();\n this.pvtSend({ $pause: {} }, this.ref.id);\n }\n\n /** Feed it messages again. */\n resume(): void {\n this.pvtRequireAskable();\n this.pvtSend({ $resume: {} }, this.ref.id);\n }\n\n /**\n * What to be told about it from now on: any of `message`, `state` and `exit`,\n * or `\"silent\"` for none of it.\n *\n * A process that crossed is silent to begin with, so this is how a handle asks\n * to hear anything at all — and what is heard is only ever what was asked for.\n * An exit nobody asked for is not sent: silence is silence, which makes this the\n * one way to leave a handle that will not answer a `wait()`, and the far side's\n * books the one place an end can go unrecorded.\n */\n tune(kinds: StreamKind[] | \"silent\"): void {\n this.pvtRequireAskable();\n this.pvtTune(kinds === \"silent\" ? [] : kinds);\n }\n\n /** Ask the far side to say exactly this much, and nothing when it is already\n * saying it. The list goes in the order the three are named in, so asking for\n * the same thing twice sends the same frame twice. */\n private pvtTune(wanted: StreamKind[]): void {\n const kinds = STREAM_KINDS.filter((kind) => wanted.includes(kind));\n if (kinds.length === this.pvtWanted.size && kinds.every((kind) => this.pvtWanted.has(kind))) {\n return;\n }\n this.pvtWanted = new Set(kinds);\n this.pvtSend({ $tune: { streams: kinds } }, this.ref.id);\n }\n\n /** Ask for one more category, because something here now wants it. A handle\n * that is gone asks nothing: there is no far side left to hear it, and nothing\n * was asked for, so what was wanted stays what it was. */\n private pvtWant(kind: StreamKind): void {\n if (this.pvtWanted.has(kind)) return;\n if (!this.pvtConnected || this.pvtReleased) return;\n this.pvtTune([...this.pvtWanted, kind]);\n }\n\n /** Hand the far process a message. */\n send(msg: InMsg): void {\n this.pvtRequireAskable();\n this.pvtSend({ $msg: { fromName: this.pvtFromName, body: msg } }, this.ref.id);\n }\n\n /** Subscribe to what it says, or to what it holds. Asking here is asking the far\n * side: a subscription is the first thing that wants the category, so it is what\n * turns it on, and unsubscribing leaves it on — the far side is not told to stop\n * saying something that another subscriber may still want. */\n subscribe(channel: \"message\", cb: RemoteMessage<OutMsg>): () => void;\n subscribe(channel: \"state\", cb: () => void): () => void;\n subscribe(channel: \"message\" | \"state\", cb: RemoteMessage<OutMsg> | (() => void)): () => void {\n if (channel === \"message\") {\n const fn = cb as RemoteMessage<OutMsg>;\n this.pvtMessageSubs.push(fn);\n this.pvtWant(\"message\");\n return () => this.pvtUnsubscribe(this.pvtMessageSubs, fn);\n }\n const fn = cb as () => void;\n this.pvtStateSubs.push(fn);\n this.pvtWant(\"state\");\n return () => this.pvtUnsubscribe(this.pvtStateSubs, fn);\n }\n\n private pvtUnsubscribe<T>(list: Array<T>, fn: T): void {\n const idx = list.indexOf(fn);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n // ── what the connection delivers ─────────────────────────────────────────\n // The handle does not read frames; the side that owns the connection hands it\n // what a frame about this process said.\n\n /** Its state, as the far side just published it. */\n receiveState(state: Record<string, unknown>): void {\n if (this.pvtReleased) return;\n this.state = Object.assign(this.state ?? {}, state);\n this.pvtStateSubs.forEach((fn) => fn());\n }\n\n /** A message it emitted. */\n receiveMessage(msg: OutMsg, fromName: string): void {\n if (this.pvtReleased) return;\n this.pvtMessageSubs.forEach((fn) => fn(msg, fromName));\n }\n\n /** It has ended, and this is what it left behind. The last thing said about a\n * process: nothing crosses about it after its exit, though the handle still\n * reaches it for what it left. */\n receiveExit(exit: RemoteExit): void {\n if (this.pvtExit !== null || this.pvtReleased) return;\n this.pvtExit = exit;\n this.pvtExitWaiter?.resolve(exit);\n }\n\n /** The methods it can answer, as functions that ask it for an answer. `call`\n * is the connection's own: a handle knows what to ask for, not how a call is\n * made or paired with its answer. */\n receiveMethods(names: string[], call: (name: string, args: unknown[]) => Promise<unknown>): void {\n for (const name of names) {\n this.$reflection[name] = (...args: unknown[]) => call(name, args);\n }\n }\n}\n","// ── What a process says once it has crossed ─────────────────────────────────\n//\n// A process that crosses the connection is numbered, and from that moment the\n// other side can be told about it: what it can answer, what it holds, and what it\n// emits. Both ends say exactly this about the processes they hold — the side that\n// hands one over, and the side that serves one — so it is written once here\n// rather than once per side.\n\nimport { isProcess, type AnyProcess } from \"../process.async.js\";\nimport { REFLECT_METHODS, STREAM_KINDS, type StreamKind } from \"./channel.js\";\n\nimport type { FrameSink } from \"./remote-process.js\";\n\n/** What a process can be asked over the wire: the functions on its reflection\n * surface, read once. On the side that serves it the list *is* the dispatch\n * table, so a name that was never on it can never be reached. */\nconst pvtReflectionNames = new WeakMap<object, string[]>();\n\nexport function reflectionNames(target: { $reflection?: unknown }): string[] {\n const known = pvtReflectionNames.get(target);\n if (known) return known;\n const surface = (target.$reflection ?? {}) as Record<string, unknown>;\n const names = Object.keys(surface).filter((name) => typeof surface[name] === \"function\");\n pvtReflectionNames.set(target, names);\n return names;\n}\n\n/**\n * The processes of one side that have crossed, and what the far side is told\n * about them.\n *\n * A stream starts once the frame that carried the reference is out: frames about\n * a process the reader cannot name yet have nowhere to land. The table numbers a\n * process while that frame is being written, so the numbering is queued here and\n * let out by `flush` right after the frame goes — which is the only thing a\n * caller has to remember.\n *\n * What a stream says is what the far side asked for. A process that crosses is silent\n * until something over there asks to hear it, and `tune` is that asking: only the\n * categories it names cross. The root of the connection is no exception. It is\n * registered here the moment the connection opens, and a side that wants to hear it\n * asks, which is what a visitor's proxy does for the state and messages it stands in\n * for.\n */\n\n/** One process that crossed, and what is said about it now. */\ninterface StreamRecord {\n target: AnyProcess;\n /** The categories that cross, out of the three. */\n kinds: Set<StreamKind>;\n /** How to stop hearing one that is armed. `exit` is not among them: a stream\n * has to hear the end to know it is over, and what it does with the news is\n * the question `kinds` answers. */\n stops: Map<StreamKind, () => void>;\n}\n\nexport class ProcessStreams {\n private pvtSink: FrameSink;\n /** The id of the connection's own end. Its end is the connection's end, so the side\n * that owns the wire says it, awaited there, instead of this watching for it as it\n * watches any other process's. */\n private pvtRootId: number;\n private pvtPending: Array<[AnyProcess, number]> = [];\n private pvtRecords = new Map<number, StreamRecord>();\n private pvtFlushing = false;\n\n constructor(sink: FrameSink, rootId: number) {\n this.pvtSink = sink;\n this.pvtRootId = rootId;\n }\n\n /** A process was numbered: it is about to cross. Anything that is not a\n * process — a handle travelling back to the side that holds it — crosses as\n * the reference it came with and is nobody's to stream. */\n crossed(proc: unknown, id: number): void {\n if (!isProcess(proc)) return;\n this.pvtPending.push([proc, id]);\n }\n\n /** Say what there is to say about whatever crossed while a frame was written. */\n flush(): void {\n if (this.pvtFlushing) return;\n this.pvtFlushing = true;\n try {\n while (this.pvtPending.length > 0) {\n const next = this.pvtPending.shift();\n if (next) this.pvtStream(next[0], next[1]);\n }\n } finally {\n this.pvtFlushing = false;\n }\n }\n\n /**\n * What to say about it from now on: the categories named, and none of the\n * others. Asking for its state says it there and then — a handle that has just\n * asked what it holds should not have to wait for it to change.\n *\n * An id with no stream here is not this side's to tune, and the frame is\n * dropped: both sides tune only what they hold, so an id names a stream on the\n * side that numbered it.\n */\n tune(id: number, kinds: StreamKind[]): void {\n const record = this.pvtRecords.get(id);\n if (!record) return;\n const wanted = new Set(kinds);\n for (const kind of STREAM_KINDS) {\n const isOn = record.kinds.has(kind);\n const want = wanted.has(kind);\n if (want === isOn) continue;\n if (want) {\n record.kinds.add(kind);\n this.pvtArm(record, id, kind);\n } else {\n record.kinds.delete(kind);\n this.pvtDisarm(record, kind);\n }\n }\n }\n\n /**\n * Say nothing more about this one. It is not that the process ended — the far\n * side asked to be left out of it, so its exit is nobody's news over here, and\n * dropping the subscription is what keeps it from being sent.\n */\n stop(id: number): void {\n const record = this.pvtRecords.get(id);\n if (!record) return;\n for (const stop of record.stops.values()) stop();\n this.pvtRecords.delete(id);\n }\n\n /** Nothing more is said about any of them: the connection is done. */\n stopAll(): void {\n for (const id of [...this.pvtRecords.keys()]) this.stop(id);\n this.pvtPending.length = 0;\n }\n\n private pvtStream(target: AnyProcess, id: number): void {\n // Nothing to begin with: what is said about a process is what the far side asks\n // for, and the root is asked for like anything else.\n const record: StreamRecord = {\n target,\n kinds: new Set(),\n stops: new Map(),\n };\n this.pvtRecords.set(id, record);\n // What it can answer comes first: a handle that hears from a process it cannot\n // name yet has nowhere to put the news. It is not one of the three categories\n // — a handle with no methods can do nothing with the process however much it\n // is told about it — so it crosses even in silence.\n this.pvtSink({ [REFLECT_METHODS]: reflectionNames(target) }, id);\n for (const kind of record.kinds) this.pvtArm(record, id, kind);\n // Its end is the last thing ever said about it, and the one thing a stream has\n // to hear to know it is over, whether or not the far side is told. A process\n // that fails to run takes the same road as one that finishes.\n //\n // Not for the root. Its end is the connection's end, and the side that owns the\n // wire says it while taking the wire down, awaiting it there because that frame has\n // to be out before the close. Both of them end up in `sayEnded`.\n if (id !== this.pvtRootId) {\n void target.wait().then(\n () => void this.sayEnded(id, 0),\n () => void this.sayEnded(id, 1),\n );\n }\n }\n\n /** Start saying this much about it, and say what there is to say now. */\n private pvtArm(record: StreamRecord, id: number, kind: StreamKind): void {\n if (kind === \"message\") {\n record.stops.set(\n \"message\",\n record.target.subscribe(\"message\", (msg, sender) => {\n this.pvtSink({ $msg: { fromName: sender.fromName, body: msg } }, id);\n }),\n );\n return;\n }\n if (kind === \"state\") {\n record.stops.set(\n \"state\",\n record.target.subscribe(\"state\", () => {\n this.pvtSink({ $state: record.target.state as Record<string, unknown> }, id);\n }),\n );\n // Asked for, so said now: in silence the far side has heard nothing about\n // its state, and this is the first word rather than a repeat.\n this.pvtSink({ $state: record.target.state as Record<string, unknown> }, id);\n }\n // `exit` needs no subscription: the end is watched from the moment the process\n // crosses, since a stream has to know when it is over. Whether it is sent is\n // read from `kinds` when it comes.\n }\n\n private pvtDisarm(record: StreamRecord, kind: StreamKind): void {\n const stop = record.stops.get(kind);\n if (!stop) return;\n stop();\n record.stops.delete(kind);\n }\n\n /**\n * It has ended: say so once, if that is among the categories asked for, and say\n * nothing more about it either way. Awaited by whoever has to have the frame out\n * before the wire closes, which is the root's end and nobody else's — no other\n * process can end after this side has stopped saying anything about it.\n */\n async sayEnded(id: number, code: number): Promise<void> {\n const record = this.pvtRecords.get(id);\n if (!record) return;\n const told = record.kinds.has(\"exit\");\n const state = record.target.state;\n this.stop(id);\n if (told) await this.pvtSink({ $exit: { code, state } }, id);\n }\n}\n","// ── Who a message that crossed the wire came from ──────────────────────────\n//\n// A frame carries its sender as a name, because a symbol cannot be written down.\n// On the other side the name is turned back into an identity a process can be\n// handed: whoever the frame names, and — when that name is the one a process was\n// told is its parent — the parent's own stable id, so a child on either side of\n// the seam recognises the same sender.\n\nimport type { SenderInfo } from \"../types.js\";\n\nexport function makeSender(\n fromName: string,\n parentName: string | null,\n parentId: symbol | null,\n): SenderInfo {\n if (parentId && fromName === parentName) {\n return { fromName, fromId: parentId };\n }\n return { fromName, fromId: Symbol() };\n}\n","// ── The call side of a connection ───────────────────────────────────────────\n//\n// Both ends of a seam make calls and answer them, and the machinery is the same\n// once the wire is: a `seq` the connection counts, the calls waiting under it, the\n// surface a handle reads to make one, and the answer that names which call it\n// settles. Only where a frame leaves differs between the two ends, which is why\n// that is the one thing handed in and the rest is written once.\n\nimport { isProcess } from \"../process.async.js\";\nimport {\n REFLECT_CALL,\n REFLECT_RESULT,\n asReflectionResult,\n encodeFrame,\n jsonProblem,\n type ReflectionCall,\n} from \"./channel.js\";\nimport { encodeProcessRefs, type ProcessHandle, type ProcessTable } from \"./process-ref.js\";\nimport { reflectionNames } from \"./process-streams.js\";\n\n/** A frame on its way out: encoded, addressed, and written to this end's wire. */\nexport type WireSink = (frame: Record<string, unknown>) => Promise<void>;\n\nexport class CallSide {\n /**\n * `seq` belongs to this connection and is never reused, so two calls to the same\n * method in flight at once stay apart; the answer names the one it belongs to,\n * whichever process it was asked of.\n */\n private pvtCalls = 0;\n private pvtWaiting = new Map<\n number,\n { name: string; resolve: (value: unknown) => void; reject: (error: Error) => void }\n >();\n private pvtWrite: WireSink;\n private pvtTable: ProcessTable<ProcessHandle>;\n\n constructor(write: WireSink, table: ProcessTable<ProcessHandle>) {\n this.pvtWrite = write;\n this.pvtTable = table;\n }\n\n /**\n * Ask a process on the far side for one of its methods. Processes among the\n * arguments become references first — this side's own, with ids from its table, or\n * the far side's coming back — and what is left has to be JSON, or nothing is sent\n * at all.\n */\n call(method: string, callArgs: unknown[], to: number): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const seq = ++this.pvtCalls;\n const frame = encodeFrame(\n { [`${REFLECT_CALL}${method}`]: { seq, args: callArgs } },\n this.pvtTable,\n to,\n );\n const problem = jsonProblem(frame);\n if (problem !== null) {\n reject(new Error(`cannot send ${problem} to ${method}`));\n return;\n }\n this.pvtWaiting.set(seq, { name: method, resolve, reject });\n void this.pvtWrite(frame).catch((error: unknown) => {\n this.pvtWaiting.delete(seq);\n reject(error instanceof Error ? error : new Error(String(error)));\n });\n });\n }\n\n /** One function per announced name, on the surface whoever calls reads. */\n install(surface: Record<string, unknown>, methods: string[], to: number): void {\n for (const method of methods) {\n surface[method] = (...callArgs: unknown[]) => this.call(method, callArgs, to);\n }\n }\n\n /**\n * An answer to a call this side made: the call waiting under that `seq` is settled\n * by it, and the frame says whether it was one at all. An answer is about the call\n * and not about a process, so a dispatcher reads it before it looks anything up.\n */\n settle(frame: Record<string, unknown>): boolean {\n const result = asReflectionResult(frame);\n if (!result) return false;\n const waiting = this.pvtWaiting.get(result.seq);\n if (waiting) {\n this.pvtWaiting.delete(result.seq);\n if (result.error === undefined) waiting.resolve(result.value);\n else waiting.reject(new Error(`${waiting.name}: ${result.error}`));\n }\n return true;\n }\n\n /** A call that was in flight when the wire went has no answer coming; it fails\n * here rather than hanging for ever. */\n rejectAll(): void {\n for (const waiting of this.pvtWaiting.values()) {\n waiting.reject(new Error(`connection closed before ${waiting.name} answered`));\n }\n this.pvtWaiting.clear();\n }\n}\n\n/**\n * Answer one call with what the process said, or why it could not. A method may be\n * written for a call that answers later; the wire has no opinion about that, it just\n * waits for the frame.\n */\nexport async function answerCall(\n call: ReflectionCall,\n target: ProcessHandle | undefined,\n write: WireSink,\n table: ProcessTable<ProcessHandle>,\n): Promise<void> {\n // An answer goes back to the far side's own end of the connection: a result is about\n // the call and not about a process, and the one waiting for it is out there.\n const reply = (body: Record<string, unknown>) =>\n write(encodeFrame({ [`${REFLECT_RESULT}${call.name}`]: body }, table, table.farRootId()));\n // Only a process this side holds can be asked: the id a call names is the holder's\n // own, and this side is the holder of what it holds.\n if (!isProcess(target)) {\n await reply({ seq: call.seq, error: \"no process with that id on this connection\" });\n return;\n }\n const names = reflectionNames(target);\n const surface = target.$reflection as unknown as Record<string, Function>;\n const method = names.includes(call.name) ? surface[call.name] : undefined;\n if (typeof method !== \"function\") {\n await reply({ seq: call.seq, error: `no reflection method named ${call.name}` });\n return;\n }\n try {\n // References in the arguments arrived as handles on processes of this side's own,\n // and processes in the answer become references. What is left has to be JSON, or\n // the call is refused rather than half-written.\n const value = encodeProcessRefs(await method(...call.args), table);\n const problem = jsonProblem(value);\n if (problem !== null) {\n await reply({\n seq: call.seq,\n error: `${call.name} returned ${problem}, which cannot cross a frame`,\n });\n return;\n }\n await reply({ seq: call.seq, value });\n } catch (err) {\n await reply({ seq: call.seq, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","// ── Server side of the seam ────────────────────────────────────────────────\n//\n// serveRemoteActor serves a posipaki actor over a frame Channel produced by a\n// spawner. It knows only the frame vocabulary (channel.ts) — no protocol, no\n// transport, no spawner. The spawner has already done the $proto handshake.\n\nimport type { ActorDefinition, ReflectionOptions } from \"../actor-types.js\";\nimport type { Message } from \"../types.js\";\nimport { isProcess } from \"../process.async.js\";\nimport type { Channel } from \"./channel.js\";\nimport {\n ProcessTable,\n SERVED_ROOT_NAME,\n isRemoteProcess,\n type ProcessHandle,\n type ProcessRef,\n} from \"./process-ref.js\";\nimport { RemoteProcess, type FrameSink } from \"./remote-process.js\";\nimport { ProcessStreams } from \"./process-streams.js\";\nimport { makeSender } from \"./sender.js\";\nimport {\n REFLECT_METHODS,\n asReflectionCall,\n decodeFrame,\n encodeFrame,\n frameTo,\n isExit,\n isInit,\n isMsg,\n isPause,\n isRelease,\n isResume,\n isState,\n isStop,\n isTune,\n isReflectionMethods,\n tuneFrame,\n} from \"./channel.js\";\nimport { CallSide, answerCall } from \"./call-side.js\";\n\nexport type Spawner = () => Promise<Channel>;\n\n/** The name the served actor is spawned under, and the one it answers to as a sender when\n * it talks to a process of the far side's: what the client states in `$init`, since the\n * process being served is the one its proxy was forked as over there. The fallback is for\n * a connection that states none — an older client, or a hand-written `$init` — where the\n * far side's name for its own end is all there is to go on. */\nlet rootName: string = SERVED_ROOT_NAME;\n\nexport async function serveRemoteActor<\n Args,\n State,\n InMsg extends Message,\n OutMsg extends Message,\n R extends ReflectionOptions,\n>(actor: ActorDefinition<Args, State, InMsg, OutMsg, R>, spawner: Spawner): Promise<void> {\n const channel = await spawner();\n\n // The table takes the even ids: the odd ones are the far side's, so the same\n // number can never name a process on both ends at once. A process that is\n // numbered here is one that is about to cross, and its stream follows the frame\n // that carried it.\n const table = new ProcessTable<ProcessHandle>(\"even\", (proc, id) => streams.crossed(proc, id));\n\n /** Put an encoded frame on the wire, and then say what it numbered. A frame that\n * carried a reference has to be out before anything about that process is. */\n const write = async (frame: Record<string, unknown>): Promise<void> => {\n await channel.send(frame);\n streams.flush();\n };\n\n const sendToFrame = (frame: Record<string, unknown>, to: number): Promise<void> =>\n write(encodeFrame(frame, table, to));\n\n /** Every frame leaves this way. The answer is handed back, since the one frame that\n * has to be out before the wire closes is awaited by the side that owns the wire. */\n const sendTo: FrameSink = (frame, to) =>\n sendToFrame(frame, to).catch((e: unknown) => {\n console.error(\"Error sending out the frame\", e);\n });\n\n // Everything is in place to speak: the sink writes to the wire, and what the\n // table numbers crosses through it.\n const streams = new ProcessStreams(sendTo, table.rootId());\n\n // Both ends of a connection make calls and answer them: a process the far side\n // holds is asked the same way this side is asked.\n const calls = new CallSide(write, table);\n\n /** The handle for a reference that arrived: the same one every time, and the process\n * itself when the reference names a process of this side's own. The roots are\n * numbered apart, so a reference to the far side's root is a reference to a process\n * of theirs, and a handle like any of those. */\n const handleFor = (ref: ProcessRef): ProcessHandle => {\n const held = table.processFor(ref.id);\n if (held) return held;\n const known = table.farHandleFor(ref.id);\n if (isRemoteProcess(known)) return known;\n const handle = new RemoteProcess(ref, sendTo, rootName, (id) => table.release(id));\n table.bindFar(ref.id, handle);\n return handle;\n };\n\n // await $init, keeping everything that arrives with it. The channel has one handler\n // slot, and a frame that arrives while the actor is still starting has nothing to be\n // dispatched to yet, so the frames wait here and are replayed below. The $init is the\n // first of them, that being what the connection is made by.\n const waiting: Record<string, unknown>[] = [];\n await new Promise<void>((resolve) => {\n channel.onMessage((frame) => {\n waiting.push(frame);\n resolve();\n });\n });\n channel.removeHandler();\n const initFrame = decodeFrame(waiting.shift() as Record<string, unknown>, handleFor);\n if (!isInit(initFrame)) {\n throw new Error(\"serveRemoteActor: expected $init\");\n }\n\n const init = initFrame.$init;\n const stated = init.rootName;\n if (typeof stated === \"string\" && stated !== \"\") rootName = stated;\n const parentName = (init.parentName as string) ?? null;\n const parentIdName = (init.parentIdName as string) ?? null;\n const parentId = parentIdName ? Symbol.for(parentIdName) : null;\n const { parentName: _pn, parentIdName: _pid, ...initArgs } = init;\n\n const proc = await actor.spawn(initArgs as unknown as Args, {\n name: rootName,\n parentName,\n parentId,\n });\n\n // This side's own end of the connection is the process it just spawned: id 0\n // here, and on the other side the proxy that asked for it.\n table.bindRoot(proc);\n\n await proc.ready();\n\n // The root is a process that crossed this connection like any other, at the id this\n // side gave it. What it can be asked is announced, and what it holds and what it\n // says are said once the far side asks: the announced list is the whole surface, so a\n // name that was never on it can never be reached. A proxy on the other end asks for\n // the state and the messages it stands in for the moment it connects.\n streams.crossed(proc, table.rootId());\n streams.flush();\n\n // bridge channel input → actor\n function dispatch(raw: Record<string, unknown>): void {\n const frame = decodeFrame(raw, handleFor);\n // An answer is about the call waiting for it and not about a process: it names\n // the seq, and is settled before anything is looked up.\n if (calls.settle(frame)) return;\n const to = frameTo(frame);\n if (to === null) return;\n // A frame answers one of two questions. News about a process the far side holds\n // lands on the handle for it: what it holds, that it is over, what it can answer.\n // An ask of a process this side holds goes to wherever that process lives: a\n // message, control, a call, a tune.\n const news = table.farHandleFor(to);\n const mine = table.processFor(to);\n if (isRelease(frame)) {\n // A process of this side's own, let go of over there: nothing more is said about\n // it, and the id the far side knew it by is no longer this connection's. The\n // process itself runs on, and a later crossing numbers it afresh. Neither root is\n // let go of, so the table refuses both.\n if (mine !== undefined) {\n streams.stop(to);\n table.release(to);\n }\n return;\n }\n if (isTune(frame)) {\n // How much the far side is told about a process of this side's own is that\n // side's to ask, and this is where the asking lands: what it names is what\n // crosses from now on. An id this side does not hold has nothing to tune.\n if (mine !== undefined) {\n const kinds = tuneFrame(frame);\n if (kinds !== null) streams.tune(to, kinds);\n }\n return;\n }\n if (isReflectionMethods(frame)) {\n // What a process the far side holds can answer, said the moment it crossed:\n // the handle here reads it as its own surface, so a name asked on it is asked\n // there. What a process of this side's own can answer is this side's to\n // announce, not the far side's to tell it.\n if (isRemoteProcess(news)) {\n news.receiveMethods(frame[REFLECT_METHODS], (method, args) => calls.call(method, args, to));\n }\n return;\n }\n if (isState(frame)) {\n // A process the far side holds, saying what it holds: that is news for the\n // handle on it, and lands where a subscription can see it. A state frame about\n // a process of this side's own is this side's to publish, not the far side's to\n // tell it.\n if (isRemoteProcess(news)) news.receiveState(frame.$state);\n return;\n }\n if (isExit(frame)) {\n // A process the far side holds, gone. Nothing more will be said about it, so\n // this is the last thing a handle can be told.\n if (isRemoteProcess(news)) news.receiveExit(frame.$exit);\n return;\n }\n if (isStop(frame) || isPause(frame) || isResume(frame)) {\n // Control, addressed to the process it is about: acted on by whoever holds that\n // process, which is this side. The root is one of those — stopping it stops\n // what the connection is for — and a handle has nothing here to act on.\n if (isProcess(mine)) {\n const sender = makeSender(rootName, parentName, parentId);\n if (isStop(frame)) void mine.stop({ from: sender });\n else if (isPause(frame)) mine.pause();\n else mine.resume();\n }\n return;\n }\n if (isMsg(frame)) {\n const { fromName, body } = frame.$msg;\n // A message for a process this side holds goes into it, the root included. One\n // about a process the far side holds — a handle here — is that process talking,\n // and goes to whoever subscribed to the handle.\n if (isProcess(mine)) mine.send(body as InMsg, makeSender(fromName, parentName, parentId));\n else if (isRemoteProcess(news)) news.receiveMessage(body as OutMsg, fromName);\n return;\n }\n const call = asReflectionCall(frame);\n if (call) void answerCall(call, mine, write, table);\n }\n\n channel.removeHandler();\n channel.onMessage(dispatch);\n for (const frame of waiting.splice(0)) dispatch(frame);\n\n // await actor exit, announce it, close\n let code = 0;\n try {\n await proc.wait();\n } catch (err) {\n console.error(\"server actor error:\", err);\n code = 1;\n }\n // The root is over, which is the last thing said about it. It is said and awaited\n // here, because the wire closes right after it.\n await streams.sayEnded(table.rootId(), code);\n // And nothing more about anything else of this side's: there is no one left to say\n // it to.\n streams.stopAll();\n // A call this side made and the far side has not answered is not going to be\n // answered now; it fails here rather than hanging.\n calls.rejectAll();\n await channel.close();\n}\n","// ── Client side of the seam ────────────────────────────────────────────────\n//\n// remoteClient builds a posipaki actor that talks to a remote server through a\n// frame Channel produced by a spawner. It knows only the frame vocabulary\n// (channel.ts) — no protocol, no transport, no spawner. The spawner has\n// already done the $proto handshake.\n\nimport { defineActor } from \"../define-actor.js\";\nimport { isProcess } from \"../process.async.js\";\nimport { stopPropagation } from \"../hooks.js\";\nimport type { HookResult } from \"../hooks.js\";\nimport type { ActorDefinition, HandlerOptions, MethodOptions, ReflectionOptions } from \"../actor-types.js\";\nimport type { Message } from \"../types.js\";\nimport type { Channel } from \"./channel.js\";\nimport {\n ProcessTable,\n SERVED_ROOT_NAME,\n isRemoteProcess,\n type ProcessHandle,\n type ProcessRef,\n} from \"./process-ref.js\";\nimport { ProcessStreams } from \"./process-streams.js\";\nimport { RemoteProcess, type FrameSink } from \"./remote-process.js\";\nimport { makeSender } from \"./sender.js\";\nimport {\n REFLECT_METHODS,\n asReflectionCall,\n decodeFrame,\n encodeFrame,\n frameTo,\n isExit,\n isMsg,\n isPause,\n isRelease,\n isResume,\n isStop,\n isReflectionMethods,\n isState,\n isTune,\n tuneFrame,\n} from \"./channel.js\";\nimport { CallSide, answerCall } from \"./call-side.js\";\n\nexport type ClientSpawner<Args> = (args: Args) => Promise<Channel>;\n\n\nexport function remoteClient<\n Args,\n State,\n InMsg extends Message,\n OutMsg extends Message,\n Methods extends MethodOptions = MethodOptions,\n Handlers extends HandlerOptions<InMsg> = HandlerOptions<InMsg>,\n R extends ReflectionOptions = ReflectionOptions,\n>(\n name: string,\n spawner: ClientSpawner<Args>,\n): ActorDefinition<Args, State, InMsg, OutMsg, R> {\n const proxyDef = defineActor<\n Args,\n {\n public: State;\n private: {\n channel: Channel;\n farRoot: RemoteProcess<InMsg, OutMsg>;\n exitPromise: Promise<{ code: number | null; state: State }>;\n };\n },\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n R\n >({\n name,\n handlers: {} as unknown as Handlers,\n async setup(args: Args) {\n // This side's own end of the connection is the root, and id 0 is how both\n // sides name it: the far actor on one end, this proxy on the other. The\n // table takes the odd ids for the processes this side holds — the far side\n // takes the even ones — so an id says on its own which side holds it.\n // A process this side hands over is numbered by the table, and from then on\n // the far side is told what it says: the stream follows the frame that\n // carried the reference.\n const table = new ProcessTable(\"odd\", (proc, id) => streams.crossed(proc, id));\n const root = this.ctx;\n table.bindRoot(root);\n const channel = await spawner(args);\n // What this side calls the process it serves: the full name, not the short one the\n // definition was written with. A process is called here what it is called on the side\n // that forked it, and the far side spells its own subtree off whatever it is told, so a\n // short name would be a second spelling of one process — and the tree would show both.\n const fromName = this.ctx.pname;\n // And the process above it, which is who a message to the served root comes from: the\n // far side is told the same thing a child here is told about its parent.\n const parentName = this.ctx.parentName ?? this.ctx.pname;\n // Everything is in place to speak: the sink writes to the wire, and what the\n // table numbers crosses through it. The sink is reached by a call rather\n // than handed over, because what it does is flush these streams.\n const streams = new ProcessStreams((frame, to) => sendTo(frame, to), table.rootId());\n\n /** Put an encoded frame on the wire, and then say what it numbered. A frame that\n * carried a reference has to be out first, or the far side hears about a process\n * it cannot name yet. */\n const write = (frame: Record<string, unknown>): Promise<void> =>\n Promise.resolve(channel.send(frame)).then(() => streams.flush());\n\n /** Every frame leaves this way: the processes in it become references, and\n * what the frame is addressed to becomes the id the far side knows. */\n const sendTo: FrameSink = (frame, to) => {\n void write(encodeFrame(frame, table, to)).catch((error: unknown) => {\n console.error(\"Error sending out the frame\", error);\n });\n };\n sendTo(\n {\n $init: {\n ...(args as unknown as Record<string, unknown>),\n // Under what name the far side serves is this side's to state: it is serving the\n // process this proxy stands in for, which is the one named here.\n rootName: fromName,\n parentName,\n parentIdName: parentName,\n },\n },\n table.farRootId(),\n );\n\n let currentState: Record<string, unknown> = {};\n\n // ── the call side ──────────────────────────────────────────────────\n // This side both makes calls and answers them, and so does the other end of\n // every connection: what a call is, and how an answer finds the one waiting\n // for it, is written once in call-side.ts.\n const calls = new CallSide(write, table);\n\n /**\n * The handle for a reference that arrived. A process handed over twice is one\n * process, so a reference that names one this side already knows gives back the\n * handle it gave last time, and one that names a process of this side's own —\n * handed back to its owner — gives back that process.\n *\n * The roots are numbered apart, so the numbers say what belongs to whom: 1 is this\n * side's own end, and 0 is the far side's root, which is a handle like any of the\n * processes they hold.\n */\n const handleFor = (ref: ProcessRef): ProcessHandle => {\n const held = table.processFor(ref.id);\n if (held) return held;\n const known = table.farHandleFor(ref.id);\n if (isRemoteProcess(known)) return known;\n const handle = new RemoteProcess(ref, sendTo, fromName, (id) => table.release(id));\n table.bindFar(ref.id, handle);\n return handle;\n };\n\n /**\n * The far side's root, which is what this proxy stands in for. It is bound here\n * like any other reference the far side sends: what it holds, what it says, when\n * it is over and what it can answer reach it as they reach any handle.\n */\n const farRoot = new RemoteProcess<InMsg, OutMsg>(\n { id: table.farRootId(), pname: fromName },\n sendTo,\n fromName,\n (id) => table.release(id),\n );\n table.bindFar(table.farRootId(), farRoot);\n\n // Setup is done when the far side has said what it holds; until then the\n // one handler below is what takes everything that arrives, so nothing\n // falls between two of them.\n let started: (() => void) | null = null;\n const start = new Promise<void>((resolve) => {\n started = resolve;\n });\n\n // All three in one asking, since this proxy stands in for the far root: what it\n // holds is this proxy's state, what it says is what this proxy says, and its end\n // is the end of the connection. A process says nothing until something asks, and\n // the root is no exception.\n farRoot.tune([\"message\", \"state\", \"exit\"]);\n farRoot.subscribe(\"state\", () => {\n // One object, updated the way the far side publishes it: the proxy's state is\n // the far root's, and a caller here reads it as `proc.state`.\n Object.assign(currentState, farRoot.state ?? {});\n root.notify();\n started?.();\n started = null;\n });\n farRoot.subscribe(\"message\", (msg) => {\n void this.emit(msg as OutMsg);\n });\n const exitPromise: Promise<{ code: number | null; state: State }> = farRoot.wait().then(\n (exit) => ({ code: exit.code, state: exit.state as State }),\n // The wire went before the far root did: what is known here is that it is over,\n // and the state last heard is the last word there is.\n () => ({ code: null, state: currentState as State }),\n );\n\n channel.onMessage((raw) => {\n const frame = decodeFrame(raw, handleFor);\n // An answer is about the call waiting for it and not about a process: it names\n // the seq, and is settled before anything is looked up.\n if (calls.settle(frame)) return;\n const to = frameTo(frame);\n if (to === null) return;\n // A frame answers one of two questions. News about a process the far side holds\n // lands on the handle for it: what it holds, what it says, that it is over, what\n // it can answer. An ask of a process this side holds goes to wherever that\n // process lives: a message, control, a call, a tune.\n const news = table.farHandleFor(to);\n const mine = table.processFor(to);\n if (isRelease(frame)) {\n // A process of this side's own, let go of over there: nothing more is said\n // about it, and the id is no longer this connection's. The process itself\n // runs on. Neither root is let go of, so the table refuses both.\n if (mine !== undefined) {\n streams.stop(to);\n table.release(to);\n }\n return;\n }\n if (isReflectionMethods(frame)) {\n // What the far side holds can answer, and how this side asks it: what was\n // announced is the whole surface, so a name never announced is never called\n // here either. The far root's names go on this proxy's own surface as well,\n // since the proxy is the process a caller here holds.\n if (isRemoteProcess(news)) {\n news.receiveMethods(frame[REFLECT_METHODS], (method, callArgs) =>\n calls.call(method, callArgs, to),\n );\n if (to === table.farRootId()) {\n calls.install(\n this.reflection as unknown as Record<string, unknown>,\n frame[REFLECT_METHODS],\n table.farRootId(),\n );\n }\n }\n return;\n }\n if (isState(frame)) {\n // A process the far side holds, saying what it holds: news for whoever\n // subscribed to the handle.\n if (isRemoteProcess(news)) news.receiveState(frame.$state);\n return;\n }\n if (isExit(frame)) {\n // A process the far side holds, gone: nothing more will be said about it.\n if (isRemoteProcess(news)) news.receiveExit(frame.$exit);\n return;\n }\n if (isMsg(frame)) {\n // A message naming a process this side holds goes into it, the proxy's own\n // root included, and the wire says who sent it by name alone. One about a\n // process the far side holds is that process talking, and goes to whoever\n // subscribed to the handle.\n if (isProcess(mine)) {\n mine.send(frame.$msg.body as InMsg, makeSender(frame.$msg.fromName, null, null));\n } else if (isRemoteProcess(news)) {\n news.receiveMessage(frame.$msg.body as OutMsg, frame.$msg.fromName);\n }\n return;\n }\n if (isTune(frame)) {\n // How much the far side hears about a process of this side's own is its to\n // ask, and this is where the asking lands.\n if (mine !== undefined) {\n const kinds = tuneFrame(frame);\n if (kinds !== null) streams.tune(to, kinds);\n }\n return;\n }\n if (isStop(frame) || isPause(frame) || isResume(frame)) {\n // Control, addressed to the process it is about, and acted on by whoever holds\n // it, which is this side. Its own root is one of those. A handle has nothing\n // here to act on.\n if (isProcess(mine)) {\n if (isStop(frame)) void mine.stop({ from: makeSender(fromName, null, null) });\n else if (isPause(frame)) mine.pause();\n else mine.resume();\n }\n return;\n }\n // A call into a process of this side's own, made from over there: the method is\n // this side's to run, and the answer goes back by name and seq.\n const call = asReflectionCall(frame);\n if (call) void answerCall(call, mine, write, table);\n });\n channel.onClose(() => {\n // A call that was in flight when the wire went away has no answer\n // coming; it fails here rather than hanging forever.\n calls.rejectAll();\n // Handles live on this connection: with it gone there is nothing to\n // reach, and nothing to wait for either.\n for (const held of table.handles()) {\n if (isRemoteProcess(held)) held.disconnect();\n }\n // And nothing more is said about the processes of this side's own that\n // were handed over: there is no one left to say it to.\n streams.stopAll();\n // A wire that goes before the far root does leaves nothing to wait for: the\n // handles are gone, and the far root's end is the connection's end, which is\n // what `wait()` on it rejects about.\n });\n\n await start;\n\n return {\n public: currentState as State,\n private: { channel, farRoot, exitPromise },\n };\n\n },\n async onMessage(msg: InMsg): Promise<HookResult> {\n const { farRoot } = this.state.private;\n // A message this side sends is for the root: that is the process the proxy stands\n // for, and it is sent the way any handle sends to a process of the far side's.\n if (farRoot.isConnected()) farRoot.send(msg);\n return stopPropagation();\n },\n async onStopRequested() {\n const { channel, farRoot, exitPromise } = this.state.private;\n if (channel) {\n // Asking the far root to stop is asking a process, not sending it a message:\n // the control frame its holder acts on, the one every other handle uses. Worth\n // asking only while there is something to ask of it — an end that has come, or\n // a wire that has gone, leaves nothing to ask and nothing to wait for.\n if (farRoot.isConnected() && !farRoot.hasEnded()) {\n void farRoot.stop().catch(() => undefined);\n }\n await exitPromise;\n }\n this.agreeToStop();\n },\n async afterEnd() {\n if (this.state.private.channel) {\n await this.state.private.channel.close();\n }\n },\n });\n\n return proxyDef as unknown as ActorDefinition<Args, State, InMsg, OutMsg, R>;\n}\n","// ── json1 wire protocol ────────────────────────────────────────────────────\n//\n// One JSON object per frame: `{\"$key\": value}`. encode/decode turn a decoded\n// frame object into a string and back. json1Channel wraps a StringTransport so\n// it moves frame objects instead of strings.\n\nimport type { Channel, StringTransport } from \"../channel.js\";\n\nexport const VERSION = \"json.v1\";\n\nexport function encode(frame: Record<string, unknown>): string {\n return JSON.stringify(frame);\n}\n\nexport function decode(str: string): Record<string, unknown> {\n return JSON.parse(str);\n}\n\nexport function json1Channel(transport: StringTransport): Channel {\n return {\n send(frame) {\n return transport.send(encode(frame));\n },\n onMessage(handler) {\n transport.onMessage((str) => handler(decode(str)));\n },\n removeHandler() {\n transport.removeHandler();\n },\n onClose(handler) {\n transport.onClose(handler);\n },\n close() {\n return transport.close();\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/remote/remote-process.ts","../../src/remote/process-ref.ts","../../src/remote/server.ts","../../src/remote/sender.ts","../../src/remote/protocols/json1.ts","../../src/remote/transports/websocket.ts","../../src/remote/transports/worker.ts","../../src/remote/spawners/ws-client.ts","../../src/remote/spawners/ws-server.ts","../../src/remote/spawners/worker-client.ts","../../src/remote/spawners/worker-self.ts"],"mappings":";;;;;UAmBiB;EACf;EACA;;;;;KAMU,aAAa,OAAO,yBAAyB,sBAAsB;;;KAInE,eAAe;;KAGf,cAAc,eAAe,UAAU,YAAY,KAAK,QAAQ;cAE/D,cAAc,cAAc,UAAU,SAAS,eAAe,UAAU;;WAE1E;;;WAGA,KAAK;;;WAGL;;EAET,OAAO;;WAEE,aAAa,mBAAmB,oBAAoB;UAErD;UACA;UACA;;;;UAIA;UACA;;UAEA;UACA;UACA;UACA;;;;;UAKA;EAER,YAAY,KAAK,YAAY,MAAM,WAAW,kBAAkB,QAAQ;;;;;;;;;;;EAmBxE;;;;;;EASA;;EASA;;;;UAOQ;UAOA;;;;;;;;;EAaR,QAAQ,QAAQ;;;;;;EAgBhB,QAAQ;;;;;;;EAgBR;;EAQA;;EAMA;;;;;;;;;;;EAeA,KAAK,OAAO;;;;UAQJ;;;;UAYA;;EAOR,KAAK,KAAK;;;;;EASV,UAAU,oBAAoB,IAAI,cAAc;EAChD,UAAU,kBAAkB;UAcpB;;EAUR,aAAa,OAAO;;EAOpB,eAAe,KAAK,QAAQ;;;;EAQ5B,YAAY,MAAM;;;;EASlB,eAAe,iBAAiB,OAAO,cAAc,oBAAoB;;;;;cC3P9D;;;;;;;iBAQG,UAAU,QAAQ;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/remote/remote-process.ts","../../src/remote/process-ref.ts","../../src/remote/server.ts","../../src/remote/sender.ts","../../src/remote/protocols/json1.ts","../../src/remote/transports/websocket.ts","../../src/remote/transports/worker.ts","../../src/remote/spawners/ws-client.ts","../../src/remote/spawners/ws-server.ts","../../src/remote/spawners/worker-client.ts","../../src/remote/spawners/worker-self.ts"],"mappings":";;;;;UAmBiB;EACf;EACA;;;;;KAMU,aAAa,OAAO,yBAAyB,sBAAsB;;;KAInE,eAAe;;KAGf,cAAc,eAAe,UAAU,YAAY,KAAK,QAAQ;cAE/D,cAAc,cAAc,UAAU,SAAS,eAAe,UAAU;;WAE1E;;;WAGA,KAAK;;;WAGL;;EAET,OAAO;;WAEE,aAAa,mBAAmB,oBAAoB;UAErD;UACA;UACA;;;;UAIA;UACA;;UAEA;UACA;UACA;UACA;;;;;UAKA;EAER,YAAY,KAAK,YAAY,MAAM,WAAW,kBAAkB,QAAQ;;;;;;;;;;;EAmBxE;;;;;;EASA;;EASA;;;;UAOQ;UAOA;;;;;;;;;EAaR,QAAQ,QAAQ;;;;;;EAgBhB,QAAQ;;;;;;;EAgBR;;EAQA;;EAMA;;;;;;;;;;;EAeA,KAAK,OAAO;;;;UAQJ;;;;UAYA;;EAOR,KAAK,KAAK;;;;;EASV,UAAU,oBAAoB,IAAI,cAAc;EAChD,UAAU,kBAAkB;UAcpB;;EAUR,aAAa,OAAO;;EAOpB,eAAe,KAAK,QAAQ;;;;EAQ5B,YAAY,MAAM;;;;EASlB,eAAe,iBAAiB,OAAO,cAAc,oBAAoB;;;;;cC3P9D;;;;;;;iBAQG,UAAU,QAAQ;;UAWjB;EACf;EACA;;;;KAYU;;;;iBAoJI,gBAAgB,iBAAiB,SAAS;;;KCzK9C,gBAAgB,QAAQ;iBASd,iBACpB,MACA,OACA,cAAc,SACd,eAAe,SACf,UAAU,mBACV,OAAO,gBAAgB,MAAM,OAAO,OAAO,QAAQ,IAAI,SAAS,UAAU;;;iBC7C5D,WACd,kBACA,2BACA,0BACC;;;cCNU;iBAEG,OAAO,OAAO;iBAId,OAAO,cAAc;iBAIrB,aAAa,WAAW,kBAAkB;;;;;;;;UCJzC;EACf,KAAK;EACL,MAAM,eAAe;WACZ;EACT,aAAa;IAAS;;EACtB;;;cAIW;cAEA,8BAA8B;UACjC;UACA;UACA;UACA;EAER,YAAY,IAAI;MAWZ;EAIJ,UAAU,UAAU;EAQpB,mBAAmB;EAMnB,QAAQ;MAIJ;EAIE,KAAK,gBAAgB;EAMrB,SAAS;;;;;cC/DJ;;;;;;UAOI;EACf,YAAY;EACZ,aAAa;IAAS;;EACtB,YAAY;EACZ;;cAGW,2BAA2B;UAC9B;UACA;UACA;UACA;EAER,YAAY,QAAQ;MAgBhB;EAIJ,UAAU,UAAU,OAAO;EAQ3B,mBAAmB,OAAO;EAM1B,QAAQ;MAIJ;EAIE,KAAK,OAAO,0BAA0B;EAKtC,SAAS;;;;KClEL,qBAAqB;WACtB;EACT,KAAK;EACL,MAAM,eAAe;EACrB;EACA,WAAW;EACX,aAAa;IAAS;;EACtB;;iBAac,gBAAgB,gBAC9B,gBAAgB,MAAM,kBACtB,gBAAe,gBACd,cAAc;;;iBCzBD,gBAAgB,IAAI,gBAAgB;;;;;;;UAcnC;EACf,KAAK;EACL,MAAM,eAAe;WACZ;EACT;;;;;;;;;;;;;;;;;;;;;iBAsBc,mBAAmB,IAAI,yBAAyB;;;KCxCpD,kBAAkB,gBAAgB;iBAI9B,oBAAoB,gBAClC,gBAAgB,MAAM,kBACtB,aAAY,aACX,cAAc;;;iBCRD,kBAAkB,YAAW,aAAmD"}
|
package/dist/remote/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as isStop, a as remoteClient, b as rootIdFor, c as RemoteProcess, d as isMsg, f as isPause, g as isState, h as isResume, i as json1Channel, l as isExit, m as isRelease, n as decode, o as serveRemoteActor, p as isProto, r as encode, s as makeSender, t as VERSION, u as isInit, v as PROCESS_REF, y as isRemoteProcess } from "../json1-
|
|
1
|
+
import { _ as isStop, a as remoteClient, b as rootIdFor, c as RemoteProcess, d as isMsg, f as isPause, g as isState, h as isResume, i as json1Channel, l as isExit, m as isRelease, n as decode, o as serveRemoteActor, p as isProto, r as encode, s as makeSender, t as VERSION, u as isInit, v as PROCESS_REF, y as isRemoteProcess } from "../json1-DYq9g7im.js";
|
|
2
2
|
//#region src/remote/transports/websocket.ts
|
|
3
3
|
/** WHATWG WebSocket readyState: OPEN. */
|
|
4
4
|
const WS_OPEN = 1;
|
package/dist/remote/node.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as LIB_VERSION } from "../version-
|
|
2
|
-
import { a as remoteClient, i as json1Channel, o as serveRemoteActor, p as isProto, t as VERSION } from "../json1-
|
|
1
|
+
import { t as LIB_VERSION } from "../version-98a9sol-.js";
|
|
2
|
+
import { a as remoteClient, i as json1Channel, o as serveRemoteActor, p as isProto, t as VERSION } from "../json1-DYq9g7im.js";
|
|
3
3
|
import { mkdtemp, open, readFile, rm, unlink } from "node:fs/promises";
|
|
4
4
|
import * as readline from "node:readline";
|
|
5
5
|
import { execFile, execSync, spawn } from "node:child_process";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/version.ts
|
|
2
2
|
/** posipaki's release version. Must equal package.json's `version`. */
|
|
3
|
-
const LIB_VERSION = "0.37.
|
|
3
|
+
const LIB_VERSION = "0.37.1";
|
|
4
4
|
//#endregion
|
|
5
5
|
export { LIB_VERSION as t };
|
|
6
6
|
|
|
7
|
-
//# sourceMappingURL=version-
|
|
7
|
+
//# sourceMappingURL=version-98a9sol-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-
|
|
1
|
+
{"version":3,"file":"version-98a9sol-.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["// ── Library identity ───────────────────────────────────────────────────────\n//\n// posipaki's own release version, as a plain inlined string. A consumer that\n// stages artifacts onto a host it knows nothing about has to name those\n// artifacts after which posipaki they speak, and the bundle that runs there has\n// no node_modules and no posipaki on disk — it can never read a file to find out.\n//\n// It is not the protocol version: that is `VERSION` in ./remote (`json.v1`), and\n// it does not move between releases. The two answer different questions.\n//\n// version.test.ts pins this to package.json, so a release that forgets to bump it\n// fails the suite rather than shipping a lie.\n\n/** posipaki's release version. Must equal package.json's `version`. */\nexport const LIB_VERSION = \"0.37.1\";\n"],"mappings":";;AAcA,MAAa,cAAc"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"json1-CWWXL69y.js","names":[],"sources":["../src/remote/process-ref.ts","../src/remote/channel.ts","../src/remote/remote-process.ts","../src/remote/process-streams.ts","../src/remote/sender.ts","../src/remote/call-side.ts","../src/remote/server.ts","../src/remote/client.ts","../src/remote/protocols/json1.ts"],"sourcesContent":["// ── Process references on the wire ─────────────────────────────────────────\n//\n// A process is not JSON: it holds state, children and methods. So a reflection\n// method that returns one cannot answer with the process itself — it answers\n// with a reference, and the caller is handed what it can read: a name, and an id\n// this connection uses for that process.\n//\n// The id belongs to the connection and to the side that holds the process: that\n// side allocates it, and both sides then know the process by it. Allocated once\n// per process — handed over twice, it is the same reference both times — and\n// never reused, so an id whose process is gone resolves to nothing rather than to\n// whatever came after it.\n//\n// The two sides allocate from one space, split by parity: the client takes the\n// odd ids, the server the even ones. Every connection also has a root, and a root is\n// numbered like anything else — the first id of the parity of the side that holds it:\n// 0 on the even side (the server), 1 on the odd one (the client). So an id says on\n// its own which side holds the process it names, the two roots included, and a frame's\n// address means the same thing whoever reads it.\n//\n// A side's own root is the process the connection is, and the far side's root is a\n// handle here like any of theirs. Neither end has to be told which number belongs to\n// whom: each root is the first id of its own parity.\n\nimport { isProcess } from \"../process.async.js\";\nimport type { RemoteProcess } from \"./remote-process.js\";\n\n/** The key that marks a process reference inside an otherwise JSON value. */\nexport const PROCESS_REF = \"$p\";\n\n/**\n * The id a side gives its own root: the first id of its parity. The two ends of a\n * connection therefore number their roots differently, and an id says whose root it is\n * as it says who holds every other process. A side hands out its next id from two\n * steps further on, the one in between belonging to the root of the side it talks to.\n */\nexport function rootIdFor(parity: IdParity): number {\n return parity === \"odd\" ? 1 : 0;\n}\n\n/** The name a served root is spawned under: what a visitor's handle on the far root\n * is called, since no frame about a root carries a name of its own. */\nexport const SERVED_ROOT_NAME = \"remote\";\n\n/** What crosses the wire in place of a process. */\nexport interface ProcessRef {\n id: number;\n pname: string;\n}\n\n/** The little a table needs of what it holds to name it: what it is called, and\n * the symbol that identifies it in this build. */\nexport interface ProcessHandle {\n readonly pname: string;\n readonly id: symbol;\n}\n\n/** Which ids a side hands out: the client takes the odd ones, the server the\n * even ones, so one number can never name a process on both sides at once. */\nexport type IdParity = \"odd\" | \"even\";\n\n/**\n * The processes one connection knows, by the ids that name them. One table per\n * connection, because an id means nothing on any other one, and it lives exactly\n * as long as the connection that owns it.\n *\n * It holds two sets, told apart by parity rather than kept apart by a rule: the\n * processes this side holds — the root, and anything it hands over — and the ones\n * the far side holds, which this side knows as handles. A frame's address is\n * looked up in both, and exactly one can answer.\n */\nexport class ProcessTable<P extends ProcessHandle = ProcessHandle> {\n /** This side's own processes, by the ids it gave them. */\n private pvtMine = new Map<number, P>();\n private pvtMineIds = new Map<P, number>();\n /** The far side's processes, by the ids they came with. */\n private pvtTheirs = new Map<number, P>();\n /** The id of this side's own root: the first of its parity. */\n private pvtRootId: number;\n /** The id the far side gave its root: the first of its parity, and the number this\n * side's own numbering skips. */\n private pvtFarRootId: number;\n /** The next id this side may hand out: its own parity, from two steps past its own\n * root, the one in between belonging to the far side's root. */\n private pvtNext: number;\n /** Told the first time a process is numbered — the moment it is about to\n * cross the connection. */\n private pvtOnCrossed: ((proc: P, id: number) => void) | undefined;\n\n constructor(parity: IdParity, onCrossed?: (proc: P, id: number) => void) {\n this.pvtRootId = rootIdFor(parity);\n this.pvtFarRootId = rootIdFor(parity === \"odd\" ? \"even\" : \"odd\");\n this.pvtNext = this.pvtRootId + 2;\n this.pvtOnCrossed = onCrossed;\n }\n\n /** The id of this side's own end of the connection. */\n rootId(): number {\n return this.pvtRootId;\n }\n\n /** The id the far side knows its own end by: the root this side reaches as a handle,\n * and the one it never hands out for anything of its own. */\n farRootId(): number {\n return this.pvtFarRootId;\n }\n\n /** Bind this side's own end of the connection — the root — to its id. */\n bindRoot(proc: P): void {\n const bound = this.pvtMine.get(this.pvtRootId);\n if (bound !== undefined && bound !== proc) {\n throw new Error(\"ProcessTable: the root is already bound\");\n }\n this.pvtMine.set(this.pvtRootId, proc);\n this.pvtMineIds.set(proc, this.pvtRootId);\n }\n\n /** The id this side gives a process it holds, allocating one the first time. */\n handleFor(proc: P): number {\n const known = this.pvtMineIds.get(proc);\n if (known !== undefined) return known;\n const id = this.pvtNext;\n this.pvtNext += 2;\n this.pvtMine.set(id, proc);\n this.pvtMineIds.set(proc, id);\n this.pvtOnCrossed?.(proc, id);\n return id;\n }\n\n /** A process this side holds, by the id it gave it. */\n processFor(id: number): P | undefined {\n return this.pvtMine.get(id);\n }\n\n /**\n * Register a process the far side holds — a handle — under the id it arrived\n * with. A root is one of these as much as anything else: both ends hold one at 0,\n * so the far side's root is a handle here, and the one this side has of itself\n * stays what it was.\n */\n bindFar(id: number, proc: P): void {\n this.pvtTheirs.set(id, proc);\n }\n\n /** A process the far side holds, by the id it gave it. */\n farHandleFor(id: number): P | undefined {\n return this.pvtTheirs.get(id);\n }\n\n /**\n * Whatever this connection knows `id` to mean: a process this side holds, or a\n * handle on one the far side holds. Only one of the two can answer, because\n * the two sides take their ids from different halves of the space — so what\n * comes back does not depend on which way the frame was going.\n */\n resolve(id: number): P | undefined {\n return this.pvtMine.get(id) ?? this.pvtTheirs.get(id);\n }\n\n /**\n * Let go of an id: the process behind it is not this connection's business any\n * more, so it is no longer known by it. Both sides' ids go the same way — the\n * side that lets a handle go names the far side's id, the side that is asked to\n * forget names its own — and an id let go is never handed out again, so nothing\n * that still names it can come to mean another process.\n *\n * Neither root is let go of: one is this side's own end of the connection, and the\n * other is what this side is talking to.\n */\n release(id: number): P | undefined {\n if (id === this.pvtRootId || id === this.pvtFarRootId) return undefined;\n const mine = this.pvtMine.get(id);\n if (mine !== undefined) {\n this.pvtMine.delete(id);\n this.pvtMineIds.delete(mine);\n return mine;\n }\n const theirs = this.pvtTheirs.get(id);\n if (theirs !== undefined) this.pvtTheirs.delete(id);\n return theirs;\n }\n\n /** Every handle this side holds on a process of the far side. */\n handles(): P[] {\n return [...this.pvtTheirs.values()];\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto = Object.getPrototypeOf(value) as object | null;\n return proto === Object.prototype || proto === null;\n}\n\n/** Whether `value` is the wire form of a reference. */\nexport function asProcessRef(value: unknown): ProcessRef | null {\n if (typeof value !== \"object\" || value === null) return null;\n const ref = (value as Record<string, unknown>)[PROCESS_REF];\n if (typeof ref !== \"object\" || ref === null) return null;\n const { id, pname } = ref as Record<string, unknown>;\n if (typeof id !== \"number\" || typeof pname !== \"string\") return null;\n return { id, pname };\n}\n\n/** Whether `value` has the shape of a handle on a far-side process. Judged by\n * what it holds rather than by `instanceof`, for the reason a process is: one\n * build can hold two copies of the class. */\nexport function isRemoteProcess(value: unknown): value is RemoteProcess {\n if (typeof value !== \"object\" || value === null) return false;\n const candidate = value as { pname?: unknown; id?: unknown; ref?: unknown; send?: unknown };\n return (\n typeof candidate.pname === \"string\" &&\n typeof candidate.id === \"symbol\" &&\n typeof candidate.send === \"function\" &&\n asProcessRef({ [PROCESS_REF]: candidate.ref }) !== null\n );\n}\n\n/**\n * Replace every process in `value` with the reference this connection uses for\n * it, so what is left is JSON that says which processes the answer is about.\n *\n * A handle goes back as the reference it came with, id and all: that id is the\n * far side's own, the one it will be read by.\n *\n * Containers are copied rather than rewritten: the objects belong to the actor\n * that returned them, and a state it is still running on is not ours to edit. A\n * node already seen is left where it is — a cycle is the encoder's to report, not\n * something to walk forever.\n */\nexport function encodeProcessRefs(\n value: unknown,\n table: ProcessTable,\n seen: Set<unknown> = new Set(),\n): unknown {\n if (isRemoteProcess(value)) {\n return { [PROCESS_REF]: { id: value.ref.id, pname: value.ref.pname } };\n }\n if (isProcess(value)) {\n return { [PROCESS_REF]: { id: table.handleFor(value), pname: value.pname } };\n }\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n return value.map((item) => encodeProcessRefs(item, table, seen));\n }\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const copy: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n copy[key] = encodeProcessRefs(item, table, seen);\n }\n return copy;\n }\n return value;\n}\n\n/** How a side turns a reference into something it can hold: a handle. */\nexport type RefResolver = (ref: ProcessRef) => unknown;\n\n/** Replace every reference in `value` with what `resolve` makes of it. */\nexport function decodeProcessRefs(\n value: unknown,\n resolve: RefResolver,\n seen: Set<unknown> = new Set(),\n): unknown {\n const ref = asProcessRef(value);\n if (ref) return resolve(ref);\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n return value.map((item) => decodeProcessRefs(item, resolve, seen));\n }\n if (isPlainObject(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n const copy: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n copy[key] = decodeProcessRefs(item, resolve, seen);\n }\n return copy;\n }\n return value;\n}\n","// ── Frame channel ──────────────────────────────────────────────────────────\n//\n// The seam's shared vocabulary. A StringTransport moves encoded frames\n// (strings); a Channel moves decoded frame objects. The frame guards narrow a\n// decoded frame to one of the `$`-key shapes. server.ts / client.ts speak only\n// in Channels and these guards — they never see a specific protocol or\n// transport.\n\nimport type { Message } from \"../types.js\";\nimport {\n decodeProcessRefs,\n encodeProcessRefs,\n type ProcessTable,\n type RefResolver,\n} from \"./process-ref.js\";\n\nexport interface StringTransport {\n send(frame: string): void | Promise<void>;\n onMessage(handler: (frame: string) => void): void;\n removeHandler(): void;\n /** Fires when the peer disconnects (transport closes from the other side). */\n onClose(handler: () => void): void;\n close(): Promise<void>;\n}\n\nexport interface Channel {\n send(frame: Record<string, unknown>): void | Promise<void>;\n onMessage(handler: (frame: Record<string, unknown>) => void): void;\n removeHandler(): void;\n /** Fires when the peer disconnects (transport closes from the other side). */\n onClose(handler: () => void): void;\n close(): Promise<void>;\n}\n\n// ── the address on a frame ─────────────────────────────────────────────────\n//\n// A frame that is about a process carries that process's id as `to`, at the top level\n// of the frame rather than inside its body: the frame is the envelope, and the address\n// says who it is for whatever kind it turns out to be. Every frame that is about a\n// process names it, the root of the connection included, since both ends number their\n// own root and neither has to be guessed at.\n\n/** The id a frame addresses, or null when it names no process. */\nexport function frameTo(frame: Record<string, unknown>): number | null {\n const to = frame.to;\n return typeof to === \"number\" ? to : null;\n}\n\n/**\n * A frame on its way out: every process in it becomes the reference this\n * connection uses for that process, and the process the frame addresses is\n * written down as `to`.\n */\nexport function encodeFrame(\n frame: Record<string, unknown>,\n table: ProcessTable,\n to: number,\n): Record<string, unknown> {\n const encoded = encodeProcessRefs(frame, table) as Record<string, unknown>;\n return { ...encoded, to };\n}\n\n/**\n * A frame just read: every reference in it becomes a handle on that process — or\n * the handle this side already made for it, since the same process handed over\n * twice is one process.\n */\nexport function decodeFrame(\n frame: Record<string, unknown>,\n resolve: RefResolver,\n): Record<string, unknown> {\n return decodeProcessRefs(frame, resolve) as Record<string, unknown>;\n}\n\n// ── frame guards ──────────────────────────────────────────────────────────\n\nexport function isProto(msg: Record<string, unknown>): msg is { $proto: string } {\n return \"$proto\" in msg;\n}\nexport function isInit(msg: Record<string, unknown>): msg is { $init: Record<string, unknown> } {\n return \"$init\" in msg;\n}\nexport function isState(msg: Record<string, unknown>): msg is { $state: Record<string, unknown> } {\n return \"$state\" in msg;\n}\nexport function isMsg(\n msg: Record<string, unknown>,\n): msg is { $msg: { fromName: string; body: Message } } {\n return \"$msg\" in msg;\n}\nexport function isExit(\n msg: Record<string, unknown>,\n): msg is { $exit: { code: number; state: unknown } } {\n return \"$exit\" in msg;\n}\n\n// ── what is said about a crossed process ────────────────────────────────────\n//\n// A process that crossed can be asked for less than everything, or for nothing at\n// all: what crosses about it is three categories, and only the ones asked for are\n// sent. Silence is the empty list, so a handle that asks for nothing hears\n// nothing — not its state, not its messages, and not that it is gone.\n//\n// {\"$tune\": {\"streams\": [\"state\"]}, \"to\": 3} this much about it, and no more\n\nexport type StreamKind = \"message\" | \"state\" | \"exit\";\n\n/** The three, in the one order they are ever named in — the order a tune frame\n * carries them in, so two ways of asking for the same thing look the same. */\nexport const STREAM_KINDS: StreamKind[] = [\"message\", \"state\", \"exit\"];\n\nexport function isStreamKind(value: unknown): value is StreamKind {\n return typeof value === \"string\" && (STREAM_KINDS as string[]).includes(value);\n}\n\n// ── control frames ─────────────────────────────────────────────────────────\n//\n// What the holder of a handle can ask of a process on the far side, beside\n// sending it a message. Each is a frame of its own rather than a message, so\n// nothing an actor reads is ever a control signal by accident:\n//\n// {\"$stop\": {}, \"to\": 3} stop it; it ends, and its `$exit` crosses back\n// {\"$pause\": {}, \"to\": 3} stop feeding it messages\n// {\"$resume\": {}, \"to\": 3} feed it again\n// {\"$release\": {}, \"to\": 3} let it go: forget this id, and stop telling me\n// about the process behind it\n// {\"$tune\": {\"streams\": [...]}, \"to\": 3}\n// say this much about it and no more: a subset of\n// message, state and exit, or the empty list for\n// silence\n//\n// They address the process they are about, so they are answered by whoever holds\n// that process — the side that can act on it. Stopping the *root* of a connection\n// is not one of these: that stays the STOP message it always was, since the root\n// is not a handle but the process this side is talking through.\n\nexport function isStop(msg: Record<string, unknown>): msg is { $stop: Record<string, unknown> } {\n return \"$stop\" in msg;\n}\nexport function isPause(msg: Record<string, unknown>): msg is { $pause: Record<string, unknown> } {\n return \"$pause\" in msg;\n}\nexport function isResume(msg: Record<string, unknown>): msg is { $resume: Record<string, unknown> } {\n return \"$resume\" in msg;\n}\nexport function isRelease(msg: Record<string, unknown>): msg is { $release: Record<string, unknown> } {\n return \"$release\" in msg;\n}\n\nexport function isTune(msg: Record<string, unknown>): msg is { $tune: Record<string, unknown> } {\n return \"$tune\" in msg;\n}\n\n/**\n * The categories a tune frame asks for, in the order they are named in — or null\n * when the frame says something this vocabulary has no word for, which is a frame\n * to ignore rather than to guess at.\n */\nexport function tuneFrame(frame: { $tune: unknown }): StreamKind[] | null {\n const body = frame.$tune;\n if (typeof body !== \"object\" || body === null) return null;\n const streams = (body as { streams?: unknown }).streams;\n if (!Array.isArray(streams)) return null;\n if (!streams.every(isStreamKind)) return null;\n return STREAM_KINDS.filter((kind) => (streams as StreamKind[]).includes(kind));\n}\n\n// ── reflection frames ──────────────────────────────────────────────────────\n//\n// A reflection call crosses the seam as one frame and its answer as another, and\n// both go both ways: whoever holds a process is the one that answers for it.\n//\n// {\"$r.methods\": [\"inspect.getTree\", …]} what a process can answer, once, when\n// it crosses (and, for the root, once\n// when the connection opens)\n// {\"$r.call.<name>\": {seq, args}} asking, addressed to the process\n// {\"$r.result.<name>\": {seq, value}} answered\n// {\"$r.result.<name>\": {seq, error}} refused\n//\n// The method name is in the frame key, so a frame says what it is without a\n// table, and `seq` — one connection's, never reused — tells two calls to the\n// same method apart while both are in flight. An answer is about the call and not\n// about a process, so it carries no address: it names the seq it settles.\n\nexport const REFLECT_METHODS = \"$r.methods\";\nexport const REFLECT_CALL = \"$r.call.\";\nexport const REFLECT_RESULT = \"$r.result.\";\n\nexport interface ReflectionCall {\n name: string;\n seq: number;\n args: unknown[];\n}\n\nexport interface ReflectionResult {\n name: string;\n seq: number;\n value?: unknown;\n error?: string;\n}\n\nexport function isReflectionMethods(\n msg: Record<string, unknown>,\n): msg is { \"$r.methods\": string[] } {\n const names = msg[REFLECT_METHODS];\n return Array.isArray(names) && names.every((name) => typeof name === \"string\");\n}\n\nfunction reflectionBody(\n frame: Record<string, unknown>,\n prefix: string,\n): { name: string; body: Record<string, unknown> } | null {\n for (const key of Object.keys(frame)) {\n if (!key.startsWith(prefix) || key.length === prefix.length) continue;\n const body = frame[key];\n if (typeof body !== \"object\" || body === null) return null;\n return { name: key.slice(prefix.length), body: body as Record<string, unknown> };\n }\n return null;\n}\n\n/** A call frame, or null — a malformed one is not worth an answer. */\nexport function asReflectionCall(frame: Record<string, unknown>): ReflectionCall | null {\n const parsed = reflectionBody(frame, REFLECT_CALL);\n if (!parsed || typeof parsed.body.seq !== \"number\") return null;\n const args = parsed.body.args;\n return {\n name: parsed.name,\n seq: parsed.body.seq,\n args: Array.isArray(args) ? args : [],\n };\n}\n\n/** An answer frame, or null. `error` present means the call was refused. */\nexport function asReflectionResult(frame: Record<string, unknown>): ReflectionResult | null {\n const parsed = reflectionBody(frame, REFLECT_RESULT);\n if (!parsed || typeof parsed.body.seq !== \"number\") return null;\n const { seq, value, error } = parsed.body;\n return typeof error === \"string\"\n ? { name: parsed.name, seq, error }\n : { name: parsed.name, seq, value };\n}\n\n/**\n * Why a value cannot cross a frame, or null when it can. Only JSON data\n * crosses: a function, a symbol or a bigint cannot be written down at all, and\n * a value with a cycle or a bigint inside it makes the encoder throw. What\n * JSON itself would quietly drop — a function stored inside an object — is the\n * caller's business, not something to invent a policy for here.\n */\nexport function jsonProblem(value: unknown): string | null {\n const kind = typeof value;\n if (kind === \"function\" || kind === \"symbol\" || kind === \"bigint\") return `a ${kind}`;\n if (kind !== \"object\" || value === null) return null;\n try {\n JSON.stringify(value);\n } catch (err) {\n return err instanceof Error ? err.message : String(err);\n }\n return null;\n}\n","// ── A process on the far side, as this side can use it ─────────────────────\n//\n// A handle. It knows the name the far side calls the process and the id this\n// connection knows it by, and one thing more than a bare reference has: a way to\n// put a frame on the wire with that id. Everything else it offers is what comes\n// back because of it — the state that streams for it, the messages it emits, the\n// methods it announced.\n//\n// A handle is not a process of this side's tree. Nothing has to make it one:\n// the far side's tree is already reachable through reflection, so asking the\n// proxy for it walks that side and gives that tree. A handle is how something\n// on the far side is talked to, not where it sits here.\n\nimport type { Message } from \"../types.js\";\nimport { makeWaiter, type Waiter } from \"../util.js\";\nimport { STREAM_KINDS, type StreamKind } from \"./channel.js\";\nimport type { ProcessRef } from \"./process-ref.js\";\n\n/** What a process left behind when it ended. */\nexport interface RemoteExit {\n code: number;\n state: unknown;\n}\n\n/** How a handle gets a frame onto the connection it belongs to, addressed to a\n * process the far side holds. The answer is handed back when a caller has to know\n * the frame is out — the root's end is said that way, just before the wire closes. */\nexport type FrameSink = (frame: Record<string, unknown>, to: number) => void | Promise<void>;\n\n/** What a side does when it lets go of a handle: stop knowing the id, so nothing\n * arriving for it can land here again. */\nexport type ReleaseHook = (id: number) => void;\n\n/** An out-message of the far process, and the name it came with. */\nexport type RemoteMessage<OutMsg extends Message = Message> = (msg: OutMsg, fromName: string) => void;\n\nexport class RemoteProcess<InMsg extends Message = Message, OutMsg extends Message = Message> {\n /** The name the far side knows it by. */\n readonly pname: string;\n /** The id this connection knows it by — the far side's own, since it is the\n * side that holds the process. */\n readonly ref: ProcessRef;\n /** A symbol of this side's own, so a handle can be told apart from any other\n * the way a process is: by holding one. */\n readonly id: symbol;\n /** What the far side has said about its state so far. */\n state: Record<string, unknown> | null = null;\n /** The methods the far side announced it can answer. */\n readonly $reflection: Record<string, (...args: unknown[]) => Promise<unknown>> = {};\n\n private pvtSend: FrameSink;\n private pvtFromName: string;\n private pvtConnected = true;\n /** This side let it go: nothing more is asked of it, and nothing arriving for it\n * is news any more. Not the same as ending, and not the same as the connection\n * going: in all three the handle is dead, and only the reason differs. */\n private pvtReleased = false;\n private pvtLetGo: ReleaseHook | undefined;\n /** What the far side said when it ended, or null while it is running. */\n private pvtExit: RemoteExit | null = null;\n private pvtExitWaiter: Waiter<RemoteExit> | null = null;\n private pvtMessageSubs: Array<RemoteMessage<OutMsg>> = [];\n private pvtStateSubs: Array<() => void> = [];\n /** What this side has asked to be told about it. A process that crosses is\n * silent, so a handle starts out having asked for nothing and hears nothing\n * until something here wants it — which is the same rule the far side holds,\n * written from the other end. */\n private pvtWanted: Set<StreamKind> = new Set();\n\n constructor(ref: ProcessRef, send: FrameSink, fromName: string, letGo?: ReleaseHook) {\n this.ref = ref;\n this.pname = ref.pname;\n this.id = Symbol(ref.pname);\n this.pvtSend = send;\n this.pvtFromName = fromName;\n this.pvtLetGo = letGo;\n }\n\n /**\n * Whether the process this handle names can still be reached: the wire is there, and\n * this side has not let the handle go.\n *\n * Reaching it is not the same as it being alive. A process that has ended is still\n * one this side has a handle on — it is what the handle points at, and what it left\n * behind is here — so an end does not put it out of reach; `hasEnded()` is that\n * answer, and the two are asked separately. From the two ways out there is no coming\n * back: no reconnect, and no way to un-release.\n */\n isConnected(): boolean {\n return this.pvtConnected && !this.pvtReleased;\n }\n\n /**\n * The connection is gone. Every handle this side holds goes out of reach with it,\n * and says so: there is no reconnect to wait for, so a send fails here and now\n * rather than disappearing into nothing.\n */\n disconnect(): void {\n if (!this.pvtConnected) return;\n this.pvtConnected = false;\n this.pvtStateSubs.forEach((fn) => fn());\n // Whoever is waiting for it to end is waiting for news that can no longer come.\n this.pvtExitWaiter?.reject(new Error(`${this.pname} cannot be reached: the connection is closed`));\n }\n\n /** Whether the process it names has ended, as far as this side has been told. */\n hasEnded(): boolean {\n return this.pvtExit !== null;\n }\n\n /** Why nothing can be asked *of the process* — let go, ended, or out of reach — or\n * nothing when something can. Those are not one thing said three ways: an ended\n * process is still reached, it simply has nothing left to receive. */\n private pvtWhyNotAskable(): string | null {\n if (this.pvtReleased) return `${this.pname} was released`;\n if (this.pvtExit !== null) return `${this.pname} has ended`;\n if (!this.pvtConnected) return `${this.pname} cannot be reached: the connection is closed`;\n return null;\n }\n\n private pvtRequireAskable(): void {\n const why = this.pvtWhyNotAskable();\n if (why !== null) throw new Error(why);\n }\n\n /**\n * Wait for the process to end. Its exit crosses back like everything else it\n * does, and what it left behind is the answer.\n *\n * A handle whose connection is gone rejects instead: what is left to wait for\n * after that is nothing, and a process that keeps running is not something this\n * side can tell from one that died with the wire.\n */\n wait(): Promise<RemoteExit> {\n if (this.pvtExit !== null) return Promise.resolve(this.pvtExit);\n const why = this.pvtWhyNotAskable();\n if (why !== null) return Promise.reject(new Error(why));\n // Waiting for it to end is a subscription to its end: nothing here hears an\n // exit that was never asked for, so asking to wait asks for it.\n this.pvtWant(\"exit\");\n this.pvtExitWaiter ??= makeWaiter<RemoteExit>();\n return this.pvtExitWaiter.promise;\n }\n\n /**\n * Ask the far side to stop it. Stops the way it always does there, and this\n * resolves when its exit has crossed back — which is all this side can know.\n * There is no deadline, so a process that refuses to stop leaves this pending.\n */\n stop(): Promise<void> {\n this.pvtRequireAskable();\n // Ask for the end before asking it to stop: whether an exit is sent is decided\n // by what the far side has been asked for when it comes, so a stop ordered ahead\n // of the asking could leave nothing to wait for.\n this.pvtWant(\"exit\");\n this.pvtSend({ $stop: {} }, this.ref.id);\n return this.wait().then(() => undefined);\n }\n\n /**\n * Let it go: the far side forgets this id and stops telling this side anything\n * about the process behind it. The process itself is untouched — it runs on, it\n * is simply nobody's here any more — and this handle is done: nothing reaches it,\n * nothing is waited for, and what arrives for it later is not news.\n */\n release(): void {\n this.pvtRequireAskable();\n this.pvtReleased = true;\n this.pvtLetGo?.(this.ref.id);\n this.pvtSend({ $release: {} }, this.ref.id);\n }\n\n /** Stop feeding it messages. It is still there: `send` still reaches it. */\n pause(): void {\n this.pvtRequireAskable();\n this.pvtSend({ $pause: {} }, this.ref.id);\n }\n\n /** Feed it messages again. */\n resume(): void {\n this.pvtRequireAskable();\n this.pvtSend({ $resume: {} }, this.ref.id);\n }\n\n /**\n * What to be told about it from now on: any of `message`, `state` and `exit`,\n * or `\"silent\"` for none of it.\n *\n * A process that crossed is silent to begin with, so this is how a handle asks\n * to hear anything at all — and what is heard is only ever what was asked for.\n * An exit nobody asked for is not sent: silence is silence, which makes this the\n * one way to leave a handle that will not answer a `wait()`, and the far side's\n * books the one place an end can go unrecorded.\n */\n tune(kinds: StreamKind[] | \"silent\"): void {\n this.pvtRequireAskable();\n this.pvtTune(kinds === \"silent\" ? [] : kinds);\n }\n\n /** Ask the far side to say exactly this much, and nothing when it is already\n * saying it. The list goes in the order the three are named in, so asking for\n * the same thing twice sends the same frame twice. */\n private pvtTune(wanted: StreamKind[]): void {\n const kinds = STREAM_KINDS.filter((kind) => wanted.includes(kind));\n if (kinds.length === this.pvtWanted.size && kinds.every((kind) => this.pvtWanted.has(kind))) {\n return;\n }\n this.pvtWanted = new Set(kinds);\n this.pvtSend({ $tune: { streams: kinds } }, this.ref.id);\n }\n\n /** Ask for one more category, because something here now wants it. A handle\n * that is gone asks nothing: there is no far side left to hear it, and nothing\n * was asked for, so what was wanted stays what it was. */\n private pvtWant(kind: StreamKind): void {\n if (this.pvtWanted.has(kind)) return;\n if (!this.pvtConnected || this.pvtReleased) return;\n this.pvtTune([...this.pvtWanted, kind]);\n }\n\n /** Hand the far process a message. */\n send(msg: InMsg): void {\n this.pvtRequireAskable();\n this.pvtSend({ $msg: { fromName: this.pvtFromName, body: msg } }, this.ref.id);\n }\n\n /** Subscribe to what it says, or to what it holds. Asking here is asking the far\n * side: a subscription is the first thing that wants the category, so it is what\n * turns it on, and unsubscribing leaves it on — the far side is not told to stop\n * saying something that another subscriber may still want. */\n subscribe(channel: \"message\", cb: RemoteMessage<OutMsg>): () => void;\n subscribe(channel: \"state\", cb: () => void): () => void;\n subscribe(channel: \"message\" | \"state\", cb: RemoteMessage<OutMsg> | (() => void)): () => void {\n if (channel === \"message\") {\n const fn = cb as RemoteMessage<OutMsg>;\n this.pvtMessageSubs.push(fn);\n this.pvtWant(\"message\");\n return () => this.pvtUnsubscribe(this.pvtMessageSubs, fn);\n }\n const fn = cb as () => void;\n this.pvtStateSubs.push(fn);\n this.pvtWant(\"state\");\n return () => this.pvtUnsubscribe(this.pvtStateSubs, fn);\n }\n\n private pvtUnsubscribe<T>(list: Array<T>, fn: T): void {\n const idx = list.indexOf(fn);\n if (idx >= 0) list.splice(idx, 1);\n }\n\n // ── what the connection delivers ─────────────────────────────────────────\n // The handle does not read frames; the side that owns the connection hands it\n // what a frame about this process said.\n\n /** Its state, as the far side just published it. */\n receiveState(state: Record<string, unknown>): void {\n if (this.pvtReleased) return;\n this.state = Object.assign(this.state ?? {}, state);\n this.pvtStateSubs.forEach((fn) => fn());\n }\n\n /** A message it emitted. */\n receiveMessage(msg: OutMsg, fromName: string): void {\n if (this.pvtReleased) return;\n this.pvtMessageSubs.forEach((fn) => fn(msg, fromName));\n }\n\n /** It has ended, and this is what it left behind. The last thing said about a\n * process: nothing crosses about it after its exit, though the handle still\n * reaches it for what it left. */\n receiveExit(exit: RemoteExit): void {\n if (this.pvtExit !== null || this.pvtReleased) return;\n this.pvtExit = exit;\n this.pvtExitWaiter?.resolve(exit);\n }\n\n /** The methods it can answer, as functions that ask it for an answer. `call`\n * is the connection's own: a handle knows what to ask for, not how a call is\n * made or paired with its answer. */\n receiveMethods(names: string[], call: (name: string, args: unknown[]) => Promise<unknown>): void {\n for (const name of names) {\n this.$reflection[name] = (...args: unknown[]) => call(name, args);\n }\n }\n}\n","// ── What a process says once it has crossed ─────────────────────────────────\n//\n// A process that crosses the connection is numbered, and from that moment the\n// other side can be told about it: what it can answer, what it holds, and what it\n// emits. Both ends say exactly this about the processes they hold — the side that\n// hands one over, and the side that serves one — so it is written once here\n// rather than once per side.\n\nimport { isProcess, type AnyProcess } from \"../process.async.js\";\nimport { REFLECT_METHODS, STREAM_KINDS, type StreamKind } from \"./channel.js\";\n\nimport type { FrameSink } from \"./remote-process.js\";\n\n/** What a process can be asked over the wire: the functions on its reflection\n * surface, read once. On the side that serves it the list *is* the dispatch\n * table, so a name that was never on it can never be reached. */\nconst pvtReflectionNames = new WeakMap<object, string[]>();\n\nexport function reflectionNames(target: { $reflection?: unknown }): string[] {\n const known = pvtReflectionNames.get(target);\n if (known) return known;\n const surface = (target.$reflection ?? {}) as Record<string, unknown>;\n const names = Object.keys(surface).filter((name) => typeof surface[name] === \"function\");\n pvtReflectionNames.set(target, names);\n return names;\n}\n\n/**\n * The processes of one side that have crossed, and what the far side is told\n * about them.\n *\n * A stream starts once the frame that carried the reference is out: frames about\n * a process the reader cannot name yet have nowhere to land. The table numbers a\n * process while that frame is being written, so the numbering is queued here and\n * let out by `flush` right after the frame goes — which is the only thing a\n * caller has to remember.\n *\n * What a stream says is what the far side asked for. A process that crosses is silent\n * until something over there asks to hear it, and `tune` is that asking: only the\n * categories it names cross. The root of the connection is no exception. It is\n * registered here the moment the connection opens, and a side that wants to hear it\n * asks, which is what a visitor's proxy does for the state and messages it stands in\n * for.\n */\n\n/** One process that crossed, and what is said about it now. */\ninterface StreamRecord {\n target: AnyProcess;\n /** The categories that cross, out of the three. */\n kinds: Set<StreamKind>;\n /** How to stop hearing one that is armed. `exit` is not among them: a stream\n * has to hear the end to know it is over, and what it does with the news is\n * the question `kinds` answers. */\n stops: Map<StreamKind, () => void>;\n}\n\nexport class ProcessStreams {\n private pvtSink: FrameSink;\n /** The id of the connection's own end. Its end is the connection's end, so the side\n * that owns the wire says it, awaited there, instead of this watching for it as it\n * watches any other process's. */\n private pvtRootId: number;\n private pvtPending: Array<[AnyProcess, number]> = [];\n private pvtRecords = new Map<number, StreamRecord>();\n private pvtFlushing = false;\n\n constructor(sink: FrameSink, rootId: number) {\n this.pvtSink = sink;\n this.pvtRootId = rootId;\n }\n\n /** A process was numbered: it is about to cross. Anything that is not a\n * process — a handle travelling back to the side that holds it — crosses as\n * the reference it came with and is nobody's to stream. */\n crossed(proc: unknown, id: number): void {\n if (!isProcess(proc)) return;\n this.pvtPending.push([proc, id]);\n }\n\n /** Say what there is to say about whatever crossed while a frame was written. */\n flush(): void {\n if (this.pvtFlushing) return;\n this.pvtFlushing = true;\n try {\n while (this.pvtPending.length > 0) {\n const next = this.pvtPending.shift();\n if (next) this.pvtStream(next[0], next[1]);\n }\n } finally {\n this.pvtFlushing = false;\n }\n }\n\n /**\n * What to say about it from now on: the categories named, and none of the\n * others. Asking for its state says it there and then — a handle that has just\n * asked what it holds should not have to wait for it to change.\n *\n * An id with no stream here is not this side's to tune, and the frame is\n * dropped: both sides tune only what they hold, so an id names a stream on the\n * side that numbered it.\n */\n tune(id: number, kinds: StreamKind[]): void {\n const record = this.pvtRecords.get(id);\n if (!record) return;\n const wanted = new Set(kinds);\n for (const kind of STREAM_KINDS) {\n const isOn = record.kinds.has(kind);\n const want = wanted.has(kind);\n if (want === isOn) continue;\n if (want) {\n record.kinds.add(kind);\n this.pvtArm(record, id, kind);\n } else {\n record.kinds.delete(kind);\n this.pvtDisarm(record, kind);\n }\n }\n }\n\n /**\n * Say nothing more about this one. It is not that the process ended — the far\n * side asked to be left out of it, so its exit is nobody's news over here, and\n * dropping the subscription is what keeps it from being sent.\n */\n stop(id: number): void {\n const record = this.pvtRecords.get(id);\n if (!record) return;\n for (const stop of record.stops.values()) stop();\n this.pvtRecords.delete(id);\n }\n\n /** Nothing more is said about any of them: the connection is done. */\n stopAll(): void {\n for (const id of [...this.pvtRecords.keys()]) this.stop(id);\n this.pvtPending.length = 0;\n }\n\n private pvtStream(target: AnyProcess, id: number): void {\n // Nothing to begin with: what is said about a process is what the far side asks\n // for, and the root is asked for like anything else.\n const record: StreamRecord = {\n target,\n kinds: new Set(),\n stops: new Map(),\n };\n this.pvtRecords.set(id, record);\n // What it can answer comes first: a handle that hears from a process it cannot\n // name yet has nowhere to put the news. It is not one of the three categories\n // — a handle with no methods can do nothing with the process however much it\n // is told about it — so it crosses even in silence.\n this.pvtSink({ [REFLECT_METHODS]: reflectionNames(target) }, id);\n for (const kind of record.kinds) this.pvtArm(record, id, kind);\n // Its end is the last thing ever said about it, and the one thing a stream has\n // to hear to know it is over, whether or not the far side is told. A process\n // that fails to run takes the same road as one that finishes.\n //\n // Not for the root. Its end is the connection's end, and the side that owns the\n // wire says it while taking the wire down, awaiting it there because that frame has\n // to be out before the close. Both of them end up in `sayEnded`.\n if (id !== this.pvtRootId) {\n void target.wait().then(\n () => void this.sayEnded(id, 0),\n () => void this.sayEnded(id, 1),\n );\n }\n }\n\n /** Start saying this much about it, and say what there is to say now. */\n private pvtArm(record: StreamRecord, id: number, kind: StreamKind): void {\n if (kind === \"message\") {\n record.stops.set(\n \"message\",\n record.target.subscribe(\"message\", (msg, sender) => {\n this.pvtSink({ $msg: { fromName: sender.fromName, body: msg } }, id);\n }),\n );\n return;\n }\n if (kind === \"state\") {\n record.stops.set(\n \"state\",\n record.target.subscribe(\"state\", () => {\n this.pvtSink({ $state: record.target.state as Record<string, unknown> }, id);\n }),\n );\n // Asked for, so said now: in silence the far side has heard nothing about\n // its state, and this is the first word rather than a repeat.\n this.pvtSink({ $state: record.target.state as Record<string, unknown> }, id);\n }\n // `exit` needs no subscription: the end is watched from the moment the process\n // crosses, since a stream has to know when it is over. Whether it is sent is\n // read from `kinds` when it comes.\n }\n\n private pvtDisarm(record: StreamRecord, kind: StreamKind): void {\n const stop = record.stops.get(kind);\n if (!stop) return;\n stop();\n record.stops.delete(kind);\n }\n\n /**\n * It has ended: say so once, if that is among the categories asked for, and say\n * nothing more about it either way. Awaited by whoever has to have the frame out\n * before the wire closes, which is the root's end and nobody else's — no other\n * process can end after this side has stopped saying anything about it.\n */\n async sayEnded(id: number, code: number): Promise<void> {\n const record = this.pvtRecords.get(id);\n if (!record) return;\n const told = record.kinds.has(\"exit\");\n const state = record.target.state;\n this.stop(id);\n if (told) await this.pvtSink({ $exit: { code, state } }, id);\n }\n}\n","// ── Who a message that crossed the wire came from ──────────────────────────\n//\n// A frame carries its sender as a name, because a symbol cannot be written down.\n// On the other side the name is turned back into an identity a process can be\n// handed: whoever the frame names, and — when that name is the one a process was\n// told is its parent — the parent's own stable id, so a child on either side of\n// the seam recognises the same sender.\n\nimport type { SenderInfo } from \"../types.js\";\n\nexport function makeSender(\n fromName: string,\n parentName: string | null,\n parentId: symbol | null,\n): SenderInfo {\n if (parentId && fromName === parentName) {\n return { fromName, fromId: parentId };\n }\n return { fromName, fromId: Symbol() };\n}\n","// ── The call side of a connection ───────────────────────────────────────────\n//\n// Both ends of a seam make calls and answer them, and the machinery is the same\n// once the wire is: a `seq` the connection counts, the calls waiting under it, the\n// surface a handle reads to make one, and the answer that names which call it\n// settles. Only where a frame leaves differs between the two ends, which is why\n// that is the one thing handed in and the rest is written once.\n\nimport { isProcess } from \"../process.async.js\";\nimport {\n REFLECT_CALL,\n REFLECT_RESULT,\n asReflectionResult,\n encodeFrame,\n jsonProblem,\n type ReflectionCall,\n} from \"./channel.js\";\nimport { encodeProcessRefs, type ProcessHandle, type ProcessTable } from \"./process-ref.js\";\nimport { reflectionNames } from \"./process-streams.js\";\n\n/** A frame on its way out: encoded, addressed, and written to this end's wire. */\nexport type WireSink = (frame: Record<string, unknown>) => Promise<void>;\n\nexport class CallSide {\n /**\n * `seq` belongs to this connection and is never reused, so two calls to the same\n * method in flight at once stay apart; the answer names the one it belongs to,\n * whichever process it was asked of.\n */\n private pvtCalls = 0;\n private pvtWaiting = new Map<\n number,\n { name: string; resolve: (value: unknown) => void; reject: (error: Error) => void }\n >();\n private pvtWrite: WireSink;\n private pvtTable: ProcessTable<ProcessHandle>;\n\n constructor(write: WireSink, table: ProcessTable<ProcessHandle>) {\n this.pvtWrite = write;\n this.pvtTable = table;\n }\n\n /**\n * Ask a process on the far side for one of its methods. Processes among the\n * arguments become references first — this side's own, with ids from its table, or\n * the far side's coming back — and what is left has to be JSON, or nothing is sent\n * at all.\n */\n call(method: string, callArgs: unknown[], to: number): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const seq = ++this.pvtCalls;\n const frame = encodeFrame(\n { [`${REFLECT_CALL}${method}`]: { seq, args: callArgs } },\n this.pvtTable,\n to,\n );\n const problem = jsonProblem(frame);\n if (problem !== null) {\n reject(new Error(`cannot send ${problem} to ${method}`));\n return;\n }\n this.pvtWaiting.set(seq, { name: method, resolve, reject });\n void this.pvtWrite(frame).catch((error: unknown) => {\n this.pvtWaiting.delete(seq);\n reject(error instanceof Error ? error : new Error(String(error)));\n });\n });\n }\n\n /** One function per announced name, on the surface whoever calls reads. */\n install(surface: Record<string, unknown>, methods: string[], to: number): void {\n for (const method of methods) {\n surface[method] = (...callArgs: unknown[]) => this.call(method, callArgs, to);\n }\n }\n\n /**\n * An answer to a call this side made: the call waiting under that `seq` is settled\n * by it, and the frame says whether it was one at all. An answer is about the call\n * and not about a process, so a dispatcher reads it before it looks anything up.\n */\n settle(frame: Record<string, unknown>): boolean {\n const result = asReflectionResult(frame);\n if (!result) return false;\n const waiting = this.pvtWaiting.get(result.seq);\n if (waiting) {\n this.pvtWaiting.delete(result.seq);\n if (result.error === undefined) waiting.resolve(result.value);\n else waiting.reject(new Error(`${waiting.name}: ${result.error}`));\n }\n return true;\n }\n\n /** A call that was in flight when the wire went has no answer coming; it fails\n * here rather than hanging for ever. */\n rejectAll(): void {\n for (const waiting of this.pvtWaiting.values()) {\n waiting.reject(new Error(`connection closed before ${waiting.name} answered`));\n }\n this.pvtWaiting.clear();\n }\n}\n\n/**\n * Answer one call with what the process said, or why it could not. A method may be\n * written for a call that answers later; the wire has no opinion about that, it just\n * waits for the frame.\n */\nexport async function answerCall(\n call: ReflectionCall,\n target: ProcessHandle | undefined,\n write: WireSink,\n table: ProcessTable<ProcessHandle>,\n): Promise<void> {\n // An answer goes back to the far side's own end of the connection: a result is about\n // the call and not about a process, and the one waiting for it is out there.\n const reply = (body: Record<string, unknown>) =>\n write(encodeFrame({ [`${REFLECT_RESULT}${call.name}`]: body }, table, table.farRootId()));\n // Only a process this side holds can be asked: the id a call names is the holder's\n // own, and this side is the holder of what it holds.\n if (!isProcess(target)) {\n await reply({ seq: call.seq, error: \"no process with that id on this connection\" });\n return;\n }\n const names = reflectionNames(target);\n const surface = target.$reflection as unknown as Record<string, Function>;\n const method = names.includes(call.name) ? surface[call.name] : undefined;\n if (typeof method !== \"function\") {\n await reply({ seq: call.seq, error: `no reflection method named ${call.name}` });\n return;\n }\n try {\n // References in the arguments arrived as handles on processes of this side's own,\n // and processes in the answer become references. What is left has to be JSON, or\n // the call is refused rather than half-written.\n const value = encodeProcessRefs(await method(...call.args), table);\n const problem = jsonProblem(value);\n if (problem !== null) {\n await reply({\n seq: call.seq,\n error: `${call.name} returned ${problem}, which cannot cross a frame`,\n });\n return;\n }\n await reply({ seq: call.seq, value });\n } catch (err) {\n await reply({ seq: call.seq, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","// ── Server side of the seam ────────────────────────────────────────────────\n//\n// serveRemoteActor serves a posipaki actor over a frame Channel produced by a\n// spawner. It knows only the frame vocabulary (channel.ts) — no protocol, no\n// transport, no spawner. The spawner has already done the $proto handshake.\n\nimport type { ActorDefinition, ReflectionOptions } from \"../actor-types.js\";\nimport type { Message } from \"../types.js\";\nimport { isProcess } from \"../process.async.js\";\nimport type { Channel } from \"./channel.js\";\nimport {\n ProcessTable,\n SERVED_ROOT_NAME,\n isRemoteProcess,\n type ProcessHandle,\n type ProcessRef,\n} from \"./process-ref.js\";\nimport { RemoteProcess, type FrameSink } from \"./remote-process.js\";\nimport { ProcessStreams } from \"./process-streams.js\";\nimport { makeSender } from \"./sender.js\";\nimport {\n REFLECT_METHODS,\n asReflectionCall,\n decodeFrame,\n encodeFrame,\n frameTo,\n isExit,\n isInit,\n isMsg,\n isPause,\n isRelease,\n isResume,\n isState,\n isStop,\n isTune,\n isReflectionMethods,\n tuneFrame,\n} from \"./channel.js\";\nimport { CallSide, answerCall } from \"./call-side.js\";\n\nexport type Spawner = () => Promise<Channel>;\n\n/** The name the served actor is spawned under, and the one it answers to as a\n * sender when it talks to a process of the far side's. A reference that names the\n * root it serves is told apart from the far side's root by it. */\nconst ROOT_NAME = SERVED_ROOT_NAME;\n\nexport async function serveRemoteActor<\n Args,\n State,\n InMsg extends Message,\n OutMsg extends Message,\n R extends ReflectionOptions,\n>(actor: ActorDefinition<Args, State, InMsg, OutMsg, R>, spawner: Spawner): Promise<void> {\n const channel = await spawner();\n\n // The table takes the even ids: the odd ones are the far side's, so the same\n // number can never name a process on both ends at once. A process that is\n // numbered here is one that is about to cross, and its stream follows the frame\n // that carried it.\n const table = new ProcessTable<ProcessHandle>(\"even\", (proc, id) => streams.crossed(proc, id));\n\n /** Put an encoded frame on the wire, and then say what it numbered. A frame that\n * carried a reference has to be out before anything about that process is. */\n const write = async (frame: Record<string, unknown>): Promise<void> => {\n await channel.send(frame);\n streams.flush();\n };\n\n const sendToFrame = (frame: Record<string, unknown>, to: number): Promise<void> =>\n write(encodeFrame(frame, table, to));\n\n /** Every frame leaves this way. The answer is handed back, since the one frame that\n * has to be out before the wire closes is awaited by the side that owns the wire. */\n const sendTo: FrameSink = (frame, to) =>\n sendToFrame(frame, to).catch((e: unknown) => {\n console.error(\"Error sending out the frame\", e);\n });\n\n // Everything is in place to speak: the sink writes to the wire, and what the\n // table numbers crosses through it.\n const streams = new ProcessStreams(sendTo, table.rootId());\n\n // Both ends of a connection make calls and answer them: a process the far side\n // holds is asked the same way this side is asked.\n const calls = new CallSide(write, table);\n\n /** The handle for a reference that arrived: the same one every time, and the process\n * itself when the reference names a process of this side's own. The roots are\n * numbered apart, so a reference to the far side's root is a reference to a process\n * of theirs, and a handle like any of those. */\n const handleFor = (ref: ProcessRef): ProcessHandle => {\n const held = table.processFor(ref.id);\n if (held) return held;\n const known = table.farHandleFor(ref.id);\n if (isRemoteProcess(known)) return known;\n const handle = new RemoteProcess(ref, sendTo, ROOT_NAME, (id) => table.release(id));\n table.bindFar(ref.id, handle);\n return handle;\n };\n\n // await $init, keeping everything that arrives with it. The channel has one handler\n // slot, and a frame that arrives while the actor is still starting has nothing to be\n // dispatched to yet, so the frames wait here and are replayed below. The $init is the\n // first of them, that being what the connection is made by.\n const waiting: Record<string, unknown>[] = [];\n await new Promise<void>((resolve) => {\n channel.onMessage((frame) => {\n waiting.push(frame);\n resolve();\n });\n });\n channel.removeHandler();\n const initFrame = decodeFrame(waiting.shift() as Record<string, unknown>, handleFor);\n if (!isInit(initFrame)) {\n throw new Error(\"serveRemoteActor: expected $init\");\n }\n\n const init = initFrame.$init;\n const parentName = (init.parentName as string) ?? null;\n const parentIdName = (init.parentIdName as string) ?? null;\n const parentId = parentIdName ? Symbol.for(parentIdName) : null;\n const { parentName: _pn, parentIdName: _pid, ...initArgs } = init;\n\n const proc = await actor.spawn(initArgs as unknown as Args, {\n name: ROOT_NAME,\n parentName,\n parentId,\n });\n\n // This side's own end of the connection is the process it just spawned: id 0\n // here, and on the other side the proxy that asked for it.\n table.bindRoot(proc);\n\n await proc.ready();\n\n // The root is a process that crossed this connection like any other, at the id this\n // side gave it. What it can be asked is announced, and what it holds and what it\n // says are said once the far side asks: the announced list is the whole surface, so a\n // name that was never on it can never be reached. A proxy on the other end asks for\n // the state and the messages it stands in for the moment it connects.\n streams.crossed(proc, table.rootId());\n streams.flush();\n\n // bridge channel input → actor\n function dispatch(raw: Record<string, unknown>): void {\n const frame = decodeFrame(raw, handleFor);\n // An answer is about the call waiting for it and not about a process: it names\n // the seq, and is settled before anything is looked up.\n if (calls.settle(frame)) return;\n const to = frameTo(frame);\n if (to === null) return;\n // A frame answers one of two questions. News about a process the far side holds\n // lands on the handle for it: what it holds, that it is over, what it can answer.\n // An ask of a process this side holds goes to wherever that process lives: a\n // message, control, a call, a tune.\n const news = table.farHandleFor(to);\n const mine = table.processFor(to);\n if (isRelease(frame)) {\n // A process of this side's own, let go of over there: nothing more is said about\n // it, and the id the far side knew it by is no longer this connection's. The\n // process itself runs on, and a later crossing numbers it afresh. Neither root is\n // let go of, so the table refuses both.\n if (mine !== undefined) {\n streams.stop(to);\n table.release(to);\n }\n return;\n }\n if (isTune(frame)) {\n // How much the far side is told about a process of this side's own is that\n // side's to ask, and this is where the asking lands: what it names is what\n // crosses from now on. An id this side does not hold has nothing to tune.\n if (mine !== undefined) {\n const kinds = tuneFrame(frame);\n if (kinds !== null) streams.tune(to, kinds);\n }\n return;\n }\n if (isReflectionMethods(frame)) {\n // What a process the far side holds can answer, said the moment it crossed:\n // the handle here reads it as its own surface, so a name asked on it is asked\n // there. What a process of this side's own can answer is this side's to\n // announce, not the far side's to tell it.\n if (isRemoteProcess(news)) {\n news.receiveMethods(frame[REFLECT_METHODS], (method, args) => calls.call(method, args, to));\n }\n return;\n }\n if (isState(frame)) {\n // A process the far side holds, saying what it holds: that is news for the\n // handle on it, and lands where a subscription can see it. A state frame about\n // a process of this side's own is this side's to publish, not the far side's to\n // tell it.\n if (isRemoteProcess(news)) news.receiveState(frame.$state);\n return;\n }\n if (isExit(frame)) {\n // A process the far side holds, gone. Nothing more will be said about it, so\n // this is the last thing a handle can be told.\n if (isRemoteProcess(news)) news.receiveExit(frame.$exit);\n return;\n }\n if (isStop(frame) || isPause(frame) || isResume(frame)) {\n // Control, addressed to the process it is about: acted on by whoever holds that\n // process, which is this side. The root is one of those — stopping it stops\n // what the connection is for — and a handle has nothing here to act on.\n if (isProcess(mine)) {\n const sender = makeSender(ROOT_NAME, parentName, parentId);\n if (isStop(frame)) void mine.stop({ from: sender });\n else if (isPause(frame)) mine.pause();\n else mine.resume();\n }\n return;\n }\n if (isMsg(frame)) {\n const { fromName, body } = frame.$msg;\n // A message for a process this side holds goes into it, the root included. One\n // about a process the far side holds — a handle here — is that process talking,\n // and goes to whoever subscribed to the handle.\n if (isProcess(mine)) mine.send(body as InMsg, makeSender(fromName, parentName, parentId));\n else if (isRemoteProcess(news)) news.receiveMessage(body as OutMsg, fromName);\n return;\n }\n const call = asReflectionCall(frame);\n if (call) void answerCall(call, mine, write, table);\n }\n\n channel.removeHandler();\n channel.onMessage(dispatch);\n for (const frame of waiting.splice(0)) dispatch(frame);\n\n // await actor exit, announce it, close\n let code = 0;\n try {\n await proc.wait();\n } catch (err) {\n console.error(\"server actor error:\", err);\n code = 1;\n }\n // The root is over, which is the last thing said about it. It is said and awaited\n // here, because the wire closes right after it.\n await streams.sayEnded(table.rootId(), code);\n // And nothing more about anything else of this side's: there is no one left to say\n // it to.\n streams.stopAll();\n // A call this side made and the far side has not answered is not going to be\n // answered now; it fails here rather than hanging.\n calls.rejectAll();\n await channel.close();\n}\n","// ── Client side of the seam ────────────────────────────────────────────────\n//\n// remoteClient builds a posipaki actor that talks to a remote server through a\n// frame Channel produced by a spawner. It knows only the frame vocabulary\n// (channel.ts) — no protocol, no transport, no spawner. The spawner has\n// already done the $proto handshake.\n\nimport { defineActor } from \"../define-actor.js\";\nimport { isProcess } from \"../process.async.js\";\nimport { stopPropagation } from \"../hooks.js\";\nimport type { HookResult } from \"../hooks.js\";\nimport type { ActorDefinition, HandlerOptions, MethodOptions, ReflectionOptions } from \"../actor-types.js\";\nimport type { Message } from \"../types.js\";\nimport type { Channel } from \"./channel.js\";\nimport {\n ProcessTable,\n SERVED_ROOT_NAME,\n isRemoteProcess,\n type ProcessHandle,\n type ProcessRef,\n} from \"./process-ref.js\";\nimport { ProcessStreams } from \"./process-streams.js\";\nimport { RemoteProcess, type FrameSink } from \"./remote-process.js\";\nimport { makeSender } from \"./sender.js\";\nimport {\n REFLECT_METHODS,\n asReflectionCall,\n decodeFrame,\n encodeFrame,\n frameTo,\n isExit,\n isMsg,\n isPause,\n isRelease,\n isResume,\n isStop,\n isReflectionMethods,\n isState,\n isTune,\n tuneFrame,\n} from \"./channel.js\";\nimport { CallSide, answerCall } from \"./call-side.js\";\n\nexport type ClientSpawner<Args> = (args: Args) => Promise<Channel>;\n\n\nexport function remoteClient<\n Args,\n State,\n InMsg extends Message,\n OutMsg extends Message,\n Methods extends MethodOptions = MethodOptions,\n Handlers extends HandlerOptions<InMsg> = HandlerOptions<InMsg>,\n R extends ReflectionOptions = ReflectionOptions,\n>(\n name: string,\n spawner: ClientSpawner<Args>,\n): ActorDefinition<Args, State, InMsg, OutMsg, R> {\n const proxyDef = defineActor<\n Args,\n {\n public: State;\n private: {\n channel: Channel;\n farRoot: RemoteProcess<InMsg, OutMsg>;\n exitPromise: Promise<{ code: number | null; state: State }>;\n };\n },\n InMsg,\n OutMsg,\n Methods,\n Handlers,\n R\n >({\n name,\n handlers: {} as unknown as Handlers,\n async setup(args: Args) {\n // This side's own end of the connection is the root, and id 0 is how both\n // sides name it: the far actor on one end, this proxy on the other. The\n // table takes the odd ids for the processes this side holds — the far side\n // takes the even ones — so an id says on its own which side holds it.\n // A process this side hands over is numbered by the table, and from then on\n // the far side is told what it says: the stream follows the frame that\n // carried the reference.\n const table = new ProcessTable(\"odd\", (proc, id) => streams.crossed(proc, id));\n const root = this.ctx;\n table.bindRoot(root);\n const channel = await spawner(args);\n const fromName = name;\n // Everything is in place to speak: the sink writes to the wire, and what the\n // table numbers crosses through it. The sink is reached by a call rather\n // than handed over, because what it does is flush these streams.\n const streams = new ProcessStreams((frame, to) => sendTo(frame, to), table.rootId());\n\n /** Put an encoded frame on the wire, and then say what it numbered. A frame that\n * carried a reference has to be out first, or the far side hears about a process\n * it cannot name yet. */\n const write = (frame: Record<string, unknown>): Promise<void> =>\n Promise.resolve(channel.send(frame)).then(() => streams.flush());\n\n /** Every frame leaves this way: the processes in it become references, and\n * what the frame is addressed to becomes the id the far side knows. */\n const sendTo: FrameSink = (frame, to) => {\n void write(encodeFrame(frame, table, to)).catch((error: unknown) => {\n console.error(\"Error sending out the frame\", error);\n });\n };\n sendTo(\n {\n $init: {\n ...(args as unknown as Record<string, unknown>),\n parentName: fromName,\n parentIdName: fromName,\n },\n },\n table.farRootId(),\n );\n\n let currentState: Record<string, unknown> = {};\n\n // ── the call side ──────────────────────────────────────────────────\n // This side both makes calls and answers them, and so does the other end of\n // every connection: what a call is, and how an answer finds the one waiting\n // for it, is written once in call-side.ts.\n const calls = new CallSide(write, table);\n\n /**\n * The handle for a reference that arrived. A process handed over twice is one\n * process, so a reference that names one this side already knows gives back the\n * handle it gave last time, and one that names a process of this side's own —\n * handed back to its owner — gives back that process.\n *\n * The roots are numbered apart, so the numbers say what belongs to whom: 1 is this\n * side's own end, and 0 is the far side's root, which is a handle like any of the\n * processes they hold.\n */\n const handleFor = (ref: ProcessRef): ProcessHandle => {\n const held = table.processFor(ref.id);\n if (held) return held;\n const known = table.farHandleFor(ref.id);\n if (isRemoteProcess(known)) return known;\n const handle = new RemoteProcess(ref, sendTo, fromName, (id) => table.release(id));\n table.bindFar(ref.id, handle);\n return handle;\n };\n\n /**\n * The far side's root, which is what this proxy stands in for. It is bound here\n * like any other reference the far side sends: what it holds, what it says, when\n * it is over and what it can answer reach it as they reach any handle.\n */\n const farRoot = new RemoteProcess<InMsg, OutMsg>(\n { id: table.farRootId(), pname: SERVED_ROOT_NAME },\n sendTo,\n fromName,\n (id) => table.release(id),\n );\n table.bindFar(table.farRootId(), farRoot);\n\n // Setup is done when the far side has said what it holds; until then the\n // one handler below is what takes everything that arrives, so nothing\n // falls between two of them.\n let started: (() => void) | null = null;\n const start = new Promise<void>((resolve) => {\n started = resolve;\n });\n\n // All three in one asking, since this proxy stands in for the far root: what it\n // holds is this proxy's state, what it says is what this proxy says, and its end\n // is the end of the connection. A process says nothing until something asks, and\n // the root is no exception.\n farRoot.tune([\"message\", \"state\", \"exit\"]);\n farRoot.subscribe(\"state\", () => {\n // One object, updated the way the far side publishes it: the proxy's state is\n // the far root's, and a caller here reads it as `proc.state`.\n Object.assign(currentState, farRoot.state ?? {});\n root.notify();\n started?.();\n started = null;\n });\n farRoot.subscribe(\"message\", (msg) => {\n void this.emit(msg as OutMsg);\n });\n const exitPromise: Promise<{ code: number | null; state: State }> = farRoot.wait().then(\n (exit) => ({ code: exit.code, state: exit.state as State }),\n // The wire went before the far root did: what is known here is that it is over,\n // and the state last heard is the last word there is.\n () => ({ code: null, state: currentState as State }),\n );\n\n channel.onMessage((raw) => {\n const frame = decodeFrame(raw, handleFor);\n // An answer is about the call waiting for it and not about a process: it names\n // the seq, and is settled before anything is looked up.\n if (calls.settle(frame)) return;\n const to = frameTo(frame);\n if (to === null) return;\n // A frame answers one of two questions. News about a process the far side holds\n // lands on the handle for it: what it holds, what it says, that it is over, what\n // it can answer. An ask of a process this side holds goes to wherever that\n // process lives: a message, control, a call, a tune.\n const news = table.farHandleFor(to);\n const mine = table.processFor(to);\n if (isRelease(frame)) {\n // A process of this side's own, let go of over there: nothing more is said\n // about it, and the id is no longer this connection's. The process itself\n // runs on. Neither root is let go of, so the table refuses both.\n if (mine !== undefined) {\n streams.stop(to);\n table.release(to);\n }\n return;\n }\n if (isReflectionMethods(frame)) {\n // What the far side holds can answer, and how this side asks it: what was\n // announced is the whole surface, so a name never announced is never called\n // here either. The far root's names go on this proxy's own surface as well,\n // since the proxy is the process a caller here holds.\n if (isRemoteProcess(news)) {\n news.receiveMethods(frame[REFLECT_METHODS], (method, callArgs) =>\n calls.call(method, callArgs, to),\n );\n if (to === table.farRootId()) {\n calls.install(\n this.reflection as unknown as Record<string, unknown>,\n frame[REFLECT_METHODS],\n table.farRootId(),\n );\n }\n }\n return;\n }\n if (isState(frame)) {\n // A process the far side holds, saying what it holds: news for whoever\n // subscribed to the handle.\n if (isRemoteProcess(news)) news.receiveState(frame.$state);\n return;\n }\n if (isExit(frame)) {\n // A process the far side holds, gone: nothing more will be said about it.\n if (isRemoteProcess(news)) news.receiveExit(frame.$exit);\n return;\n }\n if (isMsg(frame)) {\n // A message naming a process this side holds goes into it, the proxy's own\n // root included, and the wire says who sent it by name alone. One about a\n // process the far side holds is that process talking, and goes to whoever\n // subscribed to the handle.\n if (isProcess(mine)) {\n mine.send(frame.$msg.body as InMsg, makeSender(frame.$msg.fromName, null, null));\n } else if (isRemoteProcess(news)) {\n news.receiveMessage(frame.$msg.body as OutMsg, frame.$msg.fromName);\n }\n return;\n }\n if (isTune(frame)) {\n // How much the far side hears about a process of this side's own is its to\n // ask, and this is where the asking lands.\n if (mine !== undefined) {\n const kinds = tuneFrame(frame);\n if (kinds !== null) streams.tune(to, kinds);\n }\n return;\n }\n if (isStop(frame) || isPause(frame) || isResume(frame)) {\n // Control, addressed to the process it is about, and acted on by whoever holds\n // it, which is this side. Its own root is one of those. A handle has nothing\n // here to act on.\n if (isProcess(mine)) {\n if (isStop(frame)) void mine.stop({ from: makeSender(name, null, null) });\n else if (isPause(frame)) mine.pause();\n else mine.resume();\n }\n return;\n }\n // A call into a process of this side's own, made from over there: the method is\n // this side's to run, and the answer goes back by name and seq.\n const call = asReflectionCall(frame);\n if (call) void answerCall(call, mine, write, table);\n });\n channel.onClose(() => {\n // A call that was in flight when the wire went away has no answer\n // coming; it fails here rather than hanging forever.\n calls.rejectAll();\n // Handles live on this connection: with it gone there is nothing to\n // reach, and nothing to wait for either.\n for (const held of table.handles()) {\n if (isRemoteProcess(held)) held.disconnect();\n }\n // And nothing more is said about the processes of this side's own that\n // were handed over: there is no one left to say it to.\n streams.stopAll();\n // A wire that goes before the far root does leaves nothing to wait for: the\n // handles are gone, and the far root's end is the connection's end, which is\n // what `wait()` on it rejects about.\n });\n\n await start;\n\n return {\n public: currentState as State,\n private: { channel, farRoot, exitPromise },\n };\n\n },\n async onMessage(msg: InMsg): Promise<HookResult> {\n const { farRoot } = this.state.private;\n // A message this side sends is for the root: that is the process the proxy stands\n // for, and it is sent the way any handle sends to a process of the far side's.\n if (farRoot.isConnected()) farRoot.send(msg);\n return stopPropagation();\n },\n async onStopRequested() {\n const { channel, farRoot, exitPromise } = this.state.private;\n if (channel) {\n // Asking the far root to stop is asking a process, not sending it a message:\n // the control frame its holder acts on, the one every other handle uses. Worth\n // asking only while there is something to ask of it — an end that has come, or\n // a wire that has gone, leaves nothing to ask and nothing to wait for.\n if (farRoot.isConnected() && !farRoot.hasEnded()) {\n void farRoot.stop().catch(() => undefined);\n }\n await exitPromise;\n }\n this.agreeToStop();\n },\n async afterEnd() {\n if (this.state.private.channel) {\n await this.state.private.channel.close();\n }\n },\n });\n\n return proxyDef as unknown as ActorDefinition<Args, State, InMsg, OutMsg, R>;\n}\n","// ── json1 wire protocol ────────────────────────────────────────────────────\n//\n// One JSON object per frame: `{\"$key\": value}`. encode/decode turn a decoded\n// frame object into a string and back. json1Channel wraps a StringTransport so\n// it moves frame objects instead of strings.\n\nimport type { Channel, StringTransport } from \"../channel.js\";\n\nexport const VERSION = \"json.v1\";\n\nexport function encode(frame: Record<string, unknown>): string {\n return JSON.stringify(frame);\n}\n\nexport function decode(str: string): Record<string, unknown> {\n return JSON.parse(str);\n}\n\nexport function json1Channel(transport: StringTransport): Channel {\n return {\n send(frame) {\n return transport.send(encode(frame));\n },\n onMessage(handler) {\n transport.onMessage((str) => handler(decode(str)));\n },\n removeHandler() {\n transport.removeHandler();\n },\n onClose(handler) {\n transport.onClose(handler);\n },\n close() {\n return transport.close();\n },\n };\n}\n"],"mappings":"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"}
|