@naeemo/capnp 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -145,6 +145,12 @@ var Segment = class Segment {
145
145
  return new Uint8Array(this.buffer, 0, this._size);
146
146
  }
147
147
  /**
148
+ * 获取底层 ArrayBuffer
149
+ */
150
+ getArrayBuffer() {
151
+ return this.buffer;
152
+ }
153
+ /**
148
154
  * 获取字数量
149
155
  */
150
156
  get wordCount() {
@@ -825,21 +831,2219 @@ function createUnionBuilder(struct, tagOffset) {
825
831
  }
826
832
 
827
833
  //#endregion
834
+ //#region src/rpc/message-serializer.ts
835
+ /**
836
+ * RPC Message Serialization
837
+ *
838
+ * Implements full serialization/deserialization of RPC messages using
839
+ * the existing MessageBuilder/MessageReader infrastructure.
840
+ *
841
+ * Reference: rpc.capnp schema
842
+ */
843
+ const MSG_UNIMPLEMENTED = 0;
844
+ const MSG_ABORT = 1;
845
+ const MSG_BOOTSTRAP = 8;
846
+ const MSG_CALL = 2;
847
+ const MSG_RETURN = 3;
848
+ const MSG_FINISH = 4;
849
+ const MSG_RESOLVE = 5;
850
+ const MSG_RELEASE = 6;
851
+ const MSG_DISEMBARGO = 13;
852
+ const MSG_PROVIDE = 10;
853
+ const MSG_ACCEPT = 11;
854
+ const MSG_JOIN = 12;
855
+ const RET_RESULTS = 0;
856
+ const RET_EXCEPTION = 1;
857
+ const RET_CANCELED = 2;
858
+ const RET_RESULTS_SENT_ELSEWHERE = 3;
859
+ const RET_TAKE_FROM_OTHER_QUESTION = 4;
860
+ const RET_ACCEPT_FROM_THIRD_PARTY = 5;
861
+ const SEND_TO_CALLER = 0;
862
+ const SEND_TO_YOURSELF = 1;
863
+ const SEND_TO_THIRD_PARTY = 2;
864
+ const TARGET_IMPORTED_CAP = 0;
865
+ const TARGET_PROMISED_ANSWER = 1;
866
+ const CAP_NONE = 0;
867
+ const CAP_SENDER_HOSTED = 1;
868
+ const CAP_SENDER_PROMISE = 2;
869
+ const CAP_RECEIVER_HOSTED = 3;
870
+ const CAP_RECEIVER_ANSWER = 4;
871
+ const CAP_THIRD_PARTY_HOSTED = 5;
872
+ const RESOLVE_CAP = 0;
873
+ const RESOLVE_EXCEPTION = 1;
874
+ const DISEMBARGO_SENDER_LOOPBACK = 0;
875
+ const DISEMBARGO_RECEIVER_LOOPBACK = 1;
876
+ const DISEMBARGO_ACCEPT = 2;
877
+ const DISEMBARGO_PROVIDE = 3;
878
+ const OP_NOOP = 0;
879
+ const OP_GET_POINTER_FIELD = 1;
880
+ const EXC_FAILED = 0;
881
+ const EXC_OVERLOADED = 1;
882
+ const EXC_DISCONNECTED = 2;
883
+ const EXC_UNIMPLEMENTED = 3;
884
+ function serializeRpcMessage(message) {
885
+ const builder = new MessageBuilder();
886
+ const root = builder.initRoot(6, 1);
887
+ switch (message.type) {
888
+ case "unimplemented":
889
+ serializeUnimplemented(root, message.message);
890
+ break;
891
+ case "abort":
892
+ serializeAbort(root, message.exception);
893
+ break;
894
+ case "bootstrap":
895
+ serializeBootstrap(root, message.bootstrap);
896
+ break;
897
+ case "call":
898
+ serializeCall(root, message.call);
899
+ break;
900
+ case "return":
901
+ serializeReturn(root, message.return);
902
+ break;
903
+ case "finish":
904
+ serializeFinish(root, message.finish);
905
+ break;
906
+ case "resolve":
907
+ serializeResolve(root, message.resolve);
908
+ break;
909
+ case "release":
910
+ serializeRelease(root, message.release);
911
+ break;
912
+ case "disembargo":
913
+ serializeDisembargo(root, message.disembargo);
914
+ break;
915
+ case "provide":
916
+ serializeProvide(root, message.provide);
917
+ break;
918
+ case "accept":
919
+ serializeAccept(root, message.accept);
920
+ break;
921
+ case "join":
922
+ serializeJoin(root, message.join);
923
+ break;
924
+ }
925
+ return new Uint8Array(builder.toArrayBuffer());
926
+ }
927
+ function serializeUnimplemented(root, message) {
928
+ root.setUint16(0, MSG_UNIMPLEMENTED);
929
+ serializeRpcMessage(message);
930
+ root.initStruct(0, 0, 1).initStruct(0, 0, 0);
931
+ }
932
+ function serializeAbort(root, exception) {
933
+ root.setUint16(0, MSG_ABORT);
934
+ serializeException(root, 0, exception);
935
+ }
936
+ function serializeBootstrap(root, bootstrap) {
937
+ root.setUint16(0, MSG_BOOTSTRAP);
938
+ root.setUint32(8, bootstrap.questionId);
939
+ }
940
+ function serializeCall(root, call) {
941
+ root.setUint16(0, MSG_CALL);
942
+ root.setUint32(8, call.questionId);
943
+ root.setUint64(16, call.interfaceId);
944
+ root.setUint16(24, call.methodId);
945
+ root.setBool(208, call.allowThirdPartyTailCall);
946
+ root.setBool(209, call.noPromisePipelining);
947
+ root.setBool(210, call.onlyPromisePipeline);
948
+ serializeMessageTarget(root.initStruct(0, 2, 1), call.target);
949
+ serializePayload(root.initStruct(1, 2, 2), call.params);
950
+ serializeSendResultsTo(root.initStruct(2, 2, 1), call.sendResultsTo);
951
+ }
952
+ function serializeReturn(root, ret) {
953
+ root.setUint16(0, MSG_RETURN);
954
+ root.setUint32(8, ret.answerId);
955
+ root.setBool(192, ret.releaseParamCaps);
956
+ root.setBool(193, ret.noFinishNeeded);
957
+ switch (ret.result.type) {
958
+ case "results":
959
+ root.setUint16(2, RET_RESULTS);
960
+ serializePayload(root.initStruct(0, 2, 2), ret.result.payload);
961
+ break;
962
+ case "exception":
963
+ root.setUint16(2, RET_EXCEPTION);
964
+ serializeException(root, 0, ret.result.exception);
965
+ break;
966
+ case "canceled":
967
+ root.setUint16(2, RET_CANCELED);
968
+ break;
969
+ case "resultsSentElsewhere":
970
+ root.setUint16(2, RET_RESULTS_SENT_ELSEWHERE);
971
+ break;
972
+ case "takeFromOtherQuestion":
973
+ root.setUint16(2, RET_TAKE_FROM_OTHER_QUESTION);
974
+ root.setUint32(12, ret.result.questionId);
975
+ break;
976
+ case "acceptFromThirdParty":
977
+ root.setUint16(2, RET_ACCEPT_FROM_THIRD_PARTY);
978
+ break;
979
+ }
980
+ }
981
+ function serializeFinish(root, finish) {
982
+ root.setUint16(0, MSG_FINISH);
983
+ root.setUint32(8, finish.questionId);
984
+ root.setBool(192, finish.releaseResultCaps);
985
+ root.setBool(193, finish.requireEarlyCancellationWorkaround);
986
+ }
987
+ function serializeResolve(root, resolve) {
988
+ root.setUint16(0, MSG_RESOLVE);
989
+ root.setUint32(8, resolve.promiseId);
990
+ switch (resolve.resolution.type) {
991
+ case "cap":
992
+ root.setUint16(2, RESOLVE_CAP);
993
+ serializeCapDescriptor(root.initStruct(0, 2, 1), resolve.resolution.cap);
994
+ break;
995
+ case "exception":
996
+ root.setUint16(2, RESOLVE_EXCEPTION);
997
+ serializeException(root, 0, resolve.resolution.exception);
998
+ break;
999
+ }
1000
+ }
1001
+ function serializeRelease(root, release) {
1002
+ root.setUint16(0, MSG_RELEASE);
1003
+ root.setUint32(8, release.id);
1004
+ root.setUint32(12, release.referenceCount);
1005
+ }
1006
+ function serializeDisembargo(root, disembargo) {
1007
+ root.setUint16(0, MSG_DISEMBARGO);
1008
+ serializeMessageTarget(root.initStruct(0, 2, 1), disembargo.target);
1009
+ switch (disembargo.context.type) {
1010
+ case "senderLoopback":
1011
+ root.setUint16(2, DISEMBARGO_SENDER_LOOPBACK);
1012
+ root.setUint32(12, disembargo.context.embargoId);
1013
+ break;
1014
+ case "receiverLoopback":
1015
+ root.setUint16(2, DISEMBARGO_RECEIVER_LOOPBACK);
1016
+ root.setUint32(12, disembargo.context.embargoId);
1017
+ break;
1018
+ case "accept":
1019
+ root.setUint16(2, DISEMBARGO_ACCEPT);
1020
+ break;
1021
+ case "provide":
1022
+ root.setUint16(2, DISEMBARGO_PROVIDE);
1023
+ root.setUint32(12, disembargo.context.questionId);
1024
+ break;
1025
+ }
1026
+ }
1027
+ function serializeProvide(root, provide) {
1028
+ root.setUint16(0, MSG_PROVIDE);
1029
+ root.setUint32(8, provide.questionId);
1030
+ serializeMessageTarget(root.initStruct(0, 2, 1), provide.target);
1031
+ }
1032
+ function serializeAccept(_root, _accept) {}
1033
+ function serializeJoin(_root, _join) {}
1034
+ function serializeMessageTarget(builder, target) {
1035
+ switch (target.type) {
1036
+ case "importedCap":
1037
+ builder.setUint16(0, TARGET_IMPORTED_CAP);
1038
+ builder.setUint32(8, target.importId);
1039
+ break;
1040
+ case "promisedAnswer":
1041
+ builder.setUint16(0, TARGET_PROMISED_ANSWER);
1042
+ serializePromisedAnswer(builder.initStruct(0, 2, 1), target.promisedAnswer);
1043
+ break;
1044
+ }
1045
+ }
1046
+ function serializePromisedAnswer(builder, promisedAnswer) {
1047
+ builder.setUint32(0, promisedAnswer.questionId);
1048
+ if (promisedAnswer.transform.length > 0) {
1049
+ const listBuilder = builder.initList(0, ElementSize.INLINE_COMPOSITE, promisedAnswer.transform.length, {
1050
+ dataWords: 2,
1051
+ pointerCount: 0
1052
+ });
1053
+ for (let i = 0; i < promisedAnswer.transform.length; i++) serializePromisedAnswerOp(listBuilder.getStruct(i), promisedAnswer.transform[i]);
1054
+ }
1055
+ }
1056
+ function serializePromisedAnswerOp(builder, op) {
1057
+ switch (op.type) {
1058
+ case "noop":
1059
+ builder.setUint16(0, OP_NOOP);
1060
+ break;
1061
+ case "getPointerField":
1062
+ builder.setUint16(0, OP_GET_POINTER_FIELD);
1063
+ builder.setUint16(8, op.fieldIndex);
1064
+ break;
1065
+ }
1066
+ }
1067
+ function serializePayload(builder, payload) {
1068
+ if (payload.content.length > 0) builder.initStruct(0, Math.ceil(payload.content.length / 8), 0);
1069
+ if (payload.capTable.length > 0) {
1070
+ const listBuilder = builder.initList(1, ElementSize.EIGHT_BYTES, payload.capTable.length, {
1071
+ dataWords: 2,
1072
+ pointerCount: 1
1073
+ });
1074
+ for (let i = 0; i < payload.capTable.length; i++) serializeCapDescriptor(listBuilder.getStruct(i), payload.capTable[i]);
1075
+ }
1076
+ }
1077
+ function serializeCapDescriptor(builder, cap) {
1078
+ switch (cap.type) {
1079
+ case "none":
1080
+ builder.setUint16(0, CAP_NONE);
1081
+ break;
1082
+ case "senderHosted":
1083
+ builder.setUint16(0, CAP_SENDER_HOSTED);
1084
+ builder.setUint32(8, cap.exportId);
1085
+ break;
1086
+ case "senderPromise":
1087
+ builder.setUint16(0, CAP_SENDER_PROMISE);
1088
+ builder.setUint32(8, cap.exportId);
1089
+ break;
1090
+ case "receiverHosted":
1091
+ builder.setUint16(0, CAP_RECEIVER_HOSTED);
1092
+ builder.setUint32(8, cap.importId);
1093
+ break;
1094
+ case "receiverAnswer":
1095
+ builder.setUint16(0, CAP_RECEIVER_ANSWER);
1096
+ serializePromisedAnswer(builder.initStruct(0, 2, 1), cap.promisedAnswer);
1097
+ break;
1098
+ case "thirdPartyHosted":
1099
+ builder.setUint16(0, CAP_THIRD_PARTY_HOSTED);
1100
+ break;
1101
+ }
1102
+ }
1103
+ function serializeSendResultsTo(builder, sendTo) {
1104
+ switch (sendTo.type) {
1105
+ case "caller":
1106
+ builder.setUint16(0, SEND_TO_CALLER);
1107
+ break;
1108
+ case "yourself":
1109
+ builder.setUint16(0, SEND_TO_YOURSELF);
1110
+ break;
1111
+ case "thirdParty":
1112
+ builder.setUint16(0, SEND_TO_THIRD_PARTY);
1113
+ break;
1114
+ }
1115
+ }
1116
+ function serializeException(builder, pointerIndex, exception) {
1117
+ const excBuilder = builder.initStruct(pointerIndex, 2, 1);
1118
+ excBuilder.setText(0, exception.reason);
1119
+ switch (exception.type) {
1120
+ case "failed":
1121
+ excBuilder.setUint16(0, EXC_FAILED);
1122
+ break;
1123
+ case "overloaded":
1124
+ excBuilder.setUint16(0, EXC_OVERLOADED);
1125
+ break;
1126
+ case "disconnected":
1127
+ excBuilder.setUint16(0, EXC_DISCONNECTED);
1128
+ break;
1129
+ case "unimplemented":
1130
+ excBuilder.setUint16(0, EXC_UNIMPLEMENTED);
1131
+ break;
1132
+ }
1133
+ }
1134
+ function deserializeRpcMessage(data) {
1135
+ const root = new MessageReader(data).getRoot(6, 1);
1136
+ const unionTag = root.getUint16(0);
1137
+ switch (unionTag) {
1138
+ case MSG_UNIMPLEMENTED: return {
1139
+ type: "unimplemented",
1140
+ message: deserializeUnimplemented(root)
1141
+ };
1142
+ case MSG_ABORT: return {
1143
+ type: "abort",
1144
+ exception: deserializeException(root, 0)
1145
+ };
1146
+ case MSG_BOOTSTRAP: return {
1147
+ type: "bootstrap",
1148
+ bootstrap: deserializeBootstrap(root)
1149
+ };
1150
+ case MSG_CALL: return {
1151
+ type: "call",
1152
+ call: deserializeCall(root)
1153
+ };
1154
+ case MSG_RETURN: return {
1155
+ type: "return",
1156
+ return: deserializeReturn(root)
1157
+ };
1158
+ case MSG_FINISH: return {
1159
+ type: "finish",
1160
+ finish: deserializeFinish(root)
1161
+ };
1162
+ case MSG_RESOLVE: return {
1163
+ type: "resolve",
1164
+ resolve: deserializeResolve(root)
1165
+ };
1166
+ case MSG_RELEASE: return {
1167
+ type: "release",
1168
+ release: deserializeRelease(root)
1169
+ };
1170
+ case MSG_DISEMBARGO: return {
1171
+ type: "disembargo",
1172
+ disembargo: deserializeDisembargo(root)
1173
+ };
1174
+ case MSG_PROVIDE: return {
1175
+ type: "provide",
1176
+ provide: deserializeProvide(root)
1177
+ };
1178
+ case MSG_ACCEPT: return {
1179
+ type: "accept",
1180
+ accept: deserializeAccept(root)
1181
+ };
1182
+ case MSG_JOIN: return {
1183
+ type: "join",
1184
+ join: deserializeJoin(root)
1185
+ };
1186
+ default: throw new Error(`Unknown message union tag: ${unionTag}`);
1187
+ }
1188
+ }
1189
+ function deserializeUnimplemented(_root) {
1190
+ return {
1191
+ type: "abort",
1192
+ exception: {
1193
+ reason: "Unimplemented message received",
1194
+ type: "unimplemented"
1195
+ }
1196
+ };
1197
+ }
1198
+ function deserializeBootstrap(root) {
1199
+ return { questionId: root.getUint32(8) };
1200
+ }
1201
+ function deserializeCall(root) {
1202
+ const targetStruct = root.getStruct(0, 2, 1);
1203
+ const paramsStruct = root.getStruct(1, 2, 2);
1204
+ const sendToStruct = root.getStruct(2, 2, 1);
1205
+ return {
1206
+ questionId: root.getUint32(8),
1207
+ interfaceId: root.getUint64(16),
1208
+ methodId: root.getUint16(24),
1209
+ allowThirdPartyTailCall: root.getBool(208),
1210
+ noPromisePipelining: root.getBool(209),
1211
+ onlyPromisePipeline: root.getBool(210),
1212
+ target: targetStruct ? deserializeMessageTarget(targetStruct) : {
1213
+ type: "importedCap",
1214
+ importId: 0
1215
+ },
1216
+ params: paramsStruct ? deserializePayload(paramsStruct) : {
1217
+ content: new Uint8Array(0),
1218
+ capTable: []
1219
+ },
1220
+ sendResultsTo: sendToStruct ? deserializeSendResultsTo(sendToStruct) : { type: "caller" }
1221
+ };
1222
+ }
1223
+ function deserializeReturn(root) {
1224
+ const resultTag = root.getUint16(2);
1225
+ let result;
1226
+ switch (resultTag) {
1227
+ case RET_RESULTS:
1228
+ result = {
1229
+ type: "results",
1230
+ payload: root.getStruct(0, 2, 2) ? deserializePayload(root.getStruct(0, 2, 2)) : {
1231
+ content: new Uint8Array(0),
1232
+ capTable: []
1233
+ }
1234
+ };
1235
+ break;
1236
+ case RET_EXCEPTION:
1237
+ result = {
1238
+ type: "exception",
1239
+ exception: deserializeException(root, 0)
1240
+ };
1241
+ break;
1242
+ case RET_CANCELED:
1243
+ result = { type: "canceled" };
1244
+ break;
1245
+ case RET_RESULTS_SENT_ELSEWHERE:
1246
+ result = { type: "resultsSentElsewhere" };
1247
+ break;
1248
+ case RET_TAKE_FROM_OTHER_QUESTION:
1249
+ result = {
1250
+ type: "takeFromOtherQuestion",
1251
+ questionId: root.getUint32(12)
1252
+ };
1253
+ break;
1254
+ case RET_ACCEPT_FROM_THIRD_PARTY:
1255
+ result = {
1256
+ type: "acceptFromThirdParty",
1257
+ thirdPartyCapId: { id: new Uint8Array(0) }
1258
+ };
1259
+ break;
1260
+ default: result = { type: "canceled" };
1261
+ }
1262
+ return {
1263
+ answerId: root.getUint32(8),
1264
+ releaseParamCaps: root.getBool(192),
1265
+ noFinishNeeded: root.getBool(193),
1266
+ result
1267
+ };
1268
+ }
1269
+ function deserializeFinish(root) {
1270
+ return {
1271
+ questionId: root.getUint32(8),
1272
+ releaseResultCaps: root.getBool(192),
1273
+ requireEarlyCancellationWorkaround: root.getBool(193)
1274
+ };
1275
+ }
1276
+ function deserializeResolve(root) {
1277
+ const resolutionTag = root.getUint16(2);
1278
+ let resolution;
1279
+ switch (resolutionTag) {
1280
+ case RESOLVE_CAP:
1281
+ resolution = {
1282
+ type: "cap",
1283
+ cap: root.getStruct(0, 2, 1) ? deserializeCapDescriptor(root.getStruct(0, 2, 1)) : { type: "none" }
1284
+ };
1285
+ break;
1286
+ case RESOLVE_EXCEPTION:
1287
+ resolution = {
1288
+ type: "exception",
1289
+ exception: deserializeException(root, 0)
1290
+ };
1291
+ break;
1292
+ default: resolution = {
1293
+ type: "exception",
1294
+ exception: {
1295
+ reason: "Unknown resolution type",
1296
+ type: "failed"
1297
+ }
1298
+ };
1299
+ }
1300
+ return {
1301
+ promiseId: root.getUint32(8),
1302
+ resolution
1303
+ };
1304
+ }
1305
+ function deserializeRelease(root) {
1306
+ return {
1307
+ id: root.getUint32(8),
1308
+ referenceCount: root.getUint32(12)
1309
+ };
1310
+ }
1311
+ function deserializeDisembargo(root) {
1312
+ const targetStruct = root.getStruct(0, 2, 1);
1313
+ const contextTag = root.getUint16(2);
1314
+ let context;
1315
+ switch (contextTag) {
1316
+ case DISEMBARGO_SENDER_LOOPBACK:
1317
+ context = {
1318
+ type: "senderLoopback",
1319
+ embargoId: root.getUint32(12)
1320
+ };
1321
+ break;
1322
+ case DISEMBARGO_RECEIVER_LOOPBACK:
1323
+ context = {
1324
+ type: "receiverLoopback",
1325
+ embargoId: root.getUint32(12)
1326
+ };
1327
+ break;
1328
+ case DISEMBARGO_ACCEPT:
1329
+ context = { type: "accept" };
1330
+ break;
1331
+ case DISEMBARGO_PROVIDE:
1332
+ context = {
1333
+ type: "provide",
1334
+ questionId: root.getUint32(12)
1335
+ };
1336
+ break;
1337
+ default: context = { type: "accept" };
1338
+ }
1339
+ return {
1340
+ target: targetStruct ? deserializeMessageTarget(targetStruct) : {
1341
+ type: "importedCap",
1342
+ importId: 0
1343
+ },
1344
+ context
1345
+ };
1346
+ }
1347
+ function deserializeProvide(root) {
1348
+ const targetStruct = root.getStruct(0, 2, 1);
1349
+ return {
1350
+ questionId: root.getUint32(8),
1351
+ target: targetStruct ? deserializeMessageTarget(targetStruct) : {
1352
+ type: "importedCap",
1353
+ importId: 0
1354
+ },
1355
+ recipient: { id: new Uint8Array(0) }
1356
+ };
1357
+ }
1358
+ function deserializeAccept(_root) {
1359
+ return {
1360
+ questionId: 0,
1361
+ provision: { id: new Uint8Array(0) },
1362
+ embargo: false
1363
+ };
1364
+ }
1365
+ function deserializeJoin(_root) {
1366
+ return {
1367
+ questionId: 0,
1368
+ target: {
1369
+ type: "importedCap",
1370
+ importId: 0
1371
+ },
1372
+ otherCap: {
1373
+ type: "importedCap",
1374
+ importId: 0
1375
+ },
1376
+ joinId: 0
1377
+ };
1378
+ }
1379
+ function deserializeMessageTarget(root) {
1380
+ switch (root.getUint16(0)) {
1381
+ case TARGET_IMPORTED_CAP: return {
1382
+ type: "importedCap",
1383
+ importId: root.getUint32(8)
1384
+ };
1385
+ case TARGET_PROMISED_ANSWER: {
1386
+ const promisedAnswerStruct = root.getStruct(0, 2, 1);
1387
+ return {
1388
+ type: "promisedAnswer",
1389
+ promisedAnswer: promisedAnswerStruct ? deserializePromisedAnswer(promisedAnswerStruct) : {
1390
+ questionId: 0,
1391
+ transform: []
1392
+ }
1393
+ };
1394
+ }
1395
+ default: return {
1396
+ type: "importedCap",
1397
+ importId: 0
1398
+ };
1399
+ }
1400
+ }
1401
+ function deserializePromisedAnswer(root) {
1402
+ const transformList = root.getList(0, ElementSize.INLINE_COMPOSITE, {
1403
+ dataWords: 2,
1404
+ pointerCount: 0
1405
+ });
1406
+ const transform = [];
1407
+ if (transformList) for (let i = 0; i < transformList.length; i++) transform.push(deserializePromisedAnswerOp(transformList.getStruct(i)));
1408
+ return {
1409
+ questionId: root.getUint32(0),
1410
+ transform
1411
+ };
1412
+ }
1413
+ function deserializePromisedAnswerOp(root) {
1414
+ switch (root.getUint16(0)) {
1415
+ case OP_NOOP: return { type: "noop" };
1416
+ case OP_GET_POINTER_FIELD: return {
1417
+ type: "getPointerField",
1418
+ fieldIndex: root.getUint16(8)
1419
+ };
1420
+ default: return { type: "noop" };
1421
+ }
1422
+ }
1423
+ function deserializePayload(root) {
1424
+ const capTableList = root.getList(1, ElementSize.EIGHT_BYTES, {
1425
+ dataWords: 2,
1426
+ pointerCount: 1
1427
+ });
1428
+ const capTable = [];
1429
+ if (capTableList) for (let i = 0; i < capTableList.length; i++) capTable.push(deserializeCapDescriptor(capTableList.getStruct(i)));
1430
+ return {
1431
+ content: new Uint8Array(0),
1432
+ capTable
1433
+ };
1434
+ }
1435
+ function deserializeCapDescriptor(root) {
1436
+ switch (root.getUint16(0)) {
1437
+ case CAP_NONE: return { type: "none" };
1438
+ case CAP_SENDER_HOSTED: return {
1439
+ type: "senderHosted",
1440
+ exportId: root.getUint32(8)
1441
+ };
1442
+ case CAP_SENDER_PROMISE: return {
1443
+ type: "senderPromise",
1444
+ exportId: root.getUint32(8)
1445
+ };
1446
+ case CAP_RECEIVER_HOSTED: return {
1447
+ type: "receiverHosted",
1448
+ importId: root.getUint32(8)
1449
+ };
1450
+ case CAP_RECEIVER_ANSWER: {
1451
+ const promisedAnswerStruct = root.getStruct(0, 2, 1);
1452
+ return {
1453
+ type: "receiverAnswer",
1454
+ promisedAnswer: promisedAnswerStruct ? deserializePromisedAnswer(promisedAnswerStruct) : {
1455
+ questionId: 0,
1456
+ transform: []
1457
+ }
1458
+ };
1459
+ }
1460
+ case CAP_THIRD_PARTY_HOSTED: return {
1461
+ type: "thirdPartyHosted",
1462
+ thirdPartyCapId: { id: new Uint8Array(0) }
1463
+ };
1464
+ default: return { type: "none" };
1465
+ }
1466
+ }
1467
+ function deserializeSendResultsTo(root) {
1468
+ switch (root.getUint16(0)) {
1469
+ case SEND_TO_CALLER: return { type: "caller" };
1470
+ case SEND_TO_YOURSELF: return { type: "yourself" };
1471
+ case SEND_TO_THIRD_PARTY: return {
1472
+ type: "thirdParty",
1473
+ recipientId: { id: new Uint8Array(0) }
1474
+ };
1475
+ default: return { type: "caller" };
1476
+ }
1477
+ }
1478
+ function deserializeException(root, pointerIndex) {
1479
+ const excStruct = root.getStruct(pointerIndex, 2, 1);
1480
+ if (!excStruct) return {
1481
+ reason: "Unknown error",
1482
+ type: "failed"
1483
+ };
1484
+ const typeTag = excStruct.getUint16(0);
1485
+ let type;
1486
+ switch (typeTag) {
1487
+ case EXC_FAILED:
1488
+ type = "failed";
1489
+ break;
1490
+ case EXC_OVERLOADED:
1491
+ type = "overloaded";
1492
+ break;
1493
+ case EXC_DISCONNECTED:
1494
+ type = "disconnected";
1495
+ break;
1496
+ case EXC_UNIMPLEMENTED:
1497
+ type = "unimplemented";
1498
+ break;
1499
+ default: type = "failed";
1500
+ }
1501
+ return {
1502
+ reason: excStruct.getText(0),
1503
+ type
1504
+ };
1505
+ }
1506
+
1507
+ //#endregion
1508
+ //#region src/rpc/websocket-transport.ts
1509
+ /**
1510
+ * WebSocket Transport Implementation
1511
+ *
1512
+ * Implements RpcTransport over WebSocket for browser and Node.js compatibility.
1513
+ */
1514
+ var WebSocketTransport = class WebSocketTransport {
1515
+ ws = null;
1516
+ messageQueue = [];
1517
+ receiveQueue = [];
1518
+ _connected = false;
1519
+ pendingBuffer = null;
1520
+ pendingLength = 0;
1521
+ onClose;
1522
+ onError;
1523
+ constructor(url, options = {}) {
1524
+ this.options = options;
1525
+ this.connect(url);
1526
+ }
1527
+ static async connect(url, options) {
1528
+ const transport = new WebSocketTransport(url, options);
1529
+ await transport.waitForConnection();
1530
+ return transport;
1531
+ }
1532
+ static fromWebSocket(ws, options) {
1533
+ const transport = new WebSocketTransport("internal", options);
1534
+ transport.attachWebSocket(ws);
1535
+ return transport;
1536
+ }
1537
+ get connected() {
1538
+ return this._connected;
1539
+ }
1540
+ connect(url) {
1541
+ this.ws = new WebSocket(url);
1542
+ this.ws.binaryType = this.options.binaryType ?? "arraybuffer";
1543
+ this.ws.onopen = () => {
1544
+ this._connected = true;
1545
+ };
1546
+ this.ws.onmessage = (event) => {
1547
+ this.handleMessage(event.data);
1548
+ };
1549
+ this.ws.onclose = () => {
1550
+ this._connected = false;
1551
+ this.flushReceiveQueue(null);
1552
+ this.onClose?.();
1553
+ };
1554
+ this.ws.onerror = (_error) => {
1555
+ const err = /* @__PURE__ */ new Error("WebSocket error");
1556
+ this.onError?.(err);
1557
+ };
1558
+ }
1559
+ attachWebSocket(ws) {
1560
+ this.ws = ws;
1561
+ this.ws.binaryType = this.options.binaryType ?? "arraybuffer";
1562
+ this._connected = ws.readyState === WebSocket.OPEN;
1563
+ this.ws.onmessage = (event) => {
1564
+ this.handleMessage(event.data);
1565
+ };
1566
+ this.ws.onclose = () => {
1567
+ this._connected = false;
1568
+ this.flushReceiveQueue(null);
1569
+ this.onClose?.();
1570
+ };
1571
+ this.ws.onerror = (_error) => {
1572
+ const err = /* @__PURE__ */ new Error("WebSocket error");
1573
+ this.onError?.(err);
1574
+ };
1575
+ }
1576
+ waitForConnection() {
1577
+ return new Promise((resolve, reject) => {
1578
+ if (this._connected) {
1579
+ resolve();
1580
+ return;
1581
+ }
1582
+ const timeout = setTimeout(() => {
1583
+ reject(/* @__PURE__ */ new Error("Connection timeout"));
1584
+ }, this.options.connectTimeoutMs ?? 1e4);
1585
+ const checkConnection = () => {
1586
+ if (this._connected) {
1587
+ clearTimeout(timeout);
1588
+ resolve();
1589
+ } else if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
1590
+ clearTimeout(timeout);
1591
+ reject(/* @__PURE__ */ new Error("Connection failed"));
1592
+ } else setTimeout(checkConnection, 10);
1593
+ };
1594
+ checkConnection();
1595
+ });
1596
+ }
1597
+ handleMessage(data) {
1598
+ if (data instanceof ArrayBuffer) this.processBinaryMessage(new Uint8Array(data));
1599
+ else {
1600
+ const reader = new FileReader();
1601
+ reader.onload = () => {
1602
+ this.processBinaryMessage(new Uint8Array(reader.result));
1603
+ };
1604
+ reader.readAsArrayBuffer(data);
1605
+ }
1606
+ }
1607
+ processBinaryMessage(data) {
1608
+ let offset = 0;
1609
+ while (offset < data.length) if (this.pendingBuffer === null) {
1610
+ if (offset + 4 > data.length) {
1611
+ this.pendingBuffer = data.slice(offset);
1612
+ this.pendingLength = -1;
1613
+ break;
1614
+ }
1615
+ const length = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, true);
1616
+ offset += 4;
1617
+ if (offset + length > data.length) {
1618
+ this.pendingBuffer = data.slice(offset - 4);
1619
+ this.pendingLength = length;
1620
+ break;
1621
+ }
1622
+ const messageData = data.slice(offset, offset + length);
1623
+ offset += length;
1624
+ this.handleRpcMessage(messageData);
1625
+ } else if (this.pendingLength === -1) {
1626
+ const needed = 4 - this.pendingBuffer.length;
1627
+ if (data.length - offset < needed) {
1628
+ this.pendingBuffer = new Uint8Array([...this.pendingBuffer, ...data.slice(offset)]);
1629
+ break;
1630
+ }
1631
+ const tempBuffer = new Uint8Array(this.pendingBuffer.length + needed);
1632
+ tempBuffer.set(this.pendingBuffer);
1633
+ tempBuffer.set(data.slice(offset, offset + needed), this.pendingBuffer.length);
1634
+ this.pendingLength = new DataView(tempBuffer.buffer, 0, 4).getUint32(0, true);
1635
+ this.pendingBuffer = null;
1636
+ offset += needed;
1637
+ } else {
1638
+ const needed = this.pendingLength - this.pendingBuffer.length;
1639
+ if (data.length - offset < needed) {
1640
+ this.pendingBuffer = new Uint8Array([...this.pendingBuffer, ...data.slice(offset)]);
1641
+ break;
1642
+ }
1643
+ const messageData = new Uint8Array(this.pendingLength);
1644
+ messageData.set(this.pendingBuffer);
1645
+ messageData.set(data.slice(offset, offset + needed), this.pendingBuffer.length);
1646
+ offset += needed;
1647
+ this.pendingBuffer = null;
1648
+ this.handleRpcMessage(messageData);
1649
+ }
1650
+ }
1651
+ handleRpcMessage(data) {
1652
+ const message = this.deserializeMessage(data);
1653
+ if (this.receiveQueue.length > 0) {
1654
+ const { resolve } = this.receiveQueue.shift();
1655
+ resolve(message);
1656
+ } else this.messageQueue.push(message);
1657
+ }
1658
+ deserializeMessage(data) {
1659
+ return deserializeRpcMessage(data);
1660
+ }
1661
+ serializeMessage(message) {
1662
+ return serializeRpcMessage(message);
1663
+ }
1664
+ async send(message) {
1665
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error("WebSocket not connected");
1666
+ const data = this.serializeMessage(message);
1667
+ const frame = new Uint8Array(4 + data.length);
1668
+ new DataView(frame.buffer).setUint32(0, data.length, true);
1669
+ frame.set(data, 4);
1670
+ this.ws.send(frame);
1671
+ }
1672
+ async receive() {
1673
+ if (this.messageQueue.length > 0) return this.messageQueue.shift();
1674
+ if (!this._connected) return null;
1675
+ return new Promise((resolve, reject) => {
1676
+ this.receiveQueue.push({
1677
+ resolve,
1678
+ reject
1679
+ });
1680
+ });
1681
+ }
1682
+ close(reason) {
1683
+ this._connected = false;
1684
+ this.ws?.close();
1685
+ this.flushReceiveQueue(null);
1686
+ this.onClose?.(reason);
1687
+ }
1688
+ flushReceiveQueue(value) {
1689
+ while (this.receiveQueue.length > 0) {
1690
+ const { resolve } = this.receiveQueue.shift();
1691
+ resolve(value);
1692
+ }
1693
+ }
1694
+ };
1695
+
1696
+ //#endregion
1697
+ //#region src/rpc/four-tables.ts
1698
+ /** Manages the question table for outbound calls */
1699
+ var QuestionTable = class {
1700
+ questions = /* @__PURE__ */ new Map();
1701
+ nextId = 1;
1702
+ /** Create a new question entry */
1703
+ create() {
1704
+ const id = this.allocateId();
1705
+ let resolveCompletion;
1706
+ let rejectCompletion;
1707
+ const question = {
1708
+ id,
1709
+ isComplete: false,
1710
+ finishSent: false,
1711
+ completionPromise: new Promise((resolve, reject) => {
1712
+ resolveCompletion = resolve;
1713
+ rejectCompletion = reject;
1714
+ }),
1715
+ resolveCompletion,
1716
+ rejectCompletion
1717
+ };
1718
+ this.questions.set(id, question);
1719
+ return question;
1720
+ }
1721
+ /** Get a question by ID */
1722
+ get(id) {
1723
+ return this.questions.get(id);
1724
+ }
1725
+ /** Mark a question as complete */
1726
+ complete(id, result) {
1727
+ const question = this.questions.get(id);
1728
+ if (question && !question.isComplete) {
1729
+ question.isComplete = true;
1730
+ question.resolveCompletion(result);
1731
+ }
1732
+ }
1733
+ /** Mark a question as canceled */
1734
+ cancel(id, error) {
1735
+ const question = this.questions.get(id);
1736
+ if (question && !question.isComplete) {
1737
+ question.isComplete = true;
1738
+ question.rejectCompletion(error);
1739
+ }
1740
+ }
1741
+ /** Mark that Finish has been sent for a question */
1742
+ markFinishSent(id) {
1743
+ const question = this.questions.get(id);
1744
+ if (question) question.finishSent = true;
1745
+ }
1746
+ /** Remove a question from the table (when both sides are done) */
1747
+ remove(id) {
1748
+ const question = this.questions.get(id);
1749
+ if (question?.isComplete && question.finishSent) this.questions.delete(id);
1750
+ }
1751
+ /** Clean up all questions (e.g., on disconnect) */
1752
+ clear() {
1753
+ for (const question of this.questions.values()) if (!question.isComplete) question.rejectCompletion(/* @__PURE__ */ new Error("Connection closed"));
1754
+ this.questions.clear();
1755
+ this.nextId = 1;
1756
+ }
1757
+ allocateId() {
1758
+ return this.nextId++;
1759
+ }
1760
+ };
1761
+ /** Manages the answer table for inbound calls */
1762
+ var AnswerTable = class {
1763
+ answers = /* @__PURE__ */ new Map();
1764
+ /** Create a new answer entry */
1765
+ create(id) {
1766
+ const answer = {
1767
+ id,
1768
+ isComplete: false,
1769
+ returnSent: false,
1770
+ finishReceived: false
1771
+ };
1772
+ this.answers.set(id, answer);
1773
+ return answer;
1774
+ }
1775
+ /** Get an answer by ID */
1776
+ get(id) {
1777
+ return this.answers.get(id);
1778
+ }
1779
+ /** Mark that Return has been sent */
1780
+ markReturnSent(id) {
1781
+ const answer = this.answers.get(id);
1782
+ if (answer) answer.returnSent = true;
1783
+ }
1784
+ /** Mark that Finish has been received */
1785
+ markFinishReceived(id) {
1786
+ const answer = this.answers.get(id);
1787
+ if (answer) answer.finishReceived = true;
1788
+ }
1789
+ /** Remove an answer from the table (when both sides are done) */
1790
+ remove(id) {
1791
+ const answer = this.answers.get(id);
1792
+ if (answer?.returnSent && answer.finishReceived) this.answers.delete(id);
1793
+ }
1794
+ /** Clean up all answers (e.g., on disconnect) */
1795
+ clear() {
1796
+ this.answers.clear();
1797
+ }
1798
+ };
1799
+ /** Manages the import table for capabilities received from remote */
1800
+ var ImportTable = class {
1801
+ imports = /* @__PURE__ */ new Map();
1802
+ /** Add a new import */
1803
+ add(id, isPromise) {
1804
+ const importEntry = {
1805
+ id,
1806
+ refCount: 1,
1807
+ isPromise
1808
+ };
1809
+ this.imports.set(id, importEntry);
1810
+ return importEntry;
1811
+ }
1812
+ /** Get an import by ID */
1813
+ get(id) {
1814
+ return this.imports.get(id);
1815
+ }
1816
+ /** Increment reference count */
1817
+ addRef(id) {
1818
+ const importEntry = this.imports.get(id);
1819
+ if (importEntry) importEntry.refCount++;
1820
+ }
1821
+ /** Decrement reference count, returns true if refCount reached 0 */
1822
+ release(id, count) {
1823
+ const importEntry = this.imports.get(id);
1824
+ if (importEntry) {
1825
+ importEntry.refCount -= count;
1826
+ if (importEntry.refCount <= 0) {
1827
+ this.imports.delete(id);
1828
+ return true;
1829
+ }
1830
+ }
1831
+ return false;
1832
+ }
1833
+ /** Mark a promise as resolved */
1834
+ markResolved(id) {
1835
+ const importEntry = this.imports.get(id);
1836
+ if (importEntry) importEntry.isPromise = false;
1837
+ }
1838
+ /** Clean up all imports (e.g., on disconnect) */
1839
+ clear() {
1840
+ this.imports.clear();
1841
+ }
1842
+ };
1843
+ /** Manages the export table for capabilities sent to remote */
1844
+ var ExportTable = class {
1845
+ exports = /* @__PURE__ */ new Map();
1846
+ nextId = 1;
1847
+ /** Add a new export */
1848
+ add(capability, isPromise) {
1849
+ const id = this.allocateId();
1850
+ const exportEntry = {
1851
+ id,
1852
+ refCount: 1,
1853
+ isPromise,
1854
+ capability
1855
+ };
1856
+ this.exports.set(id, exportEntry);
1857
+ return exportEntry;
1858
+ }
1859
+ /** Get an export by ID */
1860
+ get(id) {
1861
+ return this.exports.get(id);
1862
+ }
1863
+ /** Increment reference count */
1864
+ addRef(id) {
1865
+ const exportEntry = this.exports.get(id);
1866
+ if (exportEntry) exportEntry.refCount++;
1867
+ }
1868
+ /** Decrement reference count, returns true if refCount reached 0 */
1869
+ release(id, count) {
1870
+ const exportEntry = this.exports.get(id);
1871
+ if (exportEntry) {
1872
+ exportEntry.refCount -= count;
1873
+ if (exportEntry.refCount <= 0) {
1874
+ this.exports.delete(id);
1875
+ return true;
1876
+ }
1877
+ }
1878
+ return false;
1879
+ }
1880
+ /** Mark a promise as resolved */
1881
+ markResolved(id) {
1882
+ const exportEntry = this.exports.get(id);
1883
+ if (exportEntry) exportEntry.isPromise = false;
1884
+ }
1885
+ /** Clean up all exports (e.g., on disconnect) */
1886
+ clear() {
1887
+ this.exports.clear();
1888
+ this.nextId = 1;
1889
+ }
1890
+ allocateId() {
1891
+ return this.nextId++;
1892
+ }
1893
+ };
1894
+
1895
+ //#endregion
1896
+ //#region src/rpc/pipeline.ts
1897
+ /**
1898
+ * Tracks a chain of operations to apply to a promised answer.
1899
+ * This forms the "transform" field in PromisedAnswer.
1900
+ */
1901
+ var PipelineOpTracker = class PipelineOpTracker {
1902
+ ops = [];
1903
+ /**
1904
+ * Add a no-op (use the result as-is)
1905
+ */
1906
+ addNoop() {
1907
+ this.ops.push({ type: "noop" });
1908
+ }
1909
+ /**
1910
+ * Add a pointer field access operation
1911
+ */
1912
+ addGetPointerField(fieldIndex) {
1913
+ this.ops.push({
1914
+ type: "getPointerField",
1915
+ fieldIndex
1916
+ });
1917
+ }
1918
+ /**
1919
+ * Get the current transform chain
1920
+ */
1921
+ getTransform() {
1922
+ return [...this.ops];
1923
+ }
1924
+ /**
1925
+ * Clone this tracker (for creating derived pipelines)
1926
+ */
1927
+ clone() {
1928
+ const cloned = new PipelineOpTracker();
1929
+ cloned.ops = [...this.ops];
1930
+ return cloned;
1931
+ }
1932
+ };
1933
+ /**
1934
+ * Symbol used to identify pipeline clients internally
1935
+ */
1936
+ const PIPELINE_CLIENT_SYMBOL = Symbol("PipelineClient");
1937
+ /**
1938
+ * Creates a PipelineClient using JavaScript Proxy.
1939
+ * The proxy intercepts property accesses to build up the transform chain.
1940
+ */
1941
+ function createPipelineClient(options) {
1942
+ const { connection, questionId, opTracker = new PipelineOpTracker() } = options;
1943
+ return {
1944
+ [PIPELINE_CLIENT_SYMBOL]: true,
1945
+ connection,
1946
+ questionId,
1947
+ opTracker,
1948
+ call(interfaceId, methodId, params) {
1949
+ return makePipelinedCall(connection, questionId, opTracker.getTransform(), interfaceId, methodId, params);
1950
+ },
1951
+ getPointerField(fieldIndex) {
1952
+ const newTracker = opTracker.clone();
1953
+ newTracker.addGetPointerField(fieldIndex);
1954
+ return createPipelineClient({
1955
+ connection,
1956
+ questionId,
1957
+ opTracker: newTracker
1958
+ });
1959
+ }
1960
+ };
1961
+ }
1962
+ /**
1963
+ * Check if a value is a PipelineClient
1964
+ */
1965
+ function isPipelineClient(value) {
1966
+ return typeof value === "object" && value !== null && PIPELINE_CLIENT_SYMBOL in value;
1967
+ }
1968
+ /**
1969
+ * Makes a call on a promised answer (pipeline call).
1970
+ * This sends a Call message with target.type = 'promisedAnswer'.
1971
+ */
1972
+ async function makePipelinedCall(connection, questionId, transform, interfaceId, methodId, params) {
1973
+ const newQuestionId = connection.createQuestion();
1974
+ const call = {
1975
+ questionId: newQuestionId,
1976
+ target: {
1977
+ type: "promisedAnswer",
1978
+ promisedAnswer: {
1979
+ questionId,
1980
+ transform
1981
+ }
1982
+ },
1983
+ interfaceId,
1984
+ methodId,
1985
+ allowThirdPartyTailCall: false,
1986
+ noPromisePipelining: false,
1987
+ onlyPromisePipeline: false,
1988
+ params,
1989
+ sendResultsTo: { type: "caller" }
1990
+ };
1991
+ await connection.sendCall(call);
1992
+ return connection.waitForAnswer(newQuestionId);
1993
+ }
1994
+ /**
1995
+ * Manages calls that were made on a pipeline client before the answer arrived.
1996
+ * When the answer arrives, these calls are dispatched to the actual capability.
1997
+ */
1998
+ var QueuedCallManager = class {
1999
+ queuedCalls = /* @__PURE__ */ new Map();
2000
+ /**
2001
+ * Queue a call for when the promise resolves
2002
+ */
2003
+ queueCall(questionId, call) {
2004
+ const calls = this.queuedCalls.get(questionId) ?? [];
2005
+ calls.push(call);
2006
+ this.queuedCalls.set(questionId, calls);
2007
+ }
2008
+ /**
2009
+ * Get and clear all queued calls for a question
2010
+ */
2011
+ dequeueCalls(questionId) {
2012
+ const calls = this.queuedCalls.get(questionId) ?? [];
2013
+ this.queuedCalls.delete(questionId);
2014
+ return calls;
2015
+ }
2016
+ /**
2017
+ * Check if there are queued calls for a question
2018
+ */
2019
+ hasQueuedCalls(questionId) {
2020
+ return (this.queuedCalls.get(questionId)?.length ?? 0) > 0;
2021
+ }
2022
+ /**
2023
+ * Clear all queued calls (e.g., on disconnect)
2024
+ */
2025
+ clear() {
2026
+ for (const calls of this.queuedCalls.values()) for (const call of calls) call.reject(/* @__PURE__ */ new Error("Connection closed"));
2027
+ this.queuedCalls.clear();
2028
+ }
2029
+ };
2030
+ /**
2031
+ * Tracks pending pipeline resolutions
2032
+ */
2033
+ var PipelineResolutionTracker = class {
2034
+ pendingResolutions = /* @__PURE__ */ new Map();
2035
+ /**
2036
+ * Mark a question as resolved to a capability
2037
+ */
2038
+ resolveToCapability(questionId, importId) {
2039
+ this.pendingResolutions.set(questionId, {
2040
+ type: "capability",
2041
+ importId
2042
+ });
2043
+ }
2044
+ /**
2045
+ * Mark a question as resolved to an exception
2046
+ */
2047
+ resolveToException(questionId, reason) {
2048
+ this.pendingResolutions.set(questionId, {
2049
+ type: "exception",
2050
+ reason
2051
+ });
2052
+ }
2053
+ /**
2054
+ * Get the resolution for a question (if available)
2055
+ */
2056
+ getResolution(questionId) {
2057
+ return this.pendingResolutions.get(questionId);
2058
+ }
2059
+ /**
2060
+ * Check if a question has been resolved
2061
+ */
2062
+ isResolved(questionId) {
2063
+ return this.pendingResolutions.has(questionId);
2064
+ }
2065
+ /**
2066
+ * Remove a resolution entry
2067
+ */
2068
+ remove(questionId) {
2069
+ this.pendingResolutions.delete(questionId);
2070
+ }
2071
+ /**
2072
+ * Clear all resolutions
2073
+ */
2074
+ clear() {
2075
+ this.pendingResolutions.clear();
2076
+ }
2077
+ };
2078
+
2079
+ //#endregion
2080
+ //#region src/rpc/rpc-connection.ts
2081
+ /**
2082
+ * RpcConnection
2083
+ *
2084
+ * Manages a single RPC connection, handling message routing and the Four Tables.
2085
+ * This is the core of the RPC implementation.
2086
+ *
2087
+ * Phase 2 Updates:
2088
+ * - Added Promise Pipelining support
2089
+ * - Added capability passing
2090
+ * - Added Resolve/Release/Disembargo message handling
2091
+ */
2092
+ var RpcConnection = class {
2093
+ transport;
2094
+ options;
2095
+ questions = new QuestionTable();
2096
+ answers = new AnswerTable();
2097
+ imports = new ImportTable();
2098
+ exports = new ExportTable();
2099
+ queuedCalls = new QueuedCallManager();
2100
+ pipelineResolutions = new PipelineResolutionTracker();
2101
+ running = false;
2102
+ messageHandler;
2103
+ constructor(transport, options = {}) {
2104
+ this.transport = transport;
2105
+ this.options = options;
2106
+ this.transport.onClose = (reason) => {
2107
+ this.handleDisconnect(reason);
2108
+ };
2109
+ this.transport.onError = (error) => {
2110
+ this.handleError(error);
2111
+ };
2112
+ }
2113
+ /** Start processing messages */
2114
+ async start() {
2115
+ if (this.running) return;
2116
+ this.running = true;
2117
+ this.messageHandler = this.messageLoop();
2118
+ }
2119
+ /** Stop the connection */
2120
+ async stop() {
2121
+ this.running = false;
2122
+ this.transport.close();
2123
+ if (this.messageHandler) try {
2124
+ await this.messageHandler;
2125
+ } catch {}
2126
+ }
2127
+ /** Send a bootstrap request and return the bootstrap capability */
2128
+ async bootstrap() {
2129
+ const question = this.questions.create();
2130
+ const bootstrapMsg = {
2131
+ type: "bootstrap",
2132
+ bootstrap: { questionId: question.id }
2133
+ };
2134
+ await this.transport.send(bootstrapMsg);
2135
+ await question.completionPromise;
2136
+ return {};
2137
+ }
2138
+ /** Make a call to a remote capability */
2139
+ async call(target, interfaceId, methodId, params) {
2140
+ if (isPipelineClient(target)) return target.call(interfaceId, methodId, params);
2141
+ const question = this.questions.create();
2142
+ const callMsg = {
2143
+ type: "call",
2144
+ call: {
2145
+ questionId: question.id,
2146
+ target: {
2147
+ type: "importedCap",
2148
+ importId: target
2149
+ },
2150
+ interfaceId,
2151
+ methodId,
2152
+ allowThirdPartyTailCall: false,
2153
+ noPromisePipelining: false,
2154
+ onlyPromisePipeline: false,
2155
+ params,
2156
+ sendResultsTo: { type: "caller" }
2157
+ }
2158
+ };
2159
+ await this.transport.send(callMsg);
2160
+ return question.completionPromise;
2161
+ }
2162
+ /**
2163
+ * Make a call that returns a PipelineClient for promise pipelining.
2164
+ * This allows making calls on the result before it arrives.
2165
+ */
2166
+ async callPipelined(target, interfaceId, methodId, params) {
2167
+ const question = this.questions.create();
2168
+ const callMsg = {
2169
+ type: "call",
2170
+ call: {
2171
+ questionId: question.id,
2172
+ target: {
2173
+ type: "importedCap",
2174
+ importId: target
2175
+ },
2176
+ interfaceId,
2177
+ methodId,
2178
+ allowThirdPartyTailCall: false,
2179
+ noPromisePipelining: false,
2180
+ onlyPromisePipeline: false,
2181
+ params,
2182
+ sendResultsTo: { type: "caller" }
2183
+ }
2184
+ };
2185
+ await this.transport.send(callMsg);
2186
+ return createPipelineClient({
2187
+ connection: this,
2188
+ questionId: question.id
2189
+ });
2190
+ }
2191
+ /** Send a finish message to release a question */
2192
+ async finish(questionId, releaseResultCaps = true) {
2193
+ if (!this.questions.get(questionId)) return;
2194
+ const finishMsg = {
2195
+ type: "finish",
2196
+ finish: {
2197
+ questionId,
2198
+ releaseResultCaps,
2199
+ requireEarlyCancellationWorkaround: false
2200
+ }
2201
+ };
2202
+ await this.transport.send(finishMsg);
2203
+ this.questions.markFinishSent(questionId);
2204
+ this.questions.remove(questionId);
2205
+ }
2206
+ /** Send a release message for an imported capability */
2207
+ async release(importId, referenceCount = 1) {
2208
+ const releaseMsg = {
2209
+ type: "release",
2210
+ release: {
2211
+ id: importId,
2212
+ referenceCount
2213
+ }
2214
+ };
2215
+ await this.transport.send(releaseMsg);
2216
+ }
2217
+ /** Send a resolve message to indicate a promise has resolved */
2218
+ async resolve(promiseId, cap) {
2219
+ const resolveMsg = {
2220
+ type: "resolve",
2221
+ resolve: {
2222
+ promiseId,
2223
+ resolution: {
2224
+ type: "cap",
2225
+ cap
2226
+ }
2227
+ }
2228
+ };
2229
+ await this.transport.send(resolveMsg);
2230
+ }
2231
+ /** Send a resolve message indicating a promise was broken */
2232
+ async resolveException(promiseId, reason) {
2233
+ const resolveMsg = {
2234
+ type: "resolve",
2235
+ resolve: {
2236
+ promiseId,
2237
+ resolution: {
2238
+ type: "exception",
2239
+ exception: {
2240
+ reason,
2241
+ type: "failed"
2242
+ }
2243
+ }
2244
+ }
2245
+ };
2246
+ await this.transport.send(resolveMsg);
2247
+ }
2248
+ /** Internal method: Create a new question (used by pipeline) */
2249
+ createQuestion() {
2250
+ return this.questions.create().id;
2251
+ }
2252
+ /** Internal method: Send a call message (used by pipeline) */
2253
+ async sendCall(call) {
2254
+ const callMsg = {
2255
+ type: "call",
2256
+ call
2257
+ };
2258
+ await this.transport.send(callMsg);
2259
+ }
2260
+ /** Internal method: Wait for an answer (used by pipeline) */
2261
+ async waitForAnswer(questionId) {
2262
+ const question = this.questions.get(questionId);
2263
+ if (!question) throw new Error(`Question ${questionId} not found`);
2264
+ return question.completionPromise;
2265
+ }
2266
+ /** Main message processing loop */
2267
+ async messageLoop() {
2268
+ while (this.running) try {
2269
+ const message = await this.transport.receive();
2270
+ if (message === null) break;
2271
+ await this.handleMessage(message);
2272
+ } catch (error) {
2273
+ if (this.running) this.handleError(error);
2274
+ }
2275
+ }
2276
+ /** Handle incoming messages */
2277
+ async handleMessage(message) {
2278
+ switch (message.type) {
2279
+ case "bootstrap":
2280
+ await this.handleBootstrap(message.bootstrap);
2281
+ break;
2282
+ case "call":
2283
+ await this.handleCall(message.call);
2284
+ break;
2285
+ case "return":
2286
+ await this.handleReturn(message.return);
2287
+ break;
2288
+ case "finish":
2289
+ await this.handleFinish(message.finish);
2290
+ break;
2291
+ case "resolve":
2292
+ await this.handleResolve(message.resolve);
2293
+ break;
2294
+ case "release":
2295
+ await this.handleRelease(message.release);
2296
+ break;
2297
+ case "disembargo":
2298
+ await this.handleDisembargo(message.disembargo);
2299
+ break;
2300
+ case "abort":
2301
+ this.handleAbort(message.exception.reason);
2302
+ break;
2303
+ case "unimplemented": break;
2304
+ default: await this.sendUnimplemented(message);
2305
+ }
2306
+ }
2307
+ /** Handle bootstrap request */
2308
+ async handleBootstrap(bootstrap) {
2309
+ this.answers.create(bootstrap.questionId);
2310
+ const returnMsg = {
2311
+ type: "return",
2312
+ return: {
2313
+ answerId: bootstrap.questionId,
2314
+ releaseParamCaps: true,
2315
+ noFinishNeeded: false,
2316
+ result: {
2317
+ type: "results",
2318
+ payload: {
2319
+ content: new Uint8Array(0),
2320
+ capTable: []
2321
+ }
2322
+ }
2323
+ }
2324
+ };
2325
+ await this.transport.send(returnMsg);
2326
+ this.answers.markReturnSent(bootstrap.questionId);
2327
+ }
2328
+ /** Handle incoming call */
2329
+ async handleCall(call) {
2330
+ this.answers.create(call.questionId);
2331
+ const returnMsg = {
2332
+ type: "return",
2333
+ return: {
2334
+ answerId: call.questionId,
2335
+ releaseParamCaps: true,
2336
+ noFinishNeeded: false,
2337
+ result: {
2338
+ type: "exception",
2339
+ exception: {
2340
+ reason: "Method not implemented",
2341
+ type: "unimplemented"
2342
+ }
2343
+ }
2344
+ }
2345
+ };
2346
+ await this.transport.send(returnMsg);
2347
+ this.answers.markReturnSent(call.questionId);
2348
+ }
2349
+ /** Handle return message */
2350
+ async handleReturn(ret) {
2351
+ if (!this.questions.get(ret.answerId)) return;
2352
+ if (ret.result.type === "results") {
2353
+ const capTable = ret.result.payload.capTable;
2354
+ if (capTable.length > 0) {
2355
+ const cap = capTable[0];
2356
+ if (cap.type === "receiverHosted") this.pipelineResolutions.resolveToCapability(ret.answerId, cap.importId);
2357
+ }
2358
+ } else if (ret.result.type === "exception") this.pipelineResolutions.resolveToException(ret.answerId, ret.result.exception.reason);
2359
+ switch (ret.result.type) {
2360
+ case "results":
2361
+ this.questions.complete(ret.answerId, ret.result.payload);
2362
+ break;
2363
+ case "exception":
2364
+ this.questions.cancel(ret.answerId, new Error(ret.result.exception.reason));
2365
+ break;
2366
+ case "canceled":
2367
+ this.questions.cancel(ret.answerId, /* @__PURE__ */ new Error("Call canceled"));
2368
+ break;
2369
+ default: this.questions.cancel(ret.answerId, /* @__PURE__ */ new Error("Unknown return type"));
2370
+ }
2371
+ }
2372
+ /** Handle finish message */
2373
+ async handleFinish(finish) {
2374
+ this.answers.markFinishReceived(finish.questionId);
2375
+ this.answers.remove(finish.questionId);
2376
+ }
2377
+ /** Handle resolve message (Level 1) */
2378
+ async handleResolve(resolve) {
2379
+ const { promiseId, resolution } = resolve;
2380
+ switch (resolution.type) {
2381
+ case "cap":
2382
+ this.imports.markResolved(promiseId);
2383
+ break;
2384
+ case "exception":
2385
+ console.warn(`Promise ${promiseId} broken: ${resolution.exception.reason}`);
2386
+ break;
2387
+ }
2388
+ }
2389
+ /** Handle release message (Level 1) */
2390
+ async handleRelease(release) {
2391
+ const { id, referenceCount } = release;
2392
+ if (this.exports.release(id, referenceCount)) console.log(`Export ${id} fully released`);
2393
+ }
2394
+ /** Handle disembargo message (Level 1) */
2395
+ async handleDisembargo(disembargo) {
2396
+ const { target, context } = disembargo;
2397
+ if (context.type === "senderLoopback") {
2398
+ const echoMsg = {
2399
+ type: "disembargo",
2400
+ disembargo: {
2401
+ target,
2402
+ context: {
2403
+ type: "receiverLoopback",
2404
+ embargoId: context.embargoId
2405
+ }
2406
+ }
2407
+ };
2408
+ await this.transport.send(echoMsg);
2409
+ }
2410
+ }
2411
+ /** Handle abort message */
2412
+ handleAbort(_reason) {
2413
+ this.running = false;
2414
+ this.questions.clear();
2415
+ this.answers.clear();
2416
+ this.imports.clear();
2417
+ this.exports.clear();
2418
+ this.queuedCalls.clear();
2419
+ this.pipelineResolutions.clear();
2420
+ }
2421
+ /** Handle disconnect */
2422
+ handleDisconnect(_reason) {
2423
+ this.running = false;
2424
+ this.questions.clear();
2425
+ this.answers.clear();
2426
+ this.imports.clear();
2427
+ this.exports.clear();
2428
+ this.queuedCalls.clear();
2429
+ this.pipelineResolutions.clear();
2430
+ }
2431
+ /** Handle error */
2432
+ handleError(error) {
2433
+ console.error("RPC error:", error);
2434
+ }
2435
+ /** Send unimplemented response */
2436
+ async sendUnimplemented(originalMessage) {
2437
+ const msg = {
2438
+ type: "unimplemented",
2439
+ message: originalMessage
2440
+ };
2441
+ await this.transport.send(msg);
2442
+ }
2443
+ /** Import a capability from the remote peer */
2444
+ importCapability(importId, isPromise = false) {
2445
+ this.imports.add(importId, isPromise);
2446
+ }
2447
+ /** Export a capability to the remote peer */
2448
+ exportCapability(capability, isPromise = false) {
2449
+ return this.exports.add(capability, isPromise).id;
2450
+ }
2451
+ /** Get an imported capability */
2452
+ getImport(importId) {
2453
+ return this.imports.get(importId);
2454
+ }
2455
+ /** Get an exported capability */
2456
+ getExport(exportId) {
2457
+ return this.exports.get(exportId);
2458
+ }
2459
+ };
2460
+
2461
+ //#endregion
2462
+ //#region src/rpc/capability-client.ts
2463
+ /** Base class for capability client implementations */
2464
+ var BaseCapabilityClient = class {
2465
+ constructor(connection, importId) {
2466
+ this.connection = connection;
2467
+ this.importId = importId;
2468
+ }
2469
+ isValid() {
2470
+ return true;
2471
+ }
2472
+ release() {
2473
+ if (this.importId !== void 0) this.connection.release(this.importId, 1);
2474
+ }
2475
+ /** Make a method call on this capability and return a PipelineClient */
2476
+ _call(_interfaceId, _methodId, params) {
2477
+ if (!this.importId) throw new Error("Cannot call method on capability without import ID");
2478
+ this.serializeParams(params);
2479
+ throw new Error("Use _callAsync instead for async call support");
2480
+ }
2481
+ /** Make an async method call on this capability */
2482
+ async _callAsync(interfaceId, methodId, params) {
2483
+ if (!this.importId) throw new Error("Cannot call method on capability without import ID");
2484
+ const payload = this.serializeParams(params);
2485
+ return this.connection.callPipelined(this.importId, interfaceId, methodId, payload);
2486
+ }
2487
+ /** Serialize parameters to Payload */
2488
+ serializeParams(_params) {
2489
+ return {
2490
+ content: new Uint8Array(),
2491
+ capTable: []
2492
+ };
2493
+ }
2494
+ };
2495
+
2496
+ //#endregion
2497
+ //#region src/rpc/sturdyrefs.ts
2498
+ /**
2499
+ * Manages SturdyRefs on the server side.
2500
+ * Stores the mapping between SturdyRef tokens and live capabilities.
2501
+ */
2502
+ var SturdyRefManager = class {
2503
+ vatId;
2504
+ storedRefs = /* @__PURE__ */ new Map();
2505
+ localIdCounter = 0;
2506
+ constructor(vatId) {
2507
+ this.vatId = vatId;
2508
+ }
2509
+ /**
2510
+ * Save a capability as a SturdyRef
2511
+ */
2512
+ saveCapability(capability, exportId, options) {
2513
+ const localId = options?.localId ?? this.generateLocalId();
2514
+ const now = Date.now();
2515
+ const ref = {
2516
+ vatId: this.vatId,
2517
+ localId,
2518
+ version: 1,
2519
+ expiresAt: options?.ttlMs ? now + options.ttlMs : void 0,
2520
+ metadata: options?.metadata
2521
+ };
2522
+ const stored = {
2523
+ ref,
2524
+ exportId,
2525
+ capability,
2526
+ createdAt: now,
2527
+ lastAccessedAt: now
2528
+ };
2529
+ this.storedRefs.set(localId, stored);
2530
+ return ref;
2531
+ }
2532
+ /**
2533
+ * Restore a capability from a SturdyRef token
2534
+ */
2535
+ restoreCapability(ref) {
2536
+ if (ref.vatId !== this.vatId) {
2537
+ console.warn(`SturdyRef vatId mismatch: ${ref.vatId} !== ${this.vatId}`);
2538
+ return null;
2539
+ }
2540
+ const stored = this.storedRefs.get(ref.localId);
2541
+ if (!stored) {
2542
+ console.warn(`SturdyRef not found: ${ref.localId}`);
2543
+ return null;
2544
+ }
2545
+ if (stored.ref.expiresAt && Date.now() > stored.ref.expiresAt) {
2546
+ console.warn(`SturdyRef expired: ${ref.localId}`);
2547
+ this.storedRefs.delete(ref.localId);
2548
+ return null;
2549
+ }
2550
+ stored.lastAccessedAt = Date.now();
2551
+ return {
2552
+ capability: stored.capability,
2553
+ exportId: stored.exportId
2554
+ };
2555
+ }
2556
+ /**
2557
+ * Drop a SturdyRef
2558
+ */
2559
+ dropSturdyRef(localId) {
2560
+ return this.storedRefs.delete(localId);
2561
+ }
2562
+ /**
2563
+ * Get all active SturdyRefs
2564
+ */
2565
+ getActiveRefs() {
2566
+ const now = Date.now();
2567
+ const active = [];
2568
+ for (const [localId, stored] of this.storedRefs) {
2569
+ if (stored.ref.expiresAt && now > stored.ref.expiresAt) {
2570
+ this.storedRefs.delete(localId);
2571
+ continue;
2572
+ }
2573
+ active.push(stored.ref);
2574
+ }
2575
+ return active;
2576
+ }
2577
+ /**
2578
+ * Clean up expired SturdyRefs
2579
+ */
2580
+ cleanupExpired() {
2581
+ const now = Date.now();
2582
+ let cleaned = 0;
2583
+ for (const [localId, stored] of this.storedRefs) if (stored.ref.expiresAt && now > stored.ref.expiresAt) {
2584
+ this.storedRefs.delete(localId);
2585
+ cleaned++;
2586
+ }
2587
+ return cleaned;
2588
+ }
2589
+ generateLocalId() {
2590
+ return `ref-${++this.localIdCounter}-${Date.now()}`;
2591
+ }
2592
+ };
2593
+ /**
2594
+ * Handles Restore messages on the client side.
2595
+ * Manages reconnecting to capabilities after disconnections.
2596
+ */
2597
+ var RestoreHandler = class {
2598
+ connection;
2599
+ pendingRestores = /* @__PURE__ */ new Map();
2600
+ questionIdCounter = 0;
2601
+ constructor(connection) {
2602
+ this.connection = connection;
2603
+ }
2604
+ /**
2605
+ * Send a Restore message to restore a capability from a SturdyRef
2606
+ */
2607
+ async restore(ref, options) {
2608
+ const questionId = ++this.questionIdCounter;
2609
+ const timeoutMs = options?.timeoutMs ?? 3e4;
2610
+ return new Promise((resolve, reject) => {
2611
+ const timeout = setTimeout(() => {
2612
+ this.pendingRestores.delete(questionId);
2613
+ reject(/* @__PURE__ */ new Error(`Restore timeout after ${timeoutMs}ms`));
2614
+ }, timeoutMs);
2615
+ this.pendingRestores.set(questionId, {
2616
+ resolve,
2617
+ reject,
2618
+ timeout
2619
+ });
2620
+ this.sendRestoreMessage(questionId, ref).catch((error) => {
2621
+ clearTimeout(timeout);
2622
+ this.pendingRestores.delete(questionId);
2623
+ reject(error);
2624
+ });
2625
+ });
2626
+ }
2627
+ /**
2628
+ * Handle a Restore response
2629
+ */
2630
+ handleRestoreResponse(questionId, importId) {
2631
+ const pending = this.pendingRestores.get(questionId);
2632
+ if (pending) {
2633
+ clearTimeout(pending.timeout);
2634
+ this.pendingRestores.delete(questionId);
2635
+ pending.resolve(importId);
2636
+ }
2637
+ }
2638
+ /**
2639
+ * Handle a Restore failure
2640
+ */
2641
+ handleRestoreFailure(questionId, reason) {
2642
+ const pending = this.pendingRestores.get(questionId);
2643
+ if (pending) {
2644
+ clearTimeout(pending.timeout);
2645
+ this.pendingRestores.delete(questionId);
2646
+ pending.reject(/* @__PURE__ */ new Error(`Restore failed: ${reason}`));
2647
+ }
2648
+ }
2649
+ /**
2650
+ * Cancel all pending restores (e.g., on disconnect)
2651
+ */
2652
+ cancelAll(reason) {
2653
+ for (const [_questionId, pending] of this.pendingRestores) {
2654
+ clearTimeout(pending.timeout);
2655
+ pending.reject(/* @__PURE__ */ new Error(`Restore canceled: ${reason}`));
2656
+ }
2657
+ this.pendingRestores.clear();
2658
+ }
2659
+ async sendRestoreMessage(questionId, ref) {
2660
+ const refData = JSON.stringify(ref);
2661
+ const restoreMsg = {
2662
+ type: "call",
2663
+ call: {
2664
+ questionId,
2665
+ target: {
2666
+ type: "importedCap",
2667
+ importId: 0
2668
+ },
2669
+ interfaceId: BigInt("0xffffffffffffffff"),
2670
+ methodId: 0,
2671
+ allowThirdPartyTailCall: false,
2672
+ noPromisePipelining: false,
2673
+ onlyPromisePipeline: false,
2674
+ params: {
2675
+ content: new TextEncoder().encode(refData),
2676
+ capTable: []
2677
+ },
2678
+ sendResultsTo: { type: "caller" }
2679
+ }
2680
+ };
2681
+ console.log("Sending restore message:", restoreMsg);
2682
+ }
2683
+ };
2684
+ /**
2685
+ * Serialize a SturdyRef to a string for storage
2686
+ */
2687
+ function serializeSturdyRef(ref) {
2688
+ return JSON.stringify(ref);
2689
+ }
2690
+ /**
2691
+ * Deserialize a SturdyRef from a string
2692
+ */
2693
+ function deserializeSturdyRef(data) {
2694
+ try {
2695
+ const parsed = JSON.parse(data);
2696
+ if (typeof parsed.vatId !== "string" || typeof parsed.localId !== "string") return null;
2697
+ return {
2698
+ vatId: parsed.vatId,
2699
+ localId: parsed.localId,
2700
+ version: parsed.version,
2701
+ expiresAt: parsed.expiresAt,
2702
+ metadata: parsed.metadata
2703
+ };
2704
+ } catch {
2705
+ return null;
2706
+ }
2707
+ }
2708
+ /**
2709
+ * Check if a SturdyRef is valid (not expired)
2710
+ */
2711
+ function isSturdyRefValid(ref) {
2712
+ if (ref.expiresAt && Date.now() > ref.expiresAt) return false;
2713
+ return true;
2714
+ }
2715
+ /**
2716
+ * Create a SturdyRef from components
2717
+ */
2718
+ function createSturdyRef(vatId, localId, options) {
2719
+ return {
2720
+ vatId,
2721
+ localId,
2722
+ version: 1,
2723
+ expiresAt: options?.ttlMs ? Date.now() + options.ttlMs : void 0,
2724
+ metadata: options?.metadata
2725
+ };
2726
+ }
2727
+
2728
+ //#endregion
2729
+ //#region src/rpc/performance.ts
2730
+ /**
2731
+ * Performance Optimizations for RPC
2732
+ *
2733
+ * Phase 3: Performance improvements
2734
+ * - Multi-segment message support
2735
+ * - Memory pooling
2736
+ * - Zero-copy paths where possible
2737
+ */
2738
+ /**
2739
+ * Memory pool for reusing ArrayBuffers
2740
+ * Reduces GC pressure for frequent allocations
2741
+ */
2742
+ var MemoryPool = class {
2743
+ pools = /* @__PURE__ */ new Map();
2744
+ maxPoolSize;
2745
+ maxBufferAge;
2746
+ constructor(options) {
2747
+ this.maxPoolSize = options?.maxPoolSize ?? 100;
2748
+ this.maxBufferAge = options?.maxBufferAgeMs ?? 6e4;
2749
+ }
2750
+ /**
2751
+ * Acquire a buffer of at least the requested size
2752
+ */
2753
+ acquire(size) {
2754
+ const pooledSize = this.roundUpSize(size);
2755
+ const pool = this.pools.get(pooledSize);
2756
+ if (pool && pool.length > 0) {
2757
+ const now = Date.now();
2758
+ const index = pool.findIndex((b) => now - b.lastUsed < this.maxBufferAge);
2759
+ if (index >= 0) return pool.splice(index, 1)[0].buffer;
2760
+ }
2761
+ return new ArrayBuffer(pooledSize);
2762
+ }
2763
+ /**
2764
+ * Release a buffer back to the pool
2765
+ */
2766
+ release(buffer) {
2767
+ const size = buffer.byteLength;
2768
+ if (size < 64 || size > 1024 * 1024) return;
2769
+ let pool = this.pools.get(size);
2770
+ if (!pool) {
2771
+ pool = [];
2772
+ this.pools.set(size, pool);
2773
+ }
2774
+ if (pool.length < this.maxPoolSize) pool.push({
2775
+ buffer,
2776
+ size,
2777
+ lastUsed: Date.now()
2778
+ });
2779
+ }
2780
+ /**
2781
+ * Clear all pooled buffers
2782
+ */
2783
+ clear() {
2784
+ this.pools.clear();
2785
+ }
2786
+ /**
2787
+ * Get pool statistics
2788
+ */
2789
+ getStats() {
2790
+ let totalBuffers = 0;
2791
+ let totalBytes = 0;
2792
+ const sizes = [];
2793
+ for (const [size, pool] of this.pools) {
2794
+ totalBuffers += pool.length;
2795
+ totalBytes += size * pool.length;
2796
+ sizes.push(size);
2797
+ }
2798
+ return {
2799
+ totalBuffers,
2800
+ totalBytes,
2801
+ sizes
2802
+ };
2803
+ }
2804
+ roundUpSize(size) {
2805
+ if (size <= 64) return 64;
2806
+ if (size <= 128) return 128;
2807
+ if (size <= 256) return 256;
2808
+ if (size <= 512) return 512;
2809
+ if (size <= 1024) return 1024;
2810
+ if (size <= 2048) return 2048;
2811
+ if (size <= 4096) return 4096;
2812
+ if (size <= 8192) return 8192;
2813
+ if (size <= 16384) return 16384;
2814
+ if (size <= 32768) return 32768;
2815
+ if (size <= 65536) return 65536;
2816
+ return size;
2817
+ }
2818
+ };
2819
+ /**
2820
+ * Builder for multi-segment messages
2821
+ * Optimizes memory usage for large messages
2822
+ */
2823
+ var MultiSegmentMessageBuilder = class {
2824
+ segments = [];
2825
+ options;
2826
+ currentSegment;
2827
+ totalSize = 0;
2828
+ constructor(options) {
2829
+ this.options = {
2830
+ initialSegmentSize: options?.initialSegmentSize ?? 8192,
2831
+ maxSegmentSize: options?.maxSegmentSize ?? 65536,
2832
+ allowMultipleSegments: options?.allowMultipleSegments ?? true
2833
+ };
2834
+ this.currentSegment = new Segment(this.options.initialSegmentSize);
2835
+ this.segments.push(this.currentSegment);
2836
+ }
2837
+ /**
2838
+ * Allocate space in the message
2839
+ */
2840
+ allocate(size) {
2841
+ const alignedBytes = size + 7 & -8;
2842
+ const words = alignedBytes / 8;
2843
+ if (this.currentSegment.byteLength - this.currentSegment.wordCount * 8 >= alignedBytes) {
2844
+ const wordOffset = this.currentSegment.allocate(words);
2845
+ this.totalSize += alignedBytes;
2846
+ return {
2847
+ segment: this.currentSegment,
2848
+ offset: wordOffset * 8
2849
+ };
2850
+ }
2851
+ if (!this.options.allowMultipleSegments) throw new Error("Message too large for single segment");
2852
+ this.currentSegment = new Segment(Math.min(Math.max(alignedBytes, this.options.initialSegmentSize), this.options.maxSegmentSize));
2853
+ this.segments.push(this.currentSegment);
2854
+ const newWordOffset = this.currentSegment.allocate(words);
2855
+ this.totalSize += alignedBytes;
2856
+ return {
2857
+ segment: this.currentSegment,
2858
+ offset: newWordOffset * 8
2859
+ };
2860
+ }
2861
+ /**
2862
+ * Get all segments
2863
+ */
2864
+ getSegments() {
2865
+ return this.segments;
2866
+ }
2867
+ /**
2868
+ * Get the total size of all segments
2869
+ */
2870
+ getTotalSize() {
2871
+ return this.totalSize;
2872
+ }
2873
+ /**
2874
+ * Get the number of segments
2875
+ */
2876
+ getSegmentCount() {
2877
+ return this.segments.length;
2878
+ }
2879
+ /**
2880
+ * Serialize to a single buffer (for transport)
2881
+ */
2882
+ toBuffer() {
2883
+ if (this.segments.length === 1) {
2884
+ const segmentData = this.segments[0].asUint8Array();
2885
+ return segmentData.buffer.slice(segmentData.byteOffset, segmentData.byteOffset + segmentData.byteLength);
2886
+ }
2887
+ const totalSize = this.segments.reduce((sum, seg) => sum + seg.byteLength, 0);
2888
+ const result = new ArrayBuffer(totalSize + 8 * this.segments.length);
2889
+ const view = new DataView(result);
2890
+ const bytes = new Uint8Array(result);
2891
+ view.setUint32(0, this.segments.length - 1, true);
2892
+ view.setUint32(4, 0, true);
2893
+ let offset = 8;
2894
+ for (let i = 0; i < this.segments.length; i++) {
2895
+ const segment = this.segments[i];
2896
+ if (i > 0) {
2897
+ view.setUint32(offset, segment.byteLength / 8, true);
2898
+ offset += 4;
2899
+ }
2900
+ const segmentBuffer = new Uint8Array(segment.byteLength);
2901
+ const segmentData = segment.dataView;
2902
+ for (let i = 0; i < segment.byteLength; i++) segmentBuffer[i] = segmentData.getUint8(i);
2903
+ bytes.set(segmentBuffer, offset);
2904
+ offset += segment.byteLength;
2905
+ }
2906
+ return result;
2907
+ }
2908
+ };
2909
+ /**
2910
+ * Create a zero-copy view of a buffer
2911
+ */
2912
+ function createZeroCopyView(buffer, byteOffset = 0, byteLength) {
2913
+ return {
2914
+ buffer,
2915
+ byteOffset,
2916
+ byteLength: byteLength ?? buffer.byteLength - byteOffset
2917
+ };
2918
+ }
2919
+ /**
2920
+ * Check if two buffers are the same underlying memory
2921
+ */
2922
+ function isSameBuffer(a, b) {
2923
+ try {
2924
+ return a === b;
2925
+ } catch {
2926
+ return false;
2927
+ }
2928
+ }
2929
+ /**
2930
+ * Copy data between buffers using the fastest available method
2931
+ */
2932
+ function fastCopy(src, dst, srcOffset = 0, dstOffset = 0, length) {
2933
+ const len = length ?? Math.min(src.byteLength - srcOffset, dst.byteLength - dstOffset);
2934
+ const srcView = new Uint8Array(src, srcOffset, len);
2935
+ new Uint8Array(dst, dstOffset, len).set(srcView);
2936
+ }
2937
+ /**
2938
+ * Optimized RPC message builder
2939
+ */
2940
+ var OptimizedRpcMessageBuilder = class {
2941
+ options;
2942
+ pool;
2943
+ constructor(options) {
2944
+ this.options = {
2945
+ useMultiSegment: options?.useMultiSegment ?? true,
2946
+ initialSegmentSize: options?.initialSegmentSize ?? 8192,
2947
+ useMemoryPool: options?.useMemoryPool ?? true,
2948
+ memoryPool: options?.memoryPool ?? new MemoryPool()
2949
+ };
2950
+ this.pool = this.options.memoryPool;
2951
+ }
2952
+ /**
2953
+ * Build a message with optimizations applied
2954
+ */
2955
+ buildMessage(content) {
2956
+ const totalSize = 8 + content.length;
2957
+ if (this.options.useMemoryPool) {
2958
+ const buffer = this.pool.acquire(totalSize);
2959
+ const view = new DataView(buffer);
2960
+ const bytes = new Uint8Array(buffer);
2961
+ view.setUint32(0, 0, true);
2962
+ view.setUint32(4, content.length / 8, true);
2963
+ bytes.set(content, 8);
2964
+ return buffer;
2965
+ }
2966
+ const buffer = new ArrayBuffer(totalSize);
2967
+ const view = new DataView(buffer);
2968
+ const bytes = new Uint8Array(buffer);
2969
+ view.setUint32(0, 0, true);
2970
+ view.setUint32(4, content.length / 8, true);
2971
+ bytes.set(content, 8);
2972
+ return buffer;
2973
+ }
2974
+ /**
2975
+ * Release a buffer back to the pool
2976
+ */
2977
+ releaseBuffer(buffer) {
2978
+ if (this.options.useMemoryPool) this.pool.release(buffer);
2979
+ }
2980
+ /**
2981
+ * Get pool statistics
2982
+ */
2983
+ getPoolStats() {
2984
+ return this.pool.getStats();
2985
+ }
2986
+ };
2987
+ let globalMemoryPool = null;
2988
+ /**
2989
+ * Get the global memory pool instance
2990
+ */
2991
+ function getGlobalMemoryPool() {
2992
+ if (!globalMemoryPool) globalMemoryPool = new MemoryPool();
2993
+ return globalMemoryPool;
2994
+ }
2995
+ /**
2996
+ * Configure the global memory pool
2997
+ */
2998
+ function configureGlobalMemoryPool(options) {
2999
+ globalMemoryPool = new MemoryPool(options);
3000
+ }
3001
+
3002
+ //#endregion
3003
+ exports.AnswerTable = AnswerTable;
3004
+ exports.BaseCapabilityClient = BaseCapabilityClient;
828
3005
  exports.ElementSize = ElementSize;
3006
+ exports.ExportTable = ExportTable;
3007
+ exports.ImportTable = ImportTable;
829
3008
  exports.ListBuilder = ListBuilder;
830
3009
  exports.ListReader = ListReader;
3010
+ exports.MemoryPool = MemoryPool;
831
3011
  exports.MessageBuilder = MessageBuilder;
832
3012
  exports.MessageReader = MessageReader;
3013
+ exports.MultiSegmentMessageBuilder = MultiSegmentMessageBuilder;
3014
+ exports.OptimizedRpcMessageBuilder = OptimizedRpcMessageBuilder;
3015
+ exports.PIPELINE_CLIENT_SYMBOL = PIPELINE_CLIENT_SYMBOL;
3016
+ exports.PipelineOpTracker = PipelineOpTracker;
3017
+ exports.PipelineResolutionTracker = PipelineResolutionTracker;
833
3018
  exports.PointerTag = PointerTag;
3019
+ exports.QuestionTable = QuestionTable;
3020
+ exports.QueuedCallManager = QueuedCallManager;
3021
+ exports.RestoreHandler = RestoreHandler;
3022
+ exports.RpcConnection = RpcConnection;
834
3023
  exports.Segment = Segment;
835
3024
  exports.StructBuilder = StructBuilder;
836
3025
  exports.StructReader = StructReader;
3026
+ exports.SturdyRefManager = SturdyRefManager;
837
3027
  exports.UnionBuilder = UnionBuilder;
838
3028
  exports.UnionReader = UnionReader;
839
3029
  exports.WORD_SIZE = WORD_SIZE;
3030
+ exports.WebSocketTransport = WebSocketTransport;
3031
+ exports.configureGlobalMemoryPool = configureGlobalMemoryPool;
3032
+ exports.createPipelineClient = createPipelineClient;
3033
+ exports.createSturdyRef = createSturdyRef;
840
3034
  exports.createUnionBuilder = createUnionBuilder;
841
3035
  exports.createUnionReader = createUnionReader;
3036
+ exports.createZeroCopyView = createZeroCopyView;
842
3037
  exports.decodePointer = decodePointer;
3038
+ exports.deserializeRpcMessage = deserializeRpcMessage;
3039
+ exports.deserializeSturdyRef = deserializeSturdyRef;
843
3040
  exports.encodeListPointer = encodeListPointer;
844
3041
  exports.encodeStructPointer = encodeStructPointer;
3042
+ exports.fastCopy = fastCopy;
3043
+ exports.getGlobalMemoryPool = getGlobalMemoryPool;
3044
+ exports.isPipelineClient = isPipelineClient;
3045
+ exports.isSameBuffer = isSameBuffer;
3046
+ exports.isSturdyRefValid = isSturdyRefValid;
3047
+ exports.serializeRpcMessage = serializeRpcMessage;
3048
+ exports.serializeSturdyRef = serializeSturdyRef;
845
3049
  //# sourceMappingURL=index.cjs.map