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