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