capnweb 0.9.0 → 0.10.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 +2 -0
- package/dist/index-bun.cjs +69 -20
- package/dist/index-bun.cjs.map +1 -1
- package/dist/index-bun.d.cts +19 -2
- package/dist/index-bun.d.ts +19 -2
- package/dist/index-bun.js +68 -21
- package/dist/index-bun.js.map +1 -1
- package/dist/index-workers.cjs +69 -20
- package/dist/index-workers.cjs.map +1 -1
- package/dist/index-workers.d.cts +19 -2
- package/dist/index-workers.d.ts +19 -2
- package/dist/index-workers.js +68 -21
- package/dist/index-workers.js.map +1 -1
- package/dist/index.cjs +69 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +68 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -931,6 +931,12 @@ var PromiseStubHook = class PromiseStubHook extends StubHook {
|
|
|
931
931
|
|
|
932
932
|
//#endregion
|
|
933
933
|
//#region src/serialize.ts
|
|
934
|
+
const DEFAULT_MAX_DEPTH = 256;
|
|
935
|
+
const DEFAULT_LIMITS = {
|
|
936
|
+
maxBigIntDigits: 16384,
|
|
937
|
+
maxDepth: 256,
|
|
938
|
+
maxMessageSize: 32 * 1024 * 1024
|
|
939
|
+
};
|
|
934
940
|
var NullExporter = class {
|
|
935
941
|
exportStub(stub) {
|
|
936
942
|
throw new Error("Cannot serialize RPC stubs without an RPC session.");
|
|
@@ -950,7 +956,7 @@ async function streamToBlob(stream, type) {
|
|
|
950
956
|
let b = await new Response(stream).blob();
|
|
951
957
|
return b.type === type ? b : b.slice(0, b.size, type);
|
|
952
958
|
}
|
|
953
|
-
const ERROR_TYPES = {
|
|
959
|
+
const ERROR_TYPES = Object.assign(Object.create(null), {
|
|
954
960
|
Error,
|
|
955
961
|
EvalError,
|
|
956
962
|
RangeError,
|
|
@@ -959,7 +965,7 @@ const ERROR_TYPES = {
|
|
|
959
965
|
TypeError,
|
|
960
966
|
URIError,
|
|
961
967
|
AggregateError
|
|
962
|
-
};
|
|
968
|
+
});
|
|
963
969
|
var Devaluator = class Devaluator {
|
|
964
970
|
exporter;
|
|
965
971
|
source;
|
|
@@ -982,7 +988,7 @@ var Devaluator = class Devaluator {
|
|
|
982
988
|
}
|
|
983
989
|
exports;
|
|
984
990
|
devaluateImpl(value, parent, depth) {
|
|
985
|
-
if (depth >=
|
|
991
|
+
if (depth >= 256) throw new Error("Serialization exceeded maximum allowed depth. (Does the message contain cycles?)");
|
|
986
992
|
switch (typeForRpc(value)) {
|
|
987
993
|
case "unsupported": {
|
|
988
994
|
let msg;
|
|
@@ -1216,6 +1222,9 @@ var NullImporter = class {
|
|
|
1216
1222
|
getPipeReadable(exportId) {
|
|
1217
1223
|
throw new Error("Cannot retrieve pipe readable without an RPC session.");
|
|
1218
1224
|
}
|
|
1225
|
+
getLimits() {
|
|
1226
|
+
return DEFAULT_LIMITS;
|
|
1227
|
+
}
|
|
1219
1228
|
};
|
|
1220
1229
|
const NULL_IMPORTER = new NullImporter();
|
|
1221
1230
|
function fixBrokenRequestBody(request, body) {
|
|
@@ -1233,16 +1242,21 @@ function streamToBlobPromise(stream, type) {
|
|
|
1233
1242
|
var Evaluator = class Evaluator {
|
|
1234
1243
|
importer;
|
|
1235
1244
|
encodingLevel;
|
|
1245
|
+
limits;
|
|
1236
1246
|
constructor(importer, encodingLevel = "string") {
|
|
1237
1247
|
this.importer = importer;
|
|
1238
1248
|
this.encodingLevel = encodingLevel;
|
|
1249
|
+
this.limits = importer.getLimits();
|
|
1239
1250
|
}
|
|
1240
1251
|
hooks = [];
|
|
1241
1252
|
promises = [];
|
|
1242
1253
|
evaluate(value) {
|
|
1254
|
+
return this.evaluateWithDepth(value, 0);
|
|
1255
|
+
}
|
|
1256
|
+
evaluateWithDepth(value, depth) {
|
|
1243
1257
|
let payload = RpcPayload.forEvaluate(this.hooks, this.promises);
|
|
1244
1258
|
try {
|
|
1245
|
-
payload.value = this.evaluateImpl(value, payload, "value");
|
|
1259
|
+
payload.value = this.evaluateImpl(value, payload, "value", depth);
|
|
1246
1260
|
return payload;
|
|
1247
1261
|
} catch (err) {
|
|
1248
1262
|
payload.dispose();
|
|
@@ -1252,18 +1266,25 @@ var Evaluator = class Evaluator {
|
|
|
1252
1266
|
evaluateCopy(value) {
|
|
1253
1267
|
return this.evaluate(structuredClone(value));
|
|
1254
1268
|
}
|
|
1255
|
-
evaluateImpl(value, parent, property) {
|
|
1269
|
+
evaluateImpl(value, parent, property, depth) {
|
|
1270
|
+
let maxDepth = this.limits.maxDepth;
|
|
1271
|
+
if (depth >= maxDepth) throw new TypeError(`Deserialization exceeded maximum allowed message depth of ${maxDepth}.`);
|
|
1256
1272
|
if (this.encodingLevel === "structuredClonable") {
|
|
1257
1273
|
if (value instanceof Date || typeof value === "bigint") return value;
|
|
1258
1274
|
}
|
|
1259
1275
|
if (value instanceof Array) {
|
|
1260
1276
|
if (value.length == 1 && value[0] instanceof Array) {
|
|
1261
1277
|
let result = value[0];
|
|
1262
|
-
for (let i = 0; i < result.length; i++) result[i] = this.evaluateImpl(result[i], result, i);
|
|
1278
|
+
for (let i = 0; i < result.length; i++) result[i] = this.evaluateImpl(result[i], result, i, depth + 1);
|
|
1263
1279
|
return result;
|
|
1264
1280
|
} else switch (value[0]) {
|
|
1265
1281
|
case "bigint":
|
|
1266
|
-
if (typeof value[1] == "string")
|
|
1282
|
+
if (typeof value[1] == "string") {
|
|
1283
|
+
let digits = value[1];
|
|
1284
|
+
let maxBigIntDigits = this.limits.maxBigIntDigits;
|
|
1285
|
+
if (digits.length > maxBigIntDigits) throw new TypeError(`Deserialized bigint exceeds maximum length of ${maxBigIntDigits} digits.`);
|
|
1286
|
+
return BigInt(digits);
|
|
1287
|
+
}
|
|
1267
1288
|
break;
|
|
1268
1289
|
case "date":
|
|
1269
1290
|
if (value[1] === null) return /* @__PURE__ */ new Date(NaN);
|
|
@@ -1293,7 +1314,11 @@ var Evaluator = class Evaluator {
|
|
|
1293
1314
|
let propsObj = props;
|
|
1294
1315
|
for (let key of Object.keys(propsObj)) {
|
|
1295
1316
|
if (key === "name" || key === "message" || key === "stack") continue;
|
|
1296
|
-
|
|
1317
|
+
if (key in Object.prototype || key === "toJSON") {
|
|
1318
|
+
this.evaluateImpl(propsObj[key], result, key, depth + 1);
|
|
1319
|
+
continue;
|
|
1320
|
+
}
|
|
1321
|
+
anyResult[key] = this.evaluateImpl(propsObj[key], result, key, depth + 1);
|
|
1297
1322
|
}
|
|
1298
1323
|
}
|
|
1299
1324
|
return result;
|
|
@@ -1314,11 +1339,11 @@ var Evaluator = class Evaluator {
|
|
|
1314
1339
|
let init = value[2];
|
|
1315
1340
|
if (typeof init !== "object" || init === null) break;
|
|
1316
1341
|
if (init.body) {
|
|
1317
|
-
init.body = this.evaluateImpl(init.body, init, "body");
|
|
1342
|
+
init.body = this.evaluateImpl(init.body, init, "body", depth + 1);
|
|
1318
1343
|
if (init.body === null || typeof init.body === "string" || init.body instanceof Uint8Array || init.body instanceof ReadableStream) {} else throw new TypeError("Request body must be of type ReadableStream.");
|
|
1319
1344
|
}
|
|
1320
1345
|
if (init.signal) {
|
|
1321
|
-
init.signal = this.evaluateImpl(init.signal, init, "signal");
|
|
1346
|
+
init.signal = this.evaluateImpl(init.signal, init, "signal", depth + 1);
|
|
1322
1347
|
if (!(init.signal instanceof AbortSignal)) throw new TypeError("Request siganl must be of type AbortSignal.");
|
|
1323
1348
|
}
|
|
1324
1349
|
if (init.headers && !(init.headers instanceof Array)) throw new TypeError("Request headers must be serialized as an array of pairs.");
|
|
@@ -1335,7 +1360,7 @@ var Evaluator = class Evaluator {
|
|
|
1335
1360
|
}
|
|
1336
1361
|
case "response": {
|
|
1337
1362
|
if (value.length !== 3) break;
|
|
1338
|
-
let body = this.evaluateImpl(value[1], parent, property);
|
|
1363
|
+
let body = this.evaluateImpl(value[1], parent, property, depth + 1);
|
|
1339
1364
|
if (body === null || typeof body === "string" || body instanceof Uint8Array || body instanceof ReadableStream) {} else throw new TypeError("Response body must be of type ReadableStream.");
|
|
1340
1365
|
let init = value[2];
|
|
1341
1366
|
if (typeof init !== "object" || init === null) break;
|
|
@@ -1346,7 +1371,7 @@ var Evaluator = class Evaluator {
|
|
|
1346
1371
|
case "blob": {
|
|
1347
1372
|
if (value.length !== 3 || typeof value[1] !== "string") break;
|
|
1348
1373
|
let contentType = value[1];
|
|
1349
|
-
let content = this.evaluateImpl(value[2], parent, property);
|
|
1374
|
+
let content = this.evaluateImpl(value[2], parent, property, depth + 1);
|
|
1350
1375
|
if (!(content instanceof ReadableStream)) throw new TypeError("Blob content must be serialized as a ReadableStream.");
|
|
1351
1376
|
let promise = streamToBlobPromise(content, contentType);
|
|
1352
1377
|
this.promises.push({
|
|
@@ -1387,7 +1412,7 @@ var Evaluator = class Evaluator {
|
|
|
1387
1412
|
if (value.length == 3) return addStub(hook.get(path));
|
|
1388
1413
|
let args = value[3];
|
|
1389
1414
|
if (!(args instanceof Array)) break;
|
|
1390
|
-
args = new Evaluator(this.importer).
|
|
1415
|
+
args = new Evaluator(this.importer).evaluateWithDepth([args], depth);
|
|
1391
1416
|
return addStub(hook.call(path, args));
|
|
1392
1417
|
}
|
|
1393
1418
|
case "remap": {
|
|
@@ -1453,9 +1478,9 @@ var Evaluator = class Evaluator {
|
|
|
1453
1478
|
} else if (value instanceof Object) {
|
|
1454
1479
|
let result = value;
|
|
1455
1480
|
for (let key in result) if (key in Object.prototype || key === "toJSON") {
|
|
1456
|
-
this.evaluateImpl(result[key], result, key);
|
|
1481
|
+
this.evaluateImpl(result[key], result, key, depth + 1);
|
|
1457
1482
|
delete result[key];
|
|
1458
|
-
} else result[key] = this.evaluateImpl(result[key], result, key);
|
|
1483
|
+
} else result[key] = this.evaluateImpl(result[key], result, key, depth + 1);
|
|
1459
1484
|
return result;
|
|
1460
1485
|
} else return value;
|
|
1461
1486
|
}
|
|
@@ -1526,6 +1551,10 @@ var ImportTableEntry = class {
|
|
|
1526
1551
|
resolution;
|
|
1527
1552
|
onBrokenRegistrations;
|
|
1528
1553
|
resolve(resolution) {
|
|
1554
|
+
if (this.resolution) {
|
|
1555
|
+
resolution.dispose();
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1529
1558
|
if (this.localRefcount == 0) {
|
|
1530
1559
|
resolution.dispose();
|
|
1531
1560
|
return;
|
|
@@ -1678,6 +1707,7 @@ var RpcSessionImpl = class {
|
|
|
1678
1707
|
pullCount = 0;
|
|
1679
1708
|
onBrokenCallbacks = [];
|
|
1680
1709
|
encodingLevel;
|
|
1710
|
+
limits;
|
|
1681
1711
|
constructor(transport, mainHook, options) {
|
|
1682
1712
|
this.transport = transport;
|
|
1683
1713
|
this.options = options;
|
|
@@ -1690,6 +1720,10 @@ var RpcSessionImpl = class {
|
|
|
1690
1720
|
}
|
|
1691
1721
|
}
|
|
1692
1722
|
this.encodingLevel = level;
|
|
1723
|
+
this.limits = {
|
|
1724
|
+
...DEFAULT_LIMITS,
|
|
1725
|
+
...options.limits
|
|
1726
|
+
};
|
|
1693
1727
|
this.exports.push({
|
|
1694
1728
|
hook: mainHook,
|
|
1695
1729
|
refcount: 1
|
|
@@ -1832,6 +1866,9 @@ var RpcSessionImpl = class {
|
|
|
1832
1866
|
entry.pipeReadable = void 0;
|
|
1833
1867
|
return readable;
|
|
1834
1868
|
}
|
|
1869
|
+
getLimits() {
|
|
1870
|
+
return this.limits;
|
|
1871
|
+
}
|
|
1835
1872
|
createPipe(readable, readableHook) {
|
|
1836
1873
|
if (this.abortReason) throw this.abortReason;
|
|
1837
1874
|
this.send(["pipe"]);
|
|
@@ -1991,6 +2028,7 @@ var RpcSessionImpl = class {
|
|
|
1991
2028
|
} finally {
|
|
1992
2029
|
if (this.cancelReadLoop === readCanceled.reject) this.cancelReadLoop = void 0;
|
|
1993
2030
|
}
|
|
2031
|
+
if (this.encodingLevel === "string" && raw.length > this.limits.maxMessageSize) throw new TypeError(`Incoming message exceeds maximum size of ${this.limits.maxMessageSize} UTF-16 code units.`);
|
|
1994
2032
|
if (this.abortReason) break;
|
|
1995
2033
|
let msg = this.encodingLevel === "string" ? JSON.parse(raw) : raw;
|
|
1996
2034
|
if (msg instanceof Array) switch (msg[0]) {
|
|
@@ -2065,7 +2103,7 @@ var RpcSessionImpl = class {
|
|
|
2065
2103
|
case "abort": {
|
|
2066
2104
|
let payload = new Evaluator(this, this.encodingLevel).evaluate(msg[1]);
|
|
2067
2105
|
payload.dispose();
|
|
2068
|
-
this.abort(payload, false);
|
|
2106
|
+
this.abort(payload.value, false);
|
|
2069
2107
|
break;
|
|
2070
2108
|
}
|
|
2071
2109
|
}
|
|
@@ -2191,6 +2229,8 @@ var WebSocketTransport = class {
|
|
|
2191
2229
|
let message;
|
|
2192
2230
|
if (reason instanceof Error) message = reason.message;
|
|
2193
2231
|
else message = `${reason}`;
|
|
2232
|
+
let reasonBytes = new TextEncoder().encode(message);
|
|
2233
|
+
if (reasonBytes.length > 123) message = new TextDecoder().decode(reasonBytes.subarray(0, 123), { stream: true });
|
|
2194
2234
|
this.#webSocket.close(3e3, message);
|
|
2195
2235
|
if (!this.#error) this.#error = reason;
|
|
2196
2236
|
}
|
|
@@ -2307,7 +2347,11 @@ async function newHttpBatchRpcResponse(request, localMain, options) {
|
|
|
2307
2347
|
* @param options Optional RPC session options. You can also pass headers to set on the response.
|
|
2308
2348
|
*/
|
|
2309
2349
|
async function nodeHttpBatchRpcResponse(request, response, localMain, options) {
|
|
2310
|
-
if (request.method !== "POST")
|
|
2350
|
+
if (request.method !== "POST") {
|
|
2351
|
+
response.writeHead(405, "This endpoint only accepts POST requests.", options?.headers);
|
|
2352
|
+
response.end();
|
|
2353
|
+
return;
|
|
2354
|
+
}
|
|
2311
2355
|
let body = await new Promise((resolve, reject) => {
|
|
2312
2356
|
let chunks = [];
|
|
2313
2357
|
request.on("data", (chunk) => {
|
|
@@ -2572,6 +2616,9 @@ var MapApplicator = class {
|
|
|
2572
2616
|
getPipeReadable(exportId) {
|
|
2573
2617
|
throw new Error("A mapper function cannot use pipe readables.");
|
|
2574
2618
|
}
|
|
2619
|
+
getLimits() {
|
|
2620
|
+
return DEFAULT_LIMITS;
|
|
2621
|
+
}
|
|
2575
2622
|
};
|
|
2576
2623
|
function applyMapToElement(input, parent, owner, captures, instructions) {
|
|
2577
2624
|
let mapper = new MapApplicator(captures, new PayloadStubHook(RpcPayload.deepCopyFrom(input, parent, owner)));
|
|
@@ -2910,16 +2957,18 @@ let newMessagePortRpcSession = newMessagePortRpcSession$1;
|
|
|
2910
2957
|
* credentials as parameters and returns the authorized API), then cross-origin requests should
|
|
2911
2958
|
* be safe.
|
|
2912
2959
|
*/
|
|
2913
|
-
async function newWorkersRpcResponse(request, localMain) {
|
|
2960
|
+
async function newWorkersRpcResponse(request, localMain, options) {
|
|
2914
2961
|
if (request.method === "POST") {
|
|
2915
|
-
let response = await newHttpBatchRpcResponse(request, localMain);
|
|
2962
|
+
let response = await newHttpBatchRpcResponse(request, localMain, options);
|
|
2916
2963
|
response.headers.set("Access-Control-Allow-Origin", "*");
|
|
2917
2964
|
return response;
|
|
2918
|
-
} else if (request.headers.get("Upgrade")?.toLowerCase() === "websocket") return newWorkersWebSocketRpcResponse(request, localMain);
|
|
2965
|
+
} else if (request.headers.get("Upgrade")?.toLowerCase() === "websocket") return newWorkersWebSocketRpcResponse(request, localMain, options);
|
|
2919
2966
|
else return new Response("This endpoint only accepts POST or WebSocket requests.", { status: 400 });
|
|
2920
2967
|
}
|
|
2921
2968
|
|
|
2922
2969
|
//#endregion
|
|
2970
|
+
exports.DEFAULT_LIMITS = DEFAULT_LIMITS;
|
|
2971
|
+
exports.DEFAULT_MAX_DEPTH = DEFAULT_MAX_DEPTH;
|
|
2923
2972
|
exports.RpcPromise = RpcPromise;
|
|
2924
2973
|
exports.RpcSession = RpcSession;
|
|
2925
2974
|
exports.RpcStub = RpcStub;
|