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.
@@ -996,12 +996,14 @@ const ERROR_TYPES = {
996
996
  var Devaluator = class Devaluator {
997
997
  exporter;
998
998
  source;
999
- constructor(exporter, source) {
999
+ encodingLevel;
1000
+ constructor(exporter, source, encodingLevel) {
1000
1001
  this.exporter = exporter;
1001
1002
  this.source = source;
1003
+ this.encodingLevel = encodingLevel;
1002
1004
  }
1003
- static devaluate(value, parent, exporter = NULL_EXPORTER, source) {
1004
- let devaluator = new Devaluator(exporter, source);
1005
+ static devaluate(value, parent, exporter = NULL_EXPORTER, source, encodingLevel = "string") {
1006
+ let devaluator = new Devaluator(exporter, source, encodingLevel);
1005
1007
  try {
1006
1008
  return devaluator.devaluateImpl(value, parent, 0);
1007
1009
  } catch (err) {
@@ -1024,10 +1026,12 @@ var Devaluator = class Devaluator {
1024
1026
  }
1025
1027
  throw new TypeError(msg);
1026
1028
  }
1027
- case "primitive": if (typeof value === "number" && !isFinite(value)) if (value === Infinity) return ["inf"];
1028
- else if (value === -Infinity) return ["-inf"];
1029
- else return ["nan"];
1030
- else return value;
1029
+ case "primitive": if (typeof value === "number" && !isFinite(value)) {
1030
+ if (this.encodingLevel === "structuredClonable") return value;
1031
+ if (value === Infinity) return ["inf"];
1032
+ else if (value === -Infinity) return ["-inf"];
1033
+ else return ["nan"];
1034
+ } else return value;
1031
1035
  case "object": {
1032
1036
  let object = value;
1033
1037
  let result = {};
@@ -1041,13 +1045,17 @@ var Devaluator = class Devaluator {
1041
1045
  for (let i = 0; i < len; i++) result[i] = this.devaluateImpl(array[i], array, depth + 1);
1042
1046
  return [result];
1043
1047
  }
1044
- case "bigint": return ["bigint", value.toString()];
1048
+ case "bigint":
1049
+ if (this.encodingLevel === "structuredClonable") return value;
1050
+ return ["bigint", value.toString()];
1045
1051
  case "date": {
1052
+ if (this.encodingLevel === "structuredClonable") return value;
1046
1053
  const time = value.getTime();
1047
1054
  return ["date", Number.isNaN(time) ? null : time];
1048
1055
  }
1049
1056
  case "bytes": {
1050
1057
  let bytes = value;
1058
+ if (this.encodingLevel === "structuredClonable" || this.encodingLevel === "jsonCompatibleWithBytes") return ["bytes", bytes];
1051
1059
  if (bytes.toBase64) return ["bytes", bytes.toBase64({ omitPadding: true })];
1052
1060
  let b64;
1053
1061
  if (typeof Buffer !== "undefined") b64 = (bytes instanceof Buffer ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)).toString("base64");
@@ -1172,7 +1180,9 @@ var Devaluator = class Devaluator {
1172
1180
  } else if (rewritten && rewritten.stack) result.push(rewritten.stack);
1173
1181
  return result;
1174
1182
  }
1175
- case "undefined": return ["undefined"];
1183
+ case "undefined":
1184
+ if (this.encodingLevel === "structuredClonable") return;
1185
+ return ["undefined"];
1176
1186
  case "stub":
1177
1187
  case "rpc-promise": {
1178
1188
  if (!this.source) throw new Error("Can't serialize RPC stubs in this context.");
@@ -1255,8 +1265,10 @@ function streamToBlobPromise(stream, type) {
1255
1265
  }
1256
1266
  var Evaluator = class Evaluator {
1257
1267
  importer;
1258
- constructor(importer) {
1268
+ encodingLevel;
1269
+ constructor(importer, encodingLevel = "string") {
1259
1270
  this.importer = importer;
1271
+ this.encodingLevel = encodingLevel;
1260
1272
  }
1261
1273
  hooks = [];
1262
1274
  promises = [];
@@ -1274,6 +1286,9 @@ var Evaluator = class Evaluator {
1274
1286
  return this.evaluate(structuredClone(value));
1275
1287
  }
1276
1288
  evaluateImpl(value, parent, property) {
1289
+ if (this.encodingLevel === "structuredClonable") {
1290
+ if (value instanceof Date || typeof value === "bigint") return value;
1291
+ }
1277
1292
  if (value instanceof Array) {
1278
1293
  if (value.length == 1 && value[0] instanceof Array) {
1279
1294
  let result = value[0];
@@ -1288,6 +1303,7 @@ var Evaluator = class Evaluator {
1288
1303
  if (typeof value[1] == "number") return new Date(value[1]);
1289
1304
  break;
1290
1305
  case "bytes":
1306
+ if (value[1] instanceof Uint8Array) return value[1];
1291
1307
  if (typeof value[1] == "string") if (typeof Buffer !== "undefined") return Buffer.from(value[1], "base64");
1292
1308
  else if (Uint8Array.fromBase64) return Uint8Array.fromBase64(value[1]);
1293
1309
  else {
@@ -1488,6 +1504,47 @@ function deserialize(value) {
1488
1504
 
1489
1505
  //#endregion
1490
1506
  //#region src/rpc.ts
1507
+ const ESTIMATED_OBJECT_OVERHEAD = 16;
1508
+ const ESTIMATED_ENTRY_OVERHEAD = 8;
1509
+ const ESTIMATED_BINARY_OVERHEAD = 16;
1510
+ const MAX_ESTIMATE_DEPTH = 64;
1511
+ function estimateStringSize(value) {
1512
+ return 2 + value.length * 3;
1513
+ }
1514
+ function estimateEncodedSize(value, seen, depth = 0) {
1515
+ if (depth >= MAX_ESTIMATE_DEPTH) return ESTIMATED_ENTRY_OVERHEAD;
1516
+ switch (typeof value) {
1517
+ case "string": return estimateStringSize(value);
1518
+ case "number": return 16;
1519
+ case "bigint": return 16;
1520
+ case "boolean": return 8;
1521
+ case "undefined": return 16;
1522
+ case "object": {
1523
+ if (value === null) return 8;
1524
+ if (ArrayBuffer.isView(value)) return ESTIMATED_BINARY_OVERHEAD + value.byteLength;
1525
+ if (value instanceof ArrayBuffer) return ESTIMATED_BINARY_OVERHEAD + value.byteLength;
1526
+ if (typeof Blob !== "undefined" && value instanceof Blob) return ESTIMATED_BINARY_OVERHEAD + value.size;
1527
+ if (value instanceof Date) return 16;
1528
+ seen ??= /* @__PURE__ */ new WeakSet();
1529
+ if (seen.has(value)) return ESTIMATED_ENTRY_OVERHEAD;
1530
+ seen.add(value);
1531
+ if (value instanceof Array) {
1532
+ let size = ESTIMATED_OBJECT_OVERHEAD;
1533
+ for (let item of value) size += ESTIMATED_ENTRY_OVERHEAD + estimateEncodedSize(item, seen, depth + 1);
1534
+ return size;
1535
+ }
1536
+ if (value instanceof Error) {
1537
+ let size = ESTIMATED_OBJECT_OVERHEAD + estimateStringSize(value.name) + estimateStringSize(value.message) + estimateStringSize(value.stack ?? "");
1538
+ for (let key of Object.keys(value)) size += ESTIMATED_ENTRY_OVERHEAD + estimateStringSize(key) + estimateEncodedSize(value[key], seen, depth + 1);
1539
+ return size;
1540
+ }
1541
+ let size = ESTIMATED_OBJECT_OVERHEAD;
1542
+ for (let key of Object.keys(value)) size += ESTIMATED_ENTRY_OVERHEAD + estimateStringSize(key) + estimateEncodedSize(value[key], seen, depth + 1);
1543
+ return size;
1544
+ }
1545
+ default: return 16;
1546
+ }
1547
+ }
1491
1548
  var ImportTableEntry = class {
1492
1549
  session;
1493
1550
  importId;
@@ -1653,9 +1710,19 @@ var RpcSessionImpl = class {
1653
1710
  onBatchDone;
1654
1711
  pullCount = 0;
1655
1712
  onBrokenCallbacks = [];
1713
+ encodingLevel;
1656
1714
  constructor(transport, mainHook, options) {
1657
1715
  this.transport = transport;
1658
1716
  this.options = options;
1717
+ let level = "string";
1718
+ if ("encodingLevel" in transport) {
1719
+ let raw = transport.encodingLevel;
1720
+ if (raw !== void 0) {
1721
+ if (raw !== "string" && raw !== "jsonCompatible" && raw !== "jsonCompatibleWithBytes" && raw !== "structuredClonable") throw new TypeError(`Unknown transport encodingLevel: ${String(raw)}`);
1722
+ level = raw;
1723
+ }
1724
+ }
1725
+ this.encodingLevel = level;
1659
1726
  this.exports.push({
1660
1727
  hook: mainHook,
1661
1728
  refcount: 1
@@ -1736,7 +1803,7 @@ var RpcSessionImpl = class {
1736
1803
  let autoRelease = exp.autoRelease;
1737
1804
  ++this.pullCount;
1738
1805
  exp.pull = resolve().then((payload) => {
1739
- let value = Devaluator.devaluate(payload.value, void 0, this, payload);
1806
+ let value = Devaluator.devaluate(payload.value, void 0, this, payload, this.encodingLevel);
1740
1807
  this.send([
1741
1808
  "resolve",
1742
1809
  exportId,
@@ -1747,7 +1814,7 @@ var RpcSessionImpl = class {
1747
1814
  this.send([
1748
1815
  "reject",
1749
1816
  exportId,
1750
- Devaluator.devaluate(error, void 0, this)
1817
+ Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
1751
1818
  ]);
1752
1819
  if (autoRelease) this.releaseExport(exportId, 1);
1753
1820
  }).catch((error) => {
@@ -1755,7 +1822,7 @@ var RpcSessionImpl = class {
1755
1822
  this.send([
1756
1823
  "reject",
1757
1824
  exportId,
1758
- Devaluator.devaluate(error, void 0, this)
1825
+ Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)
1759
1826
  ]);
1760
1827
  if (autoRelease) this.releaseExport(exportId, 1);
1761
1828
  } catch (error2) {
@@ -1811,17 +1878,33 @@ var RpcSessionImpl = class {
1811
1878
  }
1812
1879
  send(msg) {
1813
1880
  if (this.abortReason !== void 0) return 0;
1814
- let msgText;
1815
- try {
1816
- msgText = JSON.stringify(msg);
1817
- } catch (err) {
1881
+ if (this.encodingLevel === "string") {
1882
+ let msgText;
1818
1883
  try {
1819
- this.abort(err);
1820
- } catch (err2) {}
1821
- throw err;
1884
+ msgText = JSON.stringify(msg);
1885
+ } catch (err) {
1886
+ try {
1887
+ this.abort(err);
1888
+ } catch (err2) {}
1889
+ throw err;
1890
+ }
1891
+ try {
1892
+ let sent = this.transport.send(msgText);
1893
+ if (sent !== void 0 && typeof sent.catch === "function") sent.catch((err) => this.abort(err, false));
1894
+ } catch (err) {
1895
+ queueMicrotask(() => this.abort(err, false));
1896
+ }
1897
+ return msgText.length;
1898
+ } else try {
1899
+ let size = this.transport.send(msg);
1900
+ if (typeof size === "number") return size;
1901
+ let thenable = size;
1902
+ if (thenable && typeof thenable.then === "function") Promise.resolve(thenable).catch((err) => this.abort(err, false));
1903
+ return;
1904
+ } catch (err) {
1905
+ queueMicrotask(() => this.abort(err, false));
1906
+ return;
1822
1907
  }
1823
- this.transport.send(msgText).catch((err) => this.abort(err, false));
1824
- return msgText.length;
1825
1908
  }
1826
1909
  sendCall(id, path, args) {
1827
1910
  if (this.abortReason) throw this.abortReason;
@@ -1831,7 +1914,7 @@ var RpcSessionImpl = class {
1831
1914
  path
1832
1915
  ];
1833
1916
  if (args) {
1834
- let devalue = Devaluator.devaluate(args.value, void 0, this, args);
1917
+ let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
1835
1918
  value.push(devalue[0]);
1836
1919
  }
1837
1920
  this.send(["push", value]);
@@ -1846,9 +1929,11 @@ var RpcSessionImpl = class {
1846
1929
  id,
1847
1930
  path
1848
1931
  ];
1849
- let devalue = Devaluator.devaluate(args.value, void 0, this, args);
1932
+ let devalue = Devaluator.devaluate(args.value, void 0, this, args, this.encodingLevel);
1850
1933
  value.push(devalue[0]);
1851
- let size = this.send(["stream", value]);
1934
+ let msg = ["stream", value];
1935
+ let size = this.send(msg);
1936
+ if (size === void 0) size = estimateEncodedSize(msg);
1852
1937
  let importId = this.imports.length;
1853
1938
  let entry = new ImportTableEntry(this, importId, true);
1854
1939
  entry.remoteRefcount = 0;
@@ -1904,7 +1989,14 @@ var RpcSessionImpl = class {
1904
1989
  this.cancelReadLoop?.(error);
1905
1990
  this.cancelReadLoop = void 0;
1906
1991
  if (trySendAbortMessage) try {
1907
- this.transport.send(JSON.stringify(["abort", Devaluator.devaluate(error, void 0, this)])).catch((err) => {});
1992
+ let abortMsg = ["abort", Devaluator.devaluate(error, void 0, this, void 0, this.encodingLevel)];
1993
+ if (this.encodingLevel === "string") {
1994
+ let sent = this.transport.send(JSON.stringify(abortMsg));
1995
+ if (sent !== void 0 && typeof sent.catch === "function") sent.catch((err) => {});
1996
+ } else {
1997
+ let result = this.transport.send(abortMsg);
1998
+ if (result && typeof result.then === "function") Promise.resolve(result).catch((err) => {});
1999
+ }
1908
2000
  } catch (err) {}
1909
2001
  if (error === void 0) error = "undefined";
1910
2002
  this.abortReason = error;
@@ -1926,18 +2018,18 @@ var RpcSessionImpl = class {
1926
2018
  while (!this.abortReason) {
1927
2019
  let readCanceled = Promise.withResolvers();
1928
2020
  this.cancelReadLoop = readCanceled.reject;
1929
- let msgText;
2021
+ let raw;
1930
2022
  try {
1931
- msgText = await Promise.race([this.transport.receive(), readCanceled.promise]);
2023
+ raw = await Promise.race([this.transport.receive(), readCanceled.promise]);
1932
2024
  } finally {
1933
2025
  if (this.cancelReadLoop === readCanceled.reject) this.cancelReadLoop = void 0;
1934
2026
  }
1935
- let msg = JSON.parse(msgText);
1936
2027
  if (this.abortReason) break;
2028
+ let msg = this.encodingLevel === "string" ? JSON.parse(raw) : raw;
1937
2029
  if (msg instanceof Array) switch (msg[0]) {
1938
2030
  case "push":
1939
2031
  if (msg.length > 1) {
1940
- let hook = new PayloadStubHook(new Evaluator(this).evaluate(msg[1]));
2032
+ let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
1941
2033
  hook.ignoreUnhandledRejections();
1942
2034
  this.exports.push({
1943
2035
  hook,
@@ -1948,7 +2040,7 @@ var RpcSessionImpl = class {
1948
2040
  break;
1949
2041
  case "stream":
1950
2042
  if (msg.length > 1) {
1951
- let hook = new PayloadStubHook(new Evaluator(this).evaluate(msg[1]));
2043
+ let hook = new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[1]));
1952
2044
  hook.ignoreUnhandledRejections();
1953
2045
  let exportId = this.exports.length;
1954
2046
  this.exports.push({
@@ -1983,13 +2075,13 @@ var RpcSessionImpl = class {
1983
2075
  let importId = msg[1];
1984
2076
  if (typeof importId == "number" && msg.length > 2) {
1985
2077
  let imp = this.imports[importId];
1986
- if (imp) if (msg[0] == "resolve") imp.resolve(new PayloadStubHook(new Evaluator(this).evaluate(msg[2])));
2078
+ if (imp) if (msg[0] == "resolve") imp.resolve(new PayloadStubHook(new Evaluator(this, this.encodingLevel).evaluate(msg[2])));
1987
2079
  else {
1988
- let payload = new Evaluator(this).evaluate(msg[2]);
2080
+ let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[2]);
1989
2081
  payload.dispose();
1990
2082
  imp.resolve(new ErrorStubHook(payload.value));
1991
2083
  }
1992
- else if (msg[0] == "resolve") new Evaluator(this).evaluate(msg[2]).dispose();
2084
+ else if (msg[0] == "resolve") new Evaluator(this, this.encodingLevel).evaluate(msg[2]).dispose();
1993
2085
  continue;
1994
2086
  }
1995
2087
  break;
@@ -2004,7 +2096,7 @@ var RpcSessionImpl = class {
2004
2096
  break;
2005
2097
  }
2006
2098
  case "abort": {
2007
- let payload = new Evaluator(this).evaluate(msg[1]);
2099
+ let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[1]);
2008
2100
  payload.dispose();
2009
2101
  this.abort(payload, false);
2010
2102
  break;
@@ -2076,9 +2168,14 @@ function newWorkersWebSocketRpcResponse(request, localMain, options) {
2076
2168
  webSocket: pair[1]
2077
2169
  });
2078
2170
  }
2171
+ /**
2172
+ * Generic WebSocket transport. Default `T = string` is backward-compatible and satisfies
2173
+ * `RpcTransport`. Use `T = ArrayBuffer` as a building block for binary transports.
2174
+ */
2079
2175
  var WebSocketTransport = class {
2080
2176
  constructor(webSocket) {
2081
2177
  this.#webSocket = webSocket;
2178
+ webSocket.binaryType = "arraybuffer";
2082
2179
  if (webSocket.readyState === WebSocket.CONNECTING) {
2083
2180
  this.#sendQueue = [];
2084
2181
  webSocket.addEventListener("open", (event) => {
@@ -2091,12 +2188,12 @@ var WebSocketTransport = class {
2091
2188
  });
2092
2189
  }
2093
2190
  webSocket.addEventListener("message", (event) => {
2094
- if (this.#error) {} else if (typeof event.data === "string") if (this.#receiveResolver) {
2191
+ if (this.#error) {} else if (typeof event.data === "string" || event.data instanceof ArrayBuffer) if (this.#receiveResolver) {
2095
2192
  this.#receiveResolver(event.data);
2096
2193
  this.#receiveResolver = void 0;
2097
2194
  this.#receiveRejecter = void 0;
2098
2195
  } else this.#receiveQueue.push(event.data);
2099
- else this.#receivedError(/* @__PURE__ */ new TypeError("Received non-string message from WebSocket."));
2196
+ else this.#receivedError(/* @__PURE__ */ new TypeError("Received unexpected message type from WebSocket."));
2100
2197
  });
2101
2198
  webSocket.addEventListener("close", (event) => {
2102
2199
  this.#receivedError(/* @__PURE__ */ new Error(`Peer closed WebSocket: ${event.code} ${event.reason}`));
@@ -2111,13 +2208,13 @@ var WebSocketTransport = class {
2111
2208
  #receiveRejecter;
2112
2209
  #receiveQueue = [];
2113
2210
  #error;
2114
- async send(message) {
2211
+ send(message) {
2115
2212
  if (this.#sendQueue === void 0) this.#webSocket.send(message);
2116
2213
  else this.#sendQueue.push(message);
2117
2214
  }
2118
- async receive() {
2119
- if (this.#receiveQueue.length > 0) return this.#receiveQueue.shift();
2120
- else if (this.#error) throw this.#error;
2215
+ receive() {
2216
+ if (this.#receiveQueue.length > 0) return Promise.resolve(this.#receiveQueue.shift());
2217
+ else if (this.#error) return Promise.reject(this.#error);
2121
2218
  else return new Promise((resolve, reject) => {
2122
2219
  this.#receiveResolver = resolve;
2123
2220
  this.#receiveRejecter = reject;
@@ -2152,7 +2249,7 @@ var BatchClientTransport = class {
2152
2249
  #aborted;
2153
2250
  #batchToSend = [];
2154
2251
  #batchToReceive = null;
2155
- async send(message) {
2252
+ send(message) {
2156
2253
  if (this.#batchToSend !== null) this.#batchToSend.push(message);
2157
2254
  }
2158
2255
  async receive() {
@@ -2194,7 +2291,7 @@ var BatchServerTransport = class {
2194
2291
  #batchToSend = [];
2195
2292
  #batchToReceive;
2196
2293
  #allReceived = Promise.withResolvers();
2197
- async send(message) {
2294
+ send(message) {
2198
2295
  this.#batchToSend.push(message);
2199
2296
  }
2200
2297
  async receive() {
@@ -2243,7 +2340,11 @@ async function newHttpBatchRpcResponse(request, localMain, options) {
2243
2340
  * @param options Optional RPC session options. You can also pass headers to set on the response.
2244
2341
  */
2245
2342
  async function nodeHttpBatchRpcResponse(request, response, localMain, options) {
2246
- if (request.method !== "POST") response.writeHead(405, "This endpoint only accepts POST requests.");
2343
+ if (request.method !== "POST") {
2344
+ response.writeHead(405, "This endpoint only accepts POST requests.", options?.headers);
2345
+ response.end();
2346
+ return;
2347
+ }
2247
2348
  let body = await new Promise((resolve, reject) => {
2248
2349
  let chunks = [];
2249
2350
  request.on("data", (chunk) => {
@@ -2268,17 +2369,17 @@ function newMessagePortRpcSession$1(port, localMain, options) {
2268
2369
  return new RpcSession$1(new MessagePortTransport(port), localMain, options).getRemoteMain();
2269
2370
  }
2270
2371
  var MessagePortTransport = class {
2372
+ encodingLevel = "structuredClonable";
2271
2373
  constructor(port) {
2272
2374
  this.#port = port;
2273
2375
  port.start();
2274
2376
  port.addEventListener("message", (event) => {
2275
2377
  if (this.#error) {} else if (event.data === null) this.#receivedError(/* @__PURE__ */ new Error("Peer closed MessagePort connection."));
2276
- else if (typeof event.data === "string") if (this.#receiveResolver) {
2378
+ else if (this.#receiveResolver) {
2277
2379
  this.#receiveResolver(event.data);
2278
2380
  this.#receiveResolver = void 0;
2279
2381
  this.#receiveRejecter = void 0;
2280
2382
  } else this.#receiveQueue.push(event.data);
2281
- else this.#receivedError(/* @__PURE__ */ new TypeError("Received non-string message from MessagePort."));
2282
2383
  });
2283
2384
  port.addEventListener("messageerror", (event) => {
2284
2385
  this.#receivedError(/* @__PURE__ */ new Error("MessagePort message error."));
@@ -2289,7 +2390,7 @@ var MessagePortTransport = class {
2289
2390
  #receiveRejecter;
2290
2391
  #receiveQueue = [];
2291
2392
  #error;
2292
- async send(message) {
2393
+ send(message) {
2293
2394
  if (this.#error) throw this.#error;
2294
2395
  this.#port.postMessage(message);
2295
2396
  }
@@ -2860,6 +2961,7 @@ exports.RpcPromise = RpcPromise;
2860
2961
  exports.RpcSession = RpcSession;
2861
2962
  exports.RpcStub = RpcStub;
2862
2963
  exports.RpcTarget = RpcTarget;
2964
+ exports.WebSocketTransport = WebSocketTransport;
2863
2965
  exports.deserialize = deserialize;
2864
2966
  exports.newHttpBatchRpcResponse = newHttpBatchRpcResponse;
2865
2967
  exports.newHttpBatchRpcSession = newHttpBatchRpcSession;