capnweb 0.0.0-409821 → 0.0.0-47df697

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -963,12 +963,14 @@ const ERROR_TYPES = {
963
963
  var Devaluator = class Devaluator {
964
964
  exporter;
965
965
  source;
966
- constructor(exporter, source) {
966
+ encodingLevel;
967
+ constructor(exporter, source, encodingLevel) {
967
968
  this.exporter = exporter;
968
969
  this.source = source;
970
+ this.encodingLevel = encodingLevel;
969
971
  }
970
- static devaluate(value, parent, exporter = NULL_EXPORTER, source) {
971
- 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);
972
974
  try {
973
975
  return devaluator.devaluateImpl(value, parent, 0);
974
976
  } catch (err) {
@@ -991,10 +993,12 @@ var Devaluator = class Devaluator {
991
993
  }
992
994
  throw new TypeError(msg);
993
995
  }
994
- case "primitive": if (typeof value === "number" && !isFinite(value)) if (value === Infinity) return ["inf"];
995
- else if (value === -Infinity) return ["-inf"];
996
- else return ["nan"];
997
- 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;
998
1002
  case "object": {
999
1003
  let object = value;
1000
1004
  let result = {};
@@ -1008,13 +1012,17 @@ var Devaluator = class Devaluator {
1008
1012
  for (let i = 0; i < len; i++) result[i] = this.devaluateImpl(array[i], array, depth + 1);
1009
1013
  return [result];
1010
1014
  }
1011
- case "bigint": return ["bigint", value.toString()];
1015
+ case "bigint":
1016
+ if (this.encodingLevel === "structuredClonable") return value;
1017
+ return ["bigint", value.toString()];
1012
1018
  case "date": {
1019
+ if (this.encodingLevel === "structuredClonable") return value;
1013
1020
  const time = value.getTime();
1014
1021
  return ["date", Number.isNaN(time) ? null : time];
1015
1022
  }
1016
1023
  case "bytes": {
1017
1024
  let bytes = value;
1025
+ if (this.encodingLevel === "structuredClonable" || this.encodingLevel === "jsonCompatibleWithBytes") return ["bytes", bytes];
1018
1026
  if (bytes.toBase64) return ["bytes", bytes.toBase64({ omitPadding: true })];
1019
1027
  let b64;
1020
1028
  if (typeof Buffer !== "undefined") b64 = (bytes instanceof Buffer ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)).toString("base64");
@@ -1139,7 +1147,9 @@ var Devaluator = class Devaluator {
1139
1147
  } else if (rewritten && rewritten.stack) result.push(rewritten.stack);
1140
1148
  return result;
1141
1149
  }
1142
- case "undefined": return ["undefined"];
1150
+ case "undefined":
1151
+ if (this.encodingLevel === "structuredClonable") return;
1152
+ return ["undefined"];
1143
1153
  case "stub":
1144
1154
  case "rpc-promise": {
1145
1155
  if (!this.source) throw new Error("Can't serialize RPC stubs in this context.");
@@ -1222,8 +1232,10 @@ function streamToBlobPromise(stream, type) {
1222
1232
  }
1223
1233
  var Evaluator = class Evaluator {
1224
1234
  importer;
1225
- constructor(importer) {
1235
+ encodingLevel;
1236
+ constructor(importer, encodingLevel = "string") {
1226
1237
  this.importer = importer;
1238
+ this.encodingLevel = encodingLevel;
1227
1239
  }
1228
1240
  hooks = [];
1229
1241
  promises = [];
@@ -1241,6 +1253,9 @@ var Evaluator = class Evaluator {
1241
1253
  return this.evaluate(structuredClone(value));
1242
1254
  }
1243
1255
  evaluateImpl(value, parent, property) {
1256
+ if (this.encodingLevel === "structuredClonable") {
1257
+ if (value instanceof Date || typeof value === "bigint") return value;
1258
+ }
1244
1259
  if (value instanceof Array) {
1245
1260
  if (value.length == 1 && value[0] instanceof Array) {
1246
1261
  let result = value[0];
@@ -1255,6 +1270,7 @@ var Evaluator = class Evaluator {
1255
1270
  if (typeof value[1] == "number") return new Date(value[1]);
1256
1271
  break;
1257
1272
  case "bytes":
1273
+ if (value[1] instanceof Uint8Array) return value[1];
1258
1274
  if (typeof value[1] == "string") if (typeof Buffer !== "undefined") return Buffer.from(value[1], "base64");
1259
1275
  else if (Uint8Array.fromBase64) return Uint8Array.fromBase64(value[1]);
1260
1276
  else {
@@ -1455,6 +1471,47 @@ function deserialize(value) {
1455
1471
 
1456
1472
  //#endregion
1457
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
+ }
1458
1515
  var ImportTableEntry = class {
1459
1516
  session;
1460
1517
  importId;
@@ -1620,9 +1677,19 @@ var RpcSessionImpl = class {
1620
1677
  onBatchDone;
1621
1678
  pullCount = 0;
1622
1679
  onBrokenCallbacks = [];
1680
+ encodingLevel;
1623
1681
  constructor(transport, mainHook, options) {
1624
1682
  this.transport = transport;
1625
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;
1626
1693
  this.exports.push({
1627
1694
  hook: mainHook,
1628
1695
  refcount: 1
@@ -1703,7 +1770,7 @@ var RpcSessionImpl = class {
1703
1770
  let autoRelease = exp.autoRelease;
1704
1771
  ++this.pullCount;
1705
1772
  exp.pull = resolve().then((payload) => {
1706
- let value = Devaluator.devaluate(payload.value, void 0, this, payload);
1773
+ let value = Devaluator.devaluate(payload.value, void 0, this, payload, this.encodingLevel);
1707
1774
  this.send([
1708
1775
  "resolve",
1709
1776
  exportId,
@@ -1714,7 +1781,7 @@ var RpcSessionImpl = class {
1714
1781
  this.send([
1715
1782
  "reject",
1716
1783
  exportId,
1717
- Devaluator.devaluate(error, void 0, this)
1784
+ Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
1718
1785
  ]);
1719
1786
  if (autoRelease) this.releaseExport(exportId, 1);
1720
1787
  }).catch((error) => {
@@ -1722,7 +1789,7 @@ var RpcSessionImpl = class {
1722
1789
  this.send([
1723
1790
  "reject",
1724
1791
  exportId,
1725
- Devaluator.devaluate(error, void 0, this)
1792
+ Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
1726
1793
  ]);
1727
1794
  if (autoRelease) this.releaseExport(exportId, 1);
1728
1795
  } catch (error2) {
@@ -1778,17 +1845,33 @@ var RpcSessionImpl = class {
1778
1845
  }
1779
1846
  send(msg) {
1780
1847
  if (this.abortReason !== void 0) return 0;
1781
- let msgText;
1782
- try {
1783
- msgText = JSON.stringify(msg);
1784
- } catch (err) {
1848
+ if (this.encodingLevel === "string") {
1849
+ let msgText;
1785
1850
  try {
1786
- this.abort(err);
1787
- } catch (err2) {}
1788
- 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;
1789
1874
  }
1790
- this.transport.send(msgText).catch((err) => this.abort(err, false));
1791
- return msgText.length;
1792
1875
  }
1793
1876
  sendCall(id, path, args) {
1794
1877
  if (this.abortReason) throw this.abortReason;
@@ -1798,7 +1881,7 @@ var RpcSessionImpl = class {
1798
1881
  path
1799
1882
  ];
1800
1883
  if (args) {
1801
- let devalue = Devaluator.devaluate(args.value, void 0, this, args);
1884
+ let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
1802
1885
  value.push(devalue[0]);
1803
1886
  }
1804
1887
  this.send(["push", value]);
@@ -1813,9 +1896,11 @@ var RpcSessionImpl = class {
1813
1896
  id,
1814
1897
  path
1815
1898
  ];
1816
- let devalue = Devaluator.devaluate(args.value, void 0, this, args);
1899
+ let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
1817
1900
  value.push(devalue[0]);
1818
- 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);
1819
1904
  let importId = this.imports.length;
1820
1905
  let entry = new ImportTableEntry(this, importId, true);
1821
1906
  entry.remoteRefcount = 0;
@@ -1871,7 +1956,14 @@ var RpcSessionImpl = class {
1871
1956
  this.cancelReadLoop?.(error);
1872
1957
  this.cancelReadLoop = void 0;
1873
1958
  if (trySendAbortMessage) try {
1874
- 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
+ }
1875
1967
  } catch (err) {}
1876
1968
  if (error === void 0) error = "undefined";
1877
1969
  this.abortReason = error;
@@ -1893,18 +1985,18 @@ var RpcSessionImpl = class {
1893
1985
  while (!this.abortReason) {
1894
1986
  let readCanceled = Promise.withResolvers();
1895
1987
  this.cancelReadLoop = readCanceled.reject;
1896
- let msgText;
1988
+ let raw;
1897
1989
  try {
1898
- msgText = await Promise.race([this.transport.receive(), readCanceled.promise]);
1990
+ raw = await Promise.race([this.transport.receive(), readCanceled.promise]);
1899
1991
  } finally {
1900
1992
  if (this.cancelReadLoop === readCanceled.reject) this.cancelReadLoop = void 0;
1901
1993
  }
1902
- let msg = JSON.parse(msgText);
1903
1994
  if (this.abortReason) break;
1995
+ let msg = this.encodingLevel === "string" ? JSON.parse(raw) : raw;
1904
1996
  if (msg instanceof Array) switch (msg[0]) {
1905
1997
  case "push":
1906
1998
  if (msg.length > 1) {
1907
- let hook = new PayloadStubHook(new Evaluator(this).evaluate(msg[1]));
1999
+ let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
1908
2000
  hook.ignoreUnhandledRejections();
1909
2001
  this.exports.push({
1910
2002
  hook,
@@ -1915,7 +2007,7 @@ var RpcSessionImpl = class {
1915
2007
  break;
1916
2008
  case "stream":
1917
2009
  if (msg.length > 1) {
1918
- let hook = new PayloadStubHook(new Evaluator(this).evaluate(msg[1]));
2010
+ let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
1919
2011
  hook.ignoreUnhandledRejections();
1920
2012
  let exportId = this.exports.length;
1921
2013
  this.exports.push({
@@ -1950,13 +2042,13 @@ var RpcSessionImpl = class {
1950
2042
  let importId = msg[1];
1951
2043
  if (typeof importId == "number" && msg.length > 2) {
1952
2044
  let imp = this.imports[importId];
1953
- 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])));
1954
2046
  else {
1955
- let payload = new Evaluator(this).evaluate(msg[2]);
2047
+ let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[2]);
1956
2048
  payload.dispose();
1957
2049
  imp.resolve(new ErrorStubHook(payload.value));
1958
2050
  }
1959
- 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();
1960
2052
  continue;
1961
2053
  }
1962
2054
  break;
@@ -1971,7 +2063,7 @@ var RpcSessionImpl = class {
1971
2063
  break;
1972
2064
  }
1973
2065
  case "abort": {
1974
- let payload = new Evaluator(this).evaluate(msg[1]);
2066
+ let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[1]);
1975
2067
  payload.dispose();
1976
2068
  this.abort(payload, false);
1977
2069
  break;
@@ -2043,9 +2135,14 @@ function newWorkersWebSocketRpcResponse(request, localMain, options) {
2043
2135
  webSocket: pair[1]
2044
2136
  });
2045
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
+ */
2046
2142
  var WebSocketTransport = class {
2047
2143
  constructor(webSocket) {
2048
2144
  this.#webSocket = webSocket;
2145
+ webSocket.binaryType = "arraybuffer";
2049
2146
  if (webSocket.readyState === WebSocket.CONNECTING) {
2050
2147
  this.#sendQueue = [];
2051
2148
  webSocket.addEventListener("open", (event) => {
@@ -2058,12 +2155,12 @@ var WebSocketTransport = class {
2058
2155
  });
2059
2156
  }
2060
2157
  webSocket.addEventListener("message", (event) => {
2061
- 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) {
2062
2159
  this.#receiveResolver(event.data);
2063
2160
  this.#receiveResolver = void 0;
2064
2161
  this.#receiveRejecter = void 0;
2065
2162
  } else this.#receiveQueue.push(event.data);
2066
- 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."));
2067
2164
  });
2068
2165
  webSocket.addEventListener("close", (event) => {
2069
2166
  this.#receivedError(/* @__PURE__ */ new Error(`Peer closed WebSocket: ${event.code} ${event.reason}`));
@@ -2078,13 +2175,13 @@ var WebSocketTransport = class {
2078
2175
  #receiveRejecter;
2079
2176
  #receiveQueue = [];
2080
2177
  #error;
2081
- async send(message) {
2178
+ send(message) {
2082
2179
  if (this.#sendQueue === void 0) this.#webSocket.send(message);
2083
2180
  else this.#sendQueue.push(message);
2084
2181
  }
2085
- async receive() {
2086
- if (this.#receiveQueue.length > 0) return this.#receiveQueue.shift();
2087
- 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);
2088
2185
  else return new Promise((resolve, reject) => {
2089
2186
  this.#receiveResolver = resolve;
2090
2187
  this.#receiveRejecter = reject;
@@ -2119,7 +2216,7 @@ var BatchClientTransport = class {
2119
2216
  #aborted;
2120
2217
  #batchToSend = [];
2121
2218
  #batchToReceive = null;
2122
- async send(message) {
2219
+ send(message) {
2123
2220
  if (this.#batchToSend !== null) this.#batchToSend.push(message);
2124
2221
  }
2125
2222
  async receive() {
@@ -2161,7 +2258,7 @@ var BatchServerTransport = class {
2161
2258
  #batchToSend = [];
2162
2259
  #batchToReceive;
2163
2260
  #allReceived = Promise.withResolvers();
2164
- async send(message) {
2261
+ send(message) {
2165
2262
  this.#batchToSend.push(message);
2166
2263
  }
2167
2264
  async receive() {
@@ -2210,7 +2307,11 @@ async function newHttpBatchRpcResponse(request, localMain, options) {
2210
2307
  * @param options Optional RPC session options. You can also pass headers to set on the response.
2211
2308
  */
2212
2309
  async function nodeHttpBatchRpcResponse(request, response, localMain, options) {
2213
- 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
+ }
2214
2315
  let body = await new Promise((resolve, reject) => {
2215
2316
  let chunks = [];
2216
2317
  request.on("data", (chunk) => {
@@ -2235,17 +2336,17 @@ function newMessagePortRpcSession$1(port, localMain, options) {
2235
2336
  return new RpcSession$1(new MessagePortTransport(port), localMain, options).getRemoteMain();
2236
2337
  }
2237
2338
  var MessagePortTransport = class {
2339
+ encodingLevel = "structuredClonable";
2238
2340
  constructor(port) {
2239
2341
  this.#port = port;
2240
2342
  port.start();
2241
2343
  port.addEventListener("message", (event) => {
2242
2344
  if (this.#error) {} else if (event.data === null) this.#receivedError(/* @__PURE__ */ new Error("Peer closed MessagePort connection."));
2243
- else if (typeof event.data === "string") if (this.#receiveResolver) {
2345
+ else if (this.#receiveResolver) {
2244
2346
  this.#receiveResolver(event.data);
2245
2347
  this.#receiveResolver = void 0;
2246
2348
  this.#receiveRejecter = void 0;
2247
2349
  } else this.#receiveQueue.push(event.data);
2248
- else this.#receivedError(/* @__PURE__ */ new TypeError("Received non-string message from MessagePort."));
2249
2350
  });
2250
2351
  port.addEventListener("messageerror", (event) => {
2251
2352
  this.#receivedError(/* @__PURE__ */ new Error("MessagePort message error."));
@@ -2256,7 +2357,7 @@ var MessagePortTransport = class {
2256
2357
  #receiveRejecter;
2257
2358
  #receiveQueue = [];
2258
2359
  #error;
2259
- async send(message) {
2360
+ send(message) {
2260
2361
  if (this.#error) throw this.#error;
2261
2362
  this.#port.postMessage(message);
2262
2363
  }
@@ -2827,6 +2928,7 @@ exports.RpcPromise = RpcPromise;
2827
2928
  exports.RpcSession = RpcSession;
2828
2929
  exports.RpcStub = RpcStub;
2829
2930
  exports.RpcTarget = RpcTarget;
2931
+ exports.WebSocketTransport = WebSocketTransport;
2830
2932
  exports.deserialize = deserialize;
2831
2933
  exports.newHttpBatchRpcResponse = newHttpBatchRpcResponse;
2832
2934
  exports.newHttpBatchRpcSession = newHttpBatchRpcSession;