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