capnweb 0.0.0-5eb7701 → 0.0.0-610ab3a

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/README.md CHANGED
@@ -776,3 +776,10 @@ let stub: RemoteMainInterface = session.getRemoteMain();
776
776
  ```
777
777
 
778
778
  Note that sessions are entirely symmetric: neither side is defined as the "client" nor the "server". Each side can optionally expose a "main interface" to the other. In typical scenarios with a logical client and server, the server exposes a main interface but the client does not.
779
+
780
+ By default, `send()` accepts a string, and `receive()` returns a string, with Cap'n Web handling the encoding all the way to and from strings. However, transports that want more control over the serialization can declare the property `encodingLevel` to control how much encoding Cap'n Web does before passing off the message:
781
+
782
+ * `"string"` (default): Full JSON round-trip. The transport deals in strings only. Cap'n Web handles all encoding/decoding. This is what HTTP batch and WebSocket transports use.
783
+ * `"jsonCompatible"`: The transport works with JavaScript value trees, but they must be JSON-compatible. Cap'n Web still encodes special types, but skips the final `JSON.stringify`. The transport is responsible for serialization (e.g. to CBOR, MessagePack).
784
+ * `"jsonCompatibleWithBytes"`: Like `"jsonCompatible"` except that byte arrays are left as `Uint8Array` instead of base64-encoded, avoiding the ~33% base64 size overhead and the encode/decode CPU cost. Handy for use with serializations like CBOR or MessagePack that support this efficiently.
785
+ * `"structuredClonable"`: Messages are structured-clonable values. Cap'n Web passes through native structured-clone types where possible, while still handling RPC-specific values such as stubs. This is useful when the transport is a `MessagePort` or similar.
@@ -1,3 +1,4 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1
2
 
2
3
  //#region src/symbols.ts
3
4
  let WORKERS_MODULE_SYMBOL = Symbol("workers-module");
@@ -91,6 +92,7 @@ var StubHook = class {
91
92
  }
92
93
  };
93
94
  var ErrorStubHook = class extends StubHook {
95
+ error;
94
96
  constructor(error) {
95
97
  super();
96
98
  this.error = error;
@@ -264,6 +266,10 @@ async function pullPromise(promise) {
264
266
  return (await hook.pull()).deliverResolve();
265
267
  }
266
268
  var RpcPayload = class RpcPayload {
269
+ value;
270
+ source;
271
+ hooks;
272
+ promises;
267
273
  static fromAppParams(value) {
268
274
  return new RpcPayload(value, "params");
269
275
  }
@@ -955,18 +961,22 @@ const ERROR_TYPES = {
955
961
  AggregateError
956
962
  };
957
963
  var Devaluator = class Devaluator {
958
- constructor(exporter, source) {
964
+ exporter;
965
+ source;
966
+ encodingLevel;
967
+ constructor(exporter, source, encodingLevel) {
959
968
  this.exporter = exporter;
960
969
  this.source = source;
970
+ this.encodingLevel = encodingLevel;
961
971
  }
962
- static devaluate(value, parent, exporter = NULL_EXPORTER, source) {
963
- let devaluator = new Devaluator(exporter, source);
972
+ static devaluate(value, parent, exporter = NULL_EXPORTER, source, encodingLevel = "string") {
973
+ let devaluator = new Devaluator(exporter, source, encodingLevel);
964
974
  try {
965
975
  return devaluator.devaluateImpl(value, parent, 0);
966
976
  } catch (err) {
967
977
  if (devaluator.exports) try {
968
978
  exporter.unexport(devaluator.exports);
969
- } catch (err$1) {}
979
+ } catch (err) {}
970
980
  throw err;
971
981
  }
972
982
  }
@@ -983,10 +993,12 @@ var Devaluator = class Devaluator {
983
993
  }
984
994
  throw new TypeError(msg);
985
995
  }
986
- case "primitive": if (typeof value === "number" && !isFinite(value)) if (value === Infinity) return ["inf"];
987
- else if (value === -Infinity) return ["-inf"];
988
- else return ["nan"];
989
- else return value;
996
+ case "primitive": if (typeof value === "number" && !isFinite(value)) {
997
+ if (this.encodingLevel === "structuredClonable") return value;
998
+ if (value === Infinity) return ["inf"];
999
+ else if (value === -Infinity) return ["-inf"];
1000
+ else return ["nan"];
1001
+ } else return value;
990
1002
  case "object": {
991
1003
  let object = value;
992
1004
  let result = {};
@@ -1000,13 +1012,17 @@ var Devaluator = class Devaluator {
1000
1012
  for (let i = 0; i < len; i++) result[i] = this.devaluateImpl(array[i], array, depth + 1);
1001
1013
  return [result];
1002
1014
  }
1003
- case "bigint": return ["bigint", value.toString()];
1015
+ case "bigint":
1016
+ if (this.encodingLevel === "structuredClonable") return value;
1017
+ return ["bigint", value.toString()];
1004
1018
  case "date": {
1019
+ if (this.encodingLevel === "structuredClonable") return value;
1005
1020
  const time = value.getTime();
1006
1021
  return ["date", Number.isNaN(time) ? null : time];
1007
1022
  }
1008
1023
  case "bytes": {
1009
1024
  let bytes = value;
1025
+ if (this.encodingLevel === "structuredClonable" || this.encodingLevel === "jsonCompatibleWithBytes") return ["bytes", bytes];
1010
1026
  if (bytes.toBase64) return ["bytes", bytes.toBase64({ omitPadding: true })];
1011
1027
  let b64;
1012
1028
  if (typeof Buffer !== "undefined") b64 = (bytes instanceof Buffer ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)).toString("base64");
@@ -1131,7 +1147,9 @@ var Devaluator = class Devaluator {
1131
1147
  } else if (rewritten && rewritten.stack) result.push(rewritten.stack);
1132
1148
  return result;
1133
1149
  }
1134
- case "undefined": return ["undefined"];
1150
+ case "undefined":
1151
+ if (this.encodingLevel === "structuredClonable") return;
1152
+ return ["undefined"];
1135
1153
  case "stub":
1136
1154
  case "rpc-promise": {
1137
1155
  if (!this.source) throw new Error("Can't serialize RPC stubs in this context.");
@@ -1213,8 +1231,11 @@ function streamToBlobPromise(stream, type) {
1213
1231
  })), []);
1214
1232
  }
1215
1233
  var Evaluator = class Evaluator {
1216
- constructor(importer) {
1234
+ importer;
1235
+ encodingLevel;
1236
+ constructor(importer, encodingLevel = "string") {
1217
1237
  this.importer = importer;
1238
+ this.encodingLevel = encodingLevel;
1218
1239
  }
1219
1240
  hooks = [];
1220
1241
  promises = [];
@@ -1232,6 +1253,9 @@ var Evaluator = class Evaluator {
1232
1253
  return this.evaluate(structuredClone(value));
1233
1254
  }
1234
1255
  evaluateImpl(value, parent, property) {
1256
+ if (this.encodingLevel === "structuredClonable") {
1257
+ if (value instanceof Date || typeof value === "bigint") return value;
1258
+ }
1235
1259
  if (value instanceof Array) {
1236
1260
  if (value.length == 1 && value[0] instanceof Array) {
1237
1261
  let result = value[0];
@@ -1246,6 +1270,7 @@ var Evaluator = class Evaluator {
1246
1270
  if (typeof value[1] == "number") return new Date(value[1]);
1247
1271
  break;
1248
1272
  case "bytes":
1273
+ if (value[1] instanceof Uint8Array) return value[1];
1249
1274
  if (typeof value[1] == "string") if (typeof Buffer !== "undefined") return Buffer.from(value[1], "base64");
1250
1275
  else if (Uint8Array.fromBase64) return Uint8Array.fromBase64(value[1]);
1251
1276
  else {
@@ -1338,9 +1363,9 @@ var Evaluator = class Evaluator {
1338
1363
  let hook = this.importer.getExport(value[1]);
1339
1364
  if (!hook) throw new Error(`no such entry on exports table: ${value[1]}`);
1340
1365
  let isPromise = value[0] == "pipeline";
1341
- let addStub = (hook$1) => {
1366
+ let addStub = (hook) => {
1342
1367
  if (isPromise) {
1343
- let promise = new RpcPromise$1(hook$1, []);
1368
+ let promise = new RpcPromise$1(hook, []);
1344
1369
  this.promises.push({
1345
1370
  promise,
1346
1371
  parent,
@@ -1348,8 +1373,8 @@ var Evaluator = class Evaluator {
1348
1373
  });
1349
1374
  return promise;
1350
1375
  } else {
1351
- this.hooks.push(hook$1);
1352
- return new RpcPromise$1(hook$1, []);
1376
+ this.hooks.push(hook);
1377
+ return new RpcPromise$1(hook, []);
1353
1378
  }
1354
1379
  };
1355
1380
  if (value.length == 2) if (isPromise) return addStub(hook.get([]));
@@ -1446,7 +1471,50 @@ function deserialize(value) {
1446
1471
 
1447
1472
  //#endregion
1448
1473
  //#region src/rpc.ts
1474
+ const ESTIMATED_OBJECT_OVERHEAD = 16;
1475
+ const ESTIMATED_ENTRY_OVERHEAD = 8;
1476
+ const ESTIMATED_BINARY_OVERHEAD = 16;
1477
+ const MAX_ESTIMATE_DEPTH = 64;
1478
+ function estimateStringSize(value) {
1479
+ return 2 + value.length * 3;
1480
+ }
1481
+ function estimateEncodedSize(value, seen, depth = 0) {
1482
+ if (depth >= MAX_ESTIMATE_DEPTH) return ESTIMATED_ENTRY_OVERHEAD;
1483
+ switch (typeof value) {
1484
+ case "string": return estimateStringSize(value);
1485
+ case "number": return 16;
1486
+ case "bigint": return 16;
1487
+ case "boolean": return 8;
1488
+ case "undefined": return 16;
1489
+ case "object": {
1490
+ if (value === null) return 8;
1491
+ if (ArrayBuffer.isView(value)) return ESTIMATED_BINARY_OVERHEAD + value.byteLength;
1492
+ if (value instanceof ArrayBuffer) return ESTIMATED_BINARY_OVERHEAD + value.byteLength;
1493
+ if (typeof Blob !== "undefined" && value instanceof Blob) return ESTIMATED_BINARY_OVERHEAD + value.size;
1494
+ if (value instanceof Date) return 16;
1495
+ seen ??= /* @__PURE__ */ new WeakSet();
1496
+ if (seen.has(value)) return ESTIMATED_ENTRY_OVERHEAD;
1497
+ seen.add(value);
1498
+ if (value instanceof Array) {
1499
+ let size = ESTIMATED_OBJECT_OVERHEAD;
1500
+ for (let item of value) size += ESTIMATED_ENTRY_OVERHEAD + estimateEncodedSize(item, seen, depth + 1);
1501
+ return size;
1502
+ }
1503
+ if (value instanceof Error) {
1504
+ let size = ESTIMATED_OBJECT_OVERHEAD + estimateStringSize(value.name) + estimateStringSize(value.message) + estimateStringSize(value.stack ?? "");
1505
+ for (let key of Object.keys(value)) size += ESTIMATED_ENTRY_OVERHEAD + estimateStringSize(key) + estimateEncodedSize(value[key], seen, depth + 1);
1506
+ return size;
1507
+ }
1508
+ let size = ESTIMATED_OBJECT_OVERHEAD;
1509
+ for (let key of Object.keys(value)) size += ESTIMATED_ENTRY_OVERHEAD + estimateStringSize(key) + estimateEncodedSize(value[key], seen, depth + 1);
1510
+ return size;
1511
+ }
1512
+ default: return 16;
1513
+ }
1514
+ }
1449
1515
  var ImportTableEntry = class {
1516
+ session;
1517
+ importId;
1450
1518
  constructor(session, importId, pulling) {
1451
1519
  this.session = session;
1452
1520
  this.importId = importId;
@@ -1521,6 +1589,7 @@ var ImportTableEntry = class {
1521
1589
  }
1522
1590
  };
1523
1591
  var RpcImportHook = class RpcImportHook extends StubHook {
1592
+ isPromise;
1524
1593
  entry;
1525
1594
  constructor(isPromise, entry) {
1526
1595
  super();
@@ -1597,6 +1666,8 @@ var RpcMainHook = class extends RpcImportHook {
1597
1666
  }
1598
1667
  };
1599
1668
  var RpcSessionImpl = class {
1669
+ transport;
1670
+ options;
1600
1671
  exports = [];
1601
1672
  reverseExports = /* @__PURE__ */ new Map();
1602
1673
  imports = [];
@@ -1606,9 +1677,19 @@ var RpcSessionImpl = class {
1606
1677
  onBatchDone;
1607
1678
  pullCount = 0;
1608
1679
  onBrokenCallbacks = [];
1680
+ encodingLevel;
1609
1681
  constructor(transport, mainHook, options) {
1610
1682
  this.transport = transport;
1611
1683
  this.options = options;
1684
+ let level = "string";
1685
+ if ("encodingLevel" in transport) {
1686
+ let raw = transport.encodingLevel;
1687
+ if (raw !== void 0) {
1688
+ if (raw !== "string" && raw !== "jsonCompatible" && raw !== "jsonCompatibleWithBytes" && raw !== "structuredClonable") throw new TypeError(`Unknown transport encodingLevel: ${String(raw)}`);
1689
+ level = raw;
1690
+ }
1691
+ }
1692
+ this.encodingLevel = level;
1612
1693
  this.exports.push({
1613
1694
  hook: mainHook,
1614
1695
  refcount: 1
@@ -1689,7 +1770,7 @@ var RpcSessionImpl = class {
1689
1770
  let autoRelease = exp.autoRelease;
1690
1771
  ++this.pullCount;
1691
1772
  exp.pull = resolve().then((payload) => {
1692
- let value = Devaluator.devaluate(payload.value, void 0, this, payload);
1773
+ let value = Devaluator.devaluate(payload.value, void 0, this, payload, this.encodingLevel);
1693
1774
  this.send([
1694
1775
  "resolve",
1695
1776
  exportId,
@@ -1700,7 +1781,7 @@ var RpcSessionImpl = class {
1700
1781
  this.send([
1701
1782
  "reject",
1702
1783
  exportId,
1703
- Devaluator.devaluate(error, void 0, this)
1784
+ Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
1704
1785
  ]);
1705
1786
  if (autoRelease) this.releaseExport(exportId, 1);
1706
1787
  }).catch((error) => {
@@ -1708,7 +1789,7 @@ var RpcSessionImpl = class {
1708
1789
  this.send([
1709
1790
  "reject",
1710
1791
  exportId,
1711
- Devaluator.devaluate(error, void 0, this)
1792
+ Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
1712
1793
  ]);
1713
1794
  if (autoRelease) this.releaseExport(exportId, 1);
1714
1795
  } catch (error2) {
@@ -1764,17 +1845,33 @@ var RpcSessionImpl = class {
1764
1845
  }
1765
1846
  send(msg) {
1766
1847
  if (this.abortReason !== void 0) return 0;
1767
- let msgText;
1768
- try {
1769
- msgText = JSON.stringify(msg);
1770
- } catch (err) {
1848
+ if (this.encodingLevel === "string") {
1849
+ let msgText;
1771
1850
  try {
1772
- this.abort(err);
1773
- } catch (err2) {}
1774
- throw err;
1851
+ msgText = JSON.stringify(msg);
1852
+ } catch (err) {
1853
+ try {
1854
+ this.abort(err);
1855
+ } catch (err2) {}
1856
+ throw err;
1857
+ }
1858
+ try {
1859
+ let sent = this.transport.send(msgText);
1860
+ if (sent !== void 0 && typeof sent.catch === "function") sent.catch((err) => this.abort(err, false));
1861
+ } catch (err) {
1862
+ queueMicrotask(() => this.abort(err, false));
1863
+ }
1864
+ return msgText.length;
1865
+ } else try {
1866
+ let size = this.transport.send(msg);
1867
+ if (typeof size === "number") return size;
1868
+ let thenable = size;
1869
+ if (thenable && typeof thenable.then === "function") Promise.resolve(thenable).catch((err) => this.abort(err, false));
1870
+ return;
1871
+ } catch (err) {
1872
+ queueMicrotask(() => this.abort(err, false));
1873
+ return;
1775
1874
  }
1776
- this.transport.send(msgText).catch((err) => this.abort(err, false));
1777
- return msgText.length;
1778
1875
  }
1779
1876
  sendCall(id, path, args) {
1780
1877
  if (this.abortReason) throw this.abortReason;
@@ -1784,7 +1881,7 @@ var RpcSessionImpl = class {
1784
1881
  path
1785
1882
  ];
1786
1883
  if (args) {
1787
- let devalue = Devaluator.devaluate(args.value, void 0, this, args);
1884
+ let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
1788
1885
  value.push(devalue[0]);
1789
1886
  }
1790
1887
  this.send(["push", value]);
@@ -1799,9 +1896,11 @@ var RpcSessionImpl = class {
1799
1896
  id,
1800
1897
  path
1801
1898
  ];
1802
- let devalue = Devaluator.devaluate(args.value, void 0, this, args);
1899
+ let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
1803
1900
  value.push(devalue[0]);
1804
- let size = this.send(["stream", value]);
1901
+ let msg = ["stream", value];
1902
+ let size = this.send(msg);
1903
+ if (size === void 0) size = estimateEncodedSize(msg);
1805
1904
  let importId = this.imports.length;
1806
1905
  let entry = new ImportTableEntry(this, importId, true);
1807
1906
  entry.remoteRefcount = 0;
@@ -1857,7 +1956,14 @@ var RpcSessionImpl = class {
1857
1956
  this.cancelReadLoop?.(error);
1858
1957
  this.cancelReadLoop = void 0;
1859
1958
  if (trySendAbortMessage) try {
1860
- this.transport.send(JSON.stringify(["abort", Devaluator.devaluate(error, void 0, this)])).catch((err) => {});
1959
+ let abortMsg = ["abort", Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)];
1960
+ if (this.encodingLevel === "string") {
1961
+ let sent = this.transport.send(JSON.stringify(abortMsg));
1962
+ if (sent !== void 0 && typeof sent.catch === "function") sent.catch((err) => {});
1963
+ } else {
1964
+ let result = this.transport.send(abortMsg);
1965
+ if (result && typeof result.then === "function") Promise.resolve(result).catch((err) => {});
1966
+ }
1861
1967
  } catch (err) {}
1862
1968
  if (error === void 0) error = "undefined";
1863
1969
  this.abortReason = error;
@@ -1879,18 +1985,18 @@ var RpcSessionImpl = class {
1879
1985
  while (!this.abortReason) {
1880
1986
  let readCanceled = Promise.withResolvers();
1881
1987
  this.cancelReadLoop = readCanceled.reject;
1882
- let msgText;
1988
+ let raw;
1883
1989
  try {
1884
- msgText = await Promise.race([this.transport.receive(), readCanceled.promise]);
1990
+ raw = await Promise.race([this.transport.receive(), readCanceled.promise]);
1885
1991
  } finally {
1886
1992
  if (this.cancelReadLoop === readCanceled.reject) this.cancelReadLoop = void 0;
1887
1993
  }
1888
- let msg = JSON.parse(msgText);
1889
1994
  if (this.abortReason) break;
1995
+ let msg = this.encodingLevel === "string" ? JSON.parse(raw) : raw;
1890
1996
  if (msg instanceof Array) switch (msg[0]) {
1891
1997
  case "push":
1892
1998
  if (msg.length > 1) {
1893
- let hook = new PayloadStubHook(new Evaluator(this).evaluate(msg[1]));
1999
+ let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
1894
2000
  hook.ignoreUnhandledRejections();
1895
2001
  this.exports.push({
1896
2002
  hook,
@@ -1901,7 +2007,7 @@ var RpcSessionImpl = class {
1901
2007
  break;
1902
2008
  case "stream":
1903
2009
  if (msg.length > 1) {
1904
- let hook = new PayloadStubHook(new Evaluator(this).evaluate(msg[1]));
2010
+ let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
1905
2011
  hook.ignoreUnhandledRejections();
1906
2012
  let exportId = this.exports.length;
1907
2013
  this.exports.push({
@@ -1936,13 +2042,13 @@ var RpcSessionImpl = class {
1936
2042
  let importId = msg[1];
1937
2043
  if (typeof importId == "number" && msg.length > 2) {
1938
2044
  let imp = this.imports[importId];
1939
- if (imp) if (msg[0] == "resolve") imp.resolve(new PayloadStubHook(new Evaluator(this).evaluate(msg[2])));
2045
+ if (imp) if (msg[0] == "resolve") imp.resolve(new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[2])));
1940
2046
  else {
1941
- let payload = new Evaluator(this).evaluate(msg[2]);
2047
+ let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[2]);
1942
2048
  payload.dispose();
1943
2049
  imp.resolve(new ErrorStubHook(payload.value));
1944
2050
  }
1945
- else if (msg[0] == "resolve") new Evaluator(this).evaluate(msg[2]).dispose();
2051
+ else if (msg[0] == "resolve") new Evaluator(this, this.encodingLevel).evaluate(msg[2]).dispose();
1946
2052
  continue;
1947
2053
  }
1948
2054
  break;
@@ -1957,7 +2063,7 @@ var RpcSessionImpl = class {
1957
2063
  break;
1958
2064
  }
1959
2065
  case "abort": {
1960
- let payload = new Evaluator(this).evaluate(msg[1]);
2066
+ let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[1]);
1961
2067
  payload.dispose();
1962
2068
  this.abort(payload, false);
1963
2069
  break;
@@ -2029,9 +2135,14 @@ function newWorkersWebSocketRpcResponse(request, localMain, options) {
2029
2135
  webSocket: pair[1]
2030
2136
  });
2031
2137
  }
2138
+ /**
2139
+ * Generic WebSocket transport. Default `T = string` is backward-compatible and satisfies
2140
+ * `RpcTransport`. Use `T = ArrayBuffer` as a building block for binary transports.
2141
+ */
2032
2142
  var WebSocketTransport = class {
2033
2143
  constructor(webSocket) {
2034
2144
  this.#webSocket = webSocket;
2145
+ webSocket.binaryType = "arraybuffer";
2035
2146
  if (webSocket.readyState === WebSocket.CONNECTING) {
2036
2147
  this.#sendQueue = [];
2037
2148
  webSocket.addEventListener("open", (event) => {
@@ -2044,12 +2155,12 @@ var WebSocketTransport = class {
2044
2155
  });
2045
2156
  }
2046
2157
  webSocket.addEventListener("message", (event) => {
2047
- if (this.#error) {} else if (typeof event.data === "string") if (this.#receiveResolver) {
2158
+ if (this.#error) {} else if (typeof event.data === "string" || event.data instanceof ArrayBuffer) if (this.#receiveResolver) {
2048
2159
  this.#receiveResolver(event.data);
2049
2160
  this.#receiveResolver = void 0;
2050
2161
  this.#receiveRejecter = void 0;
2051
2162
  } else this.#receiveQueue.push(event.data);
2052
- else this.#receivedError(/* @__PURE__ */ new TypeError("Received non-string message from WebSocket."));
2163
+ else this.#receivedError(/* @__PURE__ */ new TypeError("Received unexpected message type from WebSocket."));
2053
2164
  });
2054
2165
  webSocket.addEventListener("close", (event) => {
2055
2166
  this.#receivedError(/* @__PURE__ */ new Error(`Peer closed WebSocket: ${event.code} ${event.reason}`));
@@ -2064,13 +2175,13 @@ var WebSocketTransport = class {
2064
2175
  #receiveRejecter;
2065
2176
  #receiveQueue = [];
2066
2177
  #error;
2067
- async send(message) {
2178
+ send(message) {
2068
2179
  if (this.#sendQueue === void 0) this.#webSocket.send(message);
2069
2180
  else this.#sendQueue.push(message);
2070
2181
  }
2071
- async receive() {
2072
- if (this.#receiveQueue.length > 0) return this.#receiveQueue.shift();
2073
- else if (this.#error) throw this.#error;
2182
+ receive() {
2183
+ if (this.#receiveQueue.length > 0) return Promise.resolve(this.#receiveQueue.shift());
2184
+ else if (this.#error) return Promise.reject(this.#error);
2074
2185
  else return new Promise((resolve, reject) => {
2075
2186
  this.#receiveResolver = resolve;
2076
2187
  this.#receiveRejecter = reject;
@@ -2105,7 +2216,7 @@ var BatchClientTransport = class {
2105
2216
  #aborted;
2106
2217
  #batchToSend = [];
2107
2218
  #batchToReceive = null;
2108
- async send(message) {
2219
+ send(message) {
2109
2220
  if (this.#batchToSend !== null) this.#batchToSend.push(message);
2110
2221
  }
2111
2222
  async receive() {
@@ -2147,7 +2258,7 @@ var BatchServerTransport = class {
2147
2258
  #batchToSend = [];
2148
2259
  #batchToReceive;
2149
2260
  #allReceived = Promise.withResolvers();
2150
- async send(message) {
2261
+ send(message) {
2151
2262
  this.#batchToSend.push(message);
2152
2263
  }
2153
2264
  async receive() {
@@ -2196,7 +2307,11 @@ async function newHttpBatchRpcResponse(request, localMain, options) {
2196
2307
  * @param options Optional RPC session options. You can also pass headers to set on the response.
2197
2308
  */
2198
2309
  async function nodeHttpBatchRpcResponse(request, response, localMain, options) {
2199
- if (request.method !== "POST") response.writeHead(405, "This endpoint only accepts POST requests.");
2310
+ if (request.method !== "POST") {
2311
+ response.writeHead(405, "This endpoint only accepts POST requests.", options?.headers);
2312
+ response.end();
2313
+ return;
2314
+ }
2200
2315
  let body = await new Promise((resolve, reject) => {
2201
2316
  let chunks = [];
2202
2317
  request.on("data", (chunk) => {
@@ -2221,17 +2336,17 @@ function newMessagePortRpcSession$1(port, localMain, options) {
2221
2336
  return new RpcSession$1(new MessagePortTransport(port), localMain, options).getRemoteMain();
2222
2337
  }
2223
2338
  var MessagePortTransport = class {
2339
+ encodingLevel = "structuredClonable";
2224
2340
  constructor(port) {
2225
2341
  this.#port = port;
2226
2342
  port.start();
2227
2343
  port.addEventListener("message", (event) => {
2228
2344
  if (this.#error) {} else if (event.data === null) this.#receivedError(/* @__PURE__ */ new Error("Peer closed MessagePort connection."));
2229
- else if (typeof event.data === "string") if (this.#receiveResolver) {
2345
+ else if (this.#receiveResolver) {
2230
2346
  this.#receiveResolver(event.data);
2231
2347
  this.#receiveResolver = void 0;
2232
2348
  this.#receiveRejecter = void 0;
2233
2349
  } else this.#receiveQueue.push(event.data);
2234
- else this.#receivedError(/* @__PURE__ */ new TypeError("Received non-string message from MessagePort."));
2235
2350
  });
2236
2351
  port.addEventListener("messageerror", (event) => {
2237
2352
  this.#receivedError(/* @__PURE__ */ new Error("MessagePort message error."));
@@ -2242,7 +2357,7 @@ var MessagePortTransport = class {
2242
2357
  #receiveRejecter;
2243
2358
  #receiveQueue = [];
2244
2359
  #error;
2245
- async send(message) {
2360
+ send(message) {
2246
2361
  if (this.#error) throw this.#error;
2247
2362
  this.#port.postMessage(message);
2248
2363
  }
@@ -2389,6 +2504,8 @@ function throwMapperBuilderUseError() {
2389
2504
  throw new Error("Attempted to use an abstract placeholder from a mapper function. Please make sure your map function has no side effects.");
2390
2505
  }
2391
2506
  var MapVariableHook = class extends StubHook {
2507
+ mapper;
2508
+ idx;
2392
2509
  constructor(mapper, idx) {
2393
2510
  super();
2394
2511
  this.mapper = mapper;
@@ -2418,6 +2535,7 @@ var MapVariableHook = class extends StubHook {
2418
2535
  }
2419
2536
  };
2420
2537
  var MapApplicator = class {
2538
+ captures;
2421
2539
  variables;
2422
2540
  constructor(captures, input) {
2423
2541
  this.captures = captures;
@@ -2558,6 +2676,7 @@ const STEADY_GROWTH_FACTOR = 1.25;
2558
2676
  const DECAY_FACTOR = .9;
2559
2677
  const STARTUP_EXIT_ROUNDS = 3;
2560
2678
  var FlowController = class {
2679
+ now;
2561
2680
  window = INITIAL_WINDOW;
2562
2681
  bytesInFlight = 0;
2563
2682
  inStartupPhase = true;
@@ -2926,6 +3045,7 @@ exports.RpcPromise = RpcPromise;
2926
3045
  exports.RpcSession = RpcSession;
2927
3046
  exports.RpcStub = RpcStub;
2928
3047
  exports.RpcTarget = RpcTarget;
3048
+ exports.WebSocketTransport = WebSocketTransport;
2929
3049
  exports.deserialize = deserialize;
2930
3050
  exports.newBunWebSocketRpcHandler = newBunWebSocketRpcHandler;
2931
3051
  exports.newBunWebSocketRpcSession = newBunWebSocketRpcSession;