@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.js CHANGED
@@ -22,6 +22,10 @@ var ARG_DELIMITER = "";
22
22
  var FRAME_DELIMITER = "\n";
23
23
 
24
24
  // src/rpc-serialization.ts
25
+ import {
26
+ Encoder,
27
+ Decoder
28
+ } from "@msgpack/msgpack";
25
29
  function serializeMessage(message, args) {
26
30
  const envelope = JSON.stringify(message);
27
31
  if (args === void 0 || args.length === 0) {
@@ -51,13 +55,263 @@ function deserializeMessage(raw) {
51
55
  try {
52
56
  return JSON.parse(s);
53
57
  } catch {
58
+ console.warn(
59
+ `[RpcSerialization] failed to parse arg as JSON: ${s.substring(0, 100)}`
60
+ );
54
61
  return s;
55
62
  }
56
63
  });
57
64
  return { message, args };
58
65
  }
66
+ var textEncoder = new TextEncoder();
67
+ var textDecoder = new TextDecoder();
68
+ var INITIAL_ENCODER_BUFFER_SIZE = 32 * 1024;
69
+ var defaultBinaryEncoder = new Encoder(
70
+ void 0,
71
+ void 0,
72
+ void 0,
73
+ INITIAL_ENCODER_BUFFER_SIZE
74
+ );
75
+ var defaultBinaryDecoder = new Decoder();
76
+ function createBinaryEncoder() {
77
+ return new Encoder(
78
+ void 0,
79
+ void 0,
80
+ void 0,
81
+ INITIAL_ENCODER_BUFFER_SIZE
82
+ );
83
+ }
84
+ function varUintByteLen(value) {
85
+ if (value < 0) value = 0;
86
+ let n = 0;
87
+ do {
88
+ n++;
89
+ value >>>= 7;
90
+ } while (value > 0);
91
+ return n;
92
+ }
93
+ function writeVarUintInto(out, pos, value) {
94
+ if (value < 0) value = 0;
95
+ do {
96
+ let byte = value & 127;
97
+ value >>>= 7;
98
+ if (value > 0) byte |= 128;
99
+ out[pos++] = byte;
100
+ } while (value > 0);
101
+ return pos;
102
+ }
103
+ function readVarUint(data, offset) {
104
+ let value = 0, shift = 0, bytesRead = 0;
105
+ do {
106
+ if (offset + bytesRead >= data.length) break;
107
+ const byte = data[offset + bytesRead];
108
+ value |= (byte & 127) << shift;
109
+ bytesRead++;
110
+ if ((byte & 128) === 0) break;
111
+ shift += 7;
112
+ } while (shift < 35);
113
+ return { value: value >>> 0, bytesRead };
114
+ }
115
+ function concatUint8Arrays(arrays) {
116
+ let totalLength = 0;
117
+ for (const arr of arrays) totalLength += arr.length;
118
+ const result = new Uint8Array(totalLength);
119
+ let offset = 0;
120
+ for (const arr of arrays) {
121
+ result.set(arr, offset);
122
+ offset += arr.length;
123
+ }
124
+ return result;
125
+ }
126
+ function serializeBinaryMessage(message, args, encoder = defaultBinaryEncoder) {
127
+ let argsDataLen = 0;
128
+ let argBufs = null;
129
+ if (args && args.length > 0) {
130
+ argBufs = new Array(args.length);
131
+ for (let i = 0; i < args.length; i++) {
132
+ const buf = encoder.encode(args[i]);
133
+ argBufs[i] = buf;
134
+ argsDataLen += buf.length;
135
+ }
136
+ }
137
+ const callType = message.CallType ?? 0;
138
+ const relatedId = message.RelatedId ?? 0;
139
+ const methodBytes = textEncoder.encode(message.Method ?? "");
140
+ const relatedIdLen = varUintByteLen(relatedId);
141
+ const methodLenVarintLen = varUintByteLen(methodBytes.length);
142
+ const headerSize = 1 + relatedIdLen + methodLenVarintLen + methodBytes.length;
143
+ const totalSize = headerSize + 4 + argsDataLen;
144
+ const out = new Uint8Array(totalSize);
145
+ let pos = 0;
146
+ out[pos++] = callType << 5 & 224;
147
+ pos = writeVarUintInto(out, pos, relatedId);
148
+ pos = writeVarUintInto(out, pos, methodBytes.length);
149
+ out.set(methodBytes, pos);
150
+ pos += methodBytes.length;
151
+ out[pos++] = argsDataLen & 255;
152
+ out[pos++] = argsDataLen >>> 8 & 255;
153
+ out[pos++] = argsDataLen >>> 16 & 255;
154
+ out[pos++] = argsDataLen >>> 24 & 255;
155
+ if (argBufs !== null) {
156
+ for (const buf of argBufs) {
157
+ out.set(buf, pos);
158
+ pos += buf.length;
159
+ }
160
+ }
161
+ return out;
162
+ }
163
+ function deserializeBinaryMessage(data, offset, decoder = defaultBinaryDecoder) {
164
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
165
+ let pos = offset;
166
+ const byte0 = data[pos++];
167
+ const callTypeId = byte0 >> 5 & 7;
168
+ const headerCount = byte0 & 31;
169
+ const relId = readVarUint(data, pos);
170
+ pos += relId.bytesRead;
171
+ const methodLen = readVarUint(data, pos);
172
+ pos += methodLen.bytesRead;
173
+ const methodBytes = data.subarray(pos, pos + methodLen.value);
174
+ const method = textDecoder.decode(methodBytes);
175
+ pos += methodLen.value;
176
+ const argDataLen = view.getInt32(pos, true);
177
+ pos += 4;
178
+ if (headerCount > 0) {
179
+ for (let h = 0; h < headerCount; h++) {
180
+ const keyLen = data[pos++];
181
+ pos += keyLen;
182
+ const valLen = readVarUint(data, pos);
183
+ pos += valLen.bytesRead + valLen.value;
184
+ }
185
+ }
186
+ const args = [];
187
+ const argEnd = pos + argDataLen;
188
+ if (argDataLen > 0) {
189
+ const argSlice = data.subarray(pos, argEnd);
190
+ for (const decoded of decoder.decodeMulti(argSlice)) {
191
+ args.push(decoded);
192
+ }
193
+ pos = argEnd;
194
+ }
195
+ const message = {
196
+ Method: method,
197
+ RelatedId: relId.value,
198
+ CallType: callTypeId
199
+ };
200
+ return { message, args, bytesRead: pos - offset };
201
+ }
202
+ function splitBinaryFrame(frame, decoder = defaultBinaryDecoder) {
203
+ const results = [];
204
+ let offset = 0;
205
+ while (offset < frame.length) {
206
+ const { message, args, bytesRead } = deserializeBinaryMessage(
207
+ frame,
208
+ offset,
209
+ decoder
210
+ );
211
+ if (bytesRead <= 0) break;
212
+ results.push({ message, args });
213
+ offset += bytesRead;
214
+ }
215
+ return results;
216
+ }
217
+ function serializeBinaryFrame(messages) {
218
+ return concatUint8Arrays(messages);
219
+ }
220
+ function serializeCompactBinaryMessage(message, args, registry, encoder = defaultBinaryEncoder) {
221
+ let argsDataLen = 0;
222
+ let argBufs = null;
223
+ if (args && args.length > 0) {
224
+ argBufs = new Array(args.length);
225
+ for (let i = 0; i < args.length; i++) {
226
+ const buf = encoder.encode(args[i]);
227
+ argBufs[i] = buf;
228
+ argsDataLen += buf.length;
229
+ }
230
+ }
231
+ const methodName = message.Method ?? "";
232
+ const methodHash = registry?.requireHash(methodName) ?? 0;
233
+ const callType = message.CallType ?? 0;
234
+ const relatedId = message.RelatedId ?? 0;
235
+ const relatedIdLen = varUintByteLen(relatedId);
236
+ const headerSize = 1 + relatedIdLen + 4;
237
+ const totalSize = headerSize + 4 + argsDataLen;
238
+ const out = new Uint8Array(totalSize);
239
+ let pos = 0;
240
+ out[pos++] = callType << 5 & 224;
241
+ pos = writeVarUintInto(out, pos, relatedId);
242
+ const hashU32 = methodHash >>> 0;
243
+ out[pos++] = hashU32 & 255;
244
+ out[pos++] = hashU32 >>> 8 & 255;
245
+ out[pos++] = hashU32 >>> 16 & 255;
246
+ out[pos++] = hashU32 >>> 24 & 255;
247
+ out[pos++] = argsDataLen & 255;
248
+ out[pos++] = argsDataLen >>> 8 & 255;
249
+ out[pos++] = argsDataLen >>> 16 & 255;
250
+ out[pos++] = argsDataLen >>> 24 & 255;
251
+ if (argBufs !== null) {
252
+ for (const buf of argBufs) {
253
+ out.set(buf, pos);
254
+ pos += buf.length;
255
+ }
256
+ }
257
+ return out;
258
+ }
259
+ function deserializeCompactBinaryMessage(data, offset, registry, decoder = defaultBinaryDecoder) {
260
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
261
+ let pos = offset;
262
+ const byte0 = data[pos++];
263
+ const callTypeId = byte0 >> 5 & 7;
264
+ const headerCount = byte0 & 31;
265
+ const relId = readVarUint(data, pos);
266
+ pos += relId.bytesRead;
267
+ const methodHash = view.getUint32(pos, true);
268
+ pos += 4;
269
+ const method = registry?.getName(methodHash | 0) ?? `<hash:0x${methodHash.toString(16).padStart(8, "0")}>`;
270
+ const argDataLen = view.getInt32(pos, true);
271
+ pos += 4;
272
+ if (headerCount > 0) {
273
+ for (let h = 0; h < headerCount; h++) {
274
+ const keyLen = data[pos++];
275
+ pos += keyLen;
276
+ const valLen = readVarUint(data, pos);
277
+ pos += valLen.bytesRead + valLen.value;
278
+ }
279
+ }
280
+ const args = [];
281
+ const argEnd = pos + argDataLen;
282
+ if (argDataLen > 0) {
283
+ const argSlice = data.subarray(pos, argEnd);
284
+ for (const decoded of decoder.decodeMulti(argSlice)) {
285
+ args.push(decoded);
286
+ }
287
+ pos = argEnd;
288
+ }
289
+ const message = {
290
+ Method: method,
291
+ RelatedId: relId.value,
292
+ CallType: callTypeId
293
+ };
294
+ return { message, args, bytesRead: pos - offset };
295
+ }
296
+ function splitCompactBinaryFrame(frame, registry, decoder = defaultBinaryDecoder) {
297
+ const results = [];
298
+ let offset = 0;
299
+ while (offset < frame.length) {
300
+ const { message, args, bytesRead } = deserializeCompactBinaryMessage(
301
+ frame,
302
+ offset,
303
+ registry,
304
+ decoder
305
+ );
306
+ if (bytesRead <= 0) break;
307
+ results.push({ message, args });
308
+ offset += bytesRead;
309
+ }
310
+ return results;
311
+ }
59
312
 
60
313
  // src/rpc-connection.ts
314
+ import { Decoder as Decoder2 } from "@msgpack/msgpack";
61
315
  import { PromiseSource, EventHandlerSet } from "@actuallab/core";
62
316
  var WebSocketState = {
63
317
  CONNECTING: 0,
@@ -69,11 +323,36 @@ var RpcWebSocketConnection = class {
69
323
  _ws;
70
324
  _sendBuffer = [];
71
325
  _connected = new PromiseSource();
326
+ /** Per-connection msgpack encoder — reused across outbound messages to
327
+ * amortise construction cost and to keep the internal write buffer at
328
+ * its largest observed size (avoids repeated `resizeBuffer` growth on
329
+ * large video frames). See serializeBinaryMessage() for details. */
330
+ _encoder = createBinaryEncoder();
331
+ /** Per-connection msgpack decoder — reused across inbound messages
332
+ * rather than reconstructing one for every `decodeMulti` call. */
333
+ _decoder = new Decoder2();
334
+ /** Exposed for callers who need to encode outbound binary messages
335
+ * through this connection (e.g. `serializeBinaryMessage`). Safe to
336
+ * pass to synchronous encode calls on the same event-loop turn. */
337
+ get encoder() {
338
+ return this._encoder;
339
+ }
340
+ get decoder() {
341
+ return this._decoder;
342
+ }
343
+ _format;
344
+ _methodRegistry;
345
+ binaryMode;
72
346
  messageReceived = new EventHandlerSet();
73
347
  closed = new EventHandlerSet();
74
348
  error = new EventHandlerSet();
75
- constructor(ws) {
349
+ constructor(ws, binaryMode = false, format, methodRegistry) {
76
350
  this._ws = ws;
351
+ this.binaryMode = binaryMode;
352
+ this._format = format;
353
+ this._methodRegistry = methodRegistry;
354
+ if (binaryMode && ws.binaryType !== void 0)
355
+ ws.binaryType = "arraybuffer";
77
356
  if (ws.readyState === WebSocketState.OPEN) {
78
357
  this._connected.resolve();
79
358
  this._flush();
@@ -83,10 +362,46 @@ var RpcWebSocketConnection = class {
83
362
  this._flush();
84
363
  };
85
364
  ws.onmessage = (ev) => {
86
- const data = typeof ev.data === "string" ? ev.data : String(ev.data);
87
- const messages = splitFrame(data);
88
- for (const msg of messages) {
89
- if (msg.length > 0) this.messageReceived.trigger(msg);
365
+ if (ev.data instanceof Uint8Array || ev.data instanceof ArrayBuffer) {
366
+ const frame = ev.data instanceof Uint8Array ? ev.data : new Uint8Array(ev.data);
367
+ try {
368
+ const messages = this._splitBinary(frame);
369
+ for (const { message, args } of messages) {
370
+ this.messageReceived.trigger({
371
+ kind: "binary",
372
+ message,
373
+ args
374
+ });
375
+ }
376
+ } catch (e) {
377
+ this.error.trigger(e);
378
+ }
379
+ } else if (typeof Blob !== "undefined" && ev.data instanceof Blob && this.binaryMode) {
380
+ void ev.data.arrayBuffer().then((ab) => {
381
+ const frame = new Uint8Array(ab);
382
+ try {
383
+ const messages = this._splitBinary(frame);
384
+ for (const { message, args } of messages) {
385
+ this.messageReceived.trigger({
386
+ kind: "binary",
387
+ message,
388
+ args
389
+ });
390
+ }
391
+ } catch (e) {
392
+ this.error.trigger(e);
393
+ }
394
+ });
395
+ } else {
396
+ const data = typeof ev.data === "string" ? ev.data : String(ev.data);
397
+ const messages = splitFrame(data);
398
+ for (const msg of messages) {
399
+ if (msg.length > 0)
400
+ this.messageReceived.trigger({
401
+ kind: "text",
402
+ raw: msg
403
+ });
404
+ }
90
405
  }
91
406
  };
92
407
  ws.onclose = (ev) => {
@@ -103,27 +418,46 @@ var RpcWebSocketConnection = class {
103
418
  return this._connected.promise;
104
419
  }
105
420
  send(serializedMessage) {
106
- try {
107
- if (this._ws.readyState === WebSocketState.OPEN)
108
- this._ws.send(serializedMessage);
109
- else if (this._ws.readyState === WebSocketState.CONNECTING)
110
- this._sendBuffer.push(serializedMessage);
111
- } catch {
112
- }
421
+ this._sendRaw(serializedMessage);
422
+ }
423
+ sendBinary(data) {
424
+ this._sendRaw(data);
425
+ }
426
+ sendTextBatch(messages) {
427
+ this._sendRaw(serializeFrame(messages));
428
+ }
429
+ sendBinaryBatch(messages) {
430
+ this._sendRaw(serializeBinaryFrame(messages));
113
431
  }
114
- sendBatch(messages) {
115
- const frame = serializeFrame(messages);
116
- this.send(frame);
432
+ /** Split a binary frame using the format (compact-aware) or default splitter. */
433
+ _splitBinary(frame) {
434
+ if (this._format) {
435
+ return this._format.splitBinaryFrame(
436
+ frame,
437
+ this._decoder,
438
+ this._methodRegistry
439
+ );
440
+ }
441
+ return splitBinaryFrame(frame, this._decoder);
117
442
  }
118
443
  close(code, reason) {
119
444
  this._ws.close(code, reason);
120
445
  }
446
+ _sendRaw(data) {
447
+ try {
448
+ if (this._ws.readyState === WebSocketState.OPEN) {
449
+ this._ws.send(data);
450
+ } else if (this._ws.readyState === WebSocketState.CONNECTING)
451
+ this._sendBuffer.push(data);
452
+ } catch {
453
+ }
454
+ }
121
455
  _flush() {
122
456
  if (this._sendBuffer.length === 0) return;
123
- const frame = serializeFrame(this._sendBuffer);
457
+ const buffer = this._sendBuffer;
124
458
  this._sendBuffer = [];
125
459
  try {
126
- this._ws.send(frame);
460
+ for (const item of buffer) this._ws.send(item);
127
461
  } catch {
128
462
  }
129
463
  }
@@ -134,6 +468,7 @@ import { EventHandlerSet as EventHandlerSet2 } from "@actuallab/core";
134
468
  var RpcMessageChannelConnection = class {
135
469
  _port;
136
470
  _open = true;
471
+ binaryMode = false;
137
472
  messageReceived = new EventHandlerSet2();
138
473
  closed = new EventHandlerSet2();
139
474
  whenConnected = Promise.resolve();
@@ -143,7 +478,8 @@ var RpcMessageChannelConnection = class {
143
478
  port.onmessage = (ev) => {
144
479
  const data = typeof ev.data === "string" ? ev.data : String(ev.data);
145
480
  for (const msg of splitFrame(data))
146
- if (msg.length > 0) this.messageReceived.trigger(msg);
481
+ if (msg.length > 0)
482
+ this.messageReceived.trigger({ kind: "text", raw: msg });
147
483
  };
148
484
  }
149
485
  get isOpen() {
@@ -156,6 +492,13 @@ var RpcMessageChannelConnection = class {
156
492
  } catch {
157
493
  }
158
494
  }
495
+ sendBinary(data) {
496
+ if (!this._open) return;
497
+ try {
498
+ this._port.postMessage(data, [data.buffer]);
499
+ } catch {
500
+ }
501
+ }
159
502
  close(code, reason) {
160
503
  if (!this._open) return;
161
504
  this._open = false;
@@ -210,8 +553,8 @@ var RpcOutboundCall = class {
210
553
  /** Whether to remove this call from the tracker on $sys.Ok. Default: true.
211
554
  * Subclasses (e.g. compute calls) override to false to stay in tracker for invalidation. */
212
555
  removeOnOk = true;
213
- /** The serialized wire message — stored for re-sending on reconnect. */
214
- serializedMessage = "";
556
+ /** The serialized wire data — stored for re-sending on reconnect. */
557
+ serializedWireData = "";
215
558
  constructor(callId, method) {
216
559
  this.callId = callId;
217
560
  this.method = method;
@@ -301,6 +644,7 @@ var RpcInboundCallTracker = class {
301
644
  };
302
645
 
303
646
  // src/rpc-stream.ts
647
+ import Denque from "denque";
304
648
  import { PromiseSource as PromiseSource3 } from "@actuallab/core";
305
649
 
306
650
  // src/rpc-object.ts
@@ -308,25 +652,49 @@ var RpcObjectKind = { Local: 0, Remote: 1 };
308
652
 
309
653
  // src/rpc-stream.ts
310
654
  function parseStreamRef(value) {
311
- if (typeof value !== "string") return null;
312
- const parts = value.split(",");
313
- if (parts.length < 4 || parts.length > 5) return null;
314
- const hostId = parts[0];
315
- const localId = parseInt(parts[1], 10);
316
- const ackPeriod = parseInt(parts[2], 10);
317
- const ackAdvance = parseInt(parts[3], 10);
318
- if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance)) return null;
319
- const allowReconnect = parts.length < 5 || parts[4] !== "0";
320
- return { hostId, localId, ackPeriod, ackAdvance, allowReconnect };
655
+ if (typeof value === "string") {
656
+ const parts = value.split(",");
657
+ if (parts.length < 4 || parts.length > 6) return null;
658
+ const hostId = parts[0];
659
+ const localId = parseInt(parts[1], 10);
660
+ const ackPeriod = parseInt(parts[2], 10);
661
+ const ackAdvance = parseInt(parts[3], 10);
662
+ if (isNaN(localId) || isNaN(ackPeriod) || isNaN(ackAdvance))
663
+ return null;
664
+ const allowReconnect = parts.length < 5 || parts[4] !== "0";
665
+ const isRealTime = parts.length >= 6 && parts[5] === "1";
666
+ return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
667
+ }
668
+ if (typeof value === "object" && value !== null) {
669
+ const obj = value;
670
+ const serializedId = obj.SerializedId;
671
+ if (!Array.isArray(serializedId) || serializedId.length < 2)
672
+ return null;
673
+ const rawHostId = serializedId[0];
674
+ const hostId = String(rawHostId);
675
+ const localId = Number(serializedId[1]);
676
+ const ackPeriod = Number(obj.AckPeriod ?? 256);
677
+ const ackAdvance = Number(obj.AckAdvance ?? 128);
678
+ const allowReconnect = obj.AllowReconnect !== false;
679
+ const isRealTime = obj.IsRealTime === true;
680
+ return { hostId, localId, ackPeriod, ackAdvance, allowReconnect, isRealTime };
681
+ }
682
+ return null;
321
683
  }
322
- var RpcStream = class {
684
+ var RpcStream = class _RpcStream {
323
685
  id;
324
686
  kind = RpcObjectKind.Remote;
325
687
  allowReconnect;
326
688
  peer;
327
689
  ackPeriod;
328
690
  ackAdvance;
329
- _buffer = [];
691
+ // Double-ended queue so consumption via `shift()` is O(1) and the
692
+ // backing store frees memory as items are drained. The previous
693
+ // `T[]` buffer kept every item for the life of the stream because
694
+ // the iterator tracked a read index instead of shifting — fine for
695
+ // short runs but a slow leak in the browser where a video call can
696
+ // last an hour.
697
+ _buffer = new Denque();
330
698
  _nextExpectedIndex = 0;
331
699
  _consumerWaiting = null;
332
700
  _completed = false;
@@ -346,6 +714,17 @@ var RpcStream = class {
346
714
  onItem(index, item) {
347
715
  if (this._disposed || this._completed) return;
348
716
  if (index > this._nextExpectedIndex) {
717
+ console.warn(
718
+ `[RpcStream] item index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
719
+ );
720
+ if (!this.allowReconnect) {
721
+ this._completed = true;
722
+ this._completionError = new Error(
723
+ `Stream gap at index ${index} (expected ${this._nextExpectedIndex}); reconnect not allowed`
724
+ );
725
+ this._notifyConsumer();
726
+ return;
727
+ }
349
728
  this._sendAck(this._nextExpectedIndex, true);
350
729
  return;
351
730
  }
@@ -362,6 +741,17 @@ var RpcStream = class {
362
741
  onBatch(index, items) {
363
742
  if (this._disposed || this._completed) return;
364
743
  if (index > this._nextExpectedIndex) {
744
+ console.warn(
745
+ `[RpcStream] batch index gap: localId=${this.id.localId}, expected=${this._nextExpectedIndex}, received=${index}`
746
+ );
747
+ if (!this.allowReconnect) {
748
+ this._completed = true;
749
+ this._completionError = new Error(
750
+ `Stream gap at index ${index} (expected ${this._nextExpectedIndex}); reconnect not allowed`
751
+ );
752
+ this._notifyConsumer();
753
+ return;
754
+ }
365
755
  this._sendAck(this._nextExpectedIndex, true);
366
756
  return;
367
757
  }
@@ -397,10 +787,9 @@ var RpcStream = class {
397
787
  }
398
788
  // -- AsyncIterable --
399
789
  [Symbol.asyncIterator]() {
400
- if (this._iterating) throw new Error("RpcStream can only be iterated once.");
790
+ if (this._iterating)
791
+ throw new Error("RpcStream can only be iterated once.");
401
792
  this._iterating = true;
402
- let bufferIndex = 0;
403
- let consumedIndex = 0;
404
793
  const self = this;
405
794
  return {
406
795
  async next() {
@@ -409,10 +798,8 @@ var RpcStream = class {
409
798
  self._sendAck(0, true);
410
799
  }
411
800
  while (true) {
412
- if (bufferIndex < self._buffer.length) {
413
- const value = self._buffer[bufferIndex];
414
- bufferIndex++;
415
- consumedIndex++;
801
+ if (!self._buffer.isEmpty()) {
802
+ const value = self._buffer.shift();
416
803
  return { value, done: false };
417
804
  }
418
805
  if (self._completed) {
@@ -451,17 +838,30 @@ var RpcStream = class {
451
838
  this._sendAck(nextIndex, false);
452
839
  }
453
840
  }
454
- _sendAck(nextIndex, _mustReset) {
841
+ static _emptyGuid = "00000000-0000-0000-0000-000000000000";
842
+ _sendAck(nextIndex, mustReset) {
455
843
  this._ackSentUpTo = nextIndex;
456
844
  const conn = this.peer.connection;
457
845
  if (conn) {
458
- this.peer.hub.systemCallSender.ack(conn, this.id.localId, nextIndex, this.id.hostId);
846
+ const hostId = mustReset ? this.id.hostId : _RpcStream._emptyGuid;
847
+ this.peer.hub.systemCallSender.ack(
848
+ conn,
849
+ this.peer.format,
850
+ this.id.localId,
851
+ nextIndex,
852
+ hostId
853
+ );
459
854
  }
460
855
  }
461
856
  _sendAckEnd() {
462
857
  const conn = this.peer.connection;
463
858
  if (conn) {
464
- this.peer.hub.systemCallSender.ackEnd(conn, this.id.localId, this.id.hostId);
859
+ this.peer.hub.systemCallSender.ackEnd(
860
+ conn,
861
+ this.peer.format,
862
+ this.id.localId,
863
+ this.id.hostId
864
+ );
465
865
  }
466
866
  }
467
867
  };
@@ -483,6 +883,8 @@ function resolveStreamRefs(value, peer) {
483
883
  return value;
484
884
  }
485
885
  if (typeof value === "object") {
886
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer)
887
+ return value;
486
888
  for (const key of Object.keys(value)) {
487
889
  value[key] = resolveStreamRefs(
488
890
  value[key],
@@ -528,21 +930,39 @@ var RpcSystemCallHandler = class {
528
930
  }
529
931
  case RpcSystemCalls.item: {
530
932
  const stream = peer.remoteObjects.get(relatedId);
531
- if (stream) stream.onItem(args[0], resolveStreamRefs(args[1], peer));
933
+ if (!stream) {
934
+ console.warn(
935
+ `[RpcSysHandler] $sys.I: no stream for relatedId=${relatedId}`
936
+ );
937
+ } else {
938
+ stream.onItem(
939
+ args[0],
940
+ resolveStreamRefs(args[1], peer)
941
+ );
942
+ }
532
943
  break;
533
944
  }
534
945
  case RpcSystemCalls.batch: {
535
946
  const stream = peer.remoteObjects.get(relatedId);
536
- if (stream) {
947
+ if (!stream) {
948
+ console.warn(
949
+ `[RpcSysHandler] $sys.B: no stream for relatedId=${relatedId}`
950
+ );
951
+ } else if (Array.isArray(args[1])) {
537
952
  const items = args[1];
538
- for (let i = 0; i < items.length; i++) items[i] = resolveStreamRefs(items[i], peer);
953
+ for (let i = 0; i < items.length; i++)
954
+ items[i] = resolveStreamRefs(items[i], peer);
539
955
  stream.onBatch(args[0], items);
540
956
  }
541
957
  break;
542
958
  }
543
959
  case RpcSystemCalls.end: {
544
960
  const stream = peer.remoteObjects.get(relatedId);
545
- if (stream) {
961
+ if (!stream) {
962
+ console.warn(
963
+ `[RpcSysHandler] $sys.End: no stream for relatedId=${relatedId}`
964
+ );
965
+ } else {
546
966
  const errorInfo = args[1];
547
967
  const msg = errorInfo?.Message ?? errorInfo?.message;
548
968
  const error = msg ? new Error(msg) : null;
@@ -560,76 +980,142 @@ var RpcSystemCallHandler = class {
560
980
  sender?.onAckEnd(args[0]);
561
981
  break;
562
982
  }
983
+ default: {
984
+ if (method === "$sys.Disconnect" || method?.startsWith("$sys.Disconnect")) {
985
+ const ids = args[0];
986
+ if (Array.isArray(ids)) {
987
+ for (const id of ids) {
988
+ const remoteObj = peer.remoteObjects.get(id);
989
+ if (remoteObj && typeof remoteObj.disconnect === "function") {
990
+ remoteObj.disconnect();
991
+ }
992
+ const sharedObj = peer.sharedObjects.get(id);
993
+ if (sharedObj && typeof sharedObj.disconnect === "function") {
994
+ sharedObj.disconnect();
995
+ }
996
+ }
997
+ }
998
+ }
999
+ break;
1000
+ }
563
1001
  }
564
1002
  }
565
1003
  };
566
1004
 
567
1005
  // src/rpc-system-call-sender.ts
568
- var RpcSystemCallSender = class {
569
- handshake(conn, peerId, hubId, index) {
570
- const msg = serializeMessage({ Method: RpcSystemCalls.handshake }, [{
1006
+ var RpcSystemCallSender = class _RpcSystemCallSender {
1007
+ // Reusable envelopes — one per hot-path method.
1008
+ _itemEnv = {
1009
+ Method: RpcSystemCalls.item,
1010
+ RelatedId: 0
1011
+ };
1012
+ _batchEnv = {
1013
+ Method: RpcSystemCalls.batch,
1014
+ RelatedId: 0
1015
+ };
1016
+ _endEnv = {
1017
+ Method: RpcSystemCalls.end,
1018
+ RelatedId: 0
1019
+ };
1020
+ _ackEnv = {
1021
+ Method: RpcSystemCalls.ack,
1022
+ RelatedId: 0
1023
+ };
1024
+ _ackEndEnv = {
1025
+ Method: RpcSystemCalls.ackEnd,
1026
+ RelatedId: 0
1027
+ };
1028
+ // Reusable arg arrays.
1029
+ _itemArgs = [0, null];
1030
+ _batchArgs = [0, null];
1031
+ _endArgs = [0, { TypeRef: "", Message: "" }];
1032
+ _ackArgs = [0, ""];
1033
+ _ackEndArgs = [""];
1034
+ static NO_ERROR = Object.freeze({ TypeRef: "", Message: "" });
1035
+ registry;
1036
+ _send(conn, format, envelope, args) {
1037
+ const wireData = format.serializeMessage(
1038
+ envelope,
1039
+ args,
1040
+ conn.encoder,
1041
+ this.registry
1042
+ );
1043
+ if (typeof wireData === "string") {
1044
+ conn.send(wireData);
1045
+ } else {
1046
+ conn.sendBinary(wireData);
1047
+ }
1048
+ }
1049
+ handshake(conn, format, peerId, hubId, index) {
1050
+ const handshakeArg = format.isBinary ? [peerId, null, hubId, 2, index] : {
571
1051
  RemotePeerId: peerId,
572
1052
  RemoteApiVersionSet: null,
573
1053
  RemoteHubId: hubId,
574
1054
  ProtocolVersion: 2,
575
1055
  Index: index
576
- }]);
577
- conn.send(msg);
578
- }
579
- ok(conn, relatedId, result) {
580
- const msg = serializeMessage({ Method: RpcSystemCalls.ok, RelatedId: relatedId }, [result]);
581
- conn.send(msg);
1056
+ };
1057
+ this._send(conn, format, { Method: RpcSystemCalls.handshake }, [
1058
+ handshakeArg
1059
+ ]);
1060
+ }
1061
+ ok(conn, format, relatedId, result) {
1062
+ this._send(
1063
+ conn,
1064
+ format,
1065
+ { Method: RpcSystemCalls.ok, RelatedId: relatedId },
1066
+ [result]
1067
+ );
582
1068
  }
583
- error(conn, relatedId, error) {
1069
+ error(conn, format, relatedId, error) {
584
1070
  const message = error instanceof Error ? error.message : String(error);
585
- const msg = serializeMessage(
1071
+ this._send(
1072
+ conn,
1073
+ format,
586
1074
  { Method: RpcSystemCalls.error, RelatedId: relatedId },
587
1075
  [{ Message: message }]
588
1076
  );
589
- conn.send(msg);
590
- }
591
- cancel(conn, relatedId) {
592
- const msg = serializeMessage({ Method: RpcSystemCalls.cancel, RelatedId: relatedId });
593
- conn.send(msg);
594
- }
595
- keepAlive(conn, activeCallIds) {
596
- const msg = serializeMessage({ Method: RpcSystemCalls.keepAlive }, [activeCallIds]);
597
- conn.send(msg);
598
- }
599
- item(conn, localId, index, item) {
600
- const msg = serializeMessage(
601
- { Method: RpcSystemCalls.item, RelatedId: localId },
602
- [index, item]
603
- );
604
- conn.send(msg);
605
- }
606
- batch(conn, localId, index, items) {
607
- const msg = serializeMessage(
608
- { Method: RpcSystemCalls.batch, RelatedId: localId },
609
- [index, items]
610
- );
611
- conn.send(msg);
612
- }
613
- end(conn, localId, index, error = null) {
614
- const msg = serializeMessage(
615
- { Method: RpcSystemCalls.end, RelatedId: localId },
616
- [index, error]
617
- );
618
- conn.send(msg);
619
1077
  }
620
- ack(conn, localId, nextIndex, hostId) {
621
- const msg = serializeMessage(
622
- { Method: RpcSystemCalls.ack, RelatedId: localId },
623
- [nextIndex, hostId]
624
- );
625
- conn.send(msg);
1078
+ cancel(conn, format, relatedId) {
1079
+ this._send(conn, format, {
1080
+ Method: RpcSystemCalls.cancel,
1081
+ RelatedId: relatedId
1082
+ });
626
1083
  }
627
- ackEnd(conn, localId, hostId) {
628
- const msg = serializeMessage(
629
- { Method: RpcSystemCalls.ackEnd, RelatedId: localId },
630
- [hostId]
631
- );
632
- conn.send(msg);
1084
+ keepAlive(conn, format, activeCallIds) {
1085
+ this._send(conn, format, { Method: RpcSystemCalls.keepAlive }, [
1086
+ activeCallIds
1087
+ ]);
1088
+ }
1089
+ item(conn, format, localId, index, item) {
1090
+ this._itemEnv.RelatedId = localId;
1091
+ this._itemArgs[0] = index;
1092
+ this._itemArgs[1] = item;
1093
+ this._send(conn, format, this._itemEnv, this._itemArgs);
1094
+ this._itemArgs[1] = null;
1095
+ }
1096
+ batch(conn, format, localId, index, items) {
1097
+ this._batchEnv.RelatedId = localId;
1098
+ this._batchArgs[0] = index;
1099
+ this._batchArgs[1] = items;
1100
+ this._send(conn, format, this._batchEnv, this._batchArgs);
1101
+ this._batchArgs[1] = null;
1102
+ }
1103
+ end(conn, format, localId, index, error = _RpcSystemCallSender.NO_ERROR) {
1104
+ this._endEnv.RelatedId = localId;
1105
+ this._endArgs[0] = index;
1106
+ this._endArgs[1] = error;
1107
+ this._send(conn, format, this._endEnv, this._endArgs);
1108
+ }
1109
+ ack(conn, format, localId, nextIndex, hostId) {
1110
+ this._ackEnv.RelatedId = localId;
1111
+ this._ackArgs[0] = nextIndex;
1112
+ this._ackArgs[1] = hostId;
1113
+ this._send(conn, format, this._ackEnv, this._ackArgs);
1114
+ }
1115
+ ackEnd(conn, format, localId, hostId) {
1116
+ this._ackEndEnv.RelatedId = localId;
1117
+ this._ackEndArgs[0] = hostId;
1118
+ this._send(conn, format, this._ackEndEnv, this._ackEndArgs);
633
1119
  }
634
1120
  };
635
1121
 
@@ -641,29 +1127,42 @@ var RpcStreamSender = class {
641
1127
  id;
642
1128
  kind = RpcObjectKind.Local;
643
1129
  allowReconnect;
1130
+ isRealTime;
1131
+ canSkipTo;
644
1132
  peer;
645
1133
  ackPeriod;
646
1134
  ackAdvance;
647
1135
  _nextIndex = 0;
648
1136
  _ended = false;
649
1137
  _started = new PromiseSource4();
650
- constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true) {
1138
+ _lastAckedIndex = 0;
1139
+ _ackWaiting = null;
1140
+ constructor(peer, ackPeriod = DEFAULT_ACK_PERIOD, ackAdvance = DEFAULT_ACK_ADVANCE, allowReconnect = true, isRealTime = false, canSkipTo = () => true) {
651
1141
  const localId = peer.sharedObjects.nextId();
652
1142
  this.id = { hostId: peer.hub.hubId, localId };
653
1143
  this.allowReconnect = allowReconnect;
1144
+ this.isRealTime = isRealTime;
1145
+ this.canSkipTo = canSkipTo;
654
1146
  this.peer = peer;
655
1147
  this.ackPeriod = ackPeriod;
656
1148
  this.ackAdvance = ackAdvance;
657
1149
  }
658
1150
  /** Returns the stream reference string for the $sys.Ok response. */
659
1151
  toRef() {
660
- return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"}`;
1152
+ return `${this.id.hostId},${this.id.localId},${this.ackPeriod},${this.ackAdvance},${this.allowReconnect ? "1" : "0"},${this.isRealTime ? "1" : "0"}`;
661
1153
  }
662
1154
  /** Called by system call handler when $sys.Ack is received from the client. */
663
- onAck(_nextIndex, _hostId) {
1155
+ onAck(nextIndex, _hostId) {
664
1156
  if (!this._started.isCompleted) {
665
1157
  this._started.resolve();
666
1158
  }
1159
+ if (nextIndex > this._lastAckedIndex) {
1160
+ this._lastAckedIndex = nextIndex;
1161
+ }
1162
+ if (this._ackWaiting) {
1163
+ this._ackWaiting.resolve();
1164
+ this._ackWaiting = null;
1165
+ }
667
1166
  }
668
1167
  /** Called by system call handler when $sys.AckEnd is received from the client. */
669
1168
  onAckEnd(_hostId) {
@@ -675,7 +1174,13 @@ var RpcStreamSender = class {
675
1174
  if (this._ended) return;
676
1175
  const conn = this.peer.connection;
677
1176
  if (!conn) return;
678
- this.peer.hub.systemCallSender.item(conn, this.id.localId, this._nextIndex, item);
1177
+ this.peer.hub.systemCallSender.item(
1178
+ conn,
1179
+ this.peer.format,
1180
+ this.id.localId,
1181
+ this._nextIndex,
1182
+ item
1183
+ );
679
1184
  this._nextIndex++;
680
1185
  }
681
1186
  /** Send a batch of items to the client. */
@@ -683,7 +1188,13 @@ var RpcStreamSender = class {
683
1188
  if (this._ended || items.length === 0) return;
684
1189
  const conn = this.peer.connection;
685
1190
  if (!conn) return;
686
- this.peer.hub.systemCallSender.batch(conn, this.id.localId, this._nextIndex, items);
1191
+ this.peer.hub.systemCallSender.batch(
1192
+ conn,
1193
+ this.peer.format,
1194
+ this.id.localId,
1195
+ this._nextIndex,
1196
+ items
1197
+ );
687
1198
  this._nextIndex += items.length;
688
1199
  }
689
1200
  /** Signal stream completion to the client. */
@@ -692,19 +1203,63 @@ var RpcStreamSender = class {
692
1203
  this._ended = true;
693
1204
  const conn = this.peer.connection;
694
1205
  if (!conn) return;
695
- const errorInfo = error ? { Message: error.message } : null;
696
- this.peer.hub.systemCallSender.end(conn, this.id.localId, this._nextIndex, errorInfo);
1206
+ const errorInfo = error ? { TypeRef: "System.Exception", Message: error.message } : { TypeRef: "", Message: "" };
1207
+ this.peer.hub.systemCallSender.end(
1208
+ conn,
1209
+ this.peer.format,
1210
+ this.id.localId,
1211
+ this._nextIndex,
1212
+ errorInfo
1213
+ );
697
1214
  }
698
1215
  /**
699
1216
  * Consume an AsyncIterable and send all items to the client.
700
1217
  * Waits for the client's initial Ack before starting to pump items.
1218
+ *
1219
+ * When `isRealTime` is true, applies flow control based on `ackAdvance`:
1220
+ * if the sender is `ackAdvance` items ahead of the last ACK, it enters
1221
+ * skip mode — draining the source and discarding items until it finds
1222
+ * one where `canSkipTo` returns true.
701
1223
  */
702
1224
  async writeFrom(source) {
703
1225
  await this._started.promise;
1226
+ const iterator = source[Symbol.asyncIterator]();
704
1227
  try {
705
- for await (const item of source) {
1228
+ while (true) {
1229
+ const next = await iterator.next();
1230
+ if (next.done || this._ended) break;
1231
+ const item = next.value;
1232
+ if (this._nextIndex < this._lastAckedIndex + this.ackAdvance) {
1233
+ this.sendItem(item);
1234
+ continue;
1235
+ }
1236
+ if (!this.isRealTime) {
1237
+ await this._waitForAckBudget();
1238
+ if (this._ended) return;
1239
+ this.sendItem(item);
1240
+ continue;
1241
+ }
1242
+ let latestSkipTarget = this.canSkipTo(item) ? item : void 0;
1243
+ let sourceExhausted = false;
1244
+ while (this._nextIndex >= this._lastAckedIndex + this.ackAdvance) {
1245
+ if (this._ended) return;
1246
+ const n = await iterator.next();
1247
+ if (n.done) {
1248
+ sourceExhausted = true;
1249
+ break;
1250
+ }
1251
+ if (this.canSkipTo(n.value)) {
1252
+ latestSkipTarget = n.value;
1253
+ }
1254
+ }
706
1255
  if (this._ended) return;
707
- this.sendItem(item);
1256
+ if (latestSkipTarget !== void 0) {
1257
+ this.sendItem(latestSkipTarget);
1258
+ }
1259
+ if (sourceExhausted) {
1260
+ if (!this._ended) this.sendEnd();
1261
+ return;
1262
+ }
708
1263
  }
709
1264
  if (!this._ended) {
710
1265
  this.sendEnd();
@@ -715,6 +1270,14 @@ var RpcStreamSender = class {
715
1270
  }
716
1271
  }
717
1272
  }
1273
+ /** Wait until _nextIndex < _lastAckedIndex + ackAdvance. */
1274
+ async _waitForAckBudget() {
1275
+ while (this._nextIndex >= this._lastAckedIndex + this.ackAdvance) {
1276
+ if (this._ended) return;
1277
+ this._ackWaiting = new PromiseSource4();
1278
+ await this._ackWaiting.promise;
1279
+ }
1280
+ }
718
1281
  // -- IRpcObject --
719
1282
  reconnect() {
720
1283
  }
@@ -736,6 +1299,9 @@ var RpcRemoteObjectTracker = class {
736
1299
  get(localId) {
737
1300
  return this._objects.get(localId);
738
1301
  }
1302
+ keys() {
1303
+ return this._objects.keys();
1304
+ }
739
1305
  unregister(obj) {
740
1306
  this._objects.delete(obj.id.localId);
741
1307
  }
@@ -747,10 +1313,8 @@ var RpcRemoteObjectTracker = class {
747
1313
  }
748
1314
  reconnectAll() {
749
1315
  for (const obj of this._objects.values()) {
750
- if (obj.allowReconnect)
751
- obj.reconnect();
752
- else
753
- obj.disconnect();
1316
+ if (obj.allowReconnect) obj.reconnect();
1317
+ else obj.disconnect();
754
1318
  }
755
1319
  }
756
1320
  };
@@ -768,6 +1332,9 @@ var RpcSharedObjectTracker = class {
768
1332
  get(localId) {
769
1333
  return this._objects.get(localId);
770
1334
  }
1335
+ keys() {
1336
+ return this._objects.keys();
1337
+ }
771
1338
  unregister(obj) {
772
1339
  this._objects.delete(obj.id.localId);
773
1340
  }
@@ -791,8 +1358,132 @@ var RpcClientPeerReconnectDelayer = class extends RetryDelayer {
791
1358
  }
792
1359
  };
793
1360
 
1361
+ // src/rpc-serialization-format.ts
1362
+ import { Decoder as Decoder3 } from "@msgpack/msgpack";
1363
+ var RpcSerializationFormat = class _RpcSerializationFormat {
1364
+ /** Create a reusable binary encoder for this format. Returns undefined for text formats. */
1365
+ createEncoder() {
1366
+ return void 0;
1367
+ }
1368
+ /** Create a reusable binary decoder for this format. Returns undefined for text formats. */
1369
+ createDecoder() {
1370
+ return void 0;
1371
+ }
1372
+ // --- Static registry ---
1373
+ static _all = /* @__PURE__ */ new Map();
1374
+ static register(format) {
1375
+ _RpcSerializationFormat._all.set(format.key, format);
1376
+ }
1377
+ static get(key) {
1378
+ const format = _RpcSerializationFormat._all.get(key);
1379
+ if (!format)
1380
+ throw new Error(`Unknown RPC serialization format: "${key}"`);
1381
+ return format;
1382
+ }
1383
+ static tryGet(key) {
1384
+ return _RpcSerializationFormat._all.get(key);
1385
+ }
1386
+ };
1387
+ var RpcJsonSerializationFormat = class extends RpcSerializationFormat {
1388
+ key;
1389
+ isBinary = false;
1390
+ isCompact = false;
1391
+ constructor(key) {
1392
+ super();
1393
+ this.key = key;
1394
+ }
1395
+ serializeMessage(message, args) {
1396
+ return serializeMessage(message, args);
1397
+ }
1398
+ deserializeTextMessage(raw) {
1399
+ return deserializeMessage(raw);
1400
+ }
1401
+ splitBinaryFrame() {
1402
+ throw new Error("Text format does not support binary frames");
1403
+ }
1404
+ serializeBinaryFrame() {
1405
+ throw new Error("Text format does not support binary frames");
1406
+ }
1407
+ };
1408
+ var RpcMessagePackSerializationFormat = class extends RpcSerializationFormat {
1409
+ key;
1410
+ isBinary = true;
1411
+ isCompact = false;
1412
+ constructor(key) {
1413
+ super();
1414
+ this.key = key;
1415
+ }
1416
+ serializeMessage(message, args, encoder) {
1417
+ return serializeBinaryMessage(message, args, encoder);
1418
+ }
1419
+ deserializeTextMessage(raw) {
1420
+ return deserializeMessage(raw);
1421
+ }
1422
+ splitBinaryFrame(frame, decoder) {
1423
+ return splitBinaryFrame(frame, decoder);
1424
+ }
1425
+ serializeBinaryFrame(messages) {
1426
+ return serializeBinaryFrame(messages);
1427
+ }
1428
+ createEncoder() {
1429
+ return createBinaryEncoder();
1430
+ }
1431
+ createDecoder() {
1432
+ return new Decoder3();
1433
+ }
1434
+ };
1435
+ var RpcMessagePackCompactSerializationFormat = class extends RpcSerializationFormat {
1436
+ key;
1437
+ isBinary = true;
1438
+ isCompact = true;
1439
+ constructor(key) {
1440
+ super();
1441
+ this.key = key;
1442
+ }
1443
+ serializeMessage(message, args, encoder, registry) {
1444
+ return serializeCompactBinaryMessage(
1445
+ message,
1446
+ args,
1447
+ registry,
1448
+ encoder
1449
+ );
1450
+ }
1451
+ deserializeTextMessage(raw) {
1452
+ return deserializeMessage(raw);
1453
+ }
1454
+ splitBinaryFrame(frame, decoder, registry) {
1455
+ return splitCompactBinaryFrame(frame, registry, decoder);
1456
+ }
1457
+ serializeBinaryFrame(messages) {
1458
+ return serializeBinaryFrame(messages);
1459
+ }
1460
+ createEncoder() {
1461
+ return createBinaryEncoder();
1462
+ }
1463
+ createDecoder() {
1464
+ return new Decoder3();
1465
+ }
1466
+ };
1467
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("json5"));
1468
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("json5np"));
1469
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("njson5"));
1470
+ RpcSerializationFormat.register(new RpcJsonSerializationFormat("njson5np"));
1471
+ RpcSerializationFormat.register(
1472
+ new RpcMessagePackSerializationFormat("msgpack6")
1473
+ );
1474
+ RpcSerializationFormat.register(
1475
+ new RpcMessagePackSerializationFormat("mempack6")
1476
+ );
1477
+ RpcSerializationFormat.register(
1478
+ new RpcMessagePackCompactSerializationFormat("msgpack6c")
1479
+ );
1480
+ RpcSerializationFormat.register(
1481
+ new RpcMessagePackCompactSerializationFormat("mempack6c")
1482
+ );
1483
+
794
1484
  // src/rpc-peer.ts
795
1485
  var DEFAULT_SERIALIZATION_FORMAT = "json5np";
1486
+ var RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
796
1487
  var defaultConnectionUrlResolver = (peer) => {
797
1488
  const sep = peer.ref.includes("?") ? "&" : "?";
798
1489
  return peer.ref + sep + `clientId=${peer.clientId}&f=${peer.serializationFormat}`;
@@ -838,17 +1529,27 @@ var RpcPeer = class {
838
1529
  this._startKeepAlive();
839
1530
  });
840
1531
  }
1532
+ /** The serialization format used by this peer. Override in subclasses. */
1533
+ get format() {
1534
+ return RpcSerializationFormat.get("json5np");
1535
+ }
841
1536
  call(method, args, options) {
842
1537
  const callId = this.outbound.nextId();
843
1538
  const outboundCall = options?.outboundCallFactory ? options.outboundCallFactory(callId, method) : new RpcOutboundCall(callId, method);
844
- const msg = serializeMessage(
845
- { Method: method, RelatedId: callId, CallType: options?.callTypeId ?? 0 },
846
- args
1539
+ const envelope = {
1540
+ Method: method,
1541
+ RelatedId: callId,
1542
+ CallType: options?.callTypeId ?? 0
1543
+ };
1544
+ outboundCall.serializedWireData = this.format.serializeMessage(
1545
+ envelope,
1546
+ args,
1547
+ this._connection?.encoder,
1548
+ this._hub.registry
847
1549
  );
848
- outboundCall.serializedMessage = msg;
849
1550
  if (this._connection !== void 0) {
850
1551
  this.outbound.register(outboundCall);
851
- this._connection.send(msg);
1552
+ this._sendWireData(outboundCall.serializedWireData);
852
1553
  } else {
853
1554
  this._pendingSends.push(outboundCall);
854
1555
  }
@@ -862,12 +1563,16 @@ var RpcPeer = class {
862
1563
  outboundCall.result.reject(new Error("Call cancelled."));
863
1564
  outboundCall.onDisconnect();
864
1565
  if (peer._connection !== void 0)
865
- hub.systemCallSender.cancel(peer._connection, callId);
1566
+ hub.systemCallSender.cancel(peer._connection, peer.format, callId);
866
1567
  } else {
867
- const idx = peer._pendingSends.findIndex((c) => c.callId === callId);
1568
+ const idx = peer._pendingSends.findIndex(
1569
+ (c) => c.callId === callId
1570
+ );
868
1571
  if (idx !== -1) {
869
1572
  peer._pendingSends.splice(idx, 1);
870
- outboundCall.result.reject(new Error("Call cancelled."));
1573
+ outboundCall.result.reject(
1574
+ new Error("Call cancelled.")
1575
+ );
871
1576
  outboundCall.onDisconnect();
872
1577
  }
873
1578
  }
@@ -879,8 +1584,14 @@ var RpcPeer = class {
879
1584
  }
880
1585
  callNoWait(method, args) {
881
1586
  if (this._connection === void 0) return;
882
- const msg = serializeMessage({ Method: method, RelatedId: 0 }, args);
883
- this._connection.send(msg);
1587
+ const envelope = { Method: method, RelatedId: 0 };
1588
+ const wireData = this.format.serializeMessage(
1589
+ envelope,
1590
+ args,
1591
+ this._connection.encoder,
1592
+ this._hub.registry
1593
+ );
1594
+ this._sendWireData(wireData);
884
1595
  }
885
1596
  close() {
886
1597
  this._stopKeepAlive();
@@ -899,23 +1610,41 @@ var RpcPeer = class {
899
1610
  }
900
1611
  /** Send any messages buffered while disconnected. Call after connection + handshake are ready. */
901
1612
  _flushPendingSends() {
902
- if (this._pendingSends.length === 0 || this._connection === void 0) return;
1613
+ if (this._pendingSends.length === 0 || this._connection === void 0)
1614
+ return;
903
1615
  for (const call of this._pendingSends) {
904
1616
  this.outbound.register(call);
905
- this._connection.send(call.serializedMessage);
1617
+ this._sendWireData(call.serializedWireData);
906
1618
  }
907
1619
  this._pendingSends.length = 0;
908
1620
  }
1621
+ /** Send pre-serialized wire data through the current connection. */
1622
+ _sendWireData(data) {
1623
+ if (this._connection === void 0) return;
1624
+ if (typeof data === "string") {
1625
+ this._connection.send(data);
1626
+ } else {
1627
+ this._connection.sendBinary(data);
1628
+ }
1629
+ }
909
1630
  /** Override in subclasses to handle the remote peer's handshake response. */
910
1631
  _onHandshakeReceived(_handshake) {
911
1632
  }
912
- _handleMessage(raw) {
913
- const { message, args } = deserializeMessage(raw);
1633
+ _handleMessage(received) {
1634
+ let message;
1635
+ let args;
1636
+ if (received.kind === "binary") {
1637
+ message = received.message;
1638
+ args = received.args;
1639
+ } else {
1640
+ const parsed = deserializeMessage(received.raw);
1641
+ message = parsed.message;
1642
+ args = parsed.args;
1643
+ }
914
1644
  const method = message.Method ?? "";
915
1645
  if (method === RpcSystemCalls.handshake) {
916
1646
  const handshake = args[0];
917
- if (handshake !== void 0)
918
- this._onHandshakeReceived(handshake);
1647
+ if (handshake !== void 0) this._onHandshakeReceived(handshake);
919
1648
  return;
920
1649
  }
921
1650
  if (method.startsWith("$sys")) {
@@ -937,19 +1666,42 @@ var RpcPeer = class {
937
1666
  if (serviceHost !== void 0) {
938
1667
  void (async () => {
939
1668
  try {
940
- const context = this._connection !== void 0 ? { __rpcDispatch: true, callId: relatedId, connection: this._connection } : void 0;
941
- const result = await serviceHost.dispatch(method, args, context);
1669
+ const context = this._connection !== void 0 ? {
1670
+ __rpcDispatch: true,
1671
+ callId: relatedId,
1672
+ connection: this._connection
1673
+ } : void 0;
1674
+ const result = await serviceHost.dispatch(
1675
+ method,
1676
+ args,
1677
+ context
1678
+ );
942
1679
  if (methodDef?.stream === true && this._connection !== void 0) {
943
1680
  const sender = new RpcStreamSender(this);
944
1681
  this.sharedObjects.register(sender);
945
- this._hub.systemCallSender.ok(this._connection, relatedId, sender.toRef());
1682
+ this._hub.systemCallSender.ok(
1683
+ this._connection,
1684
+ this.format,
1685
+ relatedId,
1686
+ sender.toRef()
1687
+ );
946
1688
  void sender.writeFrom(result);
947
1689
  } else if (!isNoWait && this._connection !== void 0) {
948
- this._hub.systemCallSender.ok(this._connection, relatedId, result);
1690
+ this._hub.systemCallSender.ok(
1691
+ this._connection,
1692
+ this.format,
1693
+ relatedId,
1694
+ result
1695
+ );
949
1696
  }
950
1697
  } catch (e) {
951
1698
  if (!isNoWait && this._connection !== void 0) {
952
- this._hub.systemCallSender.error(this._connection, relatedId, e);
1699
+ this._hub.systemCallSender.error(
1700
+ this._connection,
1701
+ this.format,
1702
+ relatedId,
1703
+ e
1704
+ );
953
1705
  }
954
1706
  } finally {
955
1707
  if (!isNoWait) {
@@ -962,7 +1714,9 @@ var RpcPeer = class {
962
1714
  _startKeepAlive() {
963
1715
  this._keepAliveTimer = setInterval(() => {
964
1716
  if (this._connection !== void 0) {
965
- this._hub.systemCallSender.keepAlive(this._connection, this.outbound.activeCallIds());
1717
+ this._hub.systemCallSender.keepAlive(this._connection, this.format, [
1718
+ ...this.remoteObjects.keys()
1719
+ ]);
966
1720
  }
967
1721
  }, 15e3);
968
1722
  }
@@ -998,6 +1752,8 @@ var RpcClientPeer = class extends RpcPeer {
998
1752
  /** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
999
1753
  connectionUrlResolver = defaultConnectionUrlResolver;
1000
1754
  peerChanged = new EventHandlerSet3();
1755
+ /** Fired when the server rejects the connection due to an unsupported serialization format (close code 4010). */
1756
+ unsupportedFormat = new EventHandlerSet3();
1001
1757
  reconnectDelayer = new RpcClientPeerReconnectDelayer();
1002
1758
  reconnectsAtChanged = new EventHandlerSet3();
1003
1759
  get reconnectsAt() {
@@ -1008,10 +1764,15 @@ var RpcClientPeer = class extends RpcPeer {
1008
1764
  this._reconnectsAt = value;
1009
1765
  this.reconnectsAtChanged.trigger();
1010
1766
  }
1767
+ _format;
1011
1768
  constructor(hub, url, serializationFormat) {
1012
1769
  super(url, hub);
1013
1770
  this.clientId = guidToBase64Url(this.id);
1014
1771
  this.serializationFormat = serializationFormat ?? DEFAULT_SERIALIZATION_FORMAT;
1772
+ this._format = RpcSerializationFormat.get(this.serializationFormat);
1773
+ }
1774
+ get format() {
1775
+ return this._format;
1015
1776
  }
1016
1777
  get connectionKind() {
1017
1778
  return this._connectionKind;
@@ -1025,18 +1786,39 @@ var RpcClientPeer = class extends RpcPeer {
1025
1786
  async run(wsFactory) {
1026
1787
  const connUrl = this.connectionUrlResolver(this);
1027
1788
  while (!this._disposed) {
1789
+ let lastCloseCode = 0;
1790
+ let lastCloseReason = "";
1028
1791
  try {
1029
1792
  const ws = wsFactory?.(connUrl) ?? new WebSocket(connUrl);
1030
- const conn = new RpcWebSocketConnection(ws);
1793
+ const conn = new RpcWebSocketConnection(
1794
+ ws,
1795
+ this.format.isBinary,
1796
+ this.format,
1797
+ this._hub.registry
1798
+ );
1031
1799
  this._connectionKind = 1 /* Connecting */;
1800
+ conn.closed.add((ev) => {
1801
+ lastCloseCode = ev.code;
1802
+ lastCloseReason = ev.reason;
1803
+ });
1032
1804
  this._pendingHandshake = new PromiseSource5();
1033
1805
  this.setupConnection(conn);
1034
1806
  this._connection = void 0;
1035
- const closedRejection = new Promise((_, reject) => conn.closed.add(() => reject(new Error("Connection failed"))));
1807
+ const closedRejection = new Promise(
1808
+ (_, reject) => conn.closed.add(
1809
+ () => reject(new Error("Connection failed"))
1810
+ )
1811
+ );
1036
1812
  closedRejection.catch(() => {
1037
1813
  });
1038
1814
  await Promise.race([conn.whenConnected, closedRejection]);
1039
- this._hub.systemCallSender.handshake(conn, this.id, this._hub.hubId, ++this._handshakeIndex);
1815
+ this._hub.systemCallSender.handshake(
1816
+ conn,
1817
+ this.format,
1818
+ this.id,
1819
+ this._hub.hubId,
1820
+ ++this._handshakeIndex
1821
+ );
1040
1822
  const remoteHandshake = await Promise.race([
1041
1823
  this._pendingHandshake.promise,
1042
1824
  closedRejection
@@ -1061,6 +1843,11 @@ var RpcClientPeer = class extends RpcPeer {
1061
1843
  }
1062
1844
  this._connectionKind = 0 /* Disconnected */;
1063
1845
  if (this._disposed) break;
1846
+ if (lastCloseCode === RPC_CLOSE_CODE_UNSUPPORTED_FORMAT) {
1847
+ this.unsupportedFormat.trigger({ reason: lastCloseReason });
1848
+ this._disposed = true;
1849
+ break;
1850
+ }
1064
1851
  this._tryIndex++;
1065
1852
  const delay = this.reconnectDelayer.getDelay(this._tryIndex);
1066
1853
  if (delay.isLimitExceeded) {
@@ -1084,7 +1871,6 @@ var RpcClientPeer = class extends RpcPeer {
1084
1871
  * Regular in-flight calls are re-sent transparently. */
1085
1872
  _reconnect(_isPeerChanged) {
1086
1873
  if (this._connection === void 0) return;
1087
- const conn = this._connection;
1088
1874
  if (_isPeerChanged) {
1089
1875
  this.remoteObjects.disconnectAll();
1090
1876
  } else {
@@ -1096,7 +1882,7 @@ var RpcClientPeer = class extends RpcPeer {
1096
1882
  call.onDisconnect();
1097
1883
  this.outbound.remove(call.callId);
1098
1884
  } else {
1099
- conn.send(call.serializedMessage);
1885
+ this._sendWireData(call.serializedWireData);
1100
1886
  }
1101
1887
  }
1102
1888
  this._flushPendingSends();
@@ -1119,7 +1905,13 @@ var RpcServerPeer = class extends RpcPeer {
1119
1905
  }
1120
1906
  _onHandshakeReceived(_handshake) {
1121
1907
  if (this._connection !== void 0) {
1122
- this._hub.systemCallSender.handshake(this._connection, this.id, this._hub.hubId, 0);
1908
+ this._hub.systemCallSender.handshake(
1909
+ this._connection,
1910
+ this.format,
1911
+ this.id,
1912
+ this._hub.hubId,
1913
+ 0
1914
+ );
1123
1915
  }
1124
1916
  }
1125
1917
  };
@@ -1147,12 +1939,16 @@ var RpcServiceHost = class {
1147
1939
  for (const methodDef of def.methods.values()) {
1148
1940
  const fn = impl[methodDef.name];
1149
1941
  if (!fn) continue;
1150
- this._methods.set(wireMethodName(methodDef), { def: methodDef, fn });
1942
+ this._methods.set(wireMethodName(methodDef), {
1943
+ def: methodDef,
1944
+ fn
1945
+ });
1151
1946
  }
1152
1947
  }
1153
1948
  async dispatch(wireMethod, args, context) {
1154
1949
  const entry = this._methods.get(wireMethod);
1155
- if (entry === void 0) throw new Error(`Method not found: ${wireMethod}`);
1950
+ if (entry === void 0)
1951
+ throw new Error(`Method not found: ${wireMethod}`);
1156
1952
  if (context !== void 0 && entry.def.callTypeId !== 0) {
1157
1953
  return await entry.fn(...args, context);
1158
1954
  }
@@ -1191,6 +1987,539 @@ function rpcMethod(options) {
1191
1987
  };
1192
1988
  }
1193
1989
 
1990
+ // src/rpc-xxhash3.ts
1991
+ var U64_MASK = 0xffffffffffffffffn;
1992
+ var U32_MASK = 0xffffffffn;
1993
+ var PRIME32_1 = 2654435761;
1994
+ var PRIME32_2 = 2246822519;
1995
+ var PRIME32_3 = 3266489917;
1996
+ var PRIME64_1 = 0x9e3779b185ebca87n;
1997
+ var PRIME64_2 = 0xc2b2ae3d27d4eb4fn;
1998
+ var PRIME64_3 = 0x165667b19e3779f9n;
1999
+ var PRIME64_4 = 0x85ebca77c2b2ae63n;
2000
+ var PRIME64_5 = 0x27d4eb2f165667c5n;
2001
+ var XXH3_SECRET_SIZE_MIN = 136;
2002
+ var XXH_SECRET_DEFAULT_SIZE = 192;
2003
+ var STRIPE_LEN = 64;
2004
+ var XXH_SECRET_CONSUME_RATE = 8;
2005
+ var ACC_NB = STRIPE_LEN / 8;
2006
+ var XXH3_MIDSIZE_MAX = 240;
2007
+ var XXH3_MIDSIZE_STARTOFFSET = 3;
2008
+ var XXH3_MIDSIZE_LASTOFFSET = 17;
2009
+ var XXH_SECRET_LASTACC_START = 7;
2010
+ var XXH_SECRET_MERGEACCS_START = 11;
2011
+ var RRMXMX = 0x9fb21c651e98df25n;
2012
+ var DEFAULT_SECRET = new Uint8Array([
2013
+ 184,
2014
+ 254,
2015
+ 108,
2016
+ 57,
2017
+ 35,
2018
+ 164,
2019
+ 75,
2020
+ 190,
2021
+ 124,
2022
+ 1,
2023
+ 129,
2024
+ 44,
2025
+ 247,
2026
+ 33,
2027
+ 173,
2028
+ 28,
2029
+ 222,
2030
+ 212,
2031
+ 109,
2032
+ 233,
2033
+ 131,
2034
+ 144,
2035
+ 151,
2036
+ 219,
2037
+ 114,
2038
+ 64,
2039
+ 164,
2040
+ 164,
2041
+ 183,
2042
+ 179,
2043
+ 103,
2044
+ 31,
2045
+ 203,
2046
+ 121,
2047
+ 230,
2048
+ 78,
2049
+ 204,
2050
+ 192,
2051
+ 229,
2052
+ 120,
2053
+ 130,
2054
+ 90,
2055
+ 208,
2056
+ 125,
2057
+ 204,
2058
+ 255,
2059
+ 114,
2060
+ 33,
2061
+ 184,
2062
+ 8,
2063
+ 70,
2064
+ 116,
2065
+ 247,
2066
+ 67,
2067
+ 36,
2068
+ 142,
2069
+ 224,
2070
+ 53,
2071
+ 144,
2072
+ 230,
2073
+ 129,
2074
+ 58,
2075
+ 38,
2076
+ 76,
2077
+ 60,
2078
+ 40,
2079
+ 82,
2080
+ 187,
2081
+ 145,
2082
+ 195,
2083
+ 0,
2084
+ 203,
2085
+ 136,
2086
+ 208,
2087
+ 101,
2088
+ 139,
2089
+ 27,
2090
+ 83,
2091
+ 46,
2092
+ 163,
2093
+ 113,
2094
+ 100,
2095
+ 72,
2096
+ 151,
2097
+ 162,
2098
+ 13,
2099
+ 249,
2100
+ 78,
2101
+ 56,
2102
+ 25,
2103
+ 239,
2104
+ 70,
2105
+ 169,
2106
+ 222,
2107
+ 172,
2108
+ 216,
2109
+ 168,
2110
+ 250,
2111
+ 118,
2112
+ 63,
2113
+ 227,
2114
+ 156,
2115
+ 52,
2116
+ 63,
2117
+ 249,
2118
+ 220,
2119
+ 187,
2120
+ 199,
2121
+ 199,
2122
+ 11,
2123
+ 79,
2124
+ 29,
2125
+ 138,
2126
+ 81,
2127
+ 224,
2128
+ 75,
2129
+ 205,
2130
+ 180,
2131
+ 89,
2132
+ 49,
2133
+ 200,
2134
+ 159,
2135
+ 126,
2136
+ 201,
2137
+ 217,
2138
+ 120,
2139
+ 115,
2140
+ 100,
2141
+ 234,
2142
+ 197,
2143
+ 172,
2144
+ 131,
2145
+ 52,
2146
+ 211,
2147
+ 235,
2148
+ 195,
2149
+ 197,
2150
+ 129,
2151
+ 160,
2152
+ 255,
2153
+ 250,
2154
+ 19,
2155
+ 99,
2156
+ 235,
2157
+ 23,
2158
+ 13,
2159
+ 221,
2160
+ 81,
2161
+ 183,
2162
+ 240,
2163
+ 218,
2164
+ 73,
2165
+ 211,
2166
+ 22,
2167
+ 85,
2168
+ 38,
2169
+ 41,
2170
+ 212,
2171
+ 104,
2172
+ 158,
2173
+ 43,
2174
+ 22,
2175
+ 190,
2176
+ 88,
2177
+ 125,
2178
+ 71,
2179
+ 161,
2180
+ 252,
2181
+ 143,
2182
+ 248,
2183
+ 184,
2184
+ 209,
2185
+ 122,
2186
+ 208,
2187
+ 49,
2188
+ 206,
2189
+ 69,
2190
+ 203,
2191
+ 58,
2192
+ 143,
2193
+ 149,
2194
+ 22,
2195
+ 4,
2196
+ 40,
2197
+ 175,
2198
+ 215,
2199
+ 251,
2200
+ 202,
2201
+ 187,
2202
+ 75,
2203
+ 64,
2204
+ 126
2205
+ ]);
2206
+ function u64(x) {
2207
+ return x & U64_MASK;
2208
+ }
2209
+ function read32LE(buf, off) {
2210
+ return (buf[off] | buf[off + 1] << 8 | buf[off + 2] << 16 | buf[off + 3] << 24) >>> 0;
2211
+ }
2212
+ function read64LE(buf, off) {
2213
+ 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;
2214
+ }
2215
+ function write64LE(buf, off, value) {
2216
+ let x = u64(value);
2217
+ for (let i = 0; i < 8; i++) {
2218
+ buf[off + i] = Number(x & 0xffn);
2219
+ x >>= 8n;
2220
+ }
2221
+ }
2222
+ function swap32(x) {
2223
+ return (x << 24 & 4278190080 | x << 8 & 16711680 | x >>> 8 & 65280 | x >>> 24 & 255) >>> 0;
2224
+ }
2225
+ function swap64(x) {
2226
+ x = u64(x);
2227
+ 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;
2228
+ }
2229
+ function rotl64(x, amount) {
2230
+ const r = BigInt(amount & 63);
2231
+ return u64(x << r | x >> 64n - r);
2232
+ }
2233
+ function mul128Fold64(lhs, rhs) {
2234
+ const product = u64(lhs) * u64(rhs);
2235
+ return u64(product) ^ u64(product >> 64n);
2236
+ }
2237
+ function xxh64Avalanche(hash) {
2238
+ let h = u64(hash);
2239
+ h ^= h >> 33n;
2240
+ h = u64(h * PRIME64_2);
2241
+ h ^= h >> 29n;
2242
+ h = u64(h * PRIME64_3);
2243
+ h ^= h >> 32n;
2244
+ return u64(h);
2245
+ }
2246
+ function xxh3Avalanche(hash) {
2247
+ let h = u64(hash);
2248
+ h ^= h >> 37n;
2249
+ h = u64(h * 0x165667919e3779f9n);
2250
+ h ^= h >> 32n;
2251
+ return u64(h);
2252
+ }
2253
+ function len0(secret, seed) {
2254
+ const acc = u64(seed ^ read64LE(secret, 56) ^ read64LE(secret, 64));
2255
+ return xxh64Avalanche(acc);
2256
+ }
2257
+ function len1to3(input, length, secret, seed) {
2258
+ const byte1 = input[0];
2259
+ const byte2 = length > 1 ? input[1] : input[0];
2260
+ const byte3 = input[length - 1];
2261
+ const combined = (byte1 << 16 | byte2 << 24 | byte3 | length << 8) >>> 0;
2262
+ const bitflip = u64(
2263
+ BigInt((read32LE(secret, 0) ^ read32LE(secret, 4)) >>> 0) + seed
2264
+ );
2265
+ const value64 = u64(BigInt(combined) ^ bitflip);
2266
+ return xxh64Avalanche(value64);
2267
+ }
2268
+ function len4to8(input, length, secret, seed) {
2269
+ const inputHi = read32LE(input, 0);
2270
+ const inputLo = read32LE(input, length - 4);
2271
+ const input64 = BigInt(inputLo) | BigInt(inputHi) << 32n;
2272
+ let acc = read64LE(secret, 8) ^ read64LE(secret, 16);
2273
+ seed ^= BigInt(swap32(Number(seed & U32_MASK))) << 32n;
2274
+ acc = u64(acc - seed);
2275
+ acc ^= input64;
2276
+ acc ^= rotl64(acc, 49) ^ rotl64(acc, 24);
2277
+ acc = u64(acc * RRMXMX);
2278
+ acc ^= (acc >> 35n) + BigInt(length);
2279
+ acc = u64(acc * RRMXMX);
2280
+ acc ^= acc >> 28n;
2281
+ return u64(acc);
2282
+ }
2283
+ function len9to16(input, length, secret, seed) {
2284
+ let inputLo = read64LE(secret, 24) ^ read64LE(secret, 32);
2285
+ let inputHi = read64LE(secret, 40) ^ read64LE(secret, 48);
2286
+ let acc = BigInt(length);
2287
+ inputLo = u64(inputLo + seed);
2288
+ inputHi = u64(inputHi - seed);
2289
+ inputLo ^= read64LE(input, 0);
2290
+ inputHi ^= read64LE(input, length - 8);
2291
+ acc = u64(acc + swap64(inputLo));
2292
+ acc = u64(acc + inputHi);
2293
+ acc = u64(acc + mul128Fold64(inputLo, inputHi));
2294
+ return xxh3Avalanche(acc);
2295
+ }
2296
+ function mix16B(input, inputOff, secret, secretOff, seed) {
2297
+ let lhs = seed;
2298
+ let rhs = u64(0n - seed);
2299
+ lhs = u64(lhs + read64LE(secret, secretOff));
2300
+ rhs = u64(rhs + read64LE(secret, secretOff + 8));
2301
+ lhs ^= read64LE(input, inputOff);
2302
+ rhs ^= read64LE(input, inputOff + 8);
2303
+ return mul128Fold64(lhs, rhs);
2304
+ }
2305
+ function len17to128(input, length, secret, seed) {
2306
+ let i = Math.floor((length - 1) / 32);
2307
+ let acc = u64(BigInt(length) * PRIME64_1);
2308
+ for (; i >= 0; i--) {
2309
+ acc = u64(acc + mix16B(input, 16 * i, secret, 32 * i, seed));
2310
+ acc = u64(
2311
+ acc + mix16B(
2312
+ input,
2313
+ length - 16 * (i + 1),
2314
+ secret,
2315
+ 32 * i + 16,
2316
+ seed
2317
+ )
2318
+ );
2319
+ }
2320
+ return xxh3Avalanche(acc);
2321
+ }
2322
+ function len129to240(input, length, secret, seed) {
2323
+ let acc = u64(BigInt(length) * PRIME64_1);
2324
+ const nbRounds = Math.floor(length / 16);
2325
+ for (let i = 0; i < 8; i++) {
2326
+ acc = u64(acc + mix16B(input, 16 * i, secret, 16 * i, seed));
2327
+ }
2328
+ acc = xxh3Avalanche(acc);
2329
+ for (let i = 8; i < nbRounds; i++) {
2330
+ acc = u64(
2331
+ acc + mix16B(
2332
+ input,
2333
+ 16 * i,
2334
+ secret,
2335
+ 16 * (i - 8) + XXH3_MIDSIZE_STARTOFFSET,
2336
+ seed
2337
+ )
2338
+ );
2339
+ }
2340
+ acc = u64(
2341
+ acc + mix16B(
2342
+ input,
2343
+ length - 16,
2344
+ secret,
2345
+ XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET,
2346
+ seed
2347
+ )
2348
+ );
2349
+ return xxh3Avalanche(acc);
2350
+ }
2351
+ function hashShort(input, length, secret, seed) {
2352
+ if (length <= 16) {
2353
+ if (length > 8) return len9to16(input, length, secret, seed);
2354
+ if (length >= 4) return len4to8(input, length, secret, seed);
2355
+ if (length !== 0) return len1to3(input, length, secret, seed);
2356
+ return len0(secret, seed);
2357
+ }
2358
+ if (length <= 128) return len17to128(input, length, secret, seed);
2359
+ return len129to240(input, length, secret, seed);
2360
+ }
2361
+ function accumulate512(acc, input, inputOff, secret, secretOff) {
2362
+ for (let i = 0; i < ACC_NB; i++) {
2363
+ const dataVal = read64LE(input, inputOff + 8 * i);
2364
+ const dataKey = dataVal ^ read64LE(secret, secretOff + 8 * i);
2365
+ acc[i ^ 1] = u64(acc[i ^ 1] + dataVal);
2366
+ const low32 = dataKey & U32_MASK;
2367
+ const high32 = dataKey >> 32n;
2368
+ acc[i] = u64(acc[i] + low32 * high32);
2369
+ }
2370
+ }
2371
+ function scrambleAcc(acc, secret, secretOff) {
2372
+ for (let i = 0; i < ACC_NB; i++) {
2373
+ let x = acc[i];
2374
+ x ^= x >> 47n;
2375
+ x ^= read64LE(secret, secretOff + 8 * i);
2376
+ x = u64(x * BigInt(PRIME32_1));
2377
+ acc[i] = x;
2378
+ }
2379
+ }
2380
+ function accumulateLoop(acc, input, inputOff, secret, secretOff, nbStripes) {
2381
+ for (let n = 0; n < nbStripes; n++) {
2382
+ accumulate512(
2383
+ acc,
2384
+ input,
2385
+ inputOff + n * STRIPE_LEN,
2386
+ secret,
2387
+ secretOff + 8 * n
2388
+ );
2389
+ }
2390
+ }
2391
+ function mix2Accs(acc, accOff, secret, secretOff) {
2392
+ return mul128Fold64(
2393
+ acc[accOff] ^ read64LE(secret, secretOff),
2394
+ acc[accOff + 1] ^ read64LE(secret, secretOff + 8)
2395
+ );
2396
+ }
2397
+ function mergeAccs(acc, key, keyOff, start) {
2398
+ let result = start;
2399
+ for (let i = 0; i < 4; i++) {
2400
+ result = u64(result + mix2Accs(acc, 2 * i, key, keyOff + 16 * i));
2401
+ }
2402
+ return xxh3Avalanche(result);
2403
+ }
2404
+ function hashLong(input, length, secret, secretSize) {
2405
+ const nbRounds = Math.floor(
2406
+ (secretSize - STRIPE_LEN) / XXH_SECRET_CONSUME_RATE
2407
+ );
2408
+ const blockLen = STRIPE_LEN * nbRounds;
2409
+ const nbBlocks = Math.floor((length - 1) / blockLen);
2410
+ const nbStripes = Math.floor(
2411
+ (length - 1 - blockLen * nbBlocks) / STRIPE_LEN
2412
+ );
2413
+ const acc = [
2414
+ BigInt(PRIME32_3),
2415
+ PRIME64_1,
2416
+ PRIME64_2,
2417
+ PRIME64_3,
2418
+ PRIME64_4,
2419
+ BigInt(PRIME32_2),
2420
+ PRIME64_5,
2421
+ BigInt(PRIME32_1)
2422
+ ];
2423
+ for (let n = 0; n < nbBlocks; n++) {
2424
+ accumulateLoop(acc, input, n * blockLen, secret, 0, nbRounds);
2425
+ scrambleAcc(acc, secret, secretSize - STRIPE_LEN);
2426
+ }
2427
+ accumulateLoop(acc, input, nbBlocks * blockLen, secret, 0, nbStripes);
2428
+ accumulate512(
2429
+ acc,
2430
+ input,
2431
+ length - STRIPE_LEN,
2432
+ secret,
2433
+ secretSize - STRIPE_LEN - XXH_SECRET_LASTACC_START
2434
+ );
2435
+ return mergeAccs(
2436
+ acc,
2437
+ secret,
2438
+ XXH_SECRET_MERGEACCS_START,
2439
+ u64(BigInt(length) * PRIME64_1)
2440
+ );
2441
+ }
2442
+ function hashLongWithSeed(input, length, seed) {
2443
+ const secret = new Uint8Array(XXH_SECRET_DEFAULT_SIZE);
2444
+ for (let i = 0; i < XXH_SECRET_DEFAULT_SIZE / 16; i++) {
2445
+ const off = 16 * i;
2446
+ write64LE(secret, off, u64(read64LE(DEFAULT_SECRET, off) + seed));
2447
+ write64LE(
2448
+ secret,
2449
+ off + 8,
2450
+ u64(read64LE(DEFAULT_SECRET, off + 8) - seed)
2451
+ );
2452
+ }
2453
+ return hashLong(input, length, secret, secret.length);
2454
+ }
2455
+ var textEncoder2 = new TextEncoder();
2456
+ function xxh3_64(input, seed = 0n) {
2457
+ const len = input.length;
2458
+ if (len <= XXH3_MIDSIZE_MAX) {
2459
+ return hashShort(input, len, DEFAULT_SECRET, u64(seed));
2460
+ }
2461
+ return hashLongWithSeed(input, len, u64(seed));
2462
+ }
2463
+ function xxh3_64str(input, seed = 0n) {
2464
+ return xxh3_64(textEncoder2.encode(input), seed);
2465
+ }
2466
+ function computeMethodHash(methodName) {
2467
+ const utf8 = textEncoder2.encode(methodName);
2468
+ const prefixValue = Math.imul(67211, utf8.length) >>> 0;
2469
+ const prefixed = new Uint8Array(4 + utf8.length);
2470
+ prefixed[0] = prefixValue & 255;
2471
+ prefixed[1] = prefixValue >>> 8 & 255;
2472
+ prefixed[2] = prefixValue >>> 16 & 255;
2473
+ prefixed[3] = prefixValue >>> 24 & 255;
2474
+ prefixed.set(utf8, 4);
2475
+ const hash64 = xxh3_64(prefixed);
2476
+ return Number(hash64 & 0xffffffffn) | 0;
2477
+ }
2478
+
2479
+ // src/rpc-method-registry.ts
2480
+ var RpcMethodRegistry = class {
2481
+ _nameToHash = /* @__PURE__ */ new Map();
2482
+ _hashToName = /* @__PURE__ */ new Map();
2483
+ /** Register a method name and compute its hash. */
2484
+ register(methodName) {
2485
+ if (this._nameToHash.has(methodName)) return;
2486
+ const hash = computeMethodHash(methodName);
2487
+ const existing = this._hashToName.get(hash);
2488
+ if (existing !== void 0 && existing !== methodName) {
2489
+ console.warn(
2490
+ `[RpcMethodRegistry] hash collision: "${methodName}" and "${existing}" both hash to ${hash}`
2491
+ );
2492
+ return;
2493
+ }
2494
+ this._nameToHash.set(methodName, hash);
2495
+ this._hashToName.set(hash, methodName);
2496
+ }
2497
+ /** Register all wire method names from a service definition. */
2498
+ registerService(serviceName, methods) {
2499
+ for (const [, def] of methods) {
2500
+ const wireName = `${serviceName}.${def.name}:${def.wireArgCount}`;
2501
+ this.register(wireName);
2502
+ }
2503
+ }
2504
+ /** Get the hash for a method name. Computes on demand if not registered. */
2505
+ getHash(methodName) {
2506
+ let hash = this._nameToHash.get(methodName);
2507
+ if (hash === void 0) {
2508
+ this.register(methodName);
2509
+ hash = this._nameToHash.get(methodName);
2510
+ }
2511
+ return hash;
2512
+ }
2513
+ /** Get the method name for a hash. Returns undefined if not registered. */
2514
+ getName(hash) {
2515
+ return this._hashToName.get(hash);
2516
+ }
2517
+ /** Get the hash for a method name, throwing if not registered. */
2518
+ requireHash(methodName) {
2519
+ return this.getHash(methodName);
2520
+ }
2521
+ };
2522
+
1194
2523
  // src/rpc-hub.ts
1195
2524
  var RpcHub = class {
1196
2525
  hubId;
@@ -1198,9 +2527,16 @@ var RpcHub = class {
1198
2527
  serviceHost;
1199
2528
  systemCallSender = new RpcSystemCallSender();
1200
2529
  systemCallHandler = new RpcSystemCallHandler();
2530
+ /** Method registry for compact format hash ↔ name resolution.
2531
+ * Created lazily, populated by addService/addClient. */
2532
+ registry = new RpcMethodRegistry();
1201
2533
  constructor(hubId) {
1202
2534
  this.hubId = hubId ?? crypto.randomUUID();
1203
2535
  this.serviceHost = new RpcServiceHost();
2536
+ this.systemCallSender.registry = this.registry;
2537
+ for (const methodName of Object.values(RpcSystemCalls)) {
2538
+ this.registry.register(methodName);
2539
+ }
1204
2540
  }
1205
2541
  addPeer(peer) {
1206
2542
  this.peers.set(peer.ref, peer);
@@ -1238,10 +2574,12 @@ var RpcHub = class {
1238
2574
  wrappedImpl[methodDef.name] = methodDef.callTypeId !== 0 ? this._wrapServerMethod(methodDef, fn, impl) : fn;
1239
2575
  }
1240
2576
  this.serviceHost.register(def, wrappedImpl);
2577
+ this.registry.registerService(def.name, def.methods);
1241
2578
  }
1242
2579
  /** Create a typed client proxy for a service on a remote peer. */
1243
2580
  addClient(peer, defOrContract) {
1244
2581
  const def = this._resolveServiceDef(defOrContract);
2582
+ this.registry.registerService(def.name, def.methods);
1245
2583
  const overloads = /* @__PURE__ */ new Map();
1246
2584
  for (const methodDef of def.methods.values()) {
1247
2585
  let byArgCount = overloads.get(methodDef.name);
@@ -1249,7 +2587,10 @@ var RpcHub = class {
1249
2587
  byArgCount = /* @__PURE__ */ new Map();
1250
2588
  overloads.set(methodDef.name, byArgCount);
1251
2589
  }
1252
- byArgCount.set(methodDef.argCount, this._createClientMethod(peer, methodDef));
2590
+ byArgCount.set(
2591
+ methodDef.argCount,
2592
+ this._createClientMethod(peer, methodDef)
2593
+ );
1253
2594
  }
1254
2595
  const methods = /* @__PURE__ */ new Map();
1255
2596
  for (const [name, byArgCount] of overloads) {
@@ -1258,7 +2599,10 @@ var RpcHub = class {
1258
2599
  } else {
1259
2600
  methods.set(name, (...args) => {
1260
2601
  const fn = byArgCount.get(args.length);
1261
- if (!fn) throw new Error(`No overload of ${name} accepts ${args.length} arguments`);
2602
+ if (!fn)
2603
+ throw new Error(
2604
+ `No overload of ${name} accepts ${args.length} arguments`
2605
+ );
1262
2606
  return fn(...args);
1263
2607
  });
1264
2608
  }
@@ -1274,7 +2618,8 @@ var RpcHub = class {
1274
2618
  /** Build an RpcServiceDef from decorator metadata on a contract class. Override in FusionHub for compute support. */
1275
2619
  _buildServiceDef(cls) {
1276
2620
  const svcMeta = getServiceMeta(cls);
1277
- if (svcMeta === void 0) throw new Error("Contract class missing @rpcService metadata");
2621
+ if (svcMeta === void 0)
2622
+ throw new Error("Contract class missing @rpcService metadata");
1278
2623
  const methodsMeta = getMethodsMeta(cls) ?? {};
1279
2624
  const methods = /* @__PURE__ */ new Map();
1280
2625
  for (const [name, meta] of Object.entries(methodsMeta)) {
@@ -1317,7 +2662,10 @@ var RpcHub = class {
1317
2662
  const outboundCall = peer.call(wireName, callArgs);
1318
2663
  const result = await outboundCall.result.promise;
1319
2664
  const ref = parseStreamRef(result);
1320
- if (!ref) throw new Error(`Expected stream reference, got: ${JSON.stringify(result)}`);
2665
+ if (!ref)
2666
+ throw new Error(
2667
+ `Expected stream reference, got: ${JSON.stringify(result)}`
2668
+ );
1321
2669
  const stream = new RpcStream(ref, peer);
1322
2670
  peer.remoteObjects.register(stream);
1323
2671
  return stream;
@@ -1356,7 +2704,10 @@ function createRpcClient(peer, serviceDef) {
1356
2704
  }
1357
2705
  methods.set(name, (...args) => {
1358
2706
  const fn = fns.get(args.length);
1359
- if (!fn) throw new Error(`No overload of ${name} accepts ${args.length} arguments`);
2707
+ if (!fn)
2708
+ throw new Error(
2709
+ `No overload of ${name} accepts ${args.length} arguments`
2710
+ );
1360
2711
  return fn(...args);
1361
2712
  });
1362
2713
  }
@@ -1401,12 +2752,10 @@ function getStateDescription(state, useLastError = false) {
1401
2752
  case 1 /* JustDisconnected */:
1402
2753
  return "Just disconnected, reconnecting...";
1403
2754
  case 2 /* Disconnected */:
1404
- if (state.reconnectsIn > 0)
1405
- break;
2755
+ if (state.reconnectsIn > 0) break;
1406
2756
  return "Reconnecting...";
1407
2757
  }
1408
- if (state.lastError == null || !useLastError)
1409
- return "Disconnected.";
2758
+ if (state.lastError == null || !useLastError) return "Disconnected.";
1410
2759
  let message = state.lastError.message.trim();
1411
2760
  if (!(message.endsWith(".") || message.endsWith("!") || message.endsWith("?")))
1412
2761
  message += ".";
@@ -1437,7 +2786,9 @@ var RpcPeerStateMonitor = class {
1437
2786
  _onDisconnected = (ev) => {
1438
2787
  const wasConnected = this._rawConnected;
1439
2788
  this._rawConnected = false;
1440
- this._lastError = new Error(`Connection closed: ${ev.reason} (code ${ev.code})`);
2789
+ this._lastError = new Error(
2790
+ `Connection closed: ${ev.reason} (code ${ev.code})`
2791
+ );
1441
2792
  if (wasConnected) {
1442
2793
  this._disconnectedAt = Date.now();
1443
2794
  }
@@ -1454,16 +2805,26 @@ var RpcPeerStateMonitor = class {
1454
2805
  this._rawConnected = peer.isConnected;
1455
2806
  if (this._rawConnected) {
1456
2807
  this._connectedAt = Date.now();
1457
- this._state = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2808
+ this._state = {
2809
+ kind: 3 /* JustConnected */,
2810
+ reconnectsIn: 0
2811
+ };
1458
2812
  } else {
1459
2813
  this._disconnectedAt = Date.now();
1460
- this._state = { kind: 1 /* JustDisconnected */, reconnectsIn: 0 };
2814
+ this._state = {
2815
+ kind: 1 /* JustDisconnected */,
2816
+ reconnectsIn: 0
2817
+ };
1461
2818
  }
1462
2819
  peer.connected.add(this._onConnected);
1463
2820
  peer.disconnected.add(this._onDisconnected);
1464
2821
  peer.reconnectsAtChanged.add(this._onReconnectsAtChanged);
1465
- peer.reconnectDelayer.cancelDelaysChanged.add(this._onCancelDelaysChanged);
1466
- this._scheduleRecompute(this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs);
2822
+ peer.reconnectDelayer.cancelDelaysChanged.add(
2823
+ this._onCancelDelaysChanged
2824
+ );
2825
+ this._scheduleRecompute(
2826
+ this._rawConnected ? JustConnectedPeriodMs : JustDisconnectedPeriodMs
2827
+ );
1467
2828
  }
1468
2829
  get state() {
1469
2830
  return this._state;
@@ -1476,7 +2837,9 @@ var RpcPeerStateMonitor = class {
1476
2837
  this.peer.connected.remove(this._onConnected);
1477
2838
  this.peer.disconnected.remove(this._onDisconnected);
1478
2839
  this.peer.reconnectsAtChanged.remove(this._onReconnectsAtChanged);
1479
- this.peer.reconnectDelayer.cancelDelaysChanged.remove(this._onCancelDelaysChanged);
2840
+ this.peer.reconnectDelayer.cancelDelaysChanged.remove(
2841
+ this._onCancelDelaysChanged
2842
+ );
1480
2843
  }
1481
2844
  _recompute() {
1482
2845
  if (this._timer !== void 0) {
@@ -1488,24 +2851,46 @@ var RpcPeerStateMonitor = class {
1488
2851
  if (this._rawConnected) {
1489
2852
  const connectedFor = now - this._connectedAt;
1490
2853
  if (connectedFor < JustConnectedPeriodMs) {
1491
- newState = { kind: 3 /* JustConnected */, reconnectsIn: 0 };
2854
+ newState = {
2855
+ kind: 3 /* JustConnected */,
2856
+ reconnectsIn: 0
2857
+ };
1492
2858
  this._scheduleRecompute(JustConnectedPeriodMs - connectedFor);
1493
2859
  } else {
1494
- newState = { kind: 0 /* Connected */, reconnectsIn: 0 };
2860
+ newState = {
2861
+ kind: 0 /* Connected */,
2862
+ reconnectsIn: 0
2863
+ };
1495
2864
  }
1496
2865
  } else {
1497
2866
  const disconnectedFor = now - this._disconnectedAt;
1498
2867
  if (disconnectedFor < JustDisconnectedPeriodMs) {
1499
- newState = { kind: 1 /* JustDisconnected */, lastError: this._lastError, reconnectsIn: 0 };
1500
- this._scheduleRecompute(JustDisconnectedPeriodMs - disconnectedFor);
2868
+ newState = {
2869
+ kind: 1 /* JustDisconnected */,
2870
+ lastError: this._lastError,
2871
+ reconnectsIn: 0
2872
+ };
2873
+ this._scheduleRecompute(
2874
+ JustDisconnectedPeriodMs - disconnectedFor
2875
+ );
1501
2876
  } else {
1502
2877
  const reconnectsAt = this.peer.reconnectsAt;
1503
2878
  const reconnectsIn = reconnectsAt > 0 ? Math.max(0, reconnectsAt - now) : 0;
1504
2879
  if (reconnectsIn < MinReconnectsInMs) {
1505
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn: 0 };
2880
+ newState = {
2881
+ kind: 2 /* Disconnected */,
2882
+ lastError: this._lastError,
2883
+ reconnectsIn: 0
2884
+ };
1506
2885
  } else {
1507
- newState = { kind: 2 /* Disconnected */, lastError: this._lastError, reconnectsIn };
1508
- this._scheduleRecompute(Math.min(1e3, reconnectsIn - MinReconnectsInMs));
2886
+ newState = {
2887
+ kind: 2 /* Disconnected */,
2888
+ lastError: this._lastError,
2889
+ reconnectsIn
2890
+ };
2891
+ this._scheduleRecompute(
2892
+ Math.min(1e3, reconnectsIn - MinReconnectsInMs)
2893
+ );
1509
2894
  }
1510
2895
  }
1511
2896
  }
@@ -1520,10 +2905,13 @@ var RpcPeerStateMonitor = class {
1520
2905
  }
1521
2906
  _scheduleRecompute(delayMs) {
1522
2907
  if (this._timer !== void 0) clearTimeout(this._timer);
1523
- this._timer = setTimeout(() => {
1524
- this._timer = void 0;
1525
- this._recompute();
1526
- }, Math.max(0, delayMs));
2908
+ this._timer = setTimeout(
2909
+ () => {
2910
+ this._timer = void 0;
2911
+ this._recompute();
2912
+ },
2913
+ Math.max(0, delayMs)
2914
+ );
1527
2915
  }
1528
2916
  };
1529
2917
  export {
@@ -1531,13 +2919,18 @@ export {
1531
2919
  DEFAULT_SERIALIZATION_FORMAT,
1532
2920
  ENVELOPE_DELIMITER,
1533
2921
  FRAME_DELIMITER,
2922
+ RPC_CLOSE_CODE_UNSUPPORTED_FORMAT,
1534
2923
  RpcCallTypeId,
1535
2924
  RpcClientPeer,
1536
2925
  RpcClientPeerReconnectDelayer,
1537
2926
  RpcHub,
1538
2927
  RpcInboundCall,
1539
2928
  RpcInboundCallTracker,
2929
+ RpcJsonSerializationFormat,
1540
2930
  RpcMessageChannelConnection,
2931
+ RpcMessagePackCompactSerializationFormat,
2932
+ RpcMessagePackSerializationFormat,
2933
+ RpcMethodRegistry,
1541
2934
  RpcObjectKind,
1542
2935
  RpcOutboundCall,
1543
2936
  RpcOutboundCallTracker,
@@ -1546,6 +2939,7 @@ export {
1546
2939
  RpcPeerStateKind,
1547
2940
  RpcPeerStateMonitor,
1548
2941
  RpcRemoteObjectTracker,
2942
+ RpcSerializationFormat,
1549
2943
  RpcServerPeer,
1550
2944
  RpcServiceHost,
1551
2945
  RpcSharedObjectTracker,
@@ -1557,10 +2951,16 @@ export {
1557
2951
  RpcType,
1558
2952
  RpcWebSocketConnection,
1559
2953
  WebSocketState,
2954
+ computeMethodHash,
2955
+ createBinaryEncoder,
1560
2956
  createMessageChannelPair,
1561
2957
  createRpcClient,
2958
+ defaultBinaryDecoder,
2959
+ defaultBinaryEncoder,
1562
2960
  defaultConnectionUrlResolver,
1563
2961
  defineRpcService,
2962
+ deserializeBinaryMessage,
2963
+ deserializeCompactBinaryMessage,
1564
2964
  deserializeMessage,
1565
2965
  getMethodsMeta,
1566
2966
  getServiceMeta,
@@ -1571,9 +2971,16 @@ export {
1571
2971
  resolveStreamRefs,
1572
2972
  rpcMethod,
1573
2973
  rpcService,
2974
+ serializeBinaryFrame,
2975
+ serializeBinaryMessage,
2976
+ serializeCompactBinaryMessage,
1574
2977
  serializeFrame,
1575
2978
  serializeMessage,
2979
+ splitBinaryFrame,
2980
+ splitCompactBinaryFrame,
1576
2981
  splitFrame,
1577
- wireMethodName
2982
+ wireMethodName,
2983
+ xxh3_64,
2984
+ xxh3_64str
1578
2985
  };
1579
2986
  //# sourceMappingURL=index.js.map