capnweb 0.7.0 → 0.8.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.
@@ -89,6 +89,7 @@ type BaseType =
89
89
  | Date
90
90
  | Error
91
91
  | RegExp
92
+ | Blob
92
93
  | ReadableStream<Uint8Array>
93
94
  | WritableStream<any> // Chunk type can be any RPC-compatible type
94
95
  | Request
@@ -89,6 +89,7 @@ type BaseType =
89
89
  | Date
90
90
  | Error
91
91
  | RegExp
92
+ | Blob
92
93
  | ReadableStream<Uint8Array>
93
94
  | WritableStream<any> // Chunk type can be any RPC-compatible type
94
95
  | Request
@@ -93,6 +93,8 @@ function typeForRpc(value) {
93
93
  return "request";
94
94
  case Response.prototype:
95
95
  return "response";
96
+ case Blob.prototype:
97
+ return "blob";
96
98
  // TODO: All other structured clone types.
97
99
  case RpcStub.prototype:
98
100
  return "stub";
@@ -563,6 +565,7 @@ var RpcPayload = class _RpcPayload {
563
565
  case "bigint":
564
566
  case "date":
565
567
  case "bytes":
568
+ case "blob":
566
569
  case "error":
567
570
  case "undefined":
568
571
  return value;
@@ -799,6 +802,7 @@ var RpcPayload = class _RpcPayload {
799
802
  case "primitive":
800
803
  case "bigint":
801
804
  case "bytes":
805
+ case "blob":
802
806
  case "date":
803
807
  case "error":
804
808
  case "undefined":
@@ -901,6 +905,7 @@ var RpcPayload = class _RpcPayload {
901
905
  case "primitive":
902
906
  case "bigint":
903
907
  case "bytes":
908
+ case "blob":
904
909
  case "date":
905
910
  case "error":
906
911
  case "undefined":
@@ -992,6 +997,7 @@ function followPath(value, parent, path, owner) {
992
997
  case "primitive":
993
998
  case "bigint":
994
999
  case "bytes":
1000
+ case "blob":
995
1001
  case "date":
996
1002
  case "error":
997
1003
  case "headers":
@@ -1318,6 +1324,10 @@ var NullExporter = class {
1318
1324
  }
1319
1325
  };
1320
1326
  var NULL_EXPORTER = new NullExporter();
1327
+ async function streamToBlob(stream, type) {
1328
+ let b = await new Response(stream).blob();
1329
+ return b.type === type ? b : b.slice(0, b.size, type);
1330
+ }
1321
1331
  var ERROR_TYPES = {
1322
1332
  Error,
1323
1333
  EvalError,
@@ -1405,8 +1415,10 @@ var Devaluator = class _Devaluator {
1405
1415
  }
1406
1416
  case "bigint":
1407
1417
  return ["bigint", value.toString()];
1408
- case "date":
1409
- return ["date", value.getTime()];
1418
+ case "date": {
1419
+ const time = value.getTime();
1420
+ return ["date", Number.isNaN(time) ? null : time];
1421
+ }
1410
1422
  case "bytes": {
1411
1423
  let bytes = value;
1412
1424
  if (bytes.toBase64) {
@@ -1492,14 +1504,52 @@ var Devaluator = class _Devaluator {
1492
1504
  }
1493
1505
  return ["response", body, init];
1494
1506
  }
1507
+ case "blob": {
1508
+ let blob = value;
1509
+ let readable = blob.stream();
1510
+ let hook = streamImpl.createReadableStreamHook(readable);
1511
+ let importId = this.exporter.createPipe(readable, hook);
1512
+ return ["blob", blob.type, ["readable", importId]];
1513
+ }
1495
1514
  case "error": {
1496
1515
  let e = value;
1497
1516
  let rewritten = this.exporter.onSendError(e);
1498
1517
  if (rewritten) {
1499
1518
  e = rewritten;
1500
1519
  }
1520
+ let anyE = e;
1521
+ let props;
1522
+ let captureProp = (key, val) => {
1523
+ let exportsBefore = this.exports?.length ?? 0;
1524
+ try {
1525
+ let encoded = this.devaluateImpl(val, e, depth + 1);
1526
+ if (!props) props = {};
1527
+ props[key] = encoded;
1528
+ } catch (err) {
1529
+ if (this.exports && this.exports.length > exportsBefore) {
1530
+ let tail = this.exports.splice(exportsBefore);
1531
+ try {
1532
+ this.exporter.unexport(tail);
1533
+ } catch (err2) {
1534
+ }
1535
+ }
1536
+ }
1537
+ };
1538
+ for (let key of Object.keys(e)) {
1539
+ if (key === "name" || key === "message" || key === "stack") continue;
1540
+ captureProp(key, anyE[key]);
1541
+ }
1542
+ if ("cause" in e) {
1543
+ captureProp("cause", anyE.cause);
1544
+ }
1545
+ if (e instanceof AggregateError) {
1546
+ captureProp("errors", e.errors);
1547
+ }
1501
1548
  let result = ["error", e.name, e.message];
1502
- if (rewritten && rewritten.stack) {
1549
+ if (props) {
1550
+ result.push(rewritten && rewritten.stack ? rewritten.stack : null);
1551
+ result.push(props);
1552
+ } else if (rewritten && rewritten.stack) {
1503
1553
  result.push(rewritten.stack);
1504
1554
  }
1505
1555
  return result;
@@ -1599,6 +1649,12 @@ function fixBrokenRequestBody(request, body) {
1599
1649
  });
1600
1650
  return new RpcPromise(new PromiseStubHook(promise), []);
1601
1651
  }
1652
+ function streamToBlobPromise(stream, type) {
1653
+ let promise = streamToBlob(stream, type).then((blob) => {
1654
+ return new PayloadStubHook(RpcPayload.fromAppReturn(blob));
1655
+ });
1656
+ return new RpcPromise(new PromiseStubHook(promise), []);
1657
+ }
1602
1658
  var Evaluator = class _Evaluator {
1603
1659
  constructor(importer) {
1604
1660
  this.importer = importer;
@@ -1634,6 +1690,9 @@ var Evaluator = class _Evaluator {
1634
1690
  }
1635
1691
  break;
1636
1692
  case "date":
1693
+ if (value[1] === null) {
1694
+ return /* @__PURE__ */ new Date(NaN);
1695
+ }
1637
1696
  if (typeof value[1] == "number") {
1638
1697
  return new Date(value[1]);
1639
1698
  }
@@ -1659,10 +1718,22 @@ var Evaluator = class _Evaluator {
1659
1718
  case "error":
1660
1719
  if (value.length >= 3 && typeof value[1] === "string" && typeof value[2] === "string") {
1661
1720
  let cls = ERROR_TYPES[value[1]] || Error;
1662
- let result = new cls(value[2]);
1721
+ let result = cls === AggregateError ? new cls([], value[2]) : new cls(value[2]);
1663
1722
  if (typeof value[3] === "string") {
1664
1723
  result.stack = value[3];
1665
1724
  }
1725
+ if (value.length >= 5) {
1726
+ let props = value[4];
1727
+ if (!props || typeof props !== "object" || Array.isArray(props)) {
1728
+ break;
1729
+ }
1730
+ let anyResult = result;
1731
+ let propsObj = props;
1732
+ for (let key of Object.keys(propsObj)) {
1733
+ if (key === "name" || key === "message" || key === "stack") continue;
1734
+ anyResult[key] = this.evaluateImpl(propsObj[key], result, key);
1735
+ }
1736
+ }
1666
1737
  return result;
1667
1738
  }
1668
1739
  break;
@@ -1727,6 +1798,17 @@ var Evaluator = class _Evaluator {
1727
1798
  }
1728
1799
  return new Response(body, init);
1729
1800
  }
1801
+ case "blob": {
1802
+ if (value.length !== 3 || typeof value[1] !== "string") break;
1803
+ let contentType = value[1];
1804
+ let content = this.evaluateImpl(value[2], parent, property);
1805
+ if (!(content instanceof ReadableStream)) {
1806
+ throw new TypeError("Blob content must be serialized as a ReadableStream.");
1807
+ }
1808
+ let promise = streamToBlobPromise(content, contentType);
1809
+ this.promises.push({ promise, parent, property });
1810
+ return promise;
1811
+ }
1730
1812
  case "import":
1731
1813
  case "pipeline": {
1732
1814
  if (value.length < 2 || value.length > 4) {
@@ -2067,12 +2149,7 @@ var RpcSessionImpl = class {
2067
2149
  this.options = options;
2068
2150
  this.exports.push({ hook: mainHook, refcount: 1 });
2069
2151
  this.imports.push(new ImportTableEntry(this, 0, false));
2070
- let rejectFunc;
2071
- let abortPromise = new Promise((resolve, reject) => {
2072
- rejectFunc = reject;
2073
- });
2074
- this.cancelReadLoop = rejectFunc;
2075
- this.readLoop(abortPromise).catch((err) => this.abort(err));
2152
+ this.readLoop().catch((err) => this.abort(err));
2076
2153
  }
2077
2154
  exports = [];
2078
2155
  reverseExports = /* @__PURE__ */ new Map();
@@ -2356,7 +2433,8 @@ var RpcSessionImpl = class {
2356
2433
  }
2357
2434
  abort(error, trySendAbortMessage = true) {
2358
2435
  if (this.abortReason !== void 0) return;
2359
- this.cancelReadLoop(error);
2436
+ this.cancelReadLoop?.(error);
2437
+ this.cancelReadLoop = void 0;
2360
2438
  if (trySendAbortMessage) {
2361
2439
  try {
2362
2440
  this.transport.send(JSON.stringify(["abort", Devaluator.devaluate(error, void 0, this)])).catch((err) => {
@@ -2392,9 +2470,19 @@ var RpcSessionImpl = class {
2392
2470
  this.exports[i].hook.dispose();
2393
2471
  }
2394
2472
  }
2395
- async readLoop(abortPromise) {
2473
+ async readLoop() {
2396
2474
  while (!this.abortReason) {
2397
- let msg = JSON.parse(await Promise.race([this.transport.receive(), abortPromise]));
2475
+ let readCanceled = Promise.withResolvers();
2476
+ this.cancelReadLoop = readCanceled.reject;
2477
+ let msgText;
2478
+ try {
2479
+ msgText = await Promise.race([this.transport.receive(), readCanceled.promise]);
2480
+ } finally {
2481
+ if (this.cancelReadLoop === readCanceled.reject) {
2482
+ this.cancelReadLoop = void 0;
2483
+ }
2484
+ }
2485
+ let msg = JSON.parse(msgText);
2398
2486
  if (this.abortReason) break;
2399
2487
  if (msg instanceof Array) {
2400
2488
  switch (msg[0]) {