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