@vastblast/capnweb 0.4.3 → 0.5.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/README.md CHANGED
@@ -202,12 +202,12 @@ The following types can be passed over RPC (in arguments or return values), and
202
202
  * `Uint8Array`
203
203
  * `Error` and its well-known subclasses
204
204
  * `ReadableStream` and `WritableStream`, with automatic flow control.
205
+ * `Headers`, `Request`, and `Response` from the Fetch API.
205
206
 
206
207
  The following types are not supported as of this writing, but may be added in the future:
207
208
  * `Map` and `Set`
208
209
  * `ArrayBuffer` and typed arrays other than `Uint8Array`
209
210
  * `RegExp`
210
- * `Headers`, `Request`, and `Response`
211
211
 
212
212
  The following are intentionally NOT supported:
213
213
  * Application-defined classes that do not extend `RpcTarget`.
@@ -85,6 +85,12 @@ function typeForRpc(value) {
85
85
  return "writable";
86
86
  case ReadableStream.prototype:
87
87
  return "readable";
88
+ case Headers.prototype:
89
+ return "headers";
90
+ case Request.prototype:
91
+ return "request";
92
+ case Response.prototype:
93
+ return "response";
88
94
  // TODO: All other structured clone types.
89
95
  case RpcStub.prototype:
90
96
  return "stub";
@@ -638,6 +644,22 @@ var RpcPayload = class _RpcPayload {
638
644
  this.hooks.push(hook);
639
645
  return stream;
640
646
  }
647
+ case "headers":
648
+ return new Headers(value);
649
+ case "request": {
650
+ let req = value;
651
+ if (req.body) {
652
+ this.deepCopy(req.body, req, "body", req, dupStubs, owner);
653
+ }
654
+ return new Request(req);
655
+ }
656
+ case "response": {
657
+ let resp = value;
658
+ if (resp.body) {
659
+ this.deepCopy(resp.body, resp, "body", resp, dupStubs, owner);
660
+ }
661
+ return new Response(resp.body, resp);
662
+ }
641
663
  default:
642
664
  throw new Error("unreachable");
643
665
  }
@@ -817,6 +839,18 @@ var RpcPayload = class _RpcPayload {
817
839
  }
818
840
  case "rpc-thenable":
819
841
  return;
842
+ case "headers":
843
+ return;
844
+ case "request": {
845
+ let req = value;
846
+ if (req.body) this.disposeImpl(req.body, req);
847
+ return;
848
+ }
849
+ case "response": {
850
+ let resp = value;
851
+ if (resp.body) this.disposeImpl(resp.body, resp);
852
+ return;
853
+ }
820
854
  case "writable": {
821
855
  let stream = value;
822
856
  let hook = this.rpcTargets?.get(stream);
@@ -872,6 +906,9 @@ var RpcPayload = class _RpcPayload {
872
906
  case "rpc-target":
873
907
  case "writable":
874
908
  case "readable":
909
+ case "headers":
910
+ case "request":
911
+ case "response":
875
912
  return;
876
913
  case "array": {
877
914
  let array = value;
@@ -955,6 +992,9 @@ function followPath(value, parent, path, owner) {
955
992
  case "bytes":
956
993
  case "date":
957
994
  case "error":
995
+ case "headers":
996
+ case "request":
997
+ case "response":
958
998
  value = void 0;
959
999
  break;
960
1000
  case "undefined":
@@ -1376,6 +1416,73 @@ var Devaluator = class _Devaluator {
1376
1416
  ];
1377
1417
  }
1378
1418
  }
1419
+ case "headers":
1420
+ return ["headers", [...value]];
1421
+ case "request": {
1422
+ let req = value;
1423
+ let init = {};
1424
+ if (req.method !== "GET") init.method = req.method;
1425
+ let headers = [...req.headers];
1426
+ if (headers.length > 0) {
1427
+ init.headers = headers;
1428
+ }
1429
+ if (req.body) {
1430
+ init.body = this.devaluateImpl(req.body, req, depth + 1);
1431
+ init.duplex = req.duplex || "half";
1432
+ } else if (req.body === void 0 && !["GET", "HEAD", "OPTIONS", "TRACE", "DELETE"].includes(req.method)) {
1433
+ let bodyPromise = req.arrayBuffer();
1434
+ let readable = new ReadableStream({
1435
+ async start(controller) {
1436
+ try {
1437
+ controller.enqueue(new Uint8Array(await bodyPromise));
1438
+ controller.close();
1439
+ } catch (err) {
1440
+ controller.error(err);
1441
+ }
1442
+ }
1443
+ });
1444
+ let hook = streamImpl.createReadableStreamHook(readable);
1445
+ let importId = this.exporter.createPipe(readable, hook);
1446
+ init.body = ["readable", importId];
1447
+ init.duplex = req.duplex || "half";
1448
+ }
1449
+ if (req.cache && req.cache !== "default") init.cache = req.cache;
1450
+ if (req.redirect !== "follow") init.redirect = req.redirect;
1451
+ if (req.integrity) init.integrity = req.integrity;
1452
+ if (req.mode && req.mode !== "cors") init.mode = req.mode;
1453
+ if (req.credentials && req.credentials !== "same-origin") {
1454
+ init.credentials = req.credentials;
1455
+ }
1456
+ if (req.referrer && req.referrer !== "about:client") init.referrer = req.referrer;
1457
+ if (req.referrerPolicy) init.referrerPolicy = req.referrerPolicy;
1458
+ if (req.keepalive) init.keepalive = req.keepalive;
1459
+ let cfReq = req;
1460
+ if (cfReq.cf) init.cf = cfReq.cf;
1461
+ if (cfReq.encodeResponseBody && cfReq.encodeResponseBody !== "automatic") {
1462
+ init.encodeResponseBody = cfReq.encodeResponseBody;
1463
+ }
1464
+ return ["request", req.url, init];
1465
+ }
1466
+ case "response": {
1467
+ let resp = value;
1468
+ let body = this.devaluateImpl(resp.body, resp, depth + 1);
1469
+ let init = {};
1470
+ if (resp.status !== 200) init.status = resp.status;
1471
+ if (resp.statusText) init.statusText = resp.statusText;
1472
+ let headers = [...resp.headers];
1473
+ if (headers.length > 0) {
1474
+ init.headers = headers;
1475
+ }
1476
+ let cfResp = resp;
1477
+ if (cfResp.cf) init.cf = cfResp.cf;
1478
+ if (cfResp.encodeBody && cfResp.encodeBody !== "automatic") {
1479
+ init.encodeBody = cfResp.encodeBody;
1480
+ }
1481
+ if (cfResp.webSocket) {
1482
+ throw new TypeError("Can't serialize a Response containing a webSocket.");
1483
+ }
1484
+ return ["response", body, init];
1485
+ }
1379
1486
  case "error": {
1380
1487
  let e = value;
1381
1488
  let rewritten = this.exporter.onSendError(e);
@@ -1475,6 +1582,14 @@ var NullImporter = class {
1475
1582
  }
1476
1583
  };
1477
1584
  var NULL_IMPORTER = new NullImporter();
1585
+ function fixBrokenRequestBody(request, body) {
1586
+ let promise = new Response(body).arrayBuffer().then((arrayBuffer) => {
1587
+ let bytes = new Uint8Array(arrayBuffer);
1588
+ let result = new Request(request, { body: bytes });
1589
+ return new PayloadStubHook(RpcPayload.fromAppReturn(result));
1590
+ });
1591
+ return new RpcPromise(new PromiseStubHook(promise), []);
1592
+ }
1478
1593
  var Evaluator = class _Evaluator {
1479
1594
  constructor(importer) {
1480
1595
  this.importer = importer;
@@ -1552,6 +1667,56 @@ var Evaluator = class _Evaluator {
1552
1667
  return -Infinity;
1553
1668
  case "nan":
1554
1669
  return NaN;
1670
+ case "headers":
1671
+ if (value.length === 2 && value[1] instanceof Array) {
1672
+ return new Headers(value[1]);
1673
+ }
1674
+ break;
1675
+ case "request": {
1676
+ if (value.length !== 3 || typeof value[1] !== "string") break;
1677
+ let url = value[1];
1678
+ let init = value[2];
1679
+ if (typeof init !== "object" || init === null) break;
1680
+ if (init.body) {
1681
+ init.body = this.evaluateImpl(init.body, init, "body");
1682
+ if (init.body === null || typeof init.body === "string" || init.body instanceof Uint8Array || init.body instanceof ReadableStream) ; else {
1683
+ throw new TypeError("Request body must be of type ReadableStream.");
1684
+ }
1685
+ }
1686
+ if (init.signal) {
1687
+ init.signal = this.evaluateImpl(init.signal, init, "signal");
1688
+ if (!(init.signal instanceof AbortSignal)) {
1689
+ throw new TypeError("Request siganl must be of type AbortSignal.");
1690
+ }
1691
+ }
1692
+ if (init.headers && !(init.headers instanceof Array)) {
1693
+ throw new TypeError("Request headers must be serialized as an array of pairs.");
1694
+ }
1695
+ let result = new Request(url, init);
1696
+ if (init.body instanceof ReadableStream && result.body === void 0) {
1697
+ let promise = fixBrokenRequestBody(result, init.body);
1698
+ this.promises.push({ promise, parent, property });
1699
+ return promise;
1700
+ } else {
1701
+ return result;
1702
+ }
1703
+ }
1704
+ case "response": {
1705
+ if (value.length !== 3) break;
1706
+ let body = this.evaluateImpl(value[1], parent, property);
1707
+ if (body === null || typeof body === "string" || body instanceof Uint8Array || body instanceof ReadableStream) ; else {
1708
+ throw new TypeError("Response body must be of type ReadableStream.");
1709
+ }
1710
+ let init = value[2];
1711
+ if (typeof init !== "object" || init === null) break;
1712
+ if (init.webSocket) {
1713
+ throw new TypeError("Can't deserialize a Response containing a webSocket.");
1714
+ }
1715
+ if (init.headers && !(init.headers instanceof Array)) {
1716
+ throw new TypeError("Request headers must be serialized as an array of pairs.");
1717
+ }
1718
+ return new Response(body, init);
1719
+ }
1555
1720
  case "import":
1556
1721
  case "pipeline": {
1557
1722
  if (value.length < 2 || value.length > 4) {