@actuallab/rpc 12.1.100 → 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
@@ -24,13 +34,18 @@ __export(index_exports, {
24
34
  DEFAULT_SERIALIZATION_FORMAT: () => DEFAULT_SERIALIZATION_FORMAT,
25
35
  ENVELOPE_DELIMITER: () => ENVELOPE_DELIMITER,
26
36
  FRAME_DELIMITER: () => FRAME_DELIMITER,
37
+ RPC_CLOSE_CODE_UNSUPPORTED_FORMAT: () => RPC_CLOSE_CODE_UNSUPPORTED_FORMAT,
27
38
  RpcCallTypeId: () => RpcCallTypeId,
28
39
  RpcClientPeer: () => RpcClientPeer,
29
40
  RpcClientPeerReconnectDelayer: () => RpcClientPeerReconnectDelayer,
30
41
  RpcHub: () => RpcHub,
31
42
  RpcInboundCall: () => RpcInboundCall,
32
43
  RpcInboundCallTracker: () => RpcInboundCallTracker,
44
+ RpcJsonSerializationFormat: () => RpcJsonSerializationFormat,
33
45
  RpcMessageChannelConnection: () => RpcMessageChannelConnection,
46
+ RpcMessagePackCompactSerializationFormat: () => RpcMessagePackCompactSerializationFormat,
47
+ RpcMessagePackSerializationFormat: () => RpcMessagePackSerializationFormat,
48
+ RpcMethodRegistry: () => RpcMethodRegistry,
34
49
  RpcObjectKind: () => RpcObjectKind,
35
50
  RpcOutboundCall: () => RpcOutboundCall,
36
51
  RpcOutboundCallTracker: () => RpcOutboundCallTracker,
@@ -39,6 +54,7 @@ __export(index_exports, {
39
54
  RpcPeerStateKind: () => RpcPeerStateKind,
40
55
  RpcPeerStateMonitor: () => RpcPeerStateMonitor,
41
56
  RpcRemoteObjectTracker: () => RpcRemoteObjectTracker,
57
+ RpcSerializationFormat: () => RpcSerializationFormat,
42
58
  RpcServerPeer: () => RpcServerPeer,
43
59
  RpcServiceHost: () => RpcServiceHost,
44
60
  RpcSharedObjectTracker: () => RpcSharedObjectTracker,
@@ -50,10 +66,16 @@ __export(index_exports, {
50
66
  RpcType: () => RpcType,
51
67
  RpcWebSocketConnection: () => RpcWebSocketConnection,
52
68
  WebSocketState: () => WebSocketState,
69
+ computeMethodHash: () => computeMethodHash,
70
+ createBinaryEncoder: () => createBinaryEncoder,
53
71
  createMessageChannelPair: () => createMessageChannelPair,
54
72
  createRpcClient: () => createRpcClient,
73
+ defaultBinaryDecoder: () => defaultBinaryDecoder,
74
+ defaultBinaryEncoder: () => defaultBinaryEncoder,
55
75
  defaultConnectionUrlResolver: () => defaultConnectionUrlResolver,
56
76
  defineRpcService: () => defineRpcService,
77
+ deserializeBinaryMessage: () => deserializeBinaryMessage,
78
+ deserializeCompactBinaryMessage: () => deserializeCompactBinaryMessage,
57
79
  deserializeMessage: () => deserializeMessage,
58
80
  getMethodsMeta: () => getMethodsMeta,
59
81
  getServiceMeta: () => getServiceMeta,
@@ -64,10 +86,17 @@ __export(index_exports, {
64
86
  resolveStreamRefs: () => resolveStreamRefs,
65
87
  rpcMethod: () => rpcMethod,
66
88
  rpcService: () => rpcService,
89
+ serializeBinaryFrame: () => serializeBinaryFrame,
90
+ serializeBinaryMessage: () => serializeBinaryMessage,
91
+ serializeCompactBinaryMessage: () => serializeCompactBinaryMessage,
67
92
  serializeFrame: () => serializeFrame,
68
93
  serializeMessage: () => serializeMessage,
94
+ splitBinaryFrame: () => splitBinaryFrame,
95
+ splitCompactBinaryFrame: () => splitCompactBinaryFrame,
69
96
  splitFrame: () => splitFrame,
70
- wireMethodName: () => wireMethodName
97
+ wireMethodName: () => wireMethodName,
98
+ xxh3_64: () => xxh3_64,
99
+ xxh3_64str: () => xxh3_64str
71
100
  });
72
101
  module.exports = __toCommonJS(index_exports);
73
102
 
@@ -95,6 +124,7 @@ var ARG_DELIMITER = "";
95
124
  var FRAME_DELIMITER = "\n";
96
125
 
97
126
  // src/rpc-serialization.ts
127
+ var import_msgpack = require("@msgpack/msgpack");
98
128
  function serializeMessage(message, args) {
99
129
  const envelope = JSON.stringify(message);
100
130
  if (args === void 0 || args.length === 0) {
@@ -124,13 +154,263 @@ function deserializeMessage(raw) {
124
154
  try {
125
155
  return JSON.parse(s);
126
156
  } catch {
157
+ console.warn(
158
+ `[RpcSerialization] failed to parse arg as JSON: ${s.substring(0, 100)}`
159
+ );
127
160
  return s;
128
161
  }
129
162
  });
130
163
  return { message, args };
131
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
+ }
132
411
 
133
412
  // src/rpc-connection.ts
413
+ var import_msgpack2 = require("@msgpack/msgpack");
134
414
  var import_core = require("@actuallab/core");
135
415
  var WebSocketState = {
136
416
  CONNECTING: 0,
@@ -142,11 +422,36 @@ var RpcWebSocketConnection = class {
142
422
  _ws;
143
423
  _sendBuffer = [];
144
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;
145
445
  messageReceived = new import_core.EventHandlerSet();
146
446
  closed = new import_core.EventHandlerSet();
147
447
  error = new import_core.EventHandlerSet();
148
- constructor(ws) {
448
+ constructor(ws, binaryMode = false, format, methodRegistry) {
149
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";
150
455
  if (ws.readyState === WebSocketState.OPEN) {
151
456
  this._connected.resolve();
152
457
  this._flush();
@@ -156,10 +461,46 @@ var RpcWebSocketConnection = class {
156
461
  this._flush();
157
462
  };
158
463
  ws.onmessage = (ev) => {
159
- const data = typeof ev.data === "string" ? ev.data : String(ev.data);
160
- const messages = splitFrame(data);
161
- for (const msg of messages) {
162
- 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
+ }
163
504
  }
164
505
  };
165
506
  ws.onclose = (ev) => {
@@ -176,27 +517,46 @@ var RpcWebSocketConnection = class {
176
517
  return this._connected.promise;
177
518
  }
178
519
  send(serializedMessage) {
179
- try {
180
- if (this._ws.readyState === WebSocketState.OPEN)
181
- this._ws.send(serializedMessage);
182
- else if (this._ws.readyState === WebSocketState.CONNECTING)
183
- this._sendBuffer.push(serializedMessage);
184
- } catch {
185
- }
520
+ this._sendRaw(serializedMessage);
521
+ }
522
+ sendBinary(data) {
523
+ this._sendRaw(data);
524
+ }
525
+ sendTextBatch(messages) {
526
+ this._sendRaw(serializeFrame(messages));
527
+ }
528
+ sendBinaryBatch(messages) {
529
+ this._sendRaw(serializeBinaryFrame(messages));
186
530
  }
187
- sendBatch(messages) {
188
- const frame = serializeFrame(messages);
189
- this.send(frame);
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);
190
541
  }
191
542
  close(code, reason) {
192
543
  this._ws.close(code, reason);
193
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
+ }
194
554
  _flush() {
195
555
  if (this._sendBuffer.length === 0) return;
196
- const frame = serializeFrame(this._sendBuffer);
556
+ const buffer = this._sendBuffer;
197
557
  this._sendBuffer = [];
198
558
  try {
199
- this._ws.send(frame);
559
+ for (const item of buffer) this._ws.send(item);
200
560
  } catch {
201
561
  }
202
562
  }
@@ -207,6 +567,7 @@ var import_core2 = require("@actuallab/core");
207
567
  var RpcMessageChannelConnection = class {
208
568
  _port;
209
569
  _open = true;
570
+ binaryMode = false;
210
571
  messageReceived = new import_core2.EventHandlerSet();
211
572
  closed = new import_core2.EventHandlerSet();
212
573
  whenConnected = Promise.resolve();
@@ -216,7 +577,8 @@ var RpcMessageChannelConnection = class {
216
577
  port.onmessage = (ev) => {
217
578
  const data = typeof ev.data === "string" ? ev.data : String(ev.data);
218
579
  for (const msg of splitFrame(data))
219
- if (msg.length > 0) this.messageReceived.trigger(msg);
580
+ if (msg.length > 0)
581
+ this.messageReceived.trigger({ kind: "text", raw: msg });
220
582
  };
221
583
  }
222
584
  get isOpen() {
@@ -229,6 +591,13 @@ var RpcMessageChannelConnection = class {
229
591
  } catch {
230
592
  }
231
593
  }
594
+ sendBinary(data) {
595
+ if (!this._open) return;
596
+ try {
597
+ this._port.postMessage(data, [data.buffer]);
598
+ } catch {
599
+ }
600
+ }
232
601
  close(code, reason) {
233
602
  if (!this._open) return;
234
603
  this._open = false;
@@ -283,8 +652,8 @@ var RpcOutboundCall = class {
283
652
  /** Whether to remove this call from the tracker on $sys.Ok. Default: true.
284
653
  * Subclasses (e.g. compute calls) override to false to stay in tracker for invalidation. */
285
654
  removeOnOk = true;
286
- /** The serialized wire message — stored for re-sending on reconnect. */
287
- serializedMessage = "";
655
+ /** The serialized wire data — stored for re-sending on reconnect. */
656
+ serializedWireData = "";
288
657
  constructor(callId, method) {
289
658
  this.callId = callId;
290
659
  this.method = method;
@@ -374,6 +743,7 @@ var RpcInboundCallTracker = class {
374
743
  };
375
744
 
376
745
  // src/rpc-stream.ts
746
+ var import_denque = __toESM(require("denque"), 1);
377
747
  var import_core4 = require("@actuallab/core");
378
748
 
379
749
  // src/rpc-object.ts
@@ -381,25 +751,49 @@ var RpcObjectKind = { Local: 0, Remote: 1 };
381
751
 
382
752
  // src/rpc-stream.ts
383
753
  function parseStreamRef(value) {
384
- if (typeof value !== "string") return null;
385
- const parts = value.split(",");
386
- if (parts.length < 4 || parts.length > 5) return null;
387
- const hostId = parts[0];
388
- const localId = parseInt(parts[1], 10);
389
- const ackPeriod = parseInt(parts[2], 10);
390
- const ackAdvance = parseInt(parts[3], 10);
391
- if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance)) return null;
392
- const allowReconnect = parts.length < 5 || parts[4] !== "0";
393
- 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;
394
782
  }
395
- var RpcStream = class {
783
+ var RpcStream = class _RpcStream {
396
784
  id;
397
785
  kind = RpcObjectKind.Remote;
398
786
  allowReconnect;
399
787
  peer;
400
788
  ackPeriod;
401
789
  ackAdvance;
402
- _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();
403
797
  _nextExpectedIndex = 0;
404
798
  _consumerWaiting = null;
405
799
  _completed = false;
@@ -419,6 +813,17 @@ var RpcStream = class {
419
813
  onItem(index, item) {
420
814
  if (this._disposed || this._completed) return;
421
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
+ }
422
827
  this._sendAck(this._nextExpectedIndex, true);
423
828
  return;
424
829
  }
@@ -435,6 +840,17 @@ var RpcStream = class {
435
840
  onBatch(index, items) {
436
841
  if (this._disposed || this._completed) return;
437
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
+ }
438
854
  this._sendAck(this._nextExpectedIndex, true);
439
855
  return;
440
856
  }
@@ -470,10 +886,9 @@ var RpcStream = class {
470
886
  }
471
887
  // -- AsyncIterable --
472
888
  [Symbol.asyncIterator]() {
473
- 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.");
474
891
  this._iterating = true;
475
- let bufferIndex = 0;
476
- let consumedIndex = 0;
477
892
  const self = this;
478
893
  return {
479
894
  async next() {
@@ -482,10 +897,8 @@ var RpcStream = class {
482
897
  self._sendAck(0, true);
483
898
  }
484
899
  while (true) {
485
- if (bufferIndex < self._buffer.length) {
486
- const value = self._buffer[bufferIndex];
487
- bufferIndex++;
488
- consumedIndex++;
900
+ if (!self._buffer.isEmpty()) {
901
+ const value = self._buffer.shift();
489
902
  return { value, done: false };
490
903
  }
491
904
  if (self._completed) {
@@ -524,17 +937,30 @@ var RpcStream = class {
524
937
  this._sendAck(nextIndex, false);
525
938
  }
526
939
  }
527
- _sendAck(nextIndex, _mustReset) {
940
+ static _emptyGuid = "00000000-0000-0000-0000-000000000000";
941
+ _sendAck(nextIndex, mustReset) {
528
942
  this._ackSentUpTo = nextIndex;
529
943
  const conn = this.peer.connection;
530
944
  if (conn) {
531
- 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
+ );
532
953
  }
533
954
  }
534
955
  _sendAckEnd() {
535
956
  const conn = this.peer.connection;
536
957
  if (conn) {
537
- 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
+ );
538
964
  }
539
965
  }
540
966
  };
@@ -556,6 +982,8 @@ function resolveStreamRefs(value, peer) {
556
982
  return value;
557
983
  }
558
984
  if (typeof value === "object") {
985
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer)
986
+ return value;
559
987
  for (const key of Object.keys(value)) {
560
988
  value[key] = resolveStreamRefs(
561
989
  value[key],
@@ -601,21 +1029,39 @@ var RpcSystemCallHandler = class {
601
1029
  }
602
1030
  case RpcSystemCalls.item: {
603
1031
  const stream = peer.remoteObjects.get(relatedId);
604
- 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
+ }
605
1042
  break;
606
1043
  }
607
1044
  case RpcSystemCalls.batch: {
608
1045
  const stream = peer.remoteObjects.get(relatedId);
609
- 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])) {
610
1051
  const items = args[1];
611
- 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);
612
1054
  stream.onBatch(args[0], items);
613
1055
  }
614
1056
  break;
615
1057
  }
616
1058
  case RpcSystemCalls.end: {
617
1059
  const stream = peer.remoteObjects.get(relatedId);
618
- if (stream) {
1060
+ if (!stream) {
1061
+ console.warn(
1062
+ `[RpcSysHandler] $sys.End: no stream for relatedId=${relatedId}`
1063
+ );
1064
+ } else {
619
1065
  const errorInfo = args[1];
620
1066
  const msg = errorInfo?.Message ?? errorInfo?.message;
621
1067
  const error = msg ? new Error(msg) : null;
@@ -633,76 +1079,142 @@ var RpcSystemCallHandler = class {
633
1079
  sender?.onAckEnd(args[0]);
634
1080
  break;
635
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
+ }
636
1100
  }
637
1101
  }
638
1102
  };
639
1103
 
640
1104
  // src/rpc-system-call-sender.ts
641
- var RpcSystemCallSender = class {
642
- handshake(conn, peerId, hubId, index) {
643
- 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] : {
644
1150
  RemotePeerId: peerId,
645
1151
  RemoteApiVersionSet: null,
646
1152
  RemoteHubId: hubId,
647
1153
  ProtocolVersion: 2,
648
1154
  Index: index
649
- }]);
650
- conn.send(msg);
651
- }
652
- ok(conn, relatedId, result) {
653
- const msg = serializeMessage({ Method: RpcSystemCalls.ok, RelatedId: relatedId }, [result]);
654
- 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
+ );
655
1167
  }
656
- error(conn, relatedId, error) {
1168
+ error(conn, format, relatedId, error) {
657
1169
  const message = error instanceof Error ? error.message : String(error);
658
- const msg = serializeMessage(
1170
+ this._send(
1171
+ conn,
1172
+ format,
659
1173
  { Method: RpcSystemCalls.error, RelatedId: relatedId },
660
1174
  [{ Message: message }]
661
1175
  );
662
- conn.send(msg);
663
- }
664
- cancel(conn, relatedId) {
665
- const msg = serializeMessage({ Method: RpcSystemCalls.cancel, RelatedId: relatedId });
666
- conn.send(msg);
667
- }
668
- keepAlive(conn, activeCallIds) {
669
- const msg = serializeMessage({ Method: RpcSystemCalls.keepAlive }, [activeCallIds]);
670
- conn.send(msg);
671
- }
672
- item(conn, localId, index, item) {
673
- const msg = serializeMessage(
674
- { Method: RpcSystemCalls.item, RelatedId: localId },
675
- [index, item]
676
- );
677
- conn.send(msg);
678
- }
679
- batch(conn, localId, index, items) {
680
- const msg = serializeMessage(
681
- { Method: RpcSystemCalls.batch, RelatedId: localId },
682
- [index, items]
683
- );
684
- conn.send(msg);
685
- }
686
- end(conn, localId, index, error = null) {
687
- const msg = serializeMessage(
688
- { Method: RpcSystemCalls.end, RelatedId: localId },
689
- [index, error]
690
- );
691
- conn.send(msg);
692
1176
  }
693
- ack(conn, localId, nextIndex, hostId) {
694
- const msg = serializeMessage(
695
- { Method: RpcSystemCalls.ack, RelatedId: localId },
696
- [nextIndex, hostId]
697
- );
698
- conn.send(msg);
1177
+ cancel(conn, format, relatedId) {
1178
+ this._send(conn, format, {
1179
+ Method: RpcSystemCalls.cancel,
1180
+ RelatedId: relatedId
1181
+ });
699
1182
  }
700
- ackEnd(conn, localId, hostId) {
701
- const msg = serializeMessage(
702
- { Method: RpcSystemCalls.ackEnd, RelatedId: localId },
703
- [hostId]
704
- );
705
- 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);
706
1218
  }
707
1219
  };
708
1220
 
@@ -714,29 +1226,42 @@ var RpcStreamSender = class {
714
1226
  id;
715
1227
  kind = RpcObjectKind.Local;
716
1228
  allowReconnect;
1229
+ isRealTime;
1230
+ canSkipTo;
717
1231
  peer;
718
1232
  ackPeriod;
719
1233
  ackAdvance;
720
1234
  _nextIndex = 0;
721
1235
  _ended = false;
722
1236
  _started = new import_core5.PromiseSource();
723
- 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) {
724
1240
  const localId = peer.sharedObjects.nextId();
725
1241
  this.id = { hostId: peer.hub.hubId, localId };
726
1242
  this.allowReconnect = allowReconnect;
1243
+ this.isRealTime = isRealTime;
1244
+ this.canSkipTo = canSkipTo;
727
1245
  this.peer = peer;
728
1246
  this.ackPeriod = ackPeriod;
729
1247
  this.ackAdvance = ackAdvance;
730
1248
  }
731
1249
  /** Returns the stream reference string for the $sys.Ok response. */
732
1250
  toRef() {
733
- 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"}`;
734
1252
  }
735
1253
  /** Called by system call handler when $sys.Ack is received from the client. */
736
- onAck(_nextIndex, _hostId) {
1254
+ onAck(nextIndex, _hostId) {
737
1255
  if (!this._started.isCompleted) {
738
1256
  this._started.resolve();
739
1257
  }
1258
+ if (nextIndex > this._lastAckedIndex) {
1259
+ this._lastAckedIndex = nextIndex;
1260
+ }
1261
+ if (this._ackWaiting) {
1262
+ this._ackWaiting.resolve();
1263
+ this._ackWaiting = null;
1264
+ }
740
1265
  }
741
1266
  /** Called by system call handler when $sys.AckEnd is received from the client. */
742
1267
  onAckEnd(_hostId) {
@@ -748,7 +1273,13 @@ var RpcStreamSender = class {
748
1273
  if (this._ended) return;
749
1274
  const conn = this.peer.connection;
750
1275
  if (!conn) return;
751
- 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
+ );
752
1283
  this._nextIndex++;
753
1284
  }
754
1285
  /** Send a batch of items to the client. */
@@ -756,7 +1287,13 @@ var RpcStreamSender = class {
756
1287
  if (this._ended || items.length === 0) return;
757
1288
  const conn = this.peer.connection;
758
1289
  if (!conn) return;
759
- 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
+ );
760
1297
  this._nextIndex += items.length;
761
1298
  }
762
1299
  /** Signal stream completion to the client. */
@@ -765,19 +1302,63 @@ var RpcStreamSender = class {
765
1302
  this._ended = true;
766
1303
  const conn = this.peer.connection;
767
1304
  if (!conn) return;
768
- const errorInfo = error ? { Message: error.message } : null;
769
- 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
+ );
770
1313
  }
771
1314
  /**
772
1315
  * Consume an AsyncIterable and send all items to the client.
773
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.
774
1322
  */
775
1323
  async writeFrom(source) {
776
1324
  await this._started.promise;
1325
+ const iterator = source[Symbol.asyncIterator]();
777
1326
  try {
778
- 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
+ }
779
1354
  if (this._ended) return;
780
- 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
+ }
781
1362
  }
782
1363
  if (!this._ended) {
783
1364
  this.sendEnd();
@@ -788,6 +1369,14 @@ var RpcStreamSender = class {
788
1369
  }
789
1370
  }
790
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
+ }
791
1380
  // -- IRpcObject --
792
1381
  reconnect() {
793
1382
  }
@@ -809,6 +1398,9 @@ var RpcRemoteObjectTracker = class {
809
1398
  get(localId) {
810
1399
  return this._objects.get(localId);
811
1400
  }
1401
+ keys() {
1402
+ return this._objects.keys();
1403
+ }
812
1404
  unregister(obj) {
813
1405
  this._objects.delete(obj.id.localId);
814
1406
  }
@@ -820,10 +1412,8 @@ var RpcRemoteObjectTracker = class {
820
1412
  }
821
1413
  reconnectAll() {
822
1414
  for (const obj of this._objects.values()) {
823
- if (obj.allowReconnect)
824
- obj.reconnect();
825
- else
826
- obj.disconnect();
1415
+ if (obj.allowReconnect) obj.reconnect();
1416
+ else obj.disconnect();
827
1417
  }
828
1418
  }
829
1419
  };
@@ -841,6 +1431,9 @@ var RpcSharedObjectTracker = class {
841
1431
  get(localId) {
842
1432
  return this._objects.get(localId);
843
1433
  }
1434
+ keys() {
1435
+ return this._objects.keys();
1436
+ }
844
1437
  unregister(obj) {
845
1438
  this._objects.delete(obj.id.localId);
846
1439
  }
@@ -864,8 +1457,132 @@ var RpcClientPeerReconnectDelayer = class extends import_core6.RetryDelayer {
864
1457
  }
865
1458
  };
866
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
+
867
1583
  // src/rpc-peer.ts
868
1584
  var DEFAULT_SERIALIZATION_FORMAT = "json5np";
1585
+ var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
869
1586
  var defaultConnectionUrlResolver = (peer) => {
870
1587
  const sep = peer.ref.includes("?") ? "&" : "?";
871
1588
  return peer.ref + sep + `clientId=${peer.clientId}&f=${peer.serializationFormat}`;
@@ -911,17 +1628,27 @@ var RpcPeer = class {
911
1628
  this._startKeepAlive();
912
1629
  });
913
1630
  }
1631
+ /** The serialization format used by this peer. Override in subclasses. */
1632
+ get format() {
1633
+ return RpcSerializationFormat.get("json5np");
1634
+ }
914
1635
  call(method, args, options) {
915
1636
  const callId = this.outbound.nextId();
916
1637
  const outboundCall = options?.outboundCallFactory ? options.outboundCallFactory(callId, method) : new RpcOutboundCall(callId, method);
917
- const msg = serializeMessage(
918
- { Method: method, RelatedId: callId, CallType: options?.callTypeId ?? 0 },
919
- 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
920
1648
  );
921
- outboundCall.serializedMessage = msg;
922
1649
  if (this._connection !== void 0) {
923
1650
  this.outbound.register(outboundCall);
924
- this._connection.send(msg);
1651
+ this._sendWireData(outboundCall.serializedWireData);
925
1652
  } else {
926
1653
  this._pendingSends.push(outboundCall);
927
1654
  }
@@ -935,12 +1662,16 @@ var RpcPeer = class {
935
1662
  outboundCall.result.reject(new Error("Call cancelled."));
936
1663
  outboundCall.onDisconnect();
937
1664
  if (peer._connection !== void 0)
938
- hub.systemCallSender.cancel(peer._connection, callId);
1665
+ hub.systemCallSender.cancel(peer._connection, peer.format, callId);
939
1666
  } else {
940
- const idx = peer._pendingSends.findIndex((c) => c.callId === callId);
1667
+ const idx = peer._pendingSends.findIndex(
1668
+ (c) => c.callId === callId
1669
+ );
941
1670
  if (idx !== -1) {
942
1671
  peer._pendingSends.splice(idx, 1);
943
- outboundCall.result.reject(new Error("Call cancelled."));
1672
+ outboundCall.result.reject(
1673
+ new Error("Call cancelled.")
1674
+ );
944
1675
  outboundCall.onDisconnect();
945
1676
  }
946
1677
  }
@@ -952,8 +1683,14 @@ var RpcPeer = class {
952
1683
  }
953
1684
  callNoWait(method, args) {
954
1685
  if (this._connection === void 0) return;
955
- const msg = serializeMessage({ Method: method, RelatedId: 0 }, args);
956
- 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);
957
1694
  }
958
1695
  close() {
959
1696
  this._stopKeepAlive();
@@ -972,23 +1709,41 @@ var RpcPeer = class {
972
1709
  }
973
1710
  /** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
974
1711
  _flushPendingSends() {
975
- if (this._pendingSends.length === 0 || this._connection === void 0) return;
1712
+ if (this._pendingSends.length === 0 || this._connection === void 0)
1713
+ return;
976
1714
  for (const call of this._pendingSends) {
977
1715
  this.outbound.register(call);
978
- this._connection.send(call.serializedMessage);
1716
+ this._sendWireData(call.serializedWireData);
979
1717
  }
980
1718
  this._pendingSends.length = 0;
981
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
+ }
982
1729
  /** Override in subclasses to handle the remote peer's handshake response. */
983
1730
  _onHandshakeReceived(_handshake) {
984
1731
  }
985
- _handleMessage(raw) {
986
- 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
+ }
987
1743
  const method = message.Method ?? "";
988
1744
  if (method === RpcSystemCalls.handshake) {
989
1745
  const handshake = args[0];
990
- if (handshake !== void 0)
991
- this._onHandshakeReceived(handshake);
1746
+ if (handshake !== void 0) this._onHandshakeReceived(handshake);
992
1747
  return;
993
1748
  }
994
1749
  if (method.startsWith("$sys")) {
@@ -1010,19 +1765,42 @@ var RpcPeer = class {
1010
1765
  if (serviceHost !== void 0) {
1011
1766
  void (async () => {
1012
1767
  try {
1013
- const context = this._connection !== void 0 ? { __rpcDispatch: true, callId: relatedId, connection: this._connection } : void 0;
1014
- 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
+ );
1015
1778
  if (methodDef?.stream === true && this._connection !== void 0) {
1016
1779
  const sender = new RpcStreamSender(this);
1017
1780
  this.sharedObjects.register(sender);
1018
- 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
+ );
1019
1787
  void sender.writeFrom(result);
1020
1788
  } else if (!isNoWait && this._connection !== void 0) {
1021
- this._hub.systemCallSender.ok(this._connection, relatedId, result);
1789
+ this._hub.systemCallSender.ok(
1790
+ this._connection,
1791
+ this.format,
1792
+ relatedId,
1793
+ result
1794
+ );
1022
1795
  }
1023
1796
  } catch (e) {
1024
1797
  if (!isNoWait && this._connection !== void 0) {
1025
- this._hub.systemCallSender.error(this._connection, relatedId, e);
1798
+ this._hub.systemCallSender.error(
1799
+ this._connection,
1800
+ this.format,
1801
+ relatedId,
1802
+ e
1803
+ );
1026
1804
  }
1027
1805
  } finally {
1028
1806
  if (!isNoWait) {
@@ -1035,7 +1813,9 @@ var RpcPeer = class {
1035
1813
  _startKeepAlive() {
1036
1814
  this._keepAliveTimer = setInterval(() => {
1037
1815
  if (this._connection !== void 0) {
1038
- this._hub.systemCallSender.keepAlive(this._connection, this.outbound.activeCallIds());
1816
+ this._hub.systemCallSender.keepAlive(this._connection, this.format, [
1817
+ ...this.remoteObjects.keys()
1818
+ ]);
1039
1819
  }
1040
1820
  }, 15e3);
1041
1821
  }
@@ -1071,6 +1851,8 @@ var RpcClientPeer = class extends RpcPeer {
1071
1851
  /** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
1072
1852
  connectionUrlResolver = defaultConnectionUrlResolver;
1073
1853
  peerChanged = new import_core7.EventHandlerSet();
1854
+ /** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
1855
+ unsupportedFormat = new import_core7.EventHandlerSet();
1074
1856
  reconnectDelayer = new RpcClientPeerReconnectDelayer();
1075
1857
  reconnectsAtChanged = new import_core7.EventHandlerSet();
1076
1858
  get reconnectsAt() {
@@ -1081,10 +1863,15 @@ var RpcClientPeer = class extends RpcPeer {
1081
1863
  this._reconnectsAt = value;
1082
1864
  this.reconnectsAtChanged.trigger();
1083
1865
  }
1866
+ _format;
1084
1867
  constructor(hub, url, serializationFormat) {
1085
1868
  super(url, hub);
1086
1869
  this.clientId = guidToBase64Url(this.id);
1087
1870
  this.serializationFormat = serializationFormat ?? DEFAULT_SERIALIZATION_FORMAT;
1871
+ this._format = RpcSerializationFormat.get(this.serializationFormat);
1872
+ }
1873
+ get format() {
1874
+ return this._format;
1088
1875
  }
1089
1876
  get connectionKind() {
1090
1877
  return this._connectionKind;
@@ -1098,18 +1885,39 @@ var RpcClientPeer = class extends RpcPeer {
1098
1885
  async run(wsFactory) {
1099
1886
  const connUrl = this.connectionUrlResolver(this);
1100
1887
  while (!this._disposed) {
1888
+ let lastCloseCode = 0;
1889
+ let lastCloseReason = "";
1101
1890
  try {
1102
1891
  const ws = wsFactory?.(connUrl) ?? new WebSocket(connUrl);
1103
- const conn = new RpcWebSocketConnection(ws);
1892
+ const conn = new RpcWebSocketConnection(
1893
+ ws,
1894
+ this.format.isBinary,
1895
+ this.format,
1896
+ this._hub.registry
1897
+ );
1104
1898
  this._connectionKind = 1 /* Connecting */;
1899
+ conn.closed.add((ev) => {
1900
+ lastCloseCode = ev.code;
1901
+ lastCloseReason = ev.reason;
1902
+ });
1105
1903
  this._pendingHandshake = new import_core7.PromiseSource();
1106
1904
  this.setupConnection(conn);
1107
1905
  this._connection = void 0;
1108
- 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
+ );
1109
1911
  closedRejection.catch(() => {
1110
1912
  });
1111
1913
  await Promise.race([conn.whenConnected, closedRejection]);
1112
- 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
+ );
1113
1921
  const remoteHandshake = await Promise.race([
1114
1922
  this._pendingHandshake.promise,
1115
1923
  closedRejection
@@ -1134,6 +1942,11 @@ var RpcClientPeer = class extends RpcPeer {
1134
1942
  }
1135
1943
  this._connectionKind = 0 /* Disconnected */;
1136
1944
  if (this._disposed) break;
1945
+ if (lastCloseCode === RPC_CLOSE_CODE_UNSUPPORTED_FORMAT) {
1946
+ this.unsupportedFormat.trigger({ reason: lastCloseReason });
1947
+ this._disposed = true;
1948
+ break;
1949
+ }
1137
1950
  this._tryIndex++;
1138
1951
  const delay = this.reconnectDelayer.getDelay(this._tryIndex);
1139
1952
  if (delay.isLimitExceeded) {
@@ -1157,7 +1970,6 @@ var RpcClientPeer = class extends RpcPeer {
1157
1970
  * Regular in-flight calls are re-sent transparently. */
1158
1971
  _reconnect(_isPeerChanged) {
1159
1972
  if (this._connection === void 0) return;
1160
- const conn = this._connection;
1161
1973
  if (_isPeerChanged) {
1162
1974
  this.remoteObjects.disconnectAll();
1163
1975
  } else {
@@ -1169,7 +1981,7 @@ var RpcClientPeer = class extends RpcPeer {
1169
1981
  call.onDisconnect();
1170
1982
  this.outbound.remove(call.callId);
1171
1983
  } else {
1172
- conn.send(call.serializedMessage);
1984
+ this._sendWireData(call.serializedWireData);
1173
1985
  }
1174
1986
  }
1175
1987
  this._flushPendingSends();
@@ -1192,7 +2004,13 @@ var RpcServerPeer = class extends RpcPeer {
1192
2004
  }
1193
2005
  _onHandshakeReceived(_handshake) {
1194
2006
  if (this._connection !== void 0) {
1195
- 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
+ );
1196
2014
  }
1197
2015
  }
1198
2016
  };
@@ -1220,12 +2038,16 @@ var RpcServiceHost = class {
1220
2038
  for (const methodDef of def.methods.values()) {
1221
2039
  const fn = impl[methodDef.name];
1222
2040
  if (!fn) continue;
1223
- this._methods.set(wireMethodName(methodDef), { def: methodDef, fn });
2041
+ this._methods.set(wireMethodName(methodDef), {
2042
+ def: methodDef,
2043
+ fn
2044
+ });
1224
2045
  }
1225
2046
  }
1226
2047
  async dispatch(wireMethod, args, context) {
1227
2048
  const entry = this._methods.get(wireMethod);
1228
- if (entry === void 0) throw new Error(`Method not found: ${wireMethod}`);
2049
+ if (entry === void 0)
2050
+ throw new Error(`Method not found: ${wireMethod}`);
1229
2051
  if (context !== void 0 && entry.def.callTypeId !== 0) {
1230
2052
  return await entry.fn(...args, context);
1231
2053
  }
@@ -1264,6 +2086,539 @@ function rpcMethod(options) {
1264
2086
  };
1265
2087
  }
1266
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
+
1267
2622
  // src/rpc-hub.ts
1268
2623
  var RpcHub = class {
1269
2624
  hubId;
@@ -1271,9 +2626,16 @@ var RpcHub = class {
1271
2626
  serviceHost;
1272
2627
  systemCallSender = new RpcSystemCallSender();
1273
2628
  systemCallHandler = new RpcSystemCallHandler();
2629
+ /** Method registry for compact format hash ↔ name resolution.
2630
+ * Created lazily, populated by addService/addClient. */
2631
+ registry = new RpcMethodRegistry();
1274
2632
  constructor(hubId) {
1275
2633
  this.hubId = hubId ?? crypto.randomUUID();
1276
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
+ }
1277
2639
  }
1278
2640
  addPeer(peer) {
1279
2641
  this.peers.set(peer.ref, peer);
@@ -1311,10 +2673,12 @@ var RpcHub = class {
1311
2673
  wrappedImpl[methodDef.name] = methodDef.callTypeId !== 0 ? this._wrapServerMethod(methodDef, fn, impl) : fn;
1312
2674
  }
1313
2675
  this.serviceHost.register(def, wrappedImpl);
2676
+ this.registry.registerService(def.name, def.methods);
1314
2677
  }
1315
2678
  /** Create a typed client proxy for a service on a remote peer. */
1316
2679
  addClient(peer, defOrContract) {
1317
2680
  const def = this._resolveServiceDef(defOrContract);
2681
+ this.registry.registerService(def.name, def.methods);
1318
2682
  const overloads = /* @__PURE__ */ new Map();
1319
2683
  for (const methodDef of def.methods.values()) {
1320
2684
  let byArgCount = overloads.get(methodDef.name);
@@ -1322,7 +2686,10 @@ var RpcHub = class {
1322
2686
  byArgCount = /* @__PURE__ */ new Map();
1323
2687
  overloads.set(methodDef.name, byArgCount);
1324
2688
  }
1325
- byArgCount.set(methodDef.argCount, this._createClientMethod(peer, methodDef));
2689
+ byArgCount.set(
2690
+ methodDef.argCount,
2691
+ this._createClientMethod(peer, methodDef)
2692
+ );
1326
2693
  }
1327
2694
  const methods = /* @__PURE__ */ new Map();
1328
2695
  for (const [name, byArgCount] of overloads) {
@@ -1331,7 +2698,10 @@ var RpcHub = class {
1331
2698
  } else {
1332
2699
  methods.set(name, (...args) => {
1333
2700
  const fn = byArgCount.get(args.length);
1334
- 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
+ );
1335
2705
  return fn(...args);
1336
2706
  });
1337
2707
  }
@@ -1347,7 +2717,8 @@ var RpcHub = class {
1347
2717
  /** Build an RpcServiceDef from decorator metadata on a contract class. Override in FusionHub for compute support. */
1348
2718
  _buildServiceDef(cls) {
1349
2719
  const svcMeta = getServiceMeta(cls);
1350
- 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");
1351
2722
  const methodsMeta = getMethodsMeta(cls) ?? {};
1352
2723
  const methods = /* @__PURE__ */ new Map();
1353
2724
  for (const [name, meta] of Object.entries(methodsMeta)) {
@@ -1390,7 +2761,10 @@ var RpcHub = class {
1390
2761
  const outboundCall = peer.call(wireName, callArgs);
1391
2762
  const result = await outboundCall.result.promise;
1392
2763
  const ref = parseStreamRef(result);
1393
- 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
+ );
1394
2768
  const stream = new RpcStream(ref, peer);
1395
2769
  peer.remoteObjects.register(stream);
1396
2770
  return stream;
@@ -1429,7 +2803,10 @@ function createRpcClient(peer, serviceDef) {
1429
2803
  }
1430
2804
  methods.set(name, (...args) => {
1431
2805
  const fn = fns.get(args.length);
1432
- 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
+ );
1433
2810
  return fn(...args);
1434
2811
  });
1435
2812
  }
@@ -1474,12 +2851,10 @@ function getStateDescription(state, useLastError = false) {
1474
2851
  case 1 /* JustDisconnected */:
1475
2852
  return "Just disconnected, reconnecting...";
1476
2853
  case 2 /* Disconnected */:
1477
- if (state.reconnectsIn > 0)
1478
- break;
2854
+ if (state.reconnectsIn > 0) break;
1479
2855
  return "Reconnecting...";
1480
2856
  }
1481
- if (state.lastError == null || !useLastError)
1482
- return "Disconnected.";
2857
+ if (state.lastError == null || !useLastError) return "Disconnected.";
1483
2858
  let message = state.lastError.message.trim();
1484
2859
  if (!(message.endsWith(".") || message.endsWith("!") || message.endsWith("?")))
1485
2860
  message += ".";
@@ -1510,7 +2885,9 @@ var RpcPeerStateMonitor = class {
1510
2885
  _onDisconnected = (ev) => {
1511
2886
  const wasConnected = this._rawConnected;
1512
2887
  this._rawConnected = false;
1513
- 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
+ );
1514
2891
  if (wasConnected) {
1515
2892
  this._disconnectedAt = Date.now();
1516
2893
  }
@@ -1527,16 +2904,26 @@ var RpcPeerStateMonitor = class {
1527
2904
  this._rawConnected = peer.isConnected;
1528
2905
  if (this._rawConnected) {
1529
2906
  this._connectedAt = Date.now();
1530
- this._state = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2907
+ this._state = {
2908
+ kind: 3 /* JustConnected */,
2909
+ reconnectsIn: 0
2910
+ };
1531
2911
  } else {
1532
2912
  this._disconnectedAt = Date.now();
1533
- this._state = { kind: 1 /* JustDisconnected */, reconnectsIn: 0 };
2913
+ this._state = {
2914
+ kind: 1 /* JustDisconnected */,
2915
+ reconnectsIn: 0
2916
+ };
1534
2917
  }
1535
2918
  peer.connected.add(this._onConnected);
1536
2919
  peer.disconnected.add(this._onDisconnected);
1537
2920
  peer.reconnectsAtChanged.add(this._onReconnectsAtChanged);
1538
- peer.reconnectDelayer.cancelDelaysChanged.add(this._onCancelDelaysChanged);
1539
- this._scheduleRecompute(this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs);
2921
+ peer.reconnectDelayer.cancelDelaysChanged.add(
2922
+ this._onCancelDelaysChanged
2923
+ );
2924
+ this._scheduleRecompute(
2925
+ this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs
2926
+ );
1540
2927
  }
1541
2928
  get state() {
1542
2929
  return this._state;
@@ -1549,7 +2936,9 @@ var RpcPeerStateMonitor = class {
1549
2936
  this.peer.connected.remove(this._onConnected);
1550
2937
  this.peer.disconnected.remove(this._onDisconnected);
1551
2938
  this.peer.reconnectsAtChanged.remove(this._onReconnectsAtChanged);
1552
- this.peer.reconnectDelayer.cancelDelaysChanged.remove(this._onCancelDelaysChanged);
2939
+ this.peer.reconnectDelayer.cancelDelaysChanged.remove(
2940
+ this._onCancelDelaysChanged
2941
+ );
1553
2942
  }
1554
2943
  _recompute() {
1555
2944
  if (this._timer !== void 0) {
@@ -1561,24 +2950,46 @@ var RpcPeerStateMonitor = class {
1561
2950
  if (this._rawConnected) {
1562
2951
  const connectedFor = now - this._connectedAt;
1563
2952
  if (connectedFor < JustConnectedPeriodMs) {
1564
- newState = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2953
+ newState = {
2954
+ kind: 3 /* JustConnected */,
2955
+ reconnectsIn: 0
2956
+ };
1565
2957
  this._scheduleRecompute(JustConnectedPeriodMs - connectedFor);
1566
2958
  } else {
1567
- newState = { kind: 0 /* Connected */, reconnectsIn: 0 };
2959
+ newState = {
2960
+ kind: 0 /* Connected */,
2961
+ reconnectsIn: 0
2962
+ };
1568
2963
  }
1569
2964
  } else {
1570
2965
  const disconnectedFor = now - this._disconnectedAt;
1571
2966
  if (disconnectedFor < JustDisconnectedPeriodMs) {
1572
- newState = { kind: 1 /* JustDisconnected */, lastError: this._lastError, reconnectsIn: 0 };
1573
- 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
+ );
1574
2975
  } else {
1575
2976
  const reconnectsAt = this.peer.reconnectsAt;
1576
2977
  const reconnectsIn = reconnectsAt > 0 ? Math.max(0, reconnectsAt - now) : 0;
1577
2978
  if (reconnectsIn < MinReconnectsInMs) {
1578
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn: 0 };
2979
+ newState = {
2980
+ kind: 2 /* Disconnected */,
2981
+ lastError: this._lastError,
2982
+ reconnectsIn: 0
2983
+ };
1579
2984
  } else {
1580
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn };
1581
- 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
+ );
1582
2993
  }
1583
2994
  }
1584
2995
  }
@@ -1593,10 +3004,13 @@ var RpcPeerStateMonitor = class {
1593
3004
  }
1594
3005
  _scheduleRecompute(delayMs) {
1595
3006
  if (this._timer !== void 0) clearTimeout(this._timer);
1596
- this._timer = setTimeout(() => {
1597
- this._timer = void 0;
1598
- this._recompute();
1599
- }, Math.max(0, delayMs));
3007
+ this._timer = setTimeout(
3008
+ () => {
3009
+ this._timer = void 0;
3010
+ this._recompute();
3011
+ },
3012
+ Math.max(0, delayMs)
3013
+ );
1600
3014
  }
1601
3015
  };
1602
3016
  // Annotate the CommonJS export names for ESM import in node:
@@ -1605,13 +3019,18 @@ var RpcPeerStateMonitor = class {
1605
3019
  DEFAULT_SERIALIZATION_FORMAT,
1606
3020
  ENVELOPE_DELIMITER,
1607
3021
  FRAME_DELIMITER,
3022
+ RPC_CLOSE_CODE_UNSUPPORTED_FORMAT,
1608
3023
  RpcCallTypeId,
1609
3024
  RpcClientPeer,
1610
3025
  RpcClientPeerReconnectDelayer,
1611
3026
  RpcHub,
1612
3027
  RpcInboundCall,
1613
3028
  RpcInboundCallTracker,
3029
+ RpcJsonSerializationFormat,
1614
3030
  RpcMessageChannelConnection,
3031
+ RpcMessagePackCompactSerializationFormat,
3032
+ RpcMessagePackSerializationFormat,
3033
+ RpcMethodRegistry,
1615
3034
  RpcObjectKind,
1616
3035
  RpcOutboundCall,
1617
3036
  RpcOutboundCallTracker,
@@ -1620,6 +3039,7 @@ var RpcPeerStateMonitor = class {
1620
3039
  RpcPeerStateKind,
1621
3040
  RpcPeerStateMonitor,
1622
3041
  RpcRemoteObjectTracker,
3042
+ RpcSerializationFormat,
1623
3043
  RpcServerPeer,
1624
3044
  RpcServiceHost,
1625
3045
  RpcSharedObjectTracker,
@@ -1631,10 +3051,16 @@ var RpcPeerStateMonitor = class {
1631
3051
  RpcType,
1632
3052
  RpcWebSocketConnection,
1633
3053
  WebSocketState,
3054
+ computeMethodHash,
3055
+ createBinaryEncoder,
1634
3056
  createMessageChannelPair,
1635
3057
  createRpcClient,
3058
+ defaultBinaryDecoder,
3059
+ defaultBinaryEncoder,
1636
3060
  defaultConnectionUrlResolver,
1637
3061
  defineRpcService,
3062
+ deserializeBinaryMessage,
3063
+ deserializeCompactBinaryMessage,
1638
3064
  deserializeMessage,
1639
3065
  getMethodsMeta,
1640
3066
  getServiceMeta,
@@ -1645,9 +3071,16 @@ var RpcPeerStateMonitor = class {
1645
3071
  resolveStreamRefs,
1646
3072
  rpcMethod,
1647
3073
  rpcService,
3074
+ serializeBinaryFrame,
3075
+ serializeBinaryMessage,
3076
+ serializeCompactBinaryMessage,
1648
3077
  serializeFrame,
1649
3078
  serializeMessage,
3079
+ splitBinaryFrame,
3080
+ splitCompactBinaryFrame,
1650
3081
  splitFrame,
1651
- wireMethodName
3082
+ wireMethodName,
3083
+ xxh3_64,
3084
+ xxh3_64str
1652
3085
  });
1653
3086
  //# sourceMappingURL=index.cjs.map