@actuallab/rpc 12.1.115 → 12.2.21

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,6 +17,14 @@ 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
@@ -31,7 +41,11 @@ __export(index_exports, {
31
41
  RpcHub: () => RpcHub,
32
42
  RpcInboundCall: () => RpcInboundCall,
33
43
  RpcInboundCallTracker: () => RpcInboundCallTracker,
44
+ RpcJsonSerializationFormat: () => RpcJsonSerializationFormat,
34
45
  RpcMessageChannelConnection: () => RpcMessageChannelConnection,
46
+ RpcMessagePackCompactSerializationFormat: () => RpcMessagePackCompactSerializationFormat,
47
+ RpcMessagePackSerializationFormat: () => RpcMessagePackSerializationFormat,
48
+ RpcMethodRegistry: () => RpcMethodRegistry,
35
49
  RpcObjectKind: () => RpcObjectKind,
36
50
  RpcOutboundCall: () => RpcOutboundCall,
37
51
  RpcOutboundCallTracker: () => RpcOutboundCallTracker,
@@ -40,6 +54,7 @@ __export(index_exports, {
40
54
  RpcPeerStateKind: () => RpcPeerStateKind,
41
55
  RpcPeerStateMonitor: () => RpcPeerStateMonitor,
42
56
  RpcRemoteObjectTracker: () => RpcRemoteObjectTracker,
57
+ RpcSerializationFormat: () => RpcSerializationFormat,
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,6 +1457,129 @@ 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 _RpcSerializationFormat {
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
+ // --- Static registry ---
1472
+ static _all = /* @__PURE__ */ new Map();
1473
+ static register(format) {
1474
+ _RpcSerializationFormat._all.set(format.key, format);
1475
+ }
1476
+ static get(key) {
1477
+ const format = _RpcSerializationFormat._all.get(key);
1478
+ if (!format)
1479
+ throw new Error(`Unknown RPC serialization format: "${key}"`);
1480
+ return format;
1481
+ }
1482
+ static tryGet(key) {
1483
+ return _RpcSerializationFormat._all.get(key);
1484
+ }
1485
+ };
1486
+ var RpcJsonSerializationFormat = class extends RpcSerializationFormat {
1487
+ key;
1488
+ isBinary = false;
1489
+ isCompact = false;
1490
+ constructor(key) {
1491
+ super();
1492
+ this.key = key;
1493
+ }
1494
+ serializeMessage(message, args) {
1495
+ return serializeMessage(message, args);
1496
+ }
1497
+ deserializeTextMessage(raw) {
1498
+ return deserializeMessage(raw);
1499
+ }
1500
+ splitBinaryFrame() {
1501
+ throw new Error("Text format does not support binary frames");
1502
+ }
1503
+ serializeBinaryFrame() {
1504
+ throw new Error("Text format does not support binary frames");
1505
+ }
1506
+ };
1507
+ var RpcMessagePackSerializationFormat = class extends RpcSerializationFormat {
1508
+ key;
1509
+ isBinary = true;
1510
+ isCompact = false;
1511
+ constructor(key) {
1512
+ super();
1513
+ this.key = key;
1514
+ }
1515
+ serializeMessage(message, args, encoder) {
1516
+ return serializeBinaryMessage(message, args, encoder);
1517
+ }
1518
+ deserializeTextMessage(raw) {
1519
+ return deserializeMessage(raw);
1520
+ }
1521
+ splitBinaryFrame(frame, decoder) {
1522
+ return splitBinaryFrame(frame, decoder);
1523
+ }
1524
+ serializeBinaryFrame(messages) {
1525
+ return serializeBinaryFrame(messages);
1526
+ }
1527
+ createEncoder() {
1528
+ return createBinaryEncoder();
1529
+ }
1530
+ createDecoder() {
1531
+ return new import_msgpack3.Decoder();
1532
+ }
1533
+ };
1534
+ var RpcMessagePackCompactSerializationFormat = class extends RpcSerializationFormat {
1535
+ key;
1536
+ isBinary = true;
1537
+ isCompact = true;
1538
+ constructor(key) {
1539
+ super();
1540
+ this.key = key;
1541
+ }
1542
+ serializeMessage(message, args, encoder, registry) {
1543
+ return serializeCompactBinaryMessage(
1544
+ message,
1545
+ args,
1546
+ registry,
1547
+ encoder
1548
+ );
1549
+ }
1550
+ deserializeTextMessage(raw) {
1551
+ return deserializeMessage(raw);
1552
+ }
1553
+ splitBinaryFrame(frame, decoder, registry) {
1554
+ return splitCompactBinaryFrame(frame, registry, decoder);
1555
+ }
1556
+ serializeBinaryFrame(messages) {
1557
+ return serializeBinaryFrame(messages);
1558
+ }
1559
+ createEncoder() {
1560
+ return createBinaryEncoder();
1561
+ }
1562
+ createDecoder() {
1563
+ return new import_msgpack3.Decoder();
1564
+ }
1565
+ };
1566
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("json5"));
1567
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("json5np"));
1568
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("njson5"));
1569
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("njson5np"));
1570
+ RpcSerializationFormat.register(
1571
+ new RpcMessagePackSerializationFormat("msgpack6")
1572
+ );
1573
+ RpcSerializationFormat.register(
1574
+ new RpcMessagePackSerializationFormat("mempack6")
1575
+ );
1576
+ RpcSerializationFormat.register(
1577
+ new RpcMessagePackCompactSerializationFormat("msgpack6c")
1578
+ );
1579
+ RpcSerializationFormat.register(
1580
+ new RpcMessagePackCompactSerializationFormat("mempack6c")
1581
+ );
1582
+
868
1583
  // src/rpc-peer.ts
869
1584
  var DEFAULT_SERIALIZATION_FORMAT = "json5np";
870
1585
  var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
@@ -913,17 +1628,27 @@ var RpcPeer = class {
913
1628
  this._startKeepAlive();
914
1629
  });
915
1630
  }
1631
+ /** The serialization format used by this peer. Override in subclasses. */
1632
+ get format() {
1633
+ return RpcSerializationFormat.get("json5np");
1634
+ }
916
1635
  call(method, args, options) {
917
1636
  const callId = this.outbound.nextId();
918
1637
  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
1638
+ const envelope = {
1639
+ Method: method,
1640
+ RelatedId: callId,
1641
+ CallType: options?.callTypeId ?? 0
1642
+ };
1643
+ outboundCall.serializedWireData = this.format.serializeMessage(
1644
+ envelope,
1645
+ args,
1646
+ this._connection?.encoder,
1647
+ this._hub.registry
922
1648
  );
923
- outboundCall.serializedMessage = msg;
924
1649
  if (this._connection !== void 0) {
925
1650
  this.outbound.register(outboundCall);
926
- this._connection.send(msg);
1651
+ this._sendWireData(outboundCall.serializedWireData);
927
1652
  } else {
928
1653
  this._pendingSends.push(outboundCall);
929
1654
  }
@@ -937,12 +1662,16 @@ var RpcPeer = class {
937
1662
  outboundCall.result.reject(new Error("Call cancelled."));
938
1663
  outboundCall.onDisconnect();
939
1664
  if (peer._connection !== void 0)
940
- hub.systemCallSender.cancel(peer._connection, callId);
1665
+ hub.systemCallSender.cancel(peer._connection, peer.format, callId);
941
1666
  } else {
942
- const idx = peer._pendingSends.findIndex((c) => c.callId === callId);
1667
+ const idx = peer._pendingSends.findIndex(
1668
+ (c) => c.callId === callId
1669
+ );
943
1670
  if (idx !== -1) {
944
1671
  peer._pendingSends.splice(idx, 1);
945
- outboundCall.result.reject(new Error("Call cancelled."));
1672
+ outboundCall.result.reject(
1673
+ new Error("Call cancelled.")
1674
+ );
946
1675
  outboundCall.onDisconnect();
947
1676
  }
948
1677
  }
@@ -954,8 +1683,14 @@ var RpcPeer = class {
954
1683
  }
955
1684
  callNoWait(method, args) {
956
1685
  if (this._connection === void 0) return;
957
- const msg = serializeMessage({ Method: method, RelatedId: 0 }, args);
958
- this._connection.send(msg);
1686
+ const envelope = { Method: method, RelatedId: 0 };
1687
+ const wireData = this.format.serializeMessage(
1688
+ envelope,
1689
+ args,
1690
+ this._connection.encoder,
1691
+ this._hub.registry
1692
+ );
1693
+ this._sendWireData(wireData);
959
1694
  }
960
1695
  close() {
961
1696
  this._stopKeepAlive();
@@ -974,23 +1709,41 @@ var RpcPeer = class {
974
1709
  }
975
1710
  /** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
976
1711
  _flushPendingSends() {
977
- if (this._pendingSends.length === 0 || this._connection === void 0) return;
1712
+ if (this._pendingSends.length === 0 || this._connection === void 0)
1713
+ return;
978
1714
  for (const call of this._pendingSends) {
979
1715
  this.outbound.register(call);
980
- this._connection.send(call.serializedMessage);
1716
+ this._sendWireData(call.serializedWireData);
981
1717
  }
982
1718
  this._pendingSends.length = 0;
983
1719
  }
1720
+ /** Send pre-serialized wire data through the current connection. */
1721
+ _sendWireData(data) {
1722
+ if (this._connection === void 0) return;
1723
+ if (typeof data === "string") {
1724
+ this._connection.send(data);
1725
+ } else {
1726
+ this._connection.sendBinary(data);
1727
+ }
1728
+ }
984
1729
  /** Override in subclasses to handle the remote peer's handshake response. */
985
1730
  _onHandshakeReceived(_handshake) {
986
1731
  }
987
- _handleMessage(raw) {
988
- const { message, args } = deserializeMessage(raw);
1732
+ _handleMessage(received) {
1733
+ let message;
1734
+ let args;
1735
+ if (received.kind === "binary") {
1736
+ message = received.message;
1737
+ args = received.args;
1738
+ } else {
1739
+ const parsed = deserializeMessage(received.raw);
1740
+ message = parsed.message;
1741
+ args = parsed.args;
1742
+ }
989
1743
  const method = message.Method ?? "";
990
1744
  if (method === RpcSystemCalls.handshake) {
991
1745
  const handshake = args[0];
992
- if (handshake !== void 0)
993
- this._onHandshakeReceived(handshake);
1746
+ if (handshake !== void 0) this._onHandshakeReceived(handshake);
994
1747
  return;
995
1748
  }
996
1749
  if (method.startsWith("$sys")) {
@@ -1012,19 +1765,42 @@ var RpcPeer = class {
1012
1765
  if (serviceHost !== void 0) {
1013
1766
  void (async () => {
1014
1767
  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);
1768
+ const context = this._connection !== void 0 ? {
1769
+ __rpcDispatch: true,
1770
+ callId: relatedId,
1771
+ connection: this._connection
1772
+ } : void 0;
1773
+ const result = await serviceHost.dispatch(
1774
+ method,
1775
+ args,
1776
+ context
1777
+ );
1017
1778
  if (methodDef?.stream === true && this._connection !== void 0) {
1018
1779
  const sender = new RpcStreamSender(this);
1019
1780
  this.sharedObjects.register(sender);
1020
- this._hub.systemCallSender.ok(this._connection, relatedId, sender.toRef());
1781
+ this._hub.systemCallSender.ok(
1782
+ this._connection,
1783
+ this.format,
1784
+ relatedId,
1785
+ sender.toRef()
1786
+ );
1021
1787
  void sender.writeFrom(result);
1022
1788
  } else if (!isNoWait && this._connection !== void 0) {
1023
- this._hub.systemCallSender.ok(this._connection, relatedId, result);
1789
+ this._hub.systemCallSender.ok(
1790
+ this._connection,
1791
+ this.format,
1792
+ relatedId,
1793
+ result
1794
+ );
1024
1795
  }
1025
1796
  } catch (e) {
1026
1797
  if (!isNoWait && this._connection !== void 0) {
1027
- this._hub.systemCallSender.error(this._connection, relatedId, e);
1798
+ this._hub.systemCallSender.error(
1799
+ this._connection,
1800
+ this.format,
1801
+ relatedId,
1802
+ e
1803
+ );
1028
1804
  }
1029
1805
  } finally {
1030
1806
  if (!isNoWait) {
@@ -1037,7 +1813,9 @@ var RpcPeer = class {
1037
1813
  _startKeepAlive() {
1038
1814
  this._keepAliveTimer = setInterval(() => {
1039
1815
  if (this._connection !== void 0) {
1040
- this._hub.systemCallSender.keepAlive(this._connection, this.outbound.activeCallIds());
1816
+ this._hub.systemCallSender.keepAlive(this._connection, this.format, [
1817
+ ...this.remoteObjects.keys()
1818
+ ]);
1041
1819
  }
1042
1820
  }, 15e3);
1043
1821
  }
@@ -1085,10 +1863,15 @@ var RpcClientPeer = class extends RpcPeer {
1085
1863
  this._reconnectsAt = value;
1086
1864
  this.reconnectsAtChanged.trigger();
1087
1865
  }
1866
+ _format;
1088
1867
  constructor(hub, url, serializationFormat) {
1089
1868
  super(url, hub);
1090
1869
  this.clientId = guidToBase64Url(this.id);
1091
1870
  this.serializationFormat = serializationFormat ?? DEFAULT_SERIALIZATION_FORMAT;
1871
+ this._format = RpcSerializationFormat.get(this.serializationFormat);
1872
+ }
1873
+ get format() {
1874
+ return this._format;
1092
1875
  }
1093
1876
  get connectionKind() {
1094
1877
  return this._connectionKind;
@@ -1106,7 +1889,12 @@ var RpcClientPeer = class extends RpcPeer {
1106
1889
  let lastCloseReason = "";
1107
1890
  try {
1108
1891
  const ws = wsFactory?.(connUrl) ?? new WebSocket(connUrl);
1109
- const conn = new RpcWebSocketConnection(ws);
1892
+ const conn = new RpcWebSocketConnection(
1893
+ ws,
1894
+ this.format.isBinary,
1895
+ this.format,
1896
+ this._hub.registry
1897
+ );
1110
1898
  this._connectionKind = 1 /* Connecting */;
1111
1899
  conn.closed.add((ev) => {
1112
1900
  lastCloseCode = ev.code;
@@ -1115,11 +1903,21 @@ var RpcClientPeer = class extends RpcPeer {
1115
1903
  this._pendingHandshake = new import_core7.PromiseSource();
1116
1904
  this.setupConnection(conn);
1117
1905
  this._connection = void 0;
1118
- const closedRejection = new Promise((_, reject) => conn.closed.add(() => reject(new Error("Connection failed"))));
1906
+ const closedRejection = new Promise(
1907
+ (_, reject) => conn.closed.add(
1908
+ () => reject(new Error("Connection failed"))
1909
+ )
1910
+ );
1119
1911
  closedRejection.catch(() => {
1120
1912
  });
1121
1913
  await Promise.race([conn.whenConnected, closedRejection]);
1122
- this._hub.systemCallSender.handshake(conn, this.id, this._hub.hubId, ++this._handshakeIndex);
1914
+ this._hub.systemCallSender.handshake(
1915
+ conn,
1916
+ this.format,
1917
+ this.id,
1918
+ this._hub.hubId,
1919
+ ++this._handshakeIndex
1920
+ );
1123
1921
  const remoteHandshake = await Promise.race([
1124
1922
  this._pendingHandshake.promise,
1125
1923
  closedRejection
@@ -1172,7 +1970,6 @@ var RpcClientPeer = class extends RpcPeer {
1172
1970
  * Regular in-flight calls are re-sent transparently. */
1173
1971
  _reconnect(_isPeerChanged) {
1174
1972
  if (this._connection === void 0) return;
1175
- const conn = this._connection;
1176
1973
  if (_isPeerChanged) {
1177
1974
  this.remoteObjects.disconnectAll();
1178
1975
  } else {
@@ -1184,7 +1981,7 @@ var RpcClientPeer = class extends RpcPeer {
1184
1981
  call.onDisconnect();
1185
1982
  this.outbound.remove(call.callId);
1186
1983
  } else {
1187
- conn.send(call.serializedMessage);
1984
+ this._sendWireData(call.serializedWireData);
1188
1985
  }
1189
1986
  }
1190
1987
  this._flushPendingSends();
@@ -1207,7 +2004,13 @@ var RpcServerPeer = class extends RpcPeer {
1207
2004
  }
1208
2005
  _onHandshakeReceived(_handshake) {
1209
2006
  if (this._connection !== void 0) {
1210
- this._hub.systemCallSender.handshake(this._connection, this.id, this._hub.hubId, 0);
2007
+ this._hub.systemCallSender.handshake(
2008
+ this._connection,
2009
+ this.format,
2010
+ this.id,
2011
+ this._hub.hubId,
2012
+ 0
2013
+ );
1211
2014
  }
1212
2015
  }
1213
2016
  };
@@ -1235,12 +2038,16 @@ var RpcServiceHost = class {
1235
2038
  for (const methodDef of def.methods.values()) {
1236
2039
  const fn = impl[methodDef.name];
1237
2040
  if (!fn) continue;
1238
- this._methods.set(wireMethodName(methodDef), { def: methodDef, fn });
2041
+ this._methods.set(wireMethodName(methodDef), {
2042
+ def: methodDef,
2043
+ fn
2044
+ });
1239
2045
  }
1240
2046
  }
1241
2047
  async dispatch(wireMethod, args, context) {
1242
2048
  const entry = this._methods.get(wireMethod);
1243
- if (entry === void 0) throw new Error(`Method not found: ${wireMethod}`);
2049
+ if (entry === void 0)
2050
+ throw new Error(`Method not found: ${wireMethod}`);
1244
2051
  if (context !== void 0 && entry.def.callTypeId !== 0) {
1245
2052
  return await entry.fn(...args, context);
1246
2053
  }
@@ -1279,6 +2086,539 @@ function rpcMethod(options) {
1279
2086
  };
1280
2087
  }
1281
2088
 
2089
+ // src/rpc-xxhash3.ts
2090
+ var U64_MASK = 0xffffffffffffffffn;
2091
+ var U32_MASK = 0xffffffffn;
2092
+ var PRIME32_1 = 2654435761;
2093
+ var PRIME32_2 = 2246822519;
2094
+ var PRIME32_3 = 3266489917;
2095
+ var PRIME64_1 = 0x9e3779b185ebca87n;
2096
+ var PRIME64_2 = 0xc2b2ae3d27d4eb4fn;
2097
+ var PRIME64_3 = 0x165667b19e3779f9n;
2098
+ var PRIME64_4 = 0x85ebca77c2b2ae63n;
2099
+ var PRIME64_5 = 0x27d4eb2f165667c5n;
2100
+ var XXH3_SECRET_SIZE_MIN = 136;
2101
+ var XXH_SECRET_DEFAULT_SIZE = 192;
2102
+ var STRIPE_LEN = 64;
2103
+ var XXH_SECRET_CONSUME_RATE = 8;
2104
+ var ACC_NB = STRIPE_LEN / 8;
2105
+ var XXH3_MIDSIZE_MAX = 240;
2106
+ var XXH3_MIDSIZE_STARTOFFSET = 3;
2107
+ var XXH3_MIDSIZE_LASTOFFSET = 17;
2108
+ var XXH_SECRET_LASTACC_START = 7;
2109
+ var XXH_SECRET_MERGEACCS_START = 11;
2110
+ var RRMXMX = 0x9fb21c651e98df25n;
2111
+ var DEFAULT_SECRET = new Uint8Array([
2112
+ 184,
2113
+ 254,
2114
+ 108,
2115
+ 57,
2116
+ 35,
2117
+ 164,
2118
+ 75,
2119
+ 190,
2120
+ 124,
2121
+ 1,
2122
+ 129,
2123
+ 44,
2124
+ 247,
2125
+ 33,
2126
+ 173,
2127
+ 28,
2128
+ 222,
2129
+ 212,
2130
+ 109,
2131
+ 233,
2132
+ 131,
2133
+ 144,
2134
+ 151,
2135
+ 219,
2136
+ 114,
2137
+ 64,
2138
+ 164,
2139
+ 164,
2140
+ 183,
2141
+ 179,
2142
+ 103,
2143
+ 31,
2144
+ 203,
2145
+ 121,
2146
+ 230,
2147
+ 78,
2148
+ 204,
2149
+ 192,
2150
+ 229,
2151
+ 120,
2152
+ 130,
2153
+ 90,
2154
+ 208,
2155
+ 125,
2156
+ 204,
2157
+ 255,
2158
+ 114,
2159
+ 33,
2160
+ 184,
2161
+ 8,
2162
+ 70,
2163
+ 116,
2164
+ 247,
2165
+ 67,
2166
+ 36,
2167
+ 142,
2168
+ 224,
2169
+ 53,
2170
+ 144,
2171
+ 230,
2172
+ 129,
2173
+ 58,
2174
+ 38,
2175
+ 76,
2176
+ 60,
2177
+ 40,
2178
+ 82,
2179
+ 187,
2180
+ 145,
2181
+ 195,
2182
+ 0,
2183
+ 203,
2184
+ 136,
2185
+ 208,
2186
+ 101,
2187
+ 139,
2188
+ 27,
2189
+ 83,
2190
+ 46,
2191
+ 163,
2192
+ 113,
2193
+ 100,
2194
+ 72,
2195
+ 151,
2196
+ 162,
2197
+ 13,
2198
+ 249,
2199
+ 78,
2200
+ 56,
2201
+ 25,
2202
+ 239,
2203
+ 70,
2204
+ 169,
2205
+ 222,
2206
+ 172,
2207
+ 216,
2208
+ 168,
2209
+ 250,
2210
+ 118,
2211
+ 63,
2212
+ 227,
2213
+ 156,
2214
+ 52,
2215
+ 63,
2216
+ 249,
2217
+ 220,
2218
+ 187,
2219
+ 199,
2220
+ 199,
2221
+ 11,
2222
+ 79,
2223
+ 29,
2224
+ 138,
2225
+ 81,
2226
+ 224,
2227
+ 75,
2228
+ 205,
2229
+ 180,
2230
+ 89,
2231
+ 49,
2232
+ 200,
2233
+ 159,
2234
+ 126,
2235
+ 201,
2236
+ 217,
2237
+ 120,
2238
+ 115,
2239
+ 100,
2240
+ 234,
2241
+ 197,
2242
+ 172,
2243
+ 131,
2244
+ 52,
2245
+ 211,
2246
+ 235,
2247
+ 195,
2248
+ 197,
2249
+ 129,
2250
+ 160,
2251
+ 255,
2252
+ 250,
2253
+ 19,
2254
+ 99,
2255
+ 235,
2256
+ 23,
2257
+ 13,
2258
+ 221,
2259
+ 81,
2260
+ 183,
2261
+ 240,
2262
+ 218,
2263
+ 73,
2264
+ 211,
2265
+ 22,
2266
+ 85,
2267
+ 38,
2268
+ 41,
2269
+ 212,
2270
+ 104,
2271
+ 158,
2272
+ 43,
2273
+ 22,
2274
+ 190,
2275
+ 88,
2276
+ 125,
2277
+ 71,
2278
+ 161,
2279
+ 252,
2280
+ 143,
2281
+ 248,
2282
+ 184,
2283
+ 209,
2284
+ 122,
2285
+ 208,
2286
+ 49,
2287
+ 206,
2288
+ 69,
2289
+ 203,
2290
+ 58,
2291
+ 143,
2292
+ 149,
2293
+ 22,
2294
+ 4,
2295
+ 40,
2296
+ 175,
2297
+ 215,
2298
+ 251,
2299
+ 202,
2300
+ 187,
2301
+ 75,
2302
+ 64,
2303
+ 126
2304
+ ]);
2305
+ function u64(x) {
2306
+ return x & U64_MASK;
2307
+ }
2308
+ function read32LE(buf, off) {
2309
+ return (buf[off] | buf[off + 1] << 8 | buf[off + 2] << 16 | buf[off + 3] << 24) >>> 0;
2310
+ }
2311
+ function read64LE(buf, off) {
2312
+ 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;
2313
+ }
2314
+ function write64LE(buf, off, value) {
2315
+ let x = u64(value);
2316
+ for (let i = 0; i < 8; i++) {
2317
+ buf[off + i] = Number(x & 0xffn);
2318
+ x >>= 8n;
2319
+ }
2320
+ }
2321
+ function swap32(x) {
2322
+ return (x << 24 & 4278190080 | x << 8 & 16711680 | x >>> 8 & 65280 | x >>> 24 & 255) >>> 0;
2323
+ }
2324
+ function swap64(x) {
2325
+ x = u64(x);
2326
+ 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;
2327
+ }
2328
+ function rotl64(x, amount) {
2329
+ const r = BigInt(amount & 63);
2330
+ return u64(x << r | x >> 64n - r);
2331
+ }
2332
+ function mul128Fold64(lhs, rhs) {
2333
+ const product = u64(lhs) * u64(rhs);
2334
+ return u64(product) ^ u64(product >> 64n);
2335
+ }
2336
+ function xxh64Avalanche(hash) {
2337
+ let h = u64(hash);
2338
+ h ^= h >> 33n;
2339
+ h = u64(h * PRIME64_2);
2340
+ h ^= h >> 29n;
2341
+ h = u64(h * PRIME64_3);
2342
+ h ^= h >> 32n;
2343
+ return u64(h);
2344
+ }
2345
+ function xxh3Avalanche(hash) {
2346
+ let h = u64(hash);
2347
+ h ^= h >> 37n;
2348
+ h = u64(h * 0x165667919e3779f9n);
2349
+ h ^= h >> 32n;
2350
+ return u64(h);
2351
+ }
2352
+ function len0(secret, seed) {
2353
+ const acc = u64(seed ^ read64LE(secret, 56) ^ read64LE(secret, 64));
2354
+ return xxh64Avalanche(acc);
2355
+ }
2356
+ function len1to3(input, length, secret, seed) {
2357
+ const byte1 = input[0];
2358
+ const byte2 = length > 1 ? input[1] : input[0];
2359
+ const byte3 = input[length - 1];
2360
+ const combined = (byte1 << 16 | byte2 << 24 | byte3 | length << 8) >>> 0;
2361
+ const bitflip = u64(
2362
+ BigInt((read32LE(secret, 0) ^ read32LE(secret, 4)) >>> 0) + seed
2363
+ );
2364
+ const value64 = u64(BigInt(combined) ^ bitflip);
2365
+ return xxh64Avalanche(value64);
2366
+ }
2367
+ function len4to8(input, length, secret, seed) {
2368
+ const inputHi = read32LE(input, 0);
2369
+ const inputLo = read32LE(input, length - 4);
2370
+ const input64 = BigInt(inputLo) | BigInt(inputHi) << 32n;
2371
+ let acc = read64LE(secret, 8) ^ read64LE(secret, 16);
2372
+ seed ^= BigInt(swap32(Number(seed & U32_MASK))) << 32n;
2373
+ acc = u64(acc - seed);
2374
+ acc ^= input64;
2375
+ acc ^= rotl64(acc, 49) ^ rotl64(acc, 24);
2376
+ acc = u64(acc * RRMXMX);
2377
+ acc ^= (acc >> 35n) + BigInt(length);
2378
+ acc = u64(acc * RRMXMX);
2379
+ acc ^= acc >> 28n;
2380
+ return u64(acc);
2381
+ }
2382
+ function len9to16(input, length, secret, seed) {
2383
+ let inputLo = read64LE(secret, 24) ^ read64LE(secret, 32);
2384
+ let inputHi = read64LE(secret, 40) ^ read64LE(secret, 48);
2385
+ let acc = BigInt(length);
2386
+ inputLo = u64(inputLo + seed);
2387
+ inputHi = u64(inputHi - seed);
2388
+ inputLo ^= read64LE(input, 0);
2389
+ inputHi ^= read64LE(input, length - 8);
2390
+ acc = u64(acc + swap64(inputLo));
2391
+ acc = u64(acc + inputHi);
2392
+ acc = u64(acc + mul128Fold64(inputLo, inputHi));
2393
+ return xxh3Avalanche(acc);
2394
+ }
2395
+ function mix16B(input, inputOff, secret, secretOff, seed) {
2396
+ let lhs = seed;
2397
+ let rhs = u64(0n - seed);
2398
+ lhs = u64(lhs + read64LE(secret, secretOff));
2399
+ rhs = u64(rhs + read64LE(secret, secretOff + 8));
2400
+ lhs ^= read64LE(input, inputOff);
2401
+ rhs ^= read64LE(input, inputOff + 8);
2402
+ return mul128Fold64(lhs, rhs);
2403
+ }
2404
+ function len17to128(input, length, secret, seed) {
2405
+ let i = Math.floor((length - 1) / 32);
2406
+ let acc = u64(BigInt(length) * PRIME64_1);
2407
+ for (; i >= 0; i--) {
2408
+ acc = u64(acc + mix16B(input, 16 * i, secret, 32 * i, seed));
2409
+ acc = u64(
2410
+ acc + mix16B(
2411
+ input,
2412
+ length - 16 * (i + 1),
2413
+ secret,
2414
+ 32 * i + 16,
2415
+ seed
2416
+ )
2417
+ );
2418
+ }
2419
+ return xxh3Avalanche(acc);
2420
+ }
2421
+ function len129to240(input, length, secret, seed) {
2422
+ let acc = u64(BigInt(length) * PRIME64_1);
2423
+ const nbRounds = Math.floor(length / 16);
2424
+ for (let i = 0; i < 8; i++) {
2425
+ acc = u64(acc + mix16B(input, 16 * i, secret, 16 * i, seed));
2426
+ }
2427
+ acc = xxh3Avalanche(acc);
2428
+ for (let i = 8; i < nbRounds; i++) {
2429
+ acc = u64(
2430
+ acc + mix16B(
2431
+ input,
2432
+ 16 * i,
2433
+ secret,
2434
+ 16 * (i - 8) + XXH3_MIDSIZE_STARTOFFSET,
2435
+ seed
2436
+ )
2437
+ );
2438
+ }
2439
+ acc = u64(
2440
+ acc + mix16B(
2441
+ input,
2442
+ length - 16,
2443
+ secret,
2444
+ XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET,
2445
+ seed
2446
+ )
2447
+ );
2448
+ return xxh3Avalanche(acc);
2449
+ }
2450
+ function hashShort(input, length, secret, seed) {
2451
+ if (length <= 16) {
2452
+ if (length > 8) return len9to16(input, length, secret, seed);
2453
+ if (length >= 4) return len4to8(input, length, secret, seed);
2454
+ if (length !== 0) return len1to3(input, length, secret, seed);
2455
+ return len0(secret, seed);
2456
+ }
2457
+ if (length <= 128) return len17to128(input, length, secret, seed);
2458
+ return len129to240(input, length, secret, seed);
2459
+ }
2460
+ function accumulate512(acc, input, inputOff, secret, secretOff) {
2461
+ for (let i = 0; i < ACC_NB; i++) {
2462
+ const dataVal = read64LE(input, inputOff + 8 * i);
2463
+ const dataKey = dataVal ^ read64LE(secret, secretOff + 8 * i);
2464
+ acc[i ^ 1] = u64(acc[i ^ 1] + dataVal);
2465
+ const low32 = dataKey & U32_MASK;
2466
+ const high32 = dataKey >> 32n;
2467
+ acc[i] = u64(acc[i] + low32 * high32);
2468
+ }
2469
+ }
2470
+ function scrambleAcc(acc, secret, secretOff) {
2471
+ for (let i = 0; i < ACC_NB; i++) {
2472
+ let x = acc[i];
2473
+ x ^= x >> 47n;
2474
+ x ^= read64LE(secret, secretOff + 8 * i);
2475
+ x = u64(x * BigInt(PRIME32_1));
2476
+ acc[i] = x;
2477
+ }
2478
+ }
2479
+ function accumulateLoop(acc, input, inputOff, secret, secretOff, nbStripes) {
2480
+ for (let n = 0; n < nbStripes; n++) {
2481
+ accumulate512(
2482
+ acc,
2483
+ input,
2484
+ inputOff + n * STRIPE_LEN,
2485
+ secret,
2486
+ secretOff + 8 * n
2487
+ );
2488
+ }
2489
+ }
2490
+ function mix2Accs(acc, accOff, secret, secretOff) {
2491
+ return mul128Fold64(
2492
+ acc[accOff] ^ read64LE(secret, secretOff),
2493
+ acc[accOff + 1] ^ read64LE(secret, secretOff + 8)
2494
+ );
2495
+ }
2496
+ function mergeAccs(acc, key, keyOff, start) {
2497
+ let result = start;
2498
+ for (let i = 0; i < 4; i++) {
2499
+ result = u64(result + mix2Accs(acc, 2 * i, key, keyOff + 16 * i));
2500
+ }
2501
+ return xxh3Avalanche(result);
2502
+ }
2503
+ function hashLong(input, length, secret, secretSize) {
2504
+ const nbRounds = Math.floor(
2505
+ (secretSize - STRIPE_LEN) / XXH_SECRET_CONSUME_RATE
2506
+ );
2507
+ const blockLen = STRIPE_LEN * nbRounds;
2508
+ const nbBlocks = Math.floor((length - 1) / blockLen);
2509
+ const nbStripes = Math.floor(
2510
+ (length - 1 - blockLen * nbBlocks) / STRIPE_LEN
2511
+ );
2512
+ const acc = [
2513
+ BigInt(PRIME32_3),
2514
+ PRIME64_1,
2515
+ PRIME64_2,
2516
+ PRIME64_3,
2517
+ PRIME64_4,
2518
+ BigInt(PRIME32_2),
2519
+ PRIME64_5,
2520
+ BigInt(PRIME32_1)
2521
+ ];
2522
+ for (let n = 0; n < nbBlocks; n++) {
2523
+ accumulateLoop(acc, input, n * blockLen, secret, 0, nbRounds);
2524
+ scrambleAcc(acc, secret, secretSize - STRIPE_LEN);
2525
+ }
2526
+ accumulateLoop(acc, input, nbBlocks * blockLen, secret, 0, nbStripes);
2527
+ accumulate512(
2528
+ acc,
2529
+ input,
2530
+ length - STRIPE_LEN,
2531
+ secret,
2532
+ secretSize - STRIPE_LEN - XXH_SECRET_LASTACC_START
2533
+ );
2534
+ return mergeAccs(
2535
+ acc,
2536
+ secret,
2537
+ XXH_SECRET_MERGEACCS_START,
2538
+ u64(BigInt(length) * PRIME64_1)
2539
+ );
2540
+ }
2541
+ function hashLongWithSeed(input, length, seed) {
2542
+ const secret = new Uint8Array(XXH_SECRET_DEFAULT_SIZE);
2543
+ for (let i = 0; i < XXH_SECRET_DEFAULT_SIZE / 16; i++) {
2544
+ const off = 16 * i;
2545
+ write64LE(secret, off, u64(read64LE(DEFAULT_SECRET, off) + seed));
2546
+ write64LE(
2547
+ secret,
2548
+ off + 8,
2549
+ u64(read64LE(DEFAULT_SECRET, off + 8) - seed)
2550
+ );
2551
+ }
2552
+ return hashLong(input, length, secret, secret.length);
2553
+ }
2554
+ var textEncoder2 = new TextEncoder();
2555
+ function xxh3_64(input, seed = 0n) {
2556
+ const len = input.length;
2557
+ if (len <= XXH3_MIDSIZE_MAX) {
2558
+ return hashShort(input, len, DEFAULT_SECRET, u64(seed));
2559
+ }
2560
+ return hashLongWithSeed(input, len, u64(seed));
2561
+ }
2562
+ function xxh3_64str(input, seed = 0n) {
2563
+ return xxh3_64(textEncoder2.encode(input), seed);
2564
+ }
2565
+ function computeMethodHash(methodName) {
2566
+ const utf8 = textEncoder2.encode(methodName);
2567
+ const prefixValue = Math.imul(67211, utf8.length) >>> 0;
2568
+ const prefixed = new Uint8Array(4 + utf8.length);
2569
+ prefixed[0] = prefixValue & 255;
2570
+ prefixed[1] = prefixValue >>> 8 & 255;
2571
+ prefixed[2] = prefixValue >>> 16 & 255;
2572
+ prefixed[3] = prefixValue >>> 24 & 255;
2573
+ prefixed.set(utf8, 4);
2574
+ const hash64 = xxh3_64(prefixed);
2575
+ return Number(hash64 & 0xffffffffn) | 0;
2576
+ }
2577
+
2578
+ // src/rpc-method-registry.ts
2579
+ var RpcMethodRegistry = class {
2580
+ _nameToHash = /* @__PURE__ */ new Map();
2581
+ _hashToName = /* @__PURE__ */ new Map();
2582
+ /** Register a method name and compute its hash. */
2583
+ register(methodName) {
2584
+ if (this._nameToHash.has(methodName)) return;
2585
+ const hash = computeMethodHash(methodName);
2586
+ const existing = this._hashToName.get(hash);
2587
+ if (existing !== void 0 && existing !== methodName) {
2588
+ console.warn(
2589
+ `[RpcMethodRegistry] hash collision: "${methodName}" and "${existing}" both hash to ${hash}`
2590
+ );
2591
+ return;
2592
+ }
2593
+ this._nameToHash.set(methodName, hash);
2594
+ this._hashToName.set(hash, methodName);
2595
+ }
2596
+ /** Register all wire method names from a service definition. */
2597
+ registerService(serviceName, methods) {
2598
+ for (const [, def] of methods) {
2599
+ const wireName = `${serviceName}.${def.name}:${def.wireArgCount}`;
2600
+ this.register(wireName);
2601
+ }
2602
+ }
2603
+ /** Get the hash for a method name. Computes on demand if not registered. */
2604
+ getHash(methodName) {
2605
+ let hash = this._nameToHash.get(methodName);
2606
+ if (hash === void 0) {
2607
+ this.register(methodName);
2608
+ hash = this._nameToHash.get(methodName);
2609
+ }
2610
+ return hash;
2611
+ }
2612
+ /** Get the method name for a hash. Returns undefined if not registered. */
2613
+ getName(hash) {
2614
+ return this._hashToName.get(hash);
2615
+ }
2616
+ /** Get the hash for a method name, throwing if not registered. */
2617
+ requireHash(methodName) {
2618
+ return this.getHash(methodName);
2619
+ }
2620
+ };
2621
+
1282
2622
  // src/rpc-hub.ts
1283
2623
  var RpcHub = class {
1284
2624
  hubId;
@@ -1286,9 +2626,16 @@ var RpcHub = class {
1286
2626
  serviceHost;
1287
2627
  systemCallSender = new RpcSystemCallSender();
1288
2628
  systemCallHandler = new RpcSystemCallHandler();
2629
+ /** Method registry for compact format hash ↔ name resolution.
2630
+ * Created lazily, populated by addService/addClient. */
2631
+ registry = new RpcMethodRegistry();
1289
2632
  constructor(hubId) {
1290
2633
  this.hubId = hubId ?? crypto.randomUUID();
1291
2634
  this.serviceHost = new RpcServiceHost();
2635
+ this.systemCallSender.registry = this.registry;
2636
+ for (const methodName of Object.values(RpcSystemCalls)) {
2637
+ this.registry.register(methodName);
2638
+ }
1292
2639
  }
1293
2640
  addPeer(peer) {
1294
2641
  this.peers.set(peer.ref, peer);
@@ -1326,10 +2673,12 @@ var RpcHub = class {
1326
2673
  wrappedImpl[methodDef.name] = methodDef.callTypeId !== 0 ? this._wrapServerMethod(methodDef, fn, impl) : fn;
1327
2674
  }
1328
2675
  this.serviceHost.register(def, wrappedImpl);
2676
+ this.registry.registerService(def.name, def.methods);
1329
2677
  }
1330
2678
  /** Create a typed client proxy for a service on a remote peer. */
1331
2679
  addClient(peer, defOrContract) {
1332
2680
  const def = this._resolveServiceDef(defOrContract);
2681
+ this.registry.registerService(def.name, def.methods);
1333
2682
  const overloads = /* @__PURE__ */ new Map();
1334
2683
  for (const methodDef of def.methods.values()) {
1335
2684
  let byArgCount = overloads.get(methodDef.name);
@@ -1337,7 +2686,10 @@ var RpcHub = class {
1337
2686
  byArgCount = /* @__PURE__ */ new Map();
1338
2687
  overloads.set(methodDef.name, byArgCount);
1339
2688
  }
1340
- byArgCount.set(methodDef.argCount, this._createClientMethod(peer, methodDef));
2689
+ byArgCount.set(
2690
+ methodDef.argCount,
2691
+ this._createClientMethod(peer, methodDef)
2692
+ );
1341
2693
  }
1342
2694
  const methods = /* @__PURE__ */ new Map();
1343
2695
  for (const [name, byArgCount] of overloads) {
@@ -1346,7 +2698,10 @@ var RpcHub = class {
1346
2698
  } else {
1347
2699
  methods.set(name, (...args) => {
1348
2700
  const fn = byArgCount.get(args.length);
1349
- if (!fn) throw new Error(`No overload of ${name} accepts ${args.length} arguments`);
2701
+ if (!fn)
2702
+ throw new Error(
2703
+ `No overload of ${name} accepts ${args.length} arguments`
2704
+ );
1350
2705
  return fn(...args);
1351
2706
  });
1352
2707
  }
@@ -1362,7 +2717,8 @@ var RpcHub = class {
1362
2717
  /** Build an RpcServiceDef from decorator metadata on a contract class. Override in FusionHub for compute support. */
1363
2718
  _buildServiceDef(cls) {
1364
2719
  const svcMeta = getServiceMeta(cls);
1365
- if (svcMeta === void 0) throw new Error("Contract class missing @rpcService metadata");
2720
+ if (svcMeta === void 0)
2721
+ throw new Error("Contract class missing @rpcService metadata");
1366
2722
  const methodsMeta = getMethodsMeta(cls) ?? {};
1367
2723
  const methods = /* @__PURE__ */ new Map();
1368
2724
  for (const [name, meta] of Object.entries(methodsMeta)) {
@@ -1405,7 +2761,10 @@ var RpcHub = class {
1405
2761
  const outboundCall = peer.call(wireName, callArgs);
1406
2762
  const result = await outboundCall.result.promise;
1407
2763
  const ref = parseStreamRef(result);
1408
- if (!ref) throw new Error(`Expected stream reference, got: ${JSON.stringify(result)}`);
2764
+ if (!ref)
2765
+ throw new Error(
2766
+ `Expected stream reference, got: ${JSON.stringify(result)}`
2767
+ );
1409
2768
  const stream = new RpcStream(ref, peer);
1410
2769
  peer.remoteObjects.register(stream);
1411
2770
  return stream;
@@ -1444,7 +2803,10 @@ function createRpcClient(peer, serviceDef) {
1444
2803
  }
1445
2804
  methods.set(name, (...args) => {
1446
2805
  const fn = fns.get(args.length);
1447
- if (!fn) throw new Error(`No overload of ${name} accepts ${args.length} arguments`);
2806
+ if (!fn)
2807
+ throw new Error(
2808
+ `No overload of ${name} accepts ${args.length} arguments`
2809
+ );
1448
2810
  return fn(...args);
1449
2811
  });
1450
2812
  }
@@ -1489,12 +2851,10 @@ function getStateDescription(state, useLastError = false) {
1489
2851
  case 1 /* JustDisconnected */:
1490
2852
  return "Just disconnected, reconnecting...";
1491
2853
  case 2 /* Disconnected */:
1492
- if (state.reconnectsIn > 0)
1493
- break;
2854
+ if (state.reconnectsIn > 0) break;
1494
2855
  return "Reconnecting...";
1495
2856
  }
1496
- if (state.lastError == null || !useLastError)
1497
- return "Disconnected.";
2857
+ if (state.lastError == null || !useLastError) return "Disconnected.";
1498
2858
  let message = state.lastError.message.trim();
1499
2859
  if (!(message.endsWith(".") || message.endsWith("!") || message.endsWith("?")))
1500
2860
  message += ".";
@@ -1525,7 +2885,9 @@ var RpcPeerStateMonitor = class {
1525
2885
  _onDisconnected = (ev) => {
1526
2886
  const wasConnected = this._rawConnected;
1527
2887
  this._rawConnected = false;
1528
- this._lastError = new Error(`Connection closed: ${ev.reason} (code ${ev.code})`);
2888
+ this._lastError = new Error(
2889
+ `Connection closed: ${ev.reason} (code ${ev.code})`
2890
+ );
1529
2891
  if (wasConnected) {
1530
2892
  this._disconnectedAt = Date.now();
1531
2893
  }
@@ -1542,16 +2904,26 @@ var RpcPeerStateMonitor = class {
1542
2904
  this._rawConnected = peer.isConnected;
1543
2905
  if (this._rawConnected) {
1544
2906
  this._connectedAt = Date.now();
1545
- this._state = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2907
+ this._state = {
2908
+ kind: 3 /* JustConnected */,
2909
+ reconnectsIn: 0
2910
+ };
1546
2911
  } else {
1547
2912
  this._disconnectedAt = Date.now();
1548
- this._state = { kind: 1 /* JustDisconnected */, reconnectsIn: 0 };
2913
+ this._state = {
2914
+ kind: 1 /* JustDisconnected */,
2915
+ reconnectsIn: 0
2916
+ };
1549
2917
  }
1550
2918
  peer.connected.add(this._onConnected);
1551
2919
  peer.disconnected.add(this._onDisconnected);
1552
2920
  peer.reconnectsAtChanged.add(this._onReconnectsAtChanged);
1553
- peer.reconnectDelayer.cancelDelaysChanged.add(this._onCancelDelaysChanged);
1554
- this._scheduleRecompute(this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs);
2921
+ peer.reconnectDelayer.cancelDelaysChanged.add(
2922
+ this._onCancelDelaysChanged
2923
+ );
2924
+ this._scheduleRecompute(
2925
+ this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs
2926
+ );
1555
2927
  }
1556
2928
  get state() {
1557
2929
  return this._state;
@@ -1564,7 +2936,9 @@ var RpcPeerStateMonitor = class {
1564
2936
  this.peer.connected.remove(this._onConnected);
1565
2937
  this.peer.disconnected.remove(this._onDisconnected);
1566
2938
  this.peer.reconnectsAtChanged.remove(this._onReconnectsAtChanged);
1567
- this.peer.reconnectDelayer.cancelDelaysChanged.remove(this._onCancelDelaysChanged);
2939
+ this.peer.reconnectDelayer.cancelDelaysChanged.remove(
2940
+ this._onCancelDelaysChanged
2941
+ );
1568
2942
  }
1569
2943
  _recompute() {
1570
2944
  if (this._timer !== void 0) {
@@ -1576,24 +2950,46 @@ var RpcPeerStateMonitor = class {
1576
2950
  if (this._rawConnected) {
1577
2951
  const connectedFor = now - this._connectedAt;
1578
2952
  if (connectedFor < JustConnectedPeriodMs) {
1579
- newState = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2953
+ newState = {
2954
+ kind: 3 /* JustConnected */,
2955
+ reconnectsIn: 0
2956
+ };
1580
2957
  this._scheduleRecompute(JustConnectedPeriodMs - connectedFor);
1581
2958
  } else {
1582
- newState = { kind: 0 /* Connected */, reconnectsIn: 0 };
2959
+ newState = {
2960
+ kind: 0 /* Connected */,
2961
+ reconnectsIn: 0
2962
+ };
1583
2963
  }
1584
2964
  } else {
1585
2965
  const disconnectedFor = now - this._disconnectedAt;
1586
2966
  if (disconnectedFor < JustDisconnectedPeriodMs) {
1587
- newState = { kind: 1 /* JustDisconnected */, lastError: this._lastError, reconnectsIn: 0 };
1588
- this._scheduleRecompute(JustDisconnectedPeriodMs - disconnectedFor);
2967
+ newState = {
2968
+ kind: 1 /* JustDisconnected */,
2969
+ lastError: this._lastError,
2970
+ reconnectsIn: 0
2971
+ };
2972
+ this._scheduleRecompute(
2973
+ JustDisconnectedPeriodMs - disconnectedFor
2974
+ );
1589
2975
  } else {
1590
2976
  const reconnectsAt = this.peer.reconnectsAt;
1591
2977
  const reconnectsIn = reconnectsAt > 0 ? Math.max(0, reconnectsAt - now) : 0;
1592
2978
  if (reconnectsIn < MinReconnectsInMs) {
1593
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn: 0 };
2979
+ newState = {
2980
+ kind: 2 /* Disconnected */,
2981
+ lastError: this._lastError,
2982
+ reconnectsIn: 0
2983
+ };
1594
2984
  } else {
1595
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn };
1596
- this._scheduleRecompute(Math.min(1e3, reconnectsIn - MinReconnectsInMs));
2985
+ newState = {
2986
+ kind: 2 /* Disconnected */,
2987
+ lastError: this._lastError,
2988
+ reconnectsIn
2989
+ };
2990
+ this._scheduleRecompute(
2991
+ Math.min(1e3, reconnectsIn - MinReconnectsInMs)
2992
+ );
1597
2993
  }
1598
2994
  }
1599
2995
  }
@@ -1608,10 +3004,13 @@ var RpcPeerStateMonitor = class {
1608
3004
  }
1609
3005
  _scheduleRecompute(delayMs) {
1610
3006
  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));
3007
+ this._timer = setTimeout(
3008
+ () => {
3009
+ this._timer = void 0;
3010
+ this._recompute();
3011
+ },
3012
+ Math.max(0, delayMs)
3013
+ );
1615
3014
  }
1616
3015
  };
1617
3016
  // Annotate the CommonJS export names for ESM import in node:
@@ -1627,7 +3026,11 @@ var RpcPeerStateMonitor = class {
1627
3026
  RpcHub,
1628
3027
  RpcInboundCall,
1629
3028
  RpcInboundCallTracker,
3029
+ RpcJsonSerializationFormat,
1630
3030
  RpcMessageChannelConnection,
3031
+ RpcMessagePackCompactSerializationFormat,
3032
+ RpcMessagePackSerializationFormat,
3033
+ RpcMethodRegistry,
1631
3034
  RpcObjectKind,
1632
3035
  RpcOutboundCall,
1633
3036
  RpcOutboundCallTracker,
@@ -1636,6 +3039,7 @@ var RpcPeerStateMonitor = class {
1636
3039
  RpcPeerStateKind,
1637
3040
  RpcPeerStateMonitor,
1638
3041
  RpcRemoteObjectTracker,
3042
+ RpcSerializationFormat,
1639
3043
  RpcServerPeer,
1640
3044
  RpcServiceHost,
1641
3045
  RpcSharedObjectTracker,
@@ -1647,10 +3051,16 @@ var RpcPeerStateMonitor = class {
1647
3051
  RpcType,
1648
3052
  RpcWebSocketConnection,
1649
3053
  WebSocketState,
3054
+ computeMethodHash,
3055
+ createBinaryEncoder,
1650
3056
  createMessageChannelPair,
1651
3057
  createRpcClient,
3058
+ defaultBinaryDecoder,
3059
+ defaultBinaryEncoder,
1652
3060
  defaultConnectionUrlResolver,
1653
3061
  defineRpcService,
3062
+ deserializeBinaryMessage,
3063
+ deserializeCompactBinaryMessage,
1654
3064
  deserializeMessage,
1655
3065
  getMethodsMeta,
1656
3066
  getServiceMeta,
@@ -1661,9 +3071,16 @@ var RpcPeerStateMonitor = class {
1661
3071
  resolveStreamRefs,
1662
3072
  rpcMethod,
1663
3073
  rpcService,
3074
+ serializeBinaryFrame,
3075
+ serializeBinaryMessage,
3076
+ serializeCompactBinaryMessage,
1664
3077
  serializeFrame,
1665
3078
  serializeMessage,
3079
+ splitBinaryFrame,
3080
+ splitCompactBinaryFrame,
1666
3081
  splitFrame,
1667
- wireMethodName
3082
+ wireMethodName,
3083
+ xxh3_64,
3084
+ xxh3_64str
1668
3085
  });
1669
3086
  //# sourceMappingURL=index.cjs.map