@actuallab/rpc 12.1.115 → 12.2.23

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.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,13 +17,20 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var index_exports = {};
22
32
  __export(index_exports, {
23
33
  ARG_DELIMITER: () => ARG_DELIMITER,
24
- DEFAULT_SERIALIZATION_FORMAT: () => DEFAULT_SERIALIZATION_FORMAT,
25
34
  ENVELOPE_DELIMITER: () => ENVELOPE_DELIMITER,
26
35
  FRAME_DELIMITER: () => FRAME_DELIMITER,
27
36
  RPC_CLOSE_CODE_UNSUPPORTED_FORMAT: () => RPC_CLOSE_CODE_UNSUPPORTED_FORMAT,
@@ -31,7 +40,11 @@ __export(index_exports, {
31
40
  RpcHub: () => RpcHub,
32
41
  RpcInboundCall: () => RpcInboundCall,
33
42
  RpcInboundCallTracker: () => RpcInboundCallTracker,
43
+ RpcJsonSerializationFormat: () => RpcJsonSerializationFormat,
34
44
  RpcMessageChannelConnection: () => RpcMessageChannelConnection,
45
+ RpcMessagePackCompactSerializationFormat: () => RpcMessagePackCompactSerializationFormat,
46
+ RpcMessagePackSerializationFormat: () => RpcMessagePackSerializationFormat,
47
+ RpcMethodRegistry: () => RpcMethodRegistry,
35
48
  RpcObjectKind: () => RpcObjectKind,
36
49
  RpcOutboundCall: () => RpcOutboundCall,
37
50
  RpcOutboundCallTracker: () => RpcOutboundCallTracker,
@@ -40,6 +53,8 @@ __export(index_exports, {
40
53
  RpcPeerStateKind: () => RpcPeerStateKind,
41
54
  RpcPeerStateMonitor: () => RpcPeerStateMonitor,
42
55
  RpcRemoteObjectTracker: () => RpcRemoteObjectTracker,
56
+ RpcSerializationFormat: () => RpcSerializationFormat,
57
+ RpcSerializationFormatResolver: () => RpcSerializationFormatResolver,
43
58
  RpcServerPeer: () => RpcServerPeer,
44
59
  RpcServiceHost: () => RpcServiceHost,
45
60
  RpcSharedObjectTracker: () => RpcSharedObjectTracker,
@@ -51,10 +66,16 @@ __export(index_exports, {
51
66
  RpcType: () => RpcType,
52
67
  RpcWebSocketConnection: () => RpcWebSocketConnection,
53
68
  WebSocketState: () => WebSocketState,
69
+ computeMethodHash: () => computeMethodHash,
70
+ createBinaryEncoder: () => createBinaryEncoder,
54
71
  createMessageChannelPair: () => createMessageChannelPair,
55
72
  createRpcClient: () => createRpcClient,
73
+ defaultBinaryDecoder: () => defaultBinaryDecoder,
74
+ defaultBinaryEncoder: () => defaultBinaryEncoder,
56
75
  defaultConnectionUrlResolver: () => defaultConnectionUrlResolver,
57
76
  defineRpcService: () => defineRpcService,
77
+ deserializeBinaryMessage: () => deserializeBinaryMessage,
78
+ deserializeCompactBinaryMessage: () => deserializeCompactBinaryMessage,
58
79
  deserializeMessage: () => deserializeMessage,
59
80
  getMethodsMeta: () => getMethodsMeta,
60
81
  getServiceMeta: () => getServiceMeta,
@@ -65,10 +86,17 @@ __export(index_exports, {
65
86
  resolveStreamRefs: () => resolveStreamRefs,
66
87
  rpcMethod: () => rpcMethod,
67
88
  rpcService: () => rpcService,
89
+ serializeBinaryFrame: () => serializeBinaryFrame,
90
+ serializeBinaryMessage: () => serializeBinaryMessage,
91
+ serializeCompactBinaryMessage: () => serializeCompactBinaryMessage,
68
92
  serializeFrame: () => serializeFrame,
69
93
  serializeMessage: () => serializeMessage,
94
+ splitBinaryFrame: () => splitBinaryFrame,
95
+ splitCompactBinaryFrame: () => splitCompactBinaryFrame,
70
96
  splitFrame: () => splitFrame,
71
- wireMethodName: () => wireMethodName
97
+ wireMethodName: () => wireMethodName,
98
+ xxh3_64: () => xxh3_64,
99
+ xxh3_64str: () => xxh3_64str
72
100
  });
73
101
  module.exports = __toCommonJS(index_exports);
74
102
 
@@ -96,6 +124,7 @@ var ARG_DELIMITER = "";
96
124
  var FRAME_DELIMITER = "\n";
97
125
 
98
126
  // src/rpc-serialization.ts
127
+ var import_msgpack = require("@msgpack/msgpack");
99
128
  function serializeMessage(message, args) {
100
129
  const envelope = JSON.stringify(message);
101
130
  if (args === void 0 || args.length === 0) {
@@ -125,13 +154,263 @@ function deserializeMessage(raw) {
125
154
  try {
126
155
  return JSON.parse(s);
127
156
  } catch {
157
+ console.warn(
158
+ `[RpcSerialization] failed to parse arg as JSON: ${s.substring(0, 100)}`
159
+ );
128
160
  return s;
129
161
  }
130
162
  });
131
163
  return { message, args };
132
164
  }
165
+ var textEncoder = new TextEncoder();
166
+ var textDecoder = new TextDecoder();
167
+ var INITIAL_ENCODER_BUFFER_SIZE = 32 * 1024;
168
+ var defaultBinaryEncoder = new import_msgpack.Encoder(
169
+ void 0,
170
+ void 0,
171
+ void 0,
172
+ INITIAL_ENCODER_BUFFER_SIZE
173
+ );
174
+ var defaultBinaryDecoder = new import_msgpack.Decoder();
175
+ function createBinaryEncoder() {
176
+ return new import_msgpack.Encoder(
177
+ void 0,
178
+ void 0,
179
+ void 0,
180
+ INITIAL_ENCODER_BUFFER_SIZE
181
+ );
182
+ }
183
+ function varUintByteLen(value) {
184
+ if (value < 0) value = 0;
185
+ let n = 0;
186
+ do {
187
+ n++;
188
+ value >>>= 7;
189
+ } while (value > 0);
190
+ return n;
191
+ }
192
+ function writeVarUintInto(out, pos, value) {
193
+ if (value < 0) value = 0;
194
+ do {
195
+ let byte = value & 127;
196
+ value >>>= 7;
197
+ if (value > 0) byte |= 128;
198
+ out[pos++] = byte;
199
+ } while (value > 0);
200
+ return pos;
201
+ }
202
+ function readVarUint(data, offset) {
203
+ let value = 0, shift = 0, bytesRead = 0;
204
+ do {
205
+ if (offset + bytesRead >= data.length) break;
206
+ const byte = data[offset + bytesRead];
207
+ value |= (byte & 127) << shift;
208
+ bytesRead++;
209
+ if ((byte & 128) === 0) break;
210
+ shift += 7;
211
+ } while (shift < 35);
212
+ return { value: value >>> 0, bytesRead };
213
+ }
214
+ function concatUint8Arrays(arrays) {
215
+ let totalLength = 0;
216
+ for (const arr of arrays) totalLength += arr.length;
217
+ const result = new Uint8Array(totalLength);
218
+ let offset = 0;
219
+ for (const arr of arrays) {
220
+ result.set(arr, offset);
221
+ offset += arr.length;
222
+ }
223
+ return result;
224
+ }
225
+ function serializeBinaryMessage(message, args, encoder = defaultBinaryEncoder) {
226
+ let argsDataLen = 0;
227
+ let argBufs = null;
228
+ if (args && args.length > 0) {
229
+ argBufs = new Array(args.length);
230
+ for (let i = 0; i < args.length; i++) {
231
+ const buf = encoder.encode(args[i]);
232
+ argBufs[i] = buf;
233
+ argsDataLen += buf.length;
234
+ }
235
+ }
236
+ const callType = message.CallType ?? 0;
237
+ const relatedId = message.RelatedId ?? 0;
238
+ const methodBytes = textEncoder.encode(message.Method ?? "");
239
+ const relatedIdLen = varUintByteLen(relatedId);
240
+ const methodLenVarintLen = varUintByteLen(methodBytes.length);
241
+ const headerSize = 1 + relatedIdLen + methodLenVarintLen + methodBytes.length;
242
+ const totalSize = headerSize + 4 + argsDataLen;
243
+ const out = new Uint8Array(totalSize);
244
+ let pos = 0;
245
+ out[pos++] = callType << 5 & 224;
246
+ pos = writeVarUintInto(out, pos, relatedId);
247
+ pos = writeVarUintInto(out, pos, methodBytes.length);
248
+ out.set(methodBytes, pos);
249
+ pos += methodBytes.length;
250
+ out[pos++] = argsDataLen & 255;
251
+ out[pos++] = argsDataLen >>> 8 & 255;
252
+ out[pos++] = argsDataLen >>> 16 & 255;
253
+ out[pos++] = argsDataLen >>> 24 & 255;
254
+ if (argBufs !== null) {
255
+ for (const buf of argBufs) {
256
+ out.set(buf, pos);
257
+ pos += buf.length;
258
+ }
259
+ }
260
+ return out;
261
+ }
262
+ function deserializeBinaryMessage(data, offset, decoder = defaultBinaryDecoder) {
263
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
264
+ let pos = offset;
265
+ const byte0 = data[pos++];
266
+ const callTypeId = byte0 >> 5 & 7;
267
+ const headerCount = byte0 & 31;
268
+ const relId = readVarUint(data, pos);
269
+ pos += relId.bytesRead;
270
+ const methodLen = readVarUint(data, pos);
271
+ pos += methodLen.bytesRead;
272
+ const methodBytes = data.subarray(pos, pos + methodLen.value);
273
+ const method = textDecoder.decode(methodBytes);
274
+ pos += methodLen.value;
275
+ const argDataLen = view.getInt32(pos, true);
276
+ pos += 4;
277
+ if (headerCount > 0) {
278
+ for (let h = 0; h < headerCount; h++) {
279
+ const keyLen = data[pos++];
280
+ pos += keyLen;
281
+ const valLen = readVarUint(data, pos);
282
+ pos += valLen.bytesRead + valLen.value;
283
+ }
284
+ }
285
+ const args = [];
286
+ const argEnd = pos + argDataLen;
287
+ if (argDataLen > 0) {
288
+ const argSlice = data.subarray(pos, argEnd);
289
+ for (const decoded of decoder.decodeMulti(argSlice)) {
290
+ args.push(decoded);
291
+ }
292
+ pos = argEnd;
293
+ }
294
+ const message = {
295
+ Method: method,
296
+ RelatedId: relId.value,
297
+ CallType: callTypeId
298
+ };
299
+ return { message, args, bytesRead: pos - offset };
300
+ }
301
+ function splitBinaryFrame(frame, decoder = defaultBinaryDecoder) {
302
+ const results = [];
303
+ let offset = 0;
304
+ while (offset < frame.length) {
305
+ const { message, args, bytesRead } = deserializeBinaryMessage(
306
+ frame,
307
+ offset,
308
+ decoder
309
+ );
310
+ if (bytesRead <= 0) break;
311
+ results.push({ message, args });
312
+ offset += bytesRead;
313
+ }
314
+ return results;
315
+ }
316
+ function serializeBinaryFrame(messages) {
317
+ return concatUint8Arrays(messages);
318
+ }
319
+ function serializeCompactBinaryMessage(message, args, registry, encoder = defaultBinaryEncoder) {
320
+ let argsDataLen = 0;
321
+ let argBufs = null;
322
+ if (args && args.length > 0) {
323
+ argBufs = new Array(args.length);
324
+ for (let i = 0; i < args.length; i++) {
325
+ const buf = encoder.encode(args[i]);
326
+ argBufs[i] = buf;
327
+ argsDataLen += buf.length;
328
+ }
329
+ }
330
+ const methodName = message.Method ?? "";
331
+ const methodHash = registry?.requireHash(methodName) ?? 0;
332
+ const callType = message.CallType ?? 0;
333
+ const relatedId = message.RelatedId ?? 0;
334
+ const relatedIdLen = varUintByteLen(relatedId);
335
+ const headerSize = 1 + relatedIdLen + 4;
336
+ const totalSize = headerSize + 4 + argsDataLen;
337
+ const out = new Uint8Array(totalSize);
338
+ let pos = 0;
339
+ out[pos++] = callType << 5 & 224;
340
+ pos = writeVarUintInto(out, pos, relatedId);
341
+ const hashU32 = methodHash >>> 0;
342
+ out[pos++] = hashU32 & 255;
343
+ out[pos++] = hashU32 >>> 8 & 255;
344
+ out[pos++] = hashU32 >>> 16 & 255;
345
+ out[pos++] = hashU32 >>> 24 & 255;
346
+ out[pos++] = argsDataLen & 255;
347
+ out[pos++] = argsDataLen >>> 8 & 255;
348
+ out[pos++] = argsDataLen >>> 16 & 255;
349
+ out[pos++] = argsDataLen >>> 24 & 255;
350
+ if (argBufs !== null) {
351
+ for (const buf of argBufs) {
352
+ out.set(buf, pos);
353
+ pos += buf.length;
354
+ }
355
+ }
356
+ return out;
357
+ }
358
+ function deserializeCompactBinaryMessage(data, offset, registry, decoder = defaultBinaryDecoder) {
359
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
360
+ let pos = offset;
361
+ const byte0 = data[pos++];
362
+ const callTypeId = byte0 >> 5 & 7;
363
+ const headerCount = byte0 & 31;
364
+ const relId = readVarUint(data, pos);
365
+ pos += relId.bytesRead;
366
+ const methodHash = view.getUint32(pos, true);
367
+ pos += 4;
368
+ const method = registry?.getName(methodHash | 0) ?? `<hash:0x${methodHash.toString(16).padStart(8, "0")}>`;
369
+ const argDataLen = view.getInt32(pos, true);
370
+ pos += 4;
371
+ if (headerCount > 0) {
372
+ for (let h = 0; h < headerCount; h++) {
373
+ const keyLen = data[pos++];
374
+ pos += keyLen;
375
+ const valLen = readVarUint(data, pos);
376
+ pos += valLen.bytesRead + valLen.value;
377
+ }
378
+ }
379
+ const args = [];
380
+ const argEnd = pos + argDataLen;
381
+ if (argDataLen > 0) {
382
+ const argSlice = data.subarray(pos, argEnd);
383
+ for (const decoded of decoder.decodeMulti(argSlice)) {
384
+ args.push(decoded);
385
+ }
386
+ pos = argEnd;
387
+ }
388
+ const message = {
389
+ Method: method,
390
+ RelatedId: relId.value,
391
+ CallType: callTypeId
392
+ };
393
+ return { message, args, bytesRead: pos - offset };
394
+ }
395
+ function splitCompactBinaryFrame(frame, registry, decoder = defaultBinaryDecoder) {
396
+ const results = [];
397
+ let offset = 0;
398
+ while (offset < frame.length) {
399
+ const { message, args, bytesRead } = deserializeCompactBinaryMessage(
400
+ frame,
401
+ offset,
402
+ registry,
403
+ decoder
404
+ );
405
+ if (bytesRead <= 0) break;
406
+ results.push({ message, args });
407
+ offset += bytesRead;
408
+ }
409
+ return results;
410
+ }
133
411
 
134
412
  // src/rpc-connection.ts
413
+ var import_msgpack2 = require("@msgpack/msgpack");
135
414
  var import_core = require("@actuallab/core");
136
415
  var WebSocketState = {
137
416
  CONNECTING: 0,
@@ -143,11 +422,36 @@ var RpcWebSocketConnection = class {
143
422
  _ws;
144
423
  _sendBuffer = [];
145
424
  _connected = new import_core.PromiseSource();
425
+ /** Per-connection msgpack encoder — reused across outbound messages to
426
+ * amortise construction cost and to keep the internal write buffer at
427
+ * its largest observed size (avoids repeated `resizeBuffer` growth on
428
+ * large video frames). See serializeBinaryMessage() for details. */
429
+ _encoder = createBinaryEncoder();
430
+ /** Per-connection msgpack decoder — reused across inbound messages
431
+ * rather than reconstructing one for every `decodeMulti` call. */
432
+ _decoder = new import_msgpack2.Decoder();
433
+ /** Exposed for callers who need to encode outbound binary messages
434
+ * through this connection (e.g. `serializeBinaryMessage`). Safe to
435
+ * pass to synchronous encode calls on the same event-loop turn. */
436
+ get encoder() {
437
+ return this._encoder;
438
+ }
439
+ get decoder() {
440
+ return this._decoder;
441
+ }
442
+ _format;
443
+ _methodRegistry;
444
+ binaryMode;
146
445
  messageReceived = new import_core.EventHandlerSet();
147
446
  closed = new import_core.EventHandlerSet();
148
447
  error = new import_core.EventHandlerSet();
149
- constructor(ws) {
448
+ constructor(ws, binaryMode = false, format, methodRegistry) {
150
449
  this._ws = ws;
450
+ this.binaryMode = binaryMode;
451
+ this._format = format;
452
+ this._methodRegistry = methodRegistry;
453
+ if (binaryMode && ws.binaryType !== void 0)
454
+ ws.binaryType = "arraybuffer";
151
455
  if (ws.readyState === WebSocketState.OPEN) {
152
456
  this._connected.resolve();
153
457
  this._flush();
@@ -157,10 +461,46 @@ var RpcWebSocketConnection = class {
157
461
  this._flush();
158
462
  };
159
463
  ws.onmessage = (ev) => {
160
- const data = typeof ev.data === "string" ? ev.data : String(ev.data);
161
- const messages = splitFrame(data);
162
- for (const msg of messages) {
163
- if (msg.length > 0) this.messageReceived.trigger(msg);
464
+ if (ev.data instanceof Uint8Array || ev.data instanceof ArrayBuffer) {
465
+ const frame = ev.data instanceof Uint8Array ? ev.data : new Uint8Array(ev.data);
466
+ try {
467
+ const messages = this._splitBinary(frame);
468
+ for (const { message, args } of messages) {
469
+ this.messageReceived.trigger({
470
+ kind: "binary",
471
+ message,
472
+ args
473
+ });
474
+ }
475
+ } catch (e) {
476
+ this.error.trigger(e);
477
+ }
478
+ } else if (typeof Blob !== "undefined" && ev.data instanceof Blob && this.binaryMode) {
479
+ void ev.data.arrayBuffer().then((ab) => {
480
+ const frame = new Uint8Array(ab);
481
+ try {
482
+ const messages = this._splitBinary(frame);
483
+ for (const { message, args } of messages) {
484
+ this.messageReceived.trigger({
485
+ kind: "binary",
486
+ message,
487
+ args
488
+ });
489
+ }
490
+ } catch (e) {
491
+ this.error.trigger(e);
492
+ }
493
+ });
494
+ } else {
495
+ const data = typeof ev.data === "string" ? ev.data : String(ev.data);
496
+ const messages = splitFrame(data);
497
+ for (const msg of messages) {
498
+ if (msg.length > 0)
499
+ this.messageReceived.trigger({
500
+ kind: "text",
501
+ raw: msg
502
+ });
503
+ }
164
504
  }
165
505
  };
166
506
  ws.onclose = (ev) => {
@@ -177,27 +517,46 @@ var RpcWebSocketConnection = class {
177
517
  return this._connected.promise;
178
518
  }
179
519
  send(serializedMessage) {
180
- try {
181
- if (this._ws.readyState === WebSocketState.OPEN)
182
- this._ws.send(serializedMessage);
183
- else if (this._ws.readyState === WebSocketState.CONNECTING)
184
- this._sendBuffer.push(serializedMessage);
185
- } catch {
186
- }
520
+ this._sendRaw(serializedMessage);
521
+ }
522
+ sendBinary(data) {
523
+ this._sendRaw(data);
524
+ }
525
+ sendTextBatch(messages) {
526
+ this._sendRaw(serializeFrame(messages));
187
527
  }
188
- sendBatch(messages) {
189
- const frame = serializeFrame(messages);
190
- this.send(frame);
528
+ sendBinaryBatch(messages) {
529
+ this._sendRaw(serializeBinaryFrame(messages));
530
+ }
531
+ /** Split a binary frame using the format (compact-aware) or default splitter. */
532
+ _splitBinary(frame) {
533
+ if (this._format) {
534
+ return this._format.splitBinaryFrame(
535
+ frame,
536
+ this._decoder,
537
+ this._methodRegistry
538
+ );
539
+ }
540
+ return splitBinaryFrame(frame, this._decoder);
191
541
  }
192
542
  close(code, reason) {
193
543
  this._ws.close(code, reason);
194
544
  }
545
+ _sendRaw(data) {
546
+ try {
547
+ if (this._ws.readyState === WebSocketState.OPEN) {
548
+ this._ws.send(data);
549
+ } else if (this._ws.readyState === WebSocketState.CONNECTING)
550
+ this._sendBuffer.push(data);
551
+ } catch {
552
+ }
553
+ }
195
554
  _flush() {
196
555
  if (this._sendBuffer.length === 0) return;
197
- const frame = serializeFrame(this._sendBuffer);
556
+ const buffer = this._sendBuffer;
198
557
  this._sendBuffer = [];
199
558
  try {
200
- this._ws.send(frame);
559
+ for (const item of buffer) this._ws.send(item);
201
560
  } catch {
202
561
  }
203
562
  }
@@ -208,6 +567,7 @@ var import_core2 = require("@actuallab/core");
208
567
  var RpcMessageChannelConnection = class {
209
568
  _port;
210
569
  _open = true;
570
+ binaryMode = false;
211
571
  messageReceived = new import_core2.EventHandlerSet();
212
572
  closed = new import_core2.EventHandlerSet();
213
573
  whenConnected = Promise.resolve();
@@ -217,7 +577,8 @@ var RpcMessageChannelConnection = class {
217
577
  port.onmessage = (ev) => {
218
578
  const data = typeof ev.data === "string" ? ev.data : String(ev.data);
219
579
  for (const msg of splitFrame(data))
220
- if (msg.length > 0) this.messageReceived.trigger(msg);
580
+ if (msg.length > 0)
581
+ this.messageReceived.trigger({ kind: "text", raw: msg });
221
582
  };
222
583
  }
223
584
  get isOpen() {
@@ -230,6 +591,13 @@ var RpcMessageChannelConnection = class {
230
591
  } catch {
231
592
  }
232
593
  }
594
+ sendBinary(data) {
595
+ if (!this._open) return;
596
+ try {
597
+ this._port.postMessage(data, [data.buffer]);
598
+ } catch {
599
+ }
600
+ }
233
601
  close(code, reason) {
234
602
  if (!this._open) return;
235
603
  this._open = false;
@@ -284,8 +652,8 @@ var RpcOutboundCall = class {
284
652
  /** Whether to remove this call from the tracker on $sys.Ok. Default: true.
285
653
  * Subclasses (e.g. compute calls) override to false to stay in tracker for invalidation. */
286
654
  removeOnOk = true;
287
- /** The serialized wire message — stored for re-sending on reconnect. */
288
- serializedMessage = "";
655
+ /** The serialized wire data — stored for re-sending on reconnect. */
656
+ serializedWireData = "";
289
657
  constructor(callId, method) {
290
658
  this.callId = callId;
291
659
  this.method = method;
@@ -375,6 +743,7 @@ var RpcInboundCallTracker = class {
375
743
  };
376
744
 
377
745
  // src/rpc-stream.ts
746
+ var import_denque = __toESM(require("denque"), 1);
378
747
  var import_core4 = require("@actuallab/core");
379
748
 
380
749
  // src/rpc-object.ts
@@ -382,25 +751,49 @@ var RpcObjectKind = { Local: 0, Remote: 1 };
382
751
 
383
752
  // src/rpc-stream.ts
384
753
  function parseStreamRef(value) {
385
- if (typeof value !== "string") return null;
386
- const parts = value.split(",");
387
- if (parts.length < 4 || parts.length > 5) return null;
388
- const hostId = parts[0];
389
- const localId = parseInt(parts[1], 10);
390
- const ackPeriod = parseInt(parts[2], 10);
391
- const ackAdvance = parseInt(parts[3], 10);
392
- if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance)) return null;
393
- const allowReconnect = parts.length < 5 || parts[4] !== "0";
394
- return { hostId, localId, ackPeriod, ackAdvance, allowReconnect };
754
+ if (typeof value === "string") {
755
+ const parts = value.split(",");
756
+ if (parts.length < 4 || parts.length > 6) return null;
757
+ const hostId = parts[0];
758
+ const localId = parseInt(parts[1], 10);
759
+ const ackPeriod = parseInt(parts[2], 10);
760
+ const ackAdvance = parseInt(parts[3], 10);
761
+ if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance))
762
+ return null;
763
+ const allowReconnect = parts.length < 5 || parts[4] !== "0";
764
+ const isRealTime = parts.length >= 6 && parts[5] === "1";
765
+ return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
766
+ }
767
+ if (typeof value === "object" && value !== null) {
768
+ const obj = value;
769
+ const serializedId = obj.SerializedId;
770
+ if (!Array.isArray(serializedId) || serializedId.length < 2)
771
+ return null;
772
+ const rawHostId = serializedId[0];
773
+ const hostId = String(rawHostId);
774
+ const localId = Number(serializedId[1]);
775
+ const ackPeriod = Number(obj.AckPeriod ?? 256);
776
+ const ackAdvance = Number(obj.AckAdvance ?? 128);
777
+ const allowReconnect = obj.AllowReconnect !== false;
778
+ const isRealTime = obj.IsRealTime === true;
779
+ return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
780
+ }
781
+ return null;
395
782
  }
396
- var RpcStream = class {
783
+ var RpcStream = class _RpcStream {
397
784
  id;
398
785
  kind = RpcObjectKind.Remote;
399
786
  allowReconnect;
400
787
  peer;
401
788
  ackPeriod;
402
789
  ackAdvance;
403
- _buffer = [];
790
+ // Double-ended queue so consumption via `shift()` is O(1) and the
791
+ // backing store frees memory as items are drained. The previous
792
+ // `T[]` buffer kept every item for the life of the stream because
793
+ // the iterator tracked a read index instead of shifting — fine for
794
+ // short runs but a slow leak in the browser where a video call can
795
+ // last an hour.
796
+ _buffer = new import_denque.default();
404
797
  _nextExpectedIndex = 0;
405
798
  _consumerWaiting = null;
406
799
  _completed = false;
@@ -420,6 +813,17 @@ var RpcStream = class {
420
813
  onItem(index, item) {
421
814
  if (this._disposed || this._completed) return;
422
815
  if (index > this._nextExpectedIndex) {
816
+ console.warn(
817
+ `[RpcStream] item index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
818
+ );
819
+ if (!this.allowReconnect) {
820
+ this._completed = true;
821
+ this._completionError = new Error(
822
+ `Stream gap at index ${index} (expected ${this._nextExpectedIndex}); reconnect not allowed`
823
+ );
824
+ this._notifyConsumer();
825
+ return;
826
+ }
423
827
  this._sendAck(this._nextExpectedIndex, true);
424
828
  return;
425
829
  }
@@ -436,6 +840,17 @@ var RpcStream = class {
436
840
  onBatch(index, items) {
437
841
  if (this._disposed || this._completed) return;
438
842
  if (index > this._nextExpectedIndex) {
843
+ console.warn(
844
+ `[RpcStream] batch index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
845
+ );
846
+ if (!this.allowReconnect) {
847
+ this._completed = true;
848
+ this._completionError = new Error(
849
+ `Stream gap at index ${index} (expected ${this._nextExpectedIndex}); reconnect not allowed`
850
+ );
851
+ this._notifyConsumer();
852
+ return;
853
+ }
439
854
  this._sendAck(this._nextExpectedIndex, true);
440
855
  return;
441
856
  }
@@ -471,10 +886,9 @@ var RpcStream = class {
471
886
  }
472
887
  // -- AsyncIterable --
473
888
  [Symbol.asyncIterator]() {
474
- if (this._iterating) throw new Error("RpcStream can only be iterated once.");
889
+ if (this._iterating)
890
+ throw new Error("RpcStream can only be iterated once.");
475
891
  this._iterating = true;
476
- let bufferIndex = 0;
477
- let consumedIndex = 0;
478
892
  const self = this;
479
893
  return {
480
894
  async next() {
@@ -483,10 +897,8 @@ var RpcStream = class {
483
897
  self._sendAck(0, true);
484
898
  }
485
899
  while (true) {
486
- if (bufferIndex < self._buffer.length) {
487
- const value = self._buffer[bufferIndex];
488
- bufferIndex++;
489
- consumedIndex++;
900
+ if (!self._buffer.isEmpty()) {
901
+ const value = self._buffer.shift();
490
902
  return { value, done: false };
491
903
  }
492
904
  if (self._completed) {
@@ -525,17 +937,30 @@ var RpcStream = class {
525
937
  this._sendAck(nextIndex, false);
526
938
  }
527
939
  }
528
- _sendAck(nextIndex, _mustReset) {
940
+ static _emptyGuid = "00000000-0000-0000-0000-000000000000";
941
+ _sendAck(nextIndex, mustReset) {
529
942
  this._ackSentUpTo = nextIndex;
530
943
  const conn = this.peer.connection;
531
944
  if (conn) {
532
- this.peer.hub.systemCallSender.ack(conn, this.id.localId, nextIndex, this.id.hostId);
945
+ const hostId = mustReset ? this.id.hostId : _RpcStream._emptyGuid;
946
+ this.peer.hub.systemCallSender.ack(
947
+ conn,
948
+ this.peer.format,
949
+ this.id.localId,
950
+ nextIndex,
951
+ hostId
952
+ );
533
953
  }
534
954
  }
535
955
  _sendAckEnd() {
536
956
  const conn = this.peer.connection;
537
957
  if (conn) {
538
- this.peer.hub.systemCallSender.ackEnd(conn, this.id.localId, this.id.hostId);
958
+ this.peer.hub.systemCallSender.ackEnd(
959
+ conn,
960
+ this.peer.format,
961
+ this.id.localId,
962
+ this.id.hostId
963
+ );
539
964
  }
540
965
  }
541
966
  };
@@ -557,6 +982,8 @@ function resolveStreamRefs(value, peer) {
557
982
  return value;
558
983
  }
559
984
  if (typeof value === "object") {
985
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer)
986
+ return value;
560
987
  for (const key of Object.keys(value)) {
561
988
  value[key] = resolveStreamRefs(
562
989
  value[key],
@@ -602,21 +1029,39 @@ var RpcSystemCallHandler = class {
602
1029
  }
603
1030
  case RpcSystemCalls.item: {
604
1031
  const stream = peer.remoteObjects.get(relatedId);
605
- if (stream) stream.onItem(args[0], resolveStreamRefs(args[1], peer));
1032
+ if (!stream) {
1033
+ console.warn(
1034
+ `[RpcSysHandler] $sys.I: no stream for relatedId=${relatedId}`
1035
+ );
1036
+ } else {
1037
+ stream.onItem(
1038
+ args[0],
1039
+ resolveStreamRefs(args[1], peer)
1040
+ );
1041
+ }
606
1042
  break;
607
1043
  }
608
1044
  case RpcSystemCalls.batch: {
609
1045
  const stream = peer.remoteObjects.get(relatedId);
610
- if (stream) {
1046
+ if (!stream) {
1047
+ console.warn(
1048
+ `[RpcSysHandler] $sys.B: no stream for relatedId=${relatedId}`
1049
+ );
1050
+ } else if (Array.isArray(args[1])) {
611
1051
  const items = args[1];
612
- for (let i = 0; i < items.length; i++) items[i] = resolveStreamRefs(items[i], peer);
1052
+ for (let i = 0; i < items.length; i++)
1053
+ items[i] = resolveStreamRefs(items[i], peer);
613
1054
  stream.onBatch(args[0], items);
614
1055
  }
615
1056
  break;
616
1057
  }
617
1058
  case RpcSystemCalls.end: {
618
1059
  const stream = peer.remoteObjects.get(relatedId);
619
- if (stream) {
1060
+ if (!stream) {
1061
+ console.warn(
1062
+ `[RpcSysHandler] $sys.End: no stream for relatedId=${relatedId}`
1063
+ );
1064
+ } else {
620
1065
  const errorInfo = args[1];
621
1066
  const msg = errorInfo?.Message ?? errorInfo?.message;
622
1067
  const error = msg ? new Error(msg) : null;
@@ -634,76 +1079,142 @@ var RpcSystemCallHandler = class {
634
1079
  sender?.onAckEnd(args[0]);
635
1080
  break;
636
1081
  }
1082
+ default: {
1083
+ if (method === "$sys.Disconnect" || method?.startsWith("$sys.Disconnect")) {
1084
+ const ids = args[0];
1085
+ if (Array.isArray(ids)) {
1086
+ for (const id of ids) {
1087
+ const remoteObj = peer.remoteObjects.get(id);
1088
+ if (remoteObj && typeof remoteObj.disconnect === "function") {
1089
+ remoteObj.disconnect();
1090
+ }
1091
+ const sharedObj = peer.sharedObjects.get(id);
1092
+ if (sharedObj && typeof sharedObj.disconnect === "function") {
1093
+ sharedObj.disconnect();
1094
+ }
1095
+ }
1096
+ }
1097
+ }
1098
+ break;
1099
+ }
637
1100
  }
638
1101
  }
639
1102
  };
640
1103
 
641
1104
  // src/rpc-system-call-sender.ts
642
- var RpcSystemCallSender = class {
643
- handshake(conn, peerId, hubId, index) {
644
- const msg = serializeMessage({ Method: RpcSystemCalls.handshake }, [{
1105
+ var RpcSystemCallSender = class _RpcSystemCallSender {
1106
+ // Reusable envelopes — one per hot-path method.
1107
+ _itemEnv = {
1108
+ Method: RpcSystemCalls.item,
1109
+ RelatedId: 0
1110
+ };
1111
+ _batchEnv = {
1112
+ Method: RpcSystemCalls.batch,
1113
+ RelatedId: 0
1114
+ };
1115
+ _endEnv = {
1116
+ Method: RpcSystemCalls.end,
1117
+ RelatedId: 0
1118
+ };
1119
+ _ackEnv = {
1120
+ Method: RpcSystemCalls.ack,
1121
+ RelatedId: 0
1122
+ };
1123
+ _ackEndEnv = {
1124
+ Method: RpcSystemCalls.ackEnd,
1125
+ RelatedId: 0
1126
+ };
1127
+ // Reusable arg arrays.
1128
+ _itemArgs = [0, null];
1129
+ _batchArgs = [0, null];
1130
+ _endArgs = [0, { TypeRef: "", Message: "" }];
1131
+ _ackArgs = [0, ""];
1132
+ _ackEndArgs = [""];
1133
+ static NO_ERROR = Object.freeze({ TypeRef: "", Message: "" });
1134
+ registry;
1135
+ _send(conn, format, envelope, args) {
1136
+ const wireData = format.serializeMessage(
1137
+ envelope,
1138
+ args,
1139
+ conn.encoder,
1140
+ this.registry
1141
+ );
1142
+ if (typeof wireData === "string") {
1143
+ conn.send(wireData);
1144
+ } else {
1145
+ conn.sendBinary(wireData);
1146
+ }
1147
+ }
1148
+ handshake(conn, format, peerId, hubId, index) {
1149
+ const handshakeArg = format.isBinary ? [peerId, null, hubId, 2, index] : {
645
1150
  RemotePeerId: peerId,
646
1151
  RemoteApiVersionSet: null,
647
1152
  RemoteHubId: hubId,
648
1153
  ProtocolVersion: 2,
649
1154
  Index: index
650
- }]);
651
- conn.send(msg);
652
- }
653
- ok(conn, relatedId, result) {
654
- const msg = serializeMessage({ Method: RpcSystemCalls.ok, RelatedId: relatedId }, [result]);
655
- conn.send(msg);
1155
+ };
1156
+ this._send(conn, format, { Method: RpcSystemCalls.handshake }, [
1157
+ handshakeArg
1158
+ ]);
1159
+ }
1160
+ ok(conn, format, relatedId, result) {
1161
+ this._send(
1162
+ conn,
1163
+ format,
1164
+ { Method: RpcSystemCalls.ok, RelatedId: relatedId },
1165
+ [result]
1166
+ );
656
1167
  }
657
- error(conn, relatedId, error) {
1168
+ error(conn, format, relatedId, error) {
658
1169
  const message = error instanceof Error ? error.message : String(error);
659
- const msg = serializeMessage(
1170
+ this._send(
1171
+ conn,
1172
+ format,
660
1173
  { Method: RpcSystemCalls.error, RelatedId: relatedId },
661
1174
  [{ Message: message }]
662
1175
  );
663
- conn.send(msg);
664
- }
665
- cancel(conn, relatedId) {
666
- const msg = serializeMessage({ Method: RpcSystemCalls.cancel, RelatedId: relatedId });
667
- conn.send(msg);
668
- }
669
- keepAlive(conn, activeCallIds) {
670
- const msg = serializeMessage({ Method: RpcSystemCalls.keepAlive }, [activeCallIds]);
671
- conn.send(msg);
672
- }
673
- item(conn, localId, index, item) {
674
- const msg = serializeMessage(
675
- { Method: RpcSystemCalls.item, RelatedId: localId },
676
- [index, item]
677
- );
678
- conn.send(msg);
679
1176
  }
680
- batch(conn, localId, index, items) {
681
- const msg = serializeMessage(
682
- { Method: RpcSystemCalls.batch, RelatedId: localId },
683
- [index, items]
684
- );
685
- conn.send(msg);
686
- }
687
- end(conn, localId, index, error = null) {
688
- const msg = serializeMessage(
689
- { Method: RpcSystemCalls.end, RelatedId: localId },
690
- [index, error]
691
- );
692
- conn.send(msg);
693
- }
694
- ack(conn, localId, nextIndex, hostId) {
695
- const msg = serializeMessage(
696
- { Method: RpcSystemCalls.ack, RelatedId: localId },
697
- [nextIndex, hostId]
698
- );
699
- conn.send(msg);
1177
+ cancel(conn, format, relatedId) {
1178
+ this._send(conn, format, {
1179
+ Method: RpcSystemCalls.cancel,
1180
+ RelatedId: relatedId
1181
+ });
700
1182
  }
701
- ackEnd(conn, localId, hostId) {
702
- const msg = serializeMessage(
703
- { Method: RpcSystemCalls.ackEnd, RelatedId: localId },
704
- [hostId]
705
- );
706
- conn.send(msg);
1183
+ keepAlive(conn, format, activeCallIds) {
1184
+ this._send(conn, format, { Method: RpcSystemCalls.keepAlive }, [
1185
+ activeCallIds
1186
+ ]);
1187
+ }
1188
+ item(conn, format, localId, index, item) {
1189
+ this._itemEnv.RelatedId = localId;
1190
+ this._itemArgs[0] = index;
1191
+ this._itemArgs[1] = item;
1192
+ this._send(conn, format, this._itemEnv, this._itemArgs);
1193
+ this._itemArgs[1] = null;
1194
+ }
1195
+ batch(conn, format, localId, index, items) {
1196
+ this._batchEnv.RelatedId = localId;
1197
+ this._batchArgs[0] = index;
1198
+ this._batchArgs[1] = items;
1199
+ this._send(conn, format, this._batchEnv, this._batchArgs);
1200
+ this._batchArgs[1] = null;
1201
+ }
1202
+ end(conn, format, localId, index, error = _RpcSystemCallSender.NO_ERROR) {
1203
+ this._endEnv.RelatedId = localId;
1204
+ this._endArgs[0] = index;
1205
+ this._endArgs[1] = error;
1206
+ this._send(conn, format, this._endEnv, this._endArgs);
1207
+ }
1208
+ ack(conn, format, localId, nextIndex, hostId) {
1209
+ this._ackEnv.RelatedId = localId;
1210
+ this._ackArgs[0] = nextIndex;
1211
+ this._ackArgs[1] = hostId;
1212
+ this._send(conn, format, this._ackEnv, this._ackArgs);
1213
+ }
1214
+ ackEnd(conn, format, localId, hostId) {
1215
+ this._ackEndEnv.RelatedId = localId;
1216
+ this._ackEndArgs[0] = hostId;
1217
+ this._send(conn, format, this._ackEndEnv, this._ackEndArgs);
707
1218
  }
708
1219
  };
709
1220
 
@@ -715,29 +1226,42 @@ var RpcStreamSender = class {
715
1226
  id;
716
1227
  kind = RpcObjectKind.Local;
717
1228
  allowReconnect;
1229
+ isRealTime;
1230
+ canSkipTo;
718
1231
  peer;
719
1232
  ackPeriod;
720
1233
  ackAdvance;
721
1234
  _nextIndex = 0;
722
1235
  _ended = false;
723
1236
  _started = new import_core5.PromiseSource();
724
- constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true) {
1237
+ _lastAckedIndex = 0;
1238
+ _ackWaiting = null;
1239
+ constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true, isRealTime = false, canSkipTo = () => true) {
725
1240
  const localId = peer.sharedObjects.nextId();
726
1241
  this.id = { hostId: peer.hub.hubId, localId };
727
1242
  this.allowReconnect = allowReconnect;
1243
+ this.isRealTime = isRealTime;
1244
+ this.canSkipTo = canSkipTo;
728
1245
  this.peer = peer;
729
1246
  this.ackPeriod = ackPeriod;
730
1247
  this.ackAdvance = ackAdvance;
731
1248
  }
732
1249
  /** Returns the stream reference string for the $sys.Ok response. */
733
1250
  toRef() {
734
- return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"}`;
1251
+ return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"},${this.isRealTime ? "1" : "0"}`;
735
1252
  }
736
1253
  /** Called by system call handler when $sys.Ack is received from the client. */
737
- onAck(_nextIndex, _hostId) {
1254
+ onAck(nextIndex, _hostId) {
738
1255
  if (!this._started.isCompleted) {
739
1256
  this._started.resolve();
740
1257
  }
1258
+ if (nextIndex > this._lastAckedIndex) {
1259
+ this._lastAckedIndex = nextIndex;
1260
+ }
1261
+ if (this._ackWaiting) {
1262
+ this._ackWaiting.resolve();
1263
+ this._ackWaiting = null;
1264
+ }
741
1265
  }
742
1266
  /** Called by system call handler when $sys.AckEnd is received from the client. */
743
1267
  onAckEnd(_hostId) {
@@ -749,7 +1273,13 @@ var RpcStreamSender = class {
749
1273
  if (this._ended) return;
750
1274
  const conn = this.peer.connection;
751
1275
  if (!conn) return;
752
- this.peer.hub.systemCallSender.item(conn, this.id.localId, this._nextIndex, item);
1276
+ this.peer.hub.systemCallSender.item(
1277
+ conn,
1278
+ this.peer.format,
1279
+ this.id.localId,
1280
+ this._nextIndex,
1281
+ item
1282
+ );
753
1283
  this._nextIndex++;
754
1284
  }
755
1285
  /** Send a batch of items to the client. */
@@ -757,7 +1287,13 @@ var RpcStreamSender = class {
757
1287
  if (this._ended || items.length === 0) return;
758
1288
  const conn = this.peer.connection;
759
1289
  if (!conn) return;
760
- this.peer.hub.systemCallSender.batch(conn, this.id.localId, this._nextIndex, items);
1290
+ this.peer.hub.systemCallSender.batch(
1291
+ conn,
1292
+ this.peer.format,
1293
+ this.id.localId,
1294
+ this._nextIndex,
1295
+ items
1296
+ );
761
1297
  this._nextIndex += items.length;
762
1298
  }
763
1299
  /** Signal stream completion to the client. */
@@ -766,19 +1302,63 @@ var RpcStreamSender = class {
766
1302
  this._ended = true;
767
1303
  const conn = this.peer.connection;
768
1304
  if (!conn) return;
769
- const errorInfo = error ? { Message: error.message } : null;
770
- this.peer.hub.systemCallSender.end(conn, this.id.localId, this._nextIndex, errorInfo);
1305
+ const errorInfo = error ? { TypeRef: "System.Exception", Message: error.message } : { TypeRef: "", Message: "" };
1306
+ this.peer.hub.systemCallSender.end(
1307
+ conn,
1308
+ this.peer.format,
1309
+ this.id.localId,
1310
+ this._nextIndex,
1311
+ errorInfo
1312
+ );
771
1313
  }
772
1314
  /**
773
1315
  * Consume an AsyncIterable and send all items to the client.
774
1316
  * Waits for the client's initial Ack before starting to pump items.
1317
+ *
1318
+ * When `isRealTime` is true, applies flow control based on `ackAdvance`:
1319
+ * if the sender is `ackAdvance` items ahead of the last ACK, it enters
1320
+ * skip mode — draining the source and discarding items until it finds
1321
+ * one where `canSkipTo` returns true.
775
1322
  */
776
1323
  async writeFrom(source) {
777
1324
  await this._started.promise;
1325
+ const iterator = source[Symbol.asyncIterator]();
778
1326
  try {
779
- for await (const item of source) {
1327
+ while (true) {
1328
+ const next = await iterator.next();
1329
+ if (next.done || this._ended) break;
1330
+ const item = next.value;
1331
+ if (this._nextIndex < this._lastAckedIndex + this.ackAdvance) {
1332
+ this.sendItem(item);
1333
+ continue;
1334
+ }
1335
+ if (!this.isRealTime) {
1336
+ await this._waitForAckBudget();
1337
+ if (this._ended) return;
1338
+ this.sendItem(item);
1339
+ continue;
1340
+ }
1341
+ let latestSkipTarget = this.canSkipTo(item) ? item : void 0;
1342
+ let sourceExhausted = false;
1343
+ while (this._nextIndex >= this._lastAckedIndex + this.ackAdvance) {
1344
+ if (this._ended) return;
1345
+ const n = await iterator.next();
1346
+ if (n.done) {
1347
+ sourceExhausted = true;
1348
+ break;
1349
+ }
1350
+ if (this.canSkipTo(n.value)) {
1351
+ latestSkipTarget = n.value;
1352
+ }
1353
+ }
780
1354
  if (this._ended) return;
781
- this.sendItem(item);
1355
+ if (latestSkipTarget !== void 0) {
1356
+ this.sendItem(latestSkipTarget);
1357
+ }
1358
+ if (sourceExhausted) {
1359
+ if (!this._ended) this.sendEnd();
1360
+ return;
1361
+ }
782
1362
  }
783
1363
  if (!this._ended) {
784
1364
  this.sendEnd();
@@ -789,6 +1369,14 @@ var RpcStreamSender = class {
789
1369
  }
790
1370
  }
791
1371
  }
1372
+ /** Wait until _nextIndex < _lastAckedIndex + ackAdvance. */
1373
+ async _waitForAckBudget() {
1374
+ while (this._nextIndex >= this._lastAckedIndex + this.ackAdvance) {
1375
+ if (this._ended) return;
1376
+ this._ackWaiting = new import_core5.PromiseSource();
1377
+ await this._ackWaiting.promise;
1378
+ }
1379
+ }
792
1380
  // -- IRpcObject --
793
1381
  reconnect() {
794
1382
  }
@@ -810,6 +1398,9 @@ var RpcRemoteObjectTracker = class {
810
1398
  get(localId) {
811
1399
  return this._objects.get(localId);
812
1400
  }
1401
+ keys() {
1402
+ return this._objects.keys();
1403
+ }
813
1404
  unregister(obj) {
814
1405
  this._objects.delete(obj.id.localId);
815
1406
  }
@@ -821,10 +1412,8 @@ var RpcRemoteObjectTracker = class {
821
1412
  }
822
1413
  reconnectAll() {
823
1414
  for (const obj of this._objects.values()) {
824
- if (obj.allowReconnect)
825
- obj.reconnect();
826
- else
827
- obj.disconnect();
1415
+ if (obj.allowReconnect) obj.reconnect();
1416
+ else obj.disconnect();
828
1417
  }
829
1418
  }
830
1419
  };
@@ -842,6 +1431,9 @@ var RpcSharedObjectTracker = class {
842
1431
  get(localId) {
843
1432
  return this._objects.get(localId);
844
1433
  }
1434
+ keys() {
1435
+ return this._objects.keys();
1436
+ }
845
1437
  unregister(obj) {
846
1438
  this._objects.delete(obj.id.localId);
847
1439
  }
@@ -865,8 +1457,164 @@ var RpcClientPeerReconnectDelayer = class extends import_core6.RetryDelayer {
865
1457
  }
866
1458
  };
867
1459
 
1460
+ // src/rpc-serialization-format.ts
1461
+ var import_msgpack3 = require("@msgpack/msgpack");
1462
+ var RpcSerializationFormat = class {
1463
+ /** Create a reusable binary encoder for this format. Returns undefined for text formats. */
1464
+ createEncoder() {
1465
+ return void 0;
1466
+ }
1467
+ /** Create a reusable binary decoder for this format. Returns undefined for text formats. */
1468
+ createDecoder() {
1469
+ return void 0;
1470
+ }
1471
+ // Named format instances — initialized in initFormats() below (after subclasses are defined)
1472
+ static SystemJsonV5;
1473
+ static SystemJsonV5NP;
1474
+ static NewtonsoftJsonV5;
1475
+ static NewtonsoftJsonV5NP;
1476
+ static MessagePackV6;
1477
+ static MemoryPackV6;
1478
+ static MessagePackV6C;
1479
+ static MemoryPackV6C;
1480
+ static All;
1481
+ /** Convenience shortcut for RpcSerializationFormatResolver.Default.get(key). */
1482
+ static get(key) {
1483
+ return RpcSerializationFormatResolver.Default.get(key);
1484
+ }
1485
+ /** Convenience shortcut for RpcSerializationFormatResolver.Default.tryGet(key). */
1486
+ static tryGet(key) {
1487
+ return RpcSerializationFormatResolver.Default.tryGet(key);
1488
+ }
1489
+ };
1490
+ var RpcJsonSerializationFormat = class extends RpcSerializationFormat {
1491
+ key;
1492
+ isBinary = false;
1493
+ isCompact = false;
1494
+ constructor(key) {
1495
+ super();
1496
+ this.key = key;
1497
+ }
1498
+ serializeMessage(message, args) {
1499
+ return serializeMessage(message, args);
1500
+ }
1501
+ deserializeTextMessage(raw) {
1502
+ return deserializeMessage(raw);
1503
+ }
1504
+ splitBinaryFrame() {
1505
+ throw new Error("Text format does not support binary frames");
1506
+ }
1507
+ serializeBinaryFrame() {
1508
+ throw new Error("Text format does not support binary frames");
1509
+ }
1510
+ };
1511
+ var RpcMessagePackSerializationFormat = class extends RpcSerializationFormat {
1512
+ key;
1513
+ isBinary = true;
1514
+ isCompact = false;
1515
+ constructor(key) {
1516
+ super();
1517
+ this.key = key;
1518
+ }
1519
+ serializeMessage(message, args, encoder) {
1520
+ return serializeBinaryMessage(message, args, encoder);
1521
+ }
1522
+ deserializeTextMessage(raw) {
1523
+ return deserializeMessage(raw);
1524
+ }
1525
+ splitBinaryFrame(frame, decoder) {
1526
+ return splitBinaryFrame(frame, decoder);
1527
+ }
1528
+ serializeBinaryFrame(messages) {
1529
+ return serializeBinaryFrame(messages);
1530
+ }
1531
+ createEncoder() {
1532
+ return createBinaryEncoder();
1533
+ }
1534
+ createDecoder() {
1535
+ return new import_msgpack3.Decoder();
1536
+ }
1537
+ };
1538
+ var RpcMessagePackCompactSerializationFormat = class extends RpcSerializationFormat {
1539
+ key;
1540
+ isBinary = true;
1541
+ isCompact = true;
1542
+ constructor(key) {
1543
+ super();
1544
+ this.key = key;
1545
+ }
1546
+ serializeMessage(message, args, encoder, registry) {
1547
+ return serializeCompactBinaryMessage(
1548
+ message,
1549
+ args,
1550
+ registry,
1551
+ encoder
1552
+ );
1553
+ }
1554
+ deserializeTextMessage(raw) {
1555
+ return deserializeMessage(raw);
1556
+ }
1557
+ splitBinaryFrame(frame, decoder, registry) {
1558
+ return splitCompactBinaryFrame(frame, registry, decoder);
1559
+ }
1560
+ serializeBinaryFrame(messages) {
1561
+ return serializeBinaryFrame(messages);
1562
+ }
1563
+ createEncoder() {
1564
+ return createBinaryEncoder();
1565
+ }
1566
+ createDecoder() {
1567
+ return new import_msgpack3.Decoder();
1568
+ }
1569
+ };
1570
+ RpcSerializationFormat.SystemJsonV5 = new RpcJsonSerializationFormat("json5");
1571
+ RpcSerializationFormat.SystemJsonV5NP = new RpcJsonSerializationFormat("json5np");
1572
+ RpcSerializationFormat.NewtonsoftJsonV5 = new RpcJsonSerializationFormat("njson5");
1573
+ RpcSerializationFormat.NewtonsoftJsonV5NP = new RpcJsonSerializationFormat("njson5np");
1574
+ RpcSerializationFormat.MessagePackV6 = new RpcMessagePackSerializationFormat("msgpack6");
1575
+ RpcSerializationFormat.MemoryPackV6 = new RpcMessagePackSerializationFormat("mempack6");
1576
+ RpcSerializationFormat.MessagePackV6C = new RpcMessagePackCompactSerializationFormat("msgpack6c");
1577
+ RpcSerializationFormat.MemoryPackV6C = new RpcMessagePackCompactSerializationFormat("mempack6c");
1578
+ RpcSerializationFormat.All = [
1579
+ RpcSerializationFormat.SystemJsonV5,
1580
+ RpcSerializationFormat.SystemJsonV5NP,
1581
+ RpcSerializationFormat.NewtonsoftJsonV5,
1582
+ RpcSerializationFormat.NewtonsoftJsonV5NP,
1583
+ RpcSerializationFormat.MessagePackV6,
1584
+ RpcSerializationFormat.MemoryPackV6,
1585
+ RpcSerializationFormat.MessagePackV6C,
1586
+ RpcSerializationFormat.MemoryPackV6C
1587
+ ];
1588
+ var RpcSerializationFormatResolver = class _RpcSerializationFormatResolver {
1589
+ static DefaultFormats = RpcSerializationFormat.All;
1590
+ static Default = new _RpcSerializationFormatResolver("json5np");
1591
+ defaultFormatKey;
1592
+ formats;
1593
+ get defaultFormat() {
1594
+ return this.get(this.defaultFormatKey);
1595
+ }
1596
+ constructor(defaultFormatKey, formats) {
1597
+ const map = /* @__PURE__ */ new Map();
1598
+ for (const f of formats ?? _RpcSerializationFormatResolver.DefaultFormats)
1599
+ map.set(f.key, f);
1600
+ if (!map.has(defaultFormatKey))
1601
+ throw new Error(`No format with key '${defaultFormatKey}'.`);
1602
+ this.defaultFormatKey = defaultFormatKey;
1603
+ this.formats = map;
1604
+ }
1605
+ get(key) {
1606
+ const format = this.tryGet(key);
1607
+ if (!format)
1608
+ throw new Error(`No format with key '${key}'.`);
1609
+ return format;
1610
+ }
1611
+ tryGet(key) {
1612
+ if (!key) key = this.defaultFormatKey;
1613
+ return this.formats.get(key);
1614
+ }
1615
+ };
1616
+
868
1617
  // src/rpc-peer.ts
869
- var DEFAULT_SERIALIZATION_FORMAT = "json5np";
870
1618
  var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
871
1619
  var defaultConnectionUrlResolver = (peer) => {
872
1620
  const sep = peer.ref.includes("?") ? "&" : "?";
@@ -913,17 +1661,27 @@ var RpcPeer = class {
913
1661
  this._startKeepAlive();
914
1662
  });
915
1663
  }
1664
+ /** The serialization format used by this peer. Override in subclasses. */
1665
+ get format() {
1666
+ return RpcSerializationFormatResolver.Default.defaultFormat;
1667
+ }
916
1668
  call(method, args, options) {
917
1669
  const callId = this.outbound.nextId();
918
1670
  const outboundCall = options?.outboundCallFactory ? options.outboundCallFactory(callId, method) : new RpcOutboundCall(callId, method);
919
- const msg = serializeMessage(
920
- { Method: method, RelatedId: callId, CallType: options?.callTypeId ?? 0 },
921
- args
1671
+ const envelope = {
1672
+ Method: method,
1673
+ RelatedId: callId,
1674
+ CallType: options?.callTypeId ?? 0
1675
+ };
1676
+ outboundCall.serializedWireData = this.format.serializeMessage(
1677
+ envelope,
1678
+ args,
1679
+ this._connection?.encoder,
1680
+ this._hub.registry
922
1681
  );
923
- outboundCall.serializedMessage = msg;
924
1682
  if (this._connection !== void 0) {
925
1683
  this.outbound.register(outboundCall);
926
- this._connection.send(msg);
1684
+ this._sendWireData(outboundCall.serializedWireData);
927
1685
  } else {
928
1686
  this._pendingSends.push(outboundCall);
929
1687
  }
@@ -937,12 +1695,16 @@ var RpcPeer = class {
937
1695
  outboundCall.result.reject(new Error("Call cancelled."));
938
1696
  outboundCall.onDisconnect();
939
1697
  if (peer._connection !== void 0)
940
- hub.systemCallSender.cancel(peer._connection, callId);
1698
+ hub.systemCallSender.cancel(peer._connection, peer.format, callId);
941
1699
  } else {
942
- const idx = peer._pendingSends.findIndex((c) => c.callId === callId);
1700
+ const idx = peer._pendingSends.findIndex(
1701
+ (c) => c.callId === callId
1702
+ );
943
1703
  if (idx !== -1) {
944
1704
  peer._pendingSends.splice(idx, 1);
945
- outboundCall.result.reject(new Error("Call cancelled."));
1705
+ outboundCall.result.reject(
1706
+ new Error("Call cancelled.")
1707
+ );
946
1708
  outboundCall.onDisconnect();
947
1709
  }
948
1710
  }
@@ -954,8 +1716,14 @@ var RpcPeer = class {
954
1716
  }
955
1717
  callNoWait(method, args) {
956
1718
  if (this._connection === void 0) return;
957
- const msg = serializeMessage({ Method: method, RelatedId: 0 }, args);
958
- this._connection.send(msg);
1719
+ const envelope = { Method: method, RelatedId: 0 };
1720
+ const wireData = this.format.serializeMessage(
1721
+ envelope,
1722
+ args,
1723
+ this._connection.encoder,
1724
+ this._hub.registry
1725
+ );
1726
+ this._sendWireData(wireData);
959
1727
  }
960
1728
  close() {
961
1729
  this._stopKeepAlive();
@@ -974,23 +1742,41 @@ var RpcPeer = class {
974
1742
  }
975
1743
  /** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
976
1744
  _flushPendingSends() {
977
- if (this._pendingSends.length === 0 || this._connection === void 0) return;
1745
+ if (this._pendingSends.length === 0 || this._connection === void 0)
1746
+ return;
978
1747
  for (const call of this._pendingSends) {
979
1748
  this.outbound.register(call);
980
- this._connection.send(call.serializedMessage);
1749
+ this._sendWireData(call.serializedWireData);
981
1750
  }
982
1751
  this._pendingSends.length = 0;
983
1752
  }
1753
+ /** Send pre-serialized wire data through the current connection. */
1754
+ _sendWireData(data) {
1755
+ if (this._connection === void 0) return;
1756
+ if (typeof data === "string") {
1757
+ this._connection.send(data);
1758
+ } else {
1759
+ this._connection.sendBinary(data);
1760
+ }
1761
+ }
984
1762
  /** Override in subclasses to handle the remote peer's handshake response. */
985
1763
  _onHandshakeReceived(_handshake) {
986
1764
  }
987
- _handleMessage(raw) {
988
- const { message, args } = deserializeMessage(raw);
1765
+ _handleMessage(received) {
1766
+ let message;
1767
+ let args;
1768
+ if (received.kind === "binary") {
1769
+ message = received.message;
1770
+ args = received.args;
1771
+ } else {
1772
+ const parsed = deserializeMessage(received.raw);
1773
+ message = parsed.message;
1774
+ args = parsed.args;
1775
+ }
989
1776
  const method = message.Method ?? "";
990
1777
  if (method === RpcSystemCalls.handshake) {
991
1778
  const handshake = args[0];
992
- if (handshake !== void 0)
993
- this._onHandshakeReceived(handshake);
1779
+ if (handshake !== void 0) this._onHandshakeReceived(handshake);
994
1780
  return;
995
1781
  }
996
1782
  if (method.startsWith("$sys")) {
@@ -1012,19 +1798,42 @@ var RpcPeer = class {
1012
1798
  if (serviceHost !== void 0) {
1013
1799
  void (async () => {
1014
1800
  try {
1015
- const context = this._connection !== void 0 ? { __rpcDispatch: true, callId: relatedId, connection: this._connection } : void 0;
1016
- const result = await serviceHost.dispatch(method, args, context);
1801
+ const context = this._connection !== void 0 ? {
1802
+ __rpcDispatch: true,
1803
+ callId: relatedId,
1804
+ connection: this._connection
1805
+ } : void 0;
1806
+ const result = await serviceHost.dispatch(
1807
+ method,
1808
+ args,
1809
+ context
1810
+ );
1017
1811
  if (methodDef?.stream === true && this._connection !== void 0) {
1018
1812
  const sender = new RpcStreamSender(this);
1019
1813
  this.sharedObjects.register(sender);
1020
- this._hub.systemCallSender.ok(this._connection, relatedId, sender.toRef());
1814
+ this._hub.systemCallSender.ok(
1815
+ this._connection,
1816
+ this.format,
1817
+ relatedId,
1818
+ sender.toRef()
1819
+ );
1021
1820
  void sender.writeFrom(result);
1022
1821
  } else if (!isNoWait && this._connection !== void 0) {
1023
- this._hub.systemCallSender.ok(this._connection, relatedId, result);
1822
+ this._hub.systemCallSender.ok(
1823
+ this._connection,
1824
+ this.format,
1825
+ relatedId,
1826
+ result
1827
+ );
1024
1828
  }
1025
1829
  } catch (e) {
1026
1830
  if (!isNoWait && this._connection !== void 0) {
1027
- this._hub.systemCallSender.error(this._connection, relatedId, e);
1831
+ this._hub.systemCallSender.error(
1832
+ this._connection,
1833
+ this.format,
1834
+ relatedId,
1835
+ e
1836
+ );
1028
1837
  }
1029
1838
  } finally {
1030
1839
  if (!isNoWait) {
@@ -1037,7 +1846,9 @@ var RpcPeer = class {
1037
1846
  _startKeepAlive() {
1038
1847
  this._keepAliveTimer = setInterval(() => {
1039
1848
  if (this._connection !== void 0) {
1040
- this._hub.systemCallSender.keepAlive(this._connection, this.outbound.activeCallIds());
1849
+ this._hub.systemCallSender.keepAlive(this._connection, this.format, [
1850
+ ...this.remoteObjects.keys()
1851
+ ]);
1041
1852
  }
1042
1853
  }, 15e3);
1043
1854
  }
@@ -1085,10 +1896,16 @@ var RpcClientPeer = class extends RpcPeer {
1085
1896
  this._reconnectsAt = value;
1086
1897
  this.reconnectsAtChanged.trigger();
1087
1898
  }
1899
+ _format;
1088
1900
  constructor(hub, url, serializationFormat) {
1089
1901
  super(url, hub);
1090
1902
  this.clientId = guidToBase64Url(this.id);
1091
- this.serializationFormat = serializationFormat ?? DEFAULT_SERIALIZATION_FORMAT;
1903
+ const resolver = RpcSerializationFormatResolver.Default;
1904
+ this.serializationFormat = serializationFormat ?? resolver.defaultFormatKey;
1905
+ this._format = resolver.get(this.serializationFormat);
1906
+ }
1907
+ get format() {
1908
+ return this._format;
1092
1909
  }
1093
1910
  get connectionKind() {
1094
1911
  return this._connectionKind;
@@ -1106,7 +1923,12 @@ var RpcClientPeer = class extends RpcPeer {
1106
1923
  let lastCloseReason = "";
1107
1924
  try {
1108
1925
  const ws = wsFactory?.(connUrl) ?? new WebSocket(connUrl);
1109
- const conn = new RpcWebSocketConnection(ws);
1926
+ const conn = new RpcWebSocketConnection(
1927
+ ws,
1928
+ this.format.isBinary,
1929
+ this.format,
1930
+ this._hub.registry
1931
+ );
1110
1932
  this._connectionKind = 1 /* Connecting */;
1111
1933
  conn.closed.add((ev) => {
1112
1934
  lastCloseCode = ev.code;
@@ -1115,11 +1937,21 @@ var RpcClientPeer = class extends RpcPeer {
1115
1937
  this._pendingHandshake = new import_core7.PromiseSource();
1116
1938
  this.setupConnection(conn);
1117
1939
  this._connection = void 0;
1118
- const closedRejection = new Promise((_, reject) => conn.closed.add(() => reject(new Error("Connection failed"))));
1940
+ const closedRejection = new Promise(
1941
+ (_, reject) => conn.closed.add(
1942
+ () => reject(new Error("Connection failed"))
1943
+ )
1944
+ );
1119
1945
  closedRejection.catch(() => {
1120
1946
  });
1121
1947
  await Promise.race([conn.whenConnected, closedRejection]);
1122
- this._hub.systemCallSender.handshake(conn, this.id, this._hub.hubId, ++this._handshakeIndex);
1948
+ this._hub.systemCallSender.handshake(
1949
+ conn,
1950
+ this.format,
1951
+ this.id,
1952
+ this._hub.hubId,
1953
+ ++this._handshakeIndex
1954
+ );
1123
1955
  const remoteHandshake = await Promise.race([
1124
1956
  this._pendingHandshake.promise,
1125
1957
  closedRejection
@@ -1172,7 +2004,6 @@ var RpcClientPeer = class extends RpcPeer {
1172
2004
  * Regular in-flight calls are re-sent transparently. */
1173
2005
  _reconnect(_isPeerChanged) {
1174
2006
  if (this._connection === void 0) return;
1175
- const conn = this._connection;
1176
2007
  if (_isPeerChanged) {
1177
2008
  this.remoteObjects.disconnectAll();
1178
2009
  } else {
@@ -1184,7 +2015,7 @@ var RpcClientPeer = class extends RpcPeer {
1184
2015
  call.onDisconnect();
1185
2016
  this.outbound.remove(call.callId);
1186
2017
  } else {
1187
- conn.send(call.serializedMessage);
2018
+ this._sendWireData(call.serializedWireData);
1188
2019
  }
1189
2020
  }
1190
2021
  this._flushPendingSends();
@@ -1207,7 +2038,13 @@ var RpcServerPeer = class extends RpcPeer {
1207
2038
  }
1208
2039
  _onHandshakeReceived(_handshake) {
1209
2040
  if (this._connection !== void 0) {
1210
- this._hub.systemCallSender.handshake(this._connection, this.id, this._hub.hubId, 0);
2041
+ this._hub.systemCallSender.handshake(
2042
+ this._connection,
2043
+ this.format,
2044
+ this.id,
2045
+ this._hub.hubId,
2046
+ 0
2047
+ );
1211
2048
  }
1212
2049
  }
1213
2050
  };
@@ -1235,12 +2072,16 @@ var RpcServiceHost = class {
1235
2072
  for (const methodDef of def.methods.values()) {
1236
2073
  const fn = impl[methodDef.name];
1237
2074
  if (!fn) continue;
1238
- this._methods.set(wireMethodName(methodDef), { def: methodDef, fn });
2075
+ this._methods.set(wireMethodName(methodDef), {
2076
+ def: methodDef,
2077
+ fn
2078
+ });
1239
2079
  }
1240
2080
  }
1241
2081
  async dispatch(wireMethod, args, context) {
1242
2082
  const entry = this._methods.get(wireMethod);
1243
- if (entry === void 0) throw new Error(`Method not found: ${wireMethod}`);
2083
+ if (entry === void 0)
2084
+ throw new Error(`Method not found: ${wireMethod}`);
1244
2085
  if (context !== void 0 && entry.def.callTypeId !== 0) {
1245
2086
  return await entry.fn(...args, context);
1246
2087
  }
@@ -1279,6 +2120,539 @@ function rpcMethod(options) {
1279
2120
  };
1280
2121
  }
1281
2122
 
2123
+ // src/rpc-xxhash3.ts
2124
+ var U64_MASK = 0xffffffffffffffffn;
2125
+ var U32_MASK = 0xffffffffn;
2126
+ var PRIME32_1 = 2654435761;
2127
+ var PRIME32_2 = 2246822519;
2128
+ var PRIME32_3 = 3266489917;
2129
+ var PRIME64_1 = 0x9e3779b185ebca87n;
2130
+ var PRIME64_2 = 0xc2b2ae3d27d4eb4fn;
2131
+ var PRIME64_3 = 0x165667b19e3779f9n;
2132
+ var PRIME64_4 = 0x85ebca77c2b2ae63n;
2133
+ var PRIME64_5 = 0x27d4eb2f165667c5n;
2134
+ var XXH3_SECRET_SIZE_MIN = 136;
2135
+ var XXH_SECRET_DEFAULT_SIZE = 192;
2136
+ var STRIPE_LEN = 64;
2137
+ var XXH_SECRET_CONSUME_RATE = 8;
2138
+ var ACC_NB = STRIPE_LEN / 8;
2139
+ var XXH3_MIDSIZE_MAX = 240;
2140
+ var XXH3_MIDSIZE_STARTOFFSET = 3;
2141
+ var XXH3_MIDSIZE_LASTOFFSET = 17;
2142
+ var XXH_SECRET_LASTACC_START = 7;
2143
+ var XXH_SECRET_MERGEACCS_START = 11;
2144
+ var RRMXMX = 0x9fb21c651e98df25n;
2145
+ var DEFAULT_SECRET = new Uint8Array([
2146
+ 184,
2147
+ 254,
2148
+ 108,
2149
+ 57,
2150
+ 35,
2151
+ 164,
2152
+ 75,
2153
+ 190,
2154
+ 124,
2155
+ 1,
2156
+ 129,
2157
+ 44,
2158
+ 247,
2159
+ 33,
2160
+ 173,
2161
+ 28,
2162
+ 222,
2163
+ 212,
2164
+ 109,
2165
+ 233,
2166
+ 131,
2167
+ 144,
2168
+ 151,
2169
+ 219,
2170
+ 114,
2171
+ 64,
2172
+ 164,
2173
+ 164,
2174
+ 183,
2175
+ 179,
2176
+ 103,
2177
+ 31,
2178
+ 203,
2179
+ 121,
2180
+ 230,
2181
+ 78,
2182
+ 204,
2183
+ 192,
2184
+ 229,
2185
+ 120,
2186
+ 130,
2187
+ 90,
2188
+ 208,
2189
+ 125,
2190
+ 204,
2191
+ 255,
2192
+ 114,
2193
+ 33,
2194
+ 184,
2195
+ 8,
2196
+ 70,
2197
+ 116,
2198
+ 247,
2199
+ 67,
2200
+ 36,
2201
+ 142,
2202
+ 224,
2203
+ 53,
2204
+ 144,
2205
+ 230,
2206
+ 129,
2207
+ 58,
2208
+ 38,
2209
+ 76,
2210
+ 60,
2211
+ 40,
2212
+ 82,
2213
+ 187,
2214
+ 145,
2215
+ 195,
2216
+ 0,
2217
+ 203,
2218
+ 136,
2219
+ 208,
2220
+ 101,
2221
+ 139,
2222
+ 27,
2223
+ 83,
2224
+ 46,
2225
+ 163,
2226
+ 113,
2227
+ 100,
2228
+ 72,
2229
+ 151,
2230
+ 162,
2231
+ 13,
2232
+ 249,
2233
+ 78,
2234
+ 56,
2235
+ 25,
2236
+ 239,
2237
+ 70,
2238
+ 169,
2239
+ 222,
2240
+ 172,
2241
+ 216,
2242
+ 168,
2243
+ 250,
2244
+ 118,
2245
+ 63,
2246
+ 227,
2247
+ 156,
2248
+ 52,
2249
+ 63,
2250
+ 249,
2251
+ 220,
2252
+ 187,
2253
+ 199,
2254
+ 199,
2255
+ 11,
2256
+ 79,
2257
+ 29,
2258
+ 138,
2259
+ 81,
2260
+ 224,
2261
+ 75,
2262
+ 205,
2263
+ 180,
2264
+ 89,
2265
+ 49,
2266
+ 200,
2267
+ 159,
2268
+ 126,
2269
+ 201,
2270
+ 217,
2271
+ 120,
2272
+ 115,
2273
+ 100,
2274
+ 234,
2275
+ 197,
2276
+ 172,
2277
+ 131,
2278
+ 52,
2279
+ 211,
2280
+ 235,
2281
+ 195,
2282
+ 197,
2283
+ 129,
2284
+ 160,
2285
+ 255,
2286
+ 250,
2287
+ 19,
2288
+ 99,
2289
+ 235,
2290
+ 23,
2291
+ 13,
2292
+ 221,
2293
+ 81,
2294
+ 183,
2295
+ 240,
2296
+ 218,
2297
+ 73,
2298
+ 211,
2299
+ 22,
2300
+ 85,
2301
+ 38,
2302
+ 41,
2303
+ 212,
2304
+ 104,
2305
+ 158,
2306
+ 43,
2307
+ 22,
2308
+ 190,
2309
+ 88,
2310
+ 125,
2311
+ 71,
2312
+ 161,
2313
+ 252,
2314
+ 143,
2315
+ 248,
2316
+ 184,
2317
+ 209,
2318
+ 122,
2319
+ 208,
2320
+ 49,
2321
+ 206,
2322
+ 69,
2323
+ 203,
2324
+ 58,
2325
+ 143,
2326
+ 149,
2327
+ 22,
2328
+ 4,
2329
+ 40,
2330
+ 175,
2331
+ 215,
2332
+ 251,
2333
+ 202,
2334
+ 187,
2335
+ 75,
2336
+ 64,
2337
+ 126
2338
+ ]);
2339
+ function u64(x) {
2340
+ return x & U64_MASK;
2341
+ }
2342
+ function read32LE(buf, off) {
2343
+ return (buf[off] | buf[off + 1] << 8 | buf[off + 2] << 16 | buf[off + 3] << 24) >>> 0;
2344
+ }
2345
+ function read64LE(buf, off) {
2346
+ return BigInt(buf[off]) | BigInt(buf[off + 1]) << 8n | BigInt(buf[off + 2]) << 16n | BigInt(buf[off + 3]) << 24n | BigInt(buf[off + 4]) << 32n | BigInt(buf[off + 5]) << 40n | BigInt(buf[off + 6]) << 48n | BigInt(buf[off + 7]) << 56n;
2347
+ }
2348
+ function write64LE(buf, off, value) {
2349
+ let x = u64(value);
2350
+ for (let i = 0; i < 8; i++) {
2351
+ buf[off + i] = Number(x & 0xffn);
2352
+ x >>= 8n;
2353
+ }
2354
+ }
2355
+ function swap32(x) {
2356
+ return (x << 24 & 4278190080 | x << 8 & 16711680 | x >>> 8 & 65280 | x >>> 24 & 255) >>> 0;
2357
+ }
2358
+ function swap64(x) {
2359
+ x = u64(x);
2360
+ return x << 56n & 0xff00000000000000n | x << 40n & 0x00ff000000000000n | x << 24n & 0x0000ff0000000000n | x << 8n & 0x000000ff00000000n | x >> 8n & 0x00000000ff000000n | x >> 24n & 0x0000000000ff0000n | x >> 40n & 0x000000000000ff00n | x >> 56n & 0x00000000000000ffn;
2361
+ }
2362
+ function rotl64(x, amount) {
2363
+ const r = BigInt(amount & 63);
2364
+ return u64(x << r | x >> 64n - r);
2365
+ }
2366
+ function mul128Fold64(lhs, rhs) {
2367
+ const product = u64(lhs) * u64(rhs);
2368
+ return u64(product) ^ u64(product >> 64n);
2369
+ }
2370
+ function xxh64Avalanche(hash) {
2371
+ let h = u64(hash);
2372
+ h ^= h >> 33n;
2373
+ h = u64(h * PRIME64_2);
2374
+ h ^= h >> 29n;
2375
+ h = u64(h * PRIME64_3);
2376
+ h ^= h >> 32n;
2377
+ return u64(h);
2378
+ }
2379
+ function xxh3Avalanche(hash) {
2380
+ let h = u64(hash);
2381
+ h ^= h >> 37n;
2382
+ h = u64(h * 0x165667919e3779f9n);
2383
+ h ^= h >> 32n;
2384
+ return u64(h);
2385
+ }
2386
+ function len0(secret, seed) {
2387
+ const acc = u64(seed ^ read64LE(secret, 56) ^ read64LE(secret, 64));
2388
+ return xxh64Avalanche(acc);
2389
+ }
2390
+ function len1to3(input, length, secret, seed) {
2391
+ const byte1 = input[0];
2392
+ const byte2 = length > 1 ? input[1] : input[0];
2393
+ const byte3 = input[length - 1];
2394
+ const combined = (byte1 << 16 | byte2 << 24 | byte3 | length << 8) >>> 0;
2395
+ const bitflip = u64(
2396
+ BigInt((read32LE(secret, 0) ^ read32LE(secret, 4)) >>> 0) + seed
2397
+ );
2398
+ const value64 = u64(BigInt(combined) ^ bitflip);
2399
+ return xxh64Avalanche(value64);
2400
+ }
2401
+ function len4to8(input, length, secret, seed) {
2402
+ const inputHi = read32LE(input, 0);
2403
+ const inputLo = read32LE(input, length - 4);
2404
+ const input64 = BigInt(inputLo) | BigInt(inputHi) << 32n;
2405
+ let acc = read64LE(secret, 8) ^ read64LE(secret, 16);
2406
+ seed ^= BigInt(swap32(Number(seed & U32_MASK))) << 32n;
2407
+ acc = u64(acc - seed);
2408
+ acc ^= input64;
2409
+ acc ^= rotl64(acc, 49) ^ rotl64(acc, 24);
2410
+ acc = u64(acc * RRMXMX);
2411
+ acc ^= (acc >> 35n) + BigInt(length);
2412
+ acc = u64(acc * RRMXMX);
2413
+ acc ^= acc >> 28n;
2414
+ return u64(acc);
2415
+ }
2416
+ function len9to16(input, length, secret, seed) {
2417
+ let inputLo = read64LE(secret, 24) ^ read64LE(secret, 32);
2418
+ let inputHi = read64LE(secret, 40) ^ read64LE(secret, 48);
2419
+ let acc = BigInt(length);
2420
+ inputLo = u64(inputLo + seed);
2421
+ inputHi = u64(inputHi - seed);
2422
+ inputLo ^= read64LE(input, 0);
2423
+ inputHi ^= read64LE(input, length - 8);
2424
+ acc = u64(acc + swap64(inputLo));
2425
+ acc = u64(acc + inputHi);
2426
+ acc = u64(acc + mul128Fold64(inputLo, inputHi));
2427
+ return xxh3Avalanche(acc);
2428
+ }
2429
+ function mix16B(input, inputOff, secret, secretOff, seed) {
2430
+ let lhs = seed;
2431
+ let rhs = u64(0n - seed);
2432
+ lhs = u64(lhs + read64LE(secret, secretOff));
2433
+ rhs = u64(rhs + read64LE(secret, secretOff + 8));
2434
+ lhs ^= read64LE(input, inputOff);
2435
+ rhs ^= read64LE(input, inputOff + 8);
2436
+ return mul128Fold64(lhs, rhs);
2437
+ }
2438
+ function len17to128(input, length, secret, seed) {
2439
+ let i = Math.floor((length - 1) / 32);
2440
+ let acc = u64(BigInt(length) * PRIME64_1);
2441
+ for (; i >= 0; i--) {
2442
+ acc = u64(acc + mix16B(input, 16 * i, secret, 32 * i, seed));
2443
+ acc = u64(
2444
+ acc + mix16B(
2445
+ input,
2446
+ length - 16 * (i + 1),
2447
+ secret,
2448
+ 32 * i + 16,
2449
+ seed
2450
+ )
2451
+ );
2452
+ }
2453
+ return xxh3Avalanche(acc);
2454
+ }
2455
+ function len129to240(input, length, secret, seed) {
2456
+ let acc = u64(BigInt(length) * PRIME64_1);
2457
+ const nbRounds = Math.floor(length / 16);
2458
+ for (let i = 0; i < 8; i++) {
2459
+ acc = u64(acc + mix16B(input, 16 * i, secret, 16 * i, seed));
2460
+ }
2461
+ acc = xxh3Avalanche(acc);
2462
+ for (let i = 8; i < nbRounds; i++) {
2463
+ acc = u64(
2464
+ acc + mix16B(
2465
+ input,
2466
+ 16 * i,
2467
+ secret,
2468
+ 16 * (i - 8) + XXH3_MIDSIZE_STARTOFFSET,
2469
+ seed
2470
+ )
2471
+ );
2472
+ }
2473
+ acc = u64(
2474
+ acc + mix16B(
2475
+ input,
2476
+ length - 16,
2477
+ secret,
2478
+ XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET,
2479
+ seed
2480
+ )
2481
+ );
2482
+ return xxh3Avalanche(acc);
2483
+ }
2484
+ function hashShort(input, length, secret, seed) {
2485
+ if (length <= 16) {
2486
+ if (length > 8) return len9to16(input, length, secret, seed);
2487
+ if (length >= 4) return len4to8(input, length, secret, seed);
2488
+ if (length !== 0) return len1to3(input, length, secret, seed);
2489
+ return len0(secret, seed);
2490
+ }
2491
+ if (length <= 128) return len17to128(input, length, secret, seed);
2492
+ return len129to240(input, length, secret, seed);
2493
+ }
2494
+ function accumulate512(acc, input, inputOff, secret, secretOff) {
2495
+ for (let i = 0; i < ACC_NB; i++) {
2496
+ const dataVal = read64LE(input, inputOff + 8 * i);
2497
+ const dataKey = dataVal ^ read64LE(secret, secretOff + 8 * i);
2498
+ acc[i ^ 1] = u64(acc[i ^ 1] + dataVal);
2499
+ const low32 = dataKey & U32_MASK;
2500
+ const high32 = dataKey >> 32n;
2501
+ acc[i] = u64(acc[i] + low32 * high32);
2502
+ }
2503
+ }
2504
+ function scrambleAcc(acc, secret, secretOff) {
2505
+ for (let i = 0; i < ACC_NB; i++) {
2506
+ let x = acc[i];
2507
+ x ^= x >> 47n;
2508
+ x ^= read64LE(secret, secretOff + 8 * i);
2509
+ x = u64(x * BigInt(PRIME32_1));
2510
+ acc[i] = x;
2511
+ }
2512
+ }
2513
+ function accumulateLoop(acc, input, inputOff, secret, secretOff, nbStripes) {
2514
+ for (let n = 0; n < nbStripes; n++) {
2515
+ accumulate512(
2516
+ acc,
2517
+ input,
2518
+ inputOff + n * STRIPE_LEN,
2519
+ secret,
2520
+ secretOff + 8 * n
2521
+ );
2522
+ }
2523
+ }
2524
+ function mix2Accs(acc, accOff, secret, secretOff) {
2525
+ return mul128Fold64(
2526
+ acc[accOff] ^ read64LE(secret, secretOff),
2527
+ acc[accOff + 1] ^ read64LE(secret, secretOff + 8)
2528
+ );
2529
+ }
2530
+ function mergeAccs(acc, key, keyOff, start) {
2531
+ let result = start;
2532
+ for (let i = 0; i < 4; i++) {
2533
+ result = u64(result + mix2Accs(acc, 2 * i, key, keyOff + 16 * i));
2534
+ }
2535
+ return xxh3Avalanche(result);
2536
+ }
2537
+ function hashLong(input, length, secret, secretSize) {
2538
+ const nbRounds = Math.floor(
2539
+ (secretSize - STRIPE_LEN) / XXH_SECRET_CONSUME_RATE
2540
+ );
2541
+ const blockLen = STRIPE_LEN * nbRounds;
2542
+ const nbBlocks = Math.floor((length - 1) / blockLen);
2543
+ const nbStripes = Math.floor(
2544
+ (length - 1 - blockLen * nbBlocks) / STRIPE_LEN
2545
+ );
2546
+ const acc = [
2547
+ BigInt(PRIME32_3),
2548
+ PRIME64_1,
2549
+ PRIME64_2,
2550
+ PRIME64_3,
2551
+ PRIME64_4,
2552
+ BigInt(PRIME32_2),
2553
+ PRIME64_5,
2554
+ BigInt(PRIME32_1)
2555
+ ];
2556
+ for (let n = 0; n < nbBlocks; n++) {
2557
+ accumulateLoop(acc, input, n * blockLen, secret, 0, nbRounds);
2558
+ scrambleAcc(acc, secret, secretSize - STRIPE_LEN);
2559
+ }
2560
+ accumulateLoop(acc, input, nbBlocks * blockLen, secret, 0, nbStripes);
2561
+ accumulate512(
2562
+ acc,
2563
+ input,
2564
+ length - STRIPE_LEN,
2565
+ secret,
2566
+ secretSize - STRIPE_LEN - XXH_SECRET_LASTACC_START
2567
+ );
2568
+ return mergeAccs(
2569
+ acc,
2570
+ secret,
2571
+ XXH_SECRET_MERGEACCS_START,
2572
+ u64(BigInt(length) * PRIME64_1)
2573
+ );
2574
+ }
2575
+ function hashLongWithSeed(input, length, seed) {
2576
+ const secret = new Uint8Array(XXH_SECRET_DEFAULT_SIZE);
2577
+ for (let i = 0; i < XXH_SECRET_DEFAULT_SIZE / 16; i++) {
2578
+ const off = 16 * i;
2579
+ write64LE(secret, off, u64(read64LE(DEFAULT_SECRET, off) + seed));
2580
+ write64LE(
2581
+ secret,
2582
+ off + 8,
2583
+ u64(read64LE(DEFAULT_SECRET, off + 8) - seed)
2584
+ );
2585
+ }
2586
+ return hashLong(input, length, secret, secret.length);
2587
+ }
2588
+ var textEncoder2 = new TextEncoder();
2589
+ function xxh3_64(input, seed = 0n) {
2590
+ const len = input.length;
2591
+ if (len <= XXH3_MIDSIZE_MAX) {
2592
+ return hashShort(input, len, DEFAULT_SECRET, u64(seed));
2593
+ }
2594
+ return hashLongWithSeed(input, len, u64(seed));
2595
+ }
2596
+ function xxh3_64str(input, seed = 0n) {
2597
+ return xxh3_64(textEncoder2.encode(input), seed);
2598
+ }
2599
+ function computeMethodHash(methodName) {
2600
+ const utf8 = textEncoder2.encode(methodName);
2601
+ const prefixValue = Math.imul(67211, utf8.length) >>> 0;
2602
+ const prefixed = new Uint8Array(4 + utf8.length);
2603
+ prefixed[0] = prefixValue & 255;
2604
+ prefixed[1] = prefixValue >>> 8 & 255;
2605
+ prefixed[2] = prefixValue >>> 16 & 255;
2606
+ prefixed[3] = prefixValue >>> 24 & 255;
2607
+ prefixed.set(utf8, 4);
2608
+ const hash64 = xxh3_64(prefixed);
2609
+ return Number(hash64 & 0xffffffffn) | 0;
2610
+ }
2611
+
2612
+ // src/rpc-method-registry.ts
2613
+ var RpcMethodRegistry = class {
2614
+ _nameToHash = /* @__PURE__ */ new Map();
2615
+ _hashToName = /* @__PURE__ */ new Map();
2616
+ /** Register a method name and compute its hash. */
2617
+ register(methodName) {
2618
+ if (this._nameToHash.has(methodName)) return;
2619
+ const hash = computeMethodHash(methodName);
2620
+ const existing = this._hashToName.get(hash);
2621
+ if (existing !== void 0 && existing !== methodName) {
2622
+ console.warn(
2623
+ `[RpcMethodRegistry] hash collision: "${methodName}" and "${existing}" both hash to ${hash}`
2624
+ );
2625
+ return;
2626
+ }
2627
+ this._nameToHash.set(methodName, hash);
2628
+ this._hashToName.set(hash, methodName);
2629
+ }
2630
+ /** Register all wire method names from a service definition. */
2631
+ registerService(serviceName, methods) {
2632
+ for (const [, def] of methods) {
2633
+ const wireName = `${serviceName}.${def.name}:${def.wireArgCount}`;
2634
+ this.register(wireName);
2635
+ }
2636
+ }
2637
+ /** Get the hash for a method name. Computes on demand if not registered. */
2638
+ getHash(methodName) {
2639
+ let hash = this._nameToHash.get(methodName);
2640
+ if (hash === void 0) {
2641
+ this.register(methodName);
2642
+ hash = this._nameToHash.get(methodName);
2643
+ }
2644
+ return hash;
2645
+ }
2646
+ /** Get the method name for a hash. Returns undefined if not registered. */
2647
+ getName(hash) {
2648
+ return this._hashToName.get(hash);
2649
+ }
2650
+ /** Get the hash for a method name, throwing if not registered. */
2651
+ requireHash(methodName) {
2652
+ return this.getHash(methodName);
2653
+ }
2654
+ };
2655
+
1282
2656
  // src/rpc-hub.ts
1283
2657
  var RpcHub = class {
1284
2658
  hubId;
@@ -1286,9 +2660,16 @@ var RpcHub = class {
1286
2660
  serviceHost;
1287
2661
  systemCallSender = new RpcSystemCallSender();
1288
2662
  systemCallHandler = new RpcSystemCallHandler();
2663
+ /** Method registry for compact format hash ↔ name resolution.
2664
+ * Created lazily, populated by addService/addClient. */
2665
+ registry = new RpcMethodRegistry();
1289
2666
  constructor(hubId) {
1290
2667
  this.hubId = hubId ?? crypto.randomUUID();
1291
2668
  this.serviceHost = new RpcServiceHost();
2669
+ this.systemCallSender.registry = this.registry;
2670
+ for (const methodName of Object.values(RpcSystemCalls)) {
2671
+ this.registry.register(methodName);
2672
+ }
1292
2673
  }
1293
2674
  addPeer(peer) {
1294
2675
  this.peers.set(peer.ref, peer);
@@ -1326,10 +2707,12 @@ var RpcHub = class {
1326
2707
  wrappedImpl[methodDef.name] = methodDef.callTypeId !== 0 ? this._wrapServerMethod(methodDef, fn, impl) : fn;
1327
2708
  }
1328
2709
  this.serviceHost.register(def, wrappedImpl);
2710
+ this.registry.registerService(def.name, def.methods);
1329
2711
  }
1330
2712
  /** Create a typed client proxy for a service on a remote peer. */
1331
2713
  addClient(peer, defOrContract) {
1332
2714
  const def = this._resolveServiceDef(defOrContract);
2715
+ this.registry.registerService(def.name, def.methods);
1333
2716
  const overloads = /* @__PURE__ */ new Map();
1334
2717
  for (const methodDef of def.methods.values()) {
1335
2718
  let byArgCount = overloads.get(methodDef.name);
@@ -1337,7 +2720,10 @@ var RpcHub = class {
1337
2720
  byArgCount = /* @__PURE__ */ new Map();
1338
2721
  overloads.set(methodDef.name, byArgCount);
1339
2722
  }
1340
- byArgCount.set(methodDef.argCount, this._createClientMethod(peer, methodDef));
2723
+ byArgCount.set(
2724
+ methodDef.argCount,
2725
+ this._createClientMethod(peer, methodDef)
2726
+ );
1341
2727
  }
1342
2728
  const methods = /* @__PURE__ */ new Map();
1343
2729
  for (const [name, byArgCount] of overloads) {
@@ -1346,7 +2732,10 @@ var RpcHub = class {
1346
2732
  } else {
1347
2733
  methods.set(name, (...args) => {
1348
2734
  const fn = byArgCount.get(args.length);
1349
- if (!fn) throw new Error(`No overload of ${name} accepts ${args.length} arguments`);
2735
+ if (!fn)
2736
+ throw new Error(
2737
+ `No overload of ${name} accepts ${args.length} arguments`
2738
+ );
1350
2739
  return fn(...args);
1351
2740
  });
1352
2741
  }
@@ -1362,7 +2751,8 @@ var RpcHub = class {
1362
2751
  /** Build an RpcServiceDef from decorator metadata on a contract class. Override in FusionHub for compute support. */
1363
2752
  _buildServiceDef(cls) {
1364
2753
  const svcMeta = getServiceMeta(cls);
1365
- if (svcMeta === void 0) throw new Error("Contract class missing @rpcService metadata");
2754
+ if (svcMeta === void 0)
2755
+ throw new Error("Contract class missing @rpcService metadata");
1366
2756
  const methodsMeta = getMethodsMeta(cls) ?? {};
1367
2757
  const methods = /* @__PURE__ */ new Map();
1368
2758
  for (const [name, meta] of Object.entries(methodsMeta)) {
@@ -1405,7 +2795,10 @@ var RpcHub = class {
1405
2795
  const outboundCall = peer.call(wireName, callArgs);
1406
2796
  const result = await outboundCall.result.promise;
1407
2797
  const ref = parseStreamRef(result);
1408
- if (!ref) throw new Error(`Expected stream reference, got: ${JSON.stringify(result)}`);
2798
+ if (!ref)
2799
+ throw new Error(
2800
+ `Expected stream reference, got: ${JSON.stringify(result)}`
2801
+ );
1409
2802
  const stream = new RpcStream(ref, peer);
1410
2803
  peer.remoteObjects.register(stream);
1411
2804
  return stream;
@@ -1444,7 +2837,10 @@ function createRpcClient(peer, serviceDef) {
1444
2837
  }
1445
2838
  methods.set(name, (...args) => {
1446
2839
  const fn = fns.get(args.length);
1447
- if (!fn) throw new Error(`No overload of ${name} accepts ${args.length} arguments`);
2840
+ if (!fn)
2841
+ throw new Error(
2842
+ `No overload of ${name} accepts ${args.length} arguments`
2843
+ );
1448
2844
  return fn(...args);
1449
2845
  });
1450
2846
  }
@@ -1489,12 +2885,10 @@ function getStateDescription(state, useLastError = false) {
1489
2885
  case 1 /* JustDisconnected */:
1490
2886
  return "Just disconnected, reconnecting...";
1491
2887
  case 2 /* Disconnected */:
1492
- if (state.reconnectsIn > 0)
1493
- break;
2888
+ if (state.reconnectsIn > 0) break;
1494
2889
  return "Reconnecting...";
1495
2890
  }
1496
- if (state.lastError == null || !useLastError)
1497
- return "Disconnected.";
2891
+ if (state.lastError == null || !useLastError) return "Disconnected.";
1498
2892
  let message = state.lastError.message.trim();
1499
2893
  if (!(message.endsWith(".") || message.endsWith("!") || message.endsWith("?")))
1500
2894
  message += ".";
@@ -1525,7 +2919,9 @@ var RpcPeerStateMonitor = class {
1525
2919
  _onDisconnected = (ev) => {
1526
2920
  const wasConnected = this._rawConnected;
1527
2921
  this._rawConnected = false;
1528
- this._lastError = new Error(`Connection closed: ${ev.reason} (code ${ev.code})`);
2922
+ this._lastError = new Error(
2923
+ `Connection closed: ${ev.reason} (code ${ev.code})`
2924
+ );
1529
2925
  if (wasConnected) {
1530
2926
  this._disconnectedAt = Date.now();
1531
2927
  }
@@ -1542,16 +2938,26 @@ var RpcPeerStateMonitor = class {
1542
2938
  this._rawConnected = peer.isConnected;
1543
2939
  if (this._rawConnected) {
1544
2940
  this._connectedAt = Date.now();
1545
- this._state = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2941
+ this._state = {
2942
+ kind: 3 /* JustConnected */,
2943
+ reconnectsIn: 0
2944
+ };
1546
2945
  } else {
1547
2946
  this._disconnectedAt = Date.now();
1548
- this._state = { kind: 1 /* JustDisconnected */, reconnectsIn: 0 };
2947
+ this._state = {
2948
+ kind: 1 /* JustDisconnected */,
2949
+ reconnectsIn: 0
2950
+ };
1549
2951
  }
1550
2952
  peer.connected.add(this._onConnected);
1551
2953
  peer.disconnected.add(this._onDisconnected);
1552
2954
  peer.reconnectsAtChanged.add(this._onReconnectsAtChanged);
1553
- peer.reconnectDelayer.cancelDelaysChanged.add(this._onCancelDelaysChanged);
1554
- this._scheduleRecompute(this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs);
2955
+ peer.reconnectDelayer.cancelDelaysChanged.add(
2956
+ this._onCancelDelaysChanged
2957
+ );
2958
+ this._scheduleRecompute(
2959
+ this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs
2960
+ );
1555
2961
  }
1556
2962
  get state() {
1557
2963
  return this._state;
@@ -1564,7 +2970,9 @@ var RpcPeerStateMonitor = class {
1564
2970
  this.peer.connected.remove(this._onConnected);
1565
2971
  this.peer.disconnected.remove(this._onDisconnected);
1566
2972
  this.peer.reconnectsAtChanged.remove(this._onReconnectsAtChanged);
1567
- this.peer.reconnectDelayer.cancelDelaysChanged.remove(this._onCancelDelaysChanged);
2973
+ this.peer.reconnectDelayer.cancelDelaysChanged.remove(
2974
+ this._onCancelDelaysChanged
2975
+ );
1568
2976
  }
1569
2977
  _recompute() {
1570
2978
  if (this._timer !== void 0) {
@@ -1576,24 +2984,46 @@ var RpcPeerStateMonitor = class {
1576
2984
  if (this._rawConnected) {
1577
2985
  const connectedFor = now - this._connectedAt;
1578
2986
  if (connectedFor < JustConnectedPeriodMs) {
1579
- newState = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2987
+ newState = {
2988
+ kind: 3 /* JustConnected */,
2989
+ reconnectsIn: 0
2990
+ };
1580
2991
  this._scheduleRecompute(JustConnectedPeriodMs - connectedFor);
1581
2992
  } else {
1582
- newState = { kind: 0 /* Connected */, reconnectsIn: 0 };
2993
+ newState = {
2994
+ kind: 0 /* Connected */,
2995
+ reconnectsIn: 0
2996
+ };
1583
2997
  }
1584
2998
  } else {
1585
2999
  const disconnectedFor = now - this._disconnectedAt;
1586
3000
  if (disconnectedFor < JustDisconnectedPeriodMs) {
1587
- newState = { kind: 1 /* JustDisconnected */, lastError: this._lastError, reconnectsIn: 0 };
1588
- this._scheduleRecompute(JustDisconnectedPeriodMs - disconnectedFor);
3001
+ newState = {
3002
+ kind: 1 /* JustDisconnected */,
3003
+ lastError: this._lastError,
3004
+ reconnectsIn: 0
3005
+ };
3006
+ this._scheduleRecompute(
3007
+ JustDisconnectedPeriodMs - disconnectedFor
3008
+ );
1589
3009
  } else {
1590
3010
  const reconnectsAt = this.peer.reconnectsAt;
1591
3011
  const reconnectsIn = reconnectsAt > 0 ? Math.max(0, reconnectsAt - now) : 0;
1592
3012
  if (reconnectsIn < MinReconnectsInMs) {
1593
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn: 0 };
3013
+ newState = {
3014
+ kind: 2 /* Disconnected */,
3015
+ lastError: this._lastError,
3016
+ reconnectsIn: 0
3017
+ };
1594
3018
  } else {
1595
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn };
1596
- this._scheduleRecompute(Math.min(1e3, reconnectsIn - MinReconnectsInMs));
3019
+ newState = {
3020
+ kind: 2 /* Disconnected */,
3021
+ lastError: this._lastError,
3022
+ reconnectsIn
3023
+ };
3024
+ this._scheduleRecompute(
3025
+ Math.min(1e3, reconnectsIn - MinReconnectsInMs)
3026
+ );
1597
3027
  }
1598
3028
  }
1599
3029
  }
@@ -1608,16 +3038,18 @@ var RpcPeerStateMonitor = class {
1608
3038
  }
1609
3039
  _scheduleRecompute(delayMs) {
1610
3040
  if (this._timer !== void 0) clearTimeout(this._timer);
1611
- this._timer = setTimeout(() => {
1612
- this._timer = void 0;
1613
- this._recompute();
1614
- }, Math.max(0, delayMs));
3041
+ this._timer = setTimeout(
3042
+ () => {
3043
+ this._timer = void 0;
3044
+ this._recompute();
3045
+ },
3046
+ Math.max(0, delayMs)
3047
+ );
1615
3048
  }
1616
3049
  };
1617
3050
  // Annotate the CommonJS export names for ESM import in node:
1618
3051
  0 && (module.exports = {
1619
3052
  ARG_DELIMITER,
1620
- DEFAULT_SERIALIZATION_FORMAT,
1621
3053
  ENVELOPE_DELIMITER,
1622
3054
  FRAME_DELIMITER,
1623
3055
  RPC_CLOSE_CODE_UNSUPPORTED_FORMAT,
@@ -1627,7 +3059,11 @@ var RpcPeerStateMonitor = class {
1627
3059
  RpcHub,
1628
3060
  RpcInboundCall,
1629
3061
  RpcInboundCallTracker,
3062
+ RpcJsonSerializationFormat,
1630
3063
  RpcMessageChannelConnection,
3064
+ RpcMessagePackCompactSerializationFormat,
3065
+ RpcMessagePackSerializationFormat,
3066
+ RpcMethodRegistry,
1631
3067
  RpcObjectKind,
1632
3068
  RpcOutboundCall,
1633
3069
  RpcOutboundCallTracker,
@@ -1636,6 +3072,8 @@ var RpcPeerStateMonitor = class {
1636
3072
  RpcPeerStateKind,
1637
3073
  RpcPeerStateMonitor,
1638
3074
  RpcRemoteObjectTracker,
3075
+ RpcSerializationFormat,
3076
+ RpcSerializationFormatResolver,
1639
3077
  RpcServerPeer,
1640
3078
  RpcServiceHost,
1641
3079
  RpcSharedObjectTracker,
@@ -1647,10 +3085,16 @@ var RpcPeerStateMonitor = class {
1647
3085
  RpcType,
1648
3086
  RpcWebSocketConnection,
1649
3087
  WebSocketState,
3088
+ computeMethodHash,
3089
+ createBinaryEncoder,
1650
3090
  createMessageChannelPair,
1651
3091
  createRpcClient,
3092
+ defaultBinaryDecoder,
3093
+ defaultBinaryEncoder,
1652
3094
  defaultConnectionUrlResolver,
1653
3095
  defineRpcService,
3096
+ deserializeBinaryMessage,
3097
+ deserializeCompactBinaryMessage,
1654
3098
  deserializeMessage,
1655
3099
  getMethodsMeta,
1656
3100
  getServiceMeta,
@@ -1661,9 +3105,16 @@ var RpcPeerStateMonitor = class {
1661
3105
  resolveStreamRefs,
1662
3106
  rpcMethod,
1663
3107
  rpcService,
3108
+ serializeBinaryFrame,
3109
+ serializeBinaryMessage,
3110
+ serializeCompactBinaryMessage,
1664
3111
  serializeFrame,
1665
3112
  serializeMessage,
3113
+ splitBinaryFrame,
3114
+ splitCompactBinaryFrame,
1666
3115
  splitFrame,
1667
- wireMethodName
3116
+ wireMethodName,
3117
+ xxh3_64,
3118
+ xxh3_64str
1668
3119
  });
1669
3120
  //# sourceMappingURL=index.cjs.map