@poe-platform/safe-js 0.1.735 → 0.1.736

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.
Files changed (54) hide show
  1. package/README.md +10 -10
  2. package/dist/safe-js/chunks/{chunk-PPIYB46P.js → chunk-33AKDRQ4.js} +3 -3
  3. package/dist/safe-js/chunks/{chunk-7R3KDASZ.js → chunk-356QH3RB.js} +7 -3
  4. package/dist/safe-js/chunks/chunk-356QH3RB.js.map +7 -0
  5. package/dist/safe-js/chunks/{chunk-RULU2F5J.js → chunk-762WTEEI.js} +2 -2
  6. package/dist/safe-js/chunks/{chunk-U33B2YAT.js → chunk-7AHNAUR5.js} +2 -2
  7. package/dist/safe-js/chunks/{chunk-WGHFQSF5.js → chunk-FUUG7UIZ.js} +4 -4
  8. package/dist/safe-js/chunks/{chunk-SHVW6TCE.js → chunk-IKRAX7Z5.js} +3 -3
  9. package/dist/safe-js/chunks/{chunk-VTIHUINQ.js → chunk-LELXBLG2.js} +6 -6
  10. package/dist/safe-js/chunks/{chunk-5X7TFA3E.js → chunk-SBFOCNNW.js} +170 -137
  11. package/dist/safe-js/chunks/{chunk-5X7TFA3E.js.map → chunk-SBFOCNNW.js.map} +3 -3
  12. package/dist/safe-js/chunks/{chunk-KETIFEA7.js → chunk-TAC75RFB.js} +2 -2
  13. package/dist/safe-js/chunks/{chunk-MTQWXXXX.js → chunk-UVJ27MVC.js} +3 -3
  14. package/dist/safe-js/chunks/{chunk-QKO4FATZ.js → chunk-VQGYRKM4.js} +36 -10
  15. package/dist/safe-js/chunks/{chunk-QKO4FATZ.js.map → chunk-VQGYRKM4.js.map} +2 -2
  16. package/dist/safe-js/chunks/{chunk-JSXHEWUQ.js → chunk-WDEOWDLS.js} +4 -4
  17. package/dist/safe-js/chunks/{chunk-6G3J4CW7.js → chunk-ZNAW4ZDX.js} +2 -2
  18. package/dist/safe-js/chunks/{cli-runtime-ZUBPVST5.js → cli-runtime-FMSBDP7G.js} +11 -11
  19. package/dist/safe-js/chunks/{dump-YCUYBGSZ.js → dump-2IM3WE2J.js} +4 -4
  20. package/dist/safe-js/chunks/harness-ZLV6ZBEU.js +11 -0
  21. package/dist/safe-js/chunks/{mcp-JBFGRP6T.js → mcp-42AFDWT3.js} +4 -4
  22. package/dist/safe-js/chunks/{migration-file-ISSKTEAS.js → migration-file-AYLLA72K.js} +5 -5
  23. package/dist/safe-js/chunks/restore-SGQO4E4M.js +14 -0
  24. package/dist/safe-js/chunks/{run-IBQKVJTY.js → run-Q5Z4TRQO.js} +7 -7
  25. package/dist/safe-js/chunks/{runtime-modules-AFF6IQR2.js → runtime-modules-3P6FZJ55.js} +4 -4
  26. package/dist/safe-js/cli.js +2 -2
  27. package/dist/safe-js/core.js +7 -7
  28. package/dist/safe-js/index.js +13 -13
  29. package/dist/safe-js/interp/host-capabilities.d.ts +5 -5
  30. package/dist/safe-js/modules/fs.d.ts +4 -1
  31. package/dist/safe-js/modules/fs.js +3 -3
  32. package/dist/safe-js/snapshot/validation.d.ts +1 -1
  33. package/package.json +2 -2
  34. package/dist/safe-js/chunks/chunk-7R3KDASZ.js.map +0 -7
  35. package/dist/safe-js/chunks/harness-BSIQQFYL.js +0 -11
  36. package/dist/safe-js/chunks/restore-NHLS3LCF.js +0 -14
  37. /package/dist/safe-js/chunks/{chunk-PPIYB46P.js.map → chunk-33AKDRQ4.js.map} +0 -0
  38. /package/dist/safe-js/chunks/{chunk-RULU2F5J.js.map → chunk-762WTEEI.js.map} +0 -0
  39. /package/dist/safe-js/chunks/{chunk-U33B2YAT.js.map → chunk-7AHNAUR5.js.map} +0 -0
  40. /package/dist/safe-js/chunks/{chunk-WGHFQSF5.js.map → chunk-FUUG7UIZ.js.map} +0 -0
  41. /package/dist/safe-js/chunks/{chunk-SHVW6TCE.js.map → chunk-IKRAX7Z5.js.map} +0 -0
  42. /package/dist/safe-js/chunks/{chunk-VTIHUINQ.js.map → chunk-LELXBLG2.js.map} +0 -0
  43. /package/dist/safe-js/chunks/{chunk-KETIFEA7.js.map → chunk-TAC75RFB.js.map} +0 -0
  44. /package/dist/safe-js/chunks/{chunk-MTQWXXXX.js.map → chunk-UVJ27MVC.js.map} +0 -0
  45. /package/dist/safe-js/chunks/{chunk-JSXHEWUQ.js.map → chunk-WDEOWDLS.js.map} +0 -0
  46. /package/dist/safe-js/chunks/{chunk-6G3J4CW7.js.map → chunk-ZNAW4ZDX.js.map} +0 -0
  47. /package/dist/safe-js/chunks/{cli-runtime-ZUBPVST5.js.map → cli-runtime-FMSBDP7G.js.map} +0 -0
  48. /package/dist/safe-js/chunks/{dump-YCUYBGSZ.js.map → dump-2IM3WE2J.js.map} +0 -0
  49. /package/dist/safe-js/chunks/{harness-BSIQQFYL.js.map → harness-ZLV6ZBEU.js.map} +0 -0
  50. /package/dist/safe-js/chunks/{mcp-JBFGRP6T.js.map → mcp-42AFDWT3.js.map} +0 -0
  51. /package/dist/safe-js/chunks/{migration-file-ISSKTEAS.js.map → migration-file-AYLLA72K.js.map} +0 -0
  52. /package/dist/safe-js/chunks/{restore-NHLS3LCF.js.map → restore-SGQO4E4M.js.map} +0 -0
  53. /package/dist/safe-js/chunks/{run-IBQKVJTY.js.map → run-Q5Z4TRQO.js.map} +0 -0
  54. /package/dist/safe-js/chunks/{runtime-modules-AFF6IQR2.js.map → runtime-modules-3P6FZJ55.js.map} +0 -0
@@ -40,7 +40,7 @@ import {
40
40
  sandboxErrorTypes,
41
41
  syntaxDiagnostics,
42
42
  templateRealms
43
- } from "./chunk-QKO4FATZ.js";
43
+ } from "./chunk-VQGYRKM4.js";
44
44
  import {
45
45
  AsyncLocalStorage,
46
46
  cloneSharedBufferWrapper,
@@ -514,7 +514,7 @@ function getGeneratorProperties(value) {
514
514
  }
515
515
 
516
516
  // packages/safe-js/src/graph-depth.ts
517
- var MAX_DATA_DEPTH = 1024;
517
+ var MAX_DATA_DEPTH = Infinity;
518
518
  var SnapshotBudgetError = class extends Error {
519
519
  code = "budgetExceeded";
520
520
  budget = "dataDepth";
@@ -530,19 +530,21 @@ var SnapshotBudgetError = class extends Error {
530
530
  replaceErrorStack(this);
531
531
  }
532
532
  };
533
- function assertSandboxDataDepth(depth) {
534
- if (depth > MAX_DATA_DEPTH) {
535
- throw new SandboxError({ budget: "dataDepth", current: depth, limit: MAX_DATA_DEPTH });
533
+ function assertSandboxDataDepth(depth, limit = MAX_DATA_DEPTH) {
534
+ if (depth > limit) {
535
+ throw new SandboxError({ budget: "dataDepth", current: depth, limit });
536
536
  }
537
537
  }
538
- function assertSnapshotDataDepth(depth, path) {
539
- if (depth > MAX_DATA_DEPTH) throw new SnapshotBudgetError(path, depth);
538
+ function assertSnapshotDataDepth(depth, path, limit = MAX_DATA_DEPTH) {
539
+ if (depth > limit) throw new SnapshotBudgetError(path, depth, limit);
540
540
  }
541
- function assertSnapshotGraphDepth(value, rootPath = "$") {
542
- walkGraphDepth(value, rootPath, (depth, path) => assertSnapshotDataDepth(depth, path));
541
+ function assertSnapshotGraphDepth(value, rootPath = "$", limit = MAX_DATA_DEPTH) {
542
+ if (limit === Infinity) return;
543
+ walkGraphDepth(value, rootPath, (depth, path) => assertSnapshotDataDepth(depth, path, limit));
543
544
  }
544
- function assertSandboxGraphDepth(value) {
545
- walkGraphDepth(value, "<root>", (depth) => assertSandboxDataDepth(depth));
545
+ function assertSandboxGraphDepth(value, limit = MAX_DATA_DEPTH) {
546
+ if (limit === Infinity) return;
547
+ walkGraphDepth(value, "<root>", (depth) => assertSandboxDataDepth(depth, limit));
546
548
  }
547
549
  function walkGraphDepth(root, rootPath, assertDepth) {
548
550
  const ancestors = /* @__PURE__ */ new WeakSet();
@@ -2567,9 +2569,6 @@ function serializedDateTime(value) {
2567
2569
  }
2568
2570
 
2569
2571
  // packages/safe-js/src/interp/host-capabilities.ts
2570
- var MAX_INDEXED_LENGTH = 65536;
2571
- var MAX_NAMED_KEYS = 65536;
2572
- var MAX_NAMED_KEY_CODE_UNITS = 1048576;
2573
2572
  var hostObjects = /* @__PURE__ */ new WeakMap();
2574
2573
  var guestObjects = /* @__PURE__ */ new WeakMap();
2575
2574
  var readHostObject = WeakMap.prototype.get.bind(hostObjects);
@@ -2617,6 +2616,12 @@ function revokeGuestReference(reference, owner) {
2617
2616
  if (state === void 0 || state.owner !== owner) throw new TypeError("Foreign guest reference.");
2618
2617
  state.root = void 0;
2619
2618
  }
2619
+ function hostObjectLimit(value, name) {
2620
+ if (value === void 0 || value === Infinity) return Infinity;
2621
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1)
2622
+ throw new RangeError(`${name} must be a positive integer or Infinity.`);
2623
+ return value;
2624
+ }
2620
2625
  function createLiveHostObject(definition, controller) {
2621
2626
  const input = readDataRecord(definition, "Host object definition");
2622
2627
  if (Object.keys(input).some((key) => !["properties", "methods", "indexed", "named", "expandos"].includes(key)))
@@ -2626,17 +2631,15 @@ function createLiveHostObject(definition, controller) {
2626
2631
  const data = readDataRecord(input.expandos, "Guest expando definition");
2627
2632
  if (Object.keys(data).some((key) => !["maxKeys", "maxKeyCodeUnits", "assertActive"].includes(key)))
2628
2633
  throw new TypeError("Unknown guest expando field.");
2629
- for (const [key, maximum] of [["maxKeys", MAX_NAMED_KEYS], ["maxKeyCodeUnits", MAX_NAMED_KEY_CODE_UNITS]]) {
2630
- if (typeof data[key] !== "number" || !Number.isInteger(data[key]) || data[key] < 1 || data[key] > maximum)
2631
- throw new RangeError(`Guest expando ${key} must be an integer from 1 to ${maximum}.`);
2632
- }
2634
+ const maxKeys = hostObjectLimit(data.maxKeys, "Guest expando maxKeys");
2635
+ const maxKeyCodeUnits = hostObjectLimit(data.maxKeyCodeUnits, "Guest expando maxKeyCodeUnits");
2633
2636
  if (data.assertActive !== void 0 && (typeof data.assertActive !== "function" || types.isProxy(data.assertActive) || types.isAsyncFunction(data.assertActive) || types.isGeneratorFunction(data.assertActive)))
2634
2637
  throw new TypeError("Guest expando assertActive must be a synchronous function, not a proxy.");
2635
2638
  expandos = {
2636
2639
  // Owned writes invalidate descriptor projections; descendants stay live.
2637
2640
  values: createIntrinsicObject(),
2638
- maxKeys: data.maxKeys,
2639
- maxKeyCodeUnits: data.maxKeyCodeUnits,
2641
+ maxKeys,
2642
+ maxKeyCodeUnits,
2640
2643
  assertActive: data.assertActive
2641
2644
  };
2642
2645
  }
@@ -2647,12 +2650,11 @@ function createLiveHostObject(definition, controller) {
2647
2650
  throw new TypeError("Unknown indexed host capability field.");
2648
2651
  if (typeof data.length !== "function" || typeof data.get !== "function")
2649
2652
  throw new TypeError("Indexed length and get must be synchronous functions.");
2650
- if (typeof data.maxLength !== "number" || !Number.isInteger(data.maxLength) || data.maxLength < 1 || data.maxLength > MAX_INDEXED_LENGTH)
2651
- throw new RangeError(`Indexed maxLength must be an integer from 1 to ${MAX_INDEXED_LENGTH}.`);
2653
+ const maxLength = hostObjectLimit(data.maxLength, "Indexed maxLength");
2652
2654
  indexed = {
2653
2655
  length: data.length,
2654
2656
  get: data.get,
2655
- maxLength: data.maxLength
2657
+ maxLength
2656
2658
  };
2657
2659
  }
2658
2660
  let named;
@@ -2668,12 +2670,8 @@ function createLiveHostObject(definition, controller) {
2668
2670
  if (typeof operation !== "function" || types.isProxy(operation) || types.isAsyncFunction(operation) || types.isGeneratorFunction(operation))
2669
2671
  throw new TypeError(`Named ${name} must be a synchronous non-generator function, not a proxy.`);
2670
2672
  }
2671
- if (typeof data.maxKeys !== "number" || !Number.isInteger(data.maxKeys) || data.maxKeys < 1 || data.maxKeys > MAX_NAMED_KEYS)
2672
- throw new RangeError(`Named maxKeys must be an integer from 1 to ${MAX_NAMED_KEYS}.`);
2673
- if (typeof data.maxKeyCodeUnits !== "number" || !Number.isInteger(data.maxKeyCodeUnits) || data.maxKeyCodeUnits < 1 || data.maxKeyCodeUnits > MAX_NAMED_KEY_CODE_UNITS)
2674
- throw new RangeError(
2675
- `Named maxKeyCodeUnits must be an integer from 1 to ${MAX_NAMED_KEY_CODE_UNITS}.`
2676
- );
2673
+ const maxKeys = hostObjectLimit(data.maxKeys, "Named maxKeys");
2674
+ const maxKeyCodeUnits = hostObjectLimit(data.maxKeyCodeUnits, "Named maxKeyCodeUnits");
2677
2675
  if (data.enumerable !== void 0 && typeof data.enumerable !== "boolean")
2678
2676
  throw new TypeError("Named enumerable must be a boolean.");
2679
2677
  named = {
@@ -2681,8 +2679,8 @@ function createLiveHostObject(definition, controller) {
2681
2679
  get: data.get,
2682
2680
  set: data.set,
2683
2681
  delete: data.delete,
2684
- maxKeys: data.maxKeys,
2685
- maxKeyCodeUnits: data.maxKeyCodeUnits,
2682
+ maxKeys,
2683
+ maxKeyCodeUnits,
2686
2684
  enumerable: data.enumerable
2687
2685
  };
2688
2686
  }
@@ -19829,7 +19827,6 @@ async function numberFormatValue(value, budget, context) {
19829
19827
  }
19830
19828
  return Number(primitive);
19831
19829
  }
19832
- var MAX_FORMAT_ALLOCATION = 16 * 1024 * 1024;
19833
19830
  function formatNumberValue(receiver, method, values, budget) {
19834
19831
  const { native, options } = numberFormatState(receiver);
19835
19832
  const magnitudes = values.map((value) => typeof value === "bigint" ? value.toString(16).length * 2 : typeof value === "string" ? value.length : 309);
@@ -19844,8 +19841,6 @@ function formatNumberValue(receiver, method, values, budget) {
19844
19841
  }
19845
19842
  const bytes = parts * 256 + characters * 2 + magnitudes.reduce((sum, digits2) => sum + digits2 * 16, 0);
19846
19843
  if (method.endsWith("ToParts")) budget.allocateArrayLength(parts);
19847
- const totalBytes = budget.currentDataSize + bytes;
19848
- if (totalBytes > MAX_FORMAT_ALLOCATION) throw new SandboxError({ budget: "dataSize", current: totalBytes, limit: MAX_FORMAT_ALLOCATION });
19849
19844
  const reservation = {};
19850
19845
  budget.setRetainedDataUsage(reservation, bytes);
19851
19846
  try {
@@ -31347,7 +31342,6 @@ function admitJson(text, budget) {
31347
31342
  }
31348
31343
  if (character === '"') quoted = true;
31349
31344
  else if (character === "[" || character === "{") {
31350
- if (frames.length >= 256) throw new SandboxError({ budget: "dataDepth", current: frames.length + 1, limit: 256 });
31351
31345
  const leave = budget.enterCall();
31352
31346
  frames.push({ array: character === "[", entries: 0, expectingValue: true, leave });
31353
31347
  } else if (character === "]" || character === "}") frames.pop()?.leave();
@@ -41308,7 +41302,7 @@ function intrinsicCatalogue() {
41308
41302
  const kinds = /* @__PURE__ */ new Map();
41309
41303
  for (const id of listIntrinsicIdentities(budget)) {
41310
41304
  const value = resolveIntrinsicIdentity(budget, id);
41311
- if (getIntrinsicIdentity(value) === id) kinds.set(id, isSandboxClosure(value));
41305
+ if (getIntrinsicIdentity(value) === id) kinds.set(id, { callable: isSandboxClosure(value), constructible: isSandboxClosure(value) && value.construct !== void 0 });
41312
41306
  }
41313
41307
  intrinsicKinds = kinds;
41314
41308
  return kinds;
@@ -41316,6 +41310,28 @@ function intrinsicCatalogue() {
41316
41310
  releaseObjectPrototype(budget);
41317
41311
  }
41318
41312
  }
41313
+ function targetFlags(node) {
41314
+ if (node.kind === "bound-function") return void 0;
41315
+ if (node.kind === "guest-proxy") return { callable: node.callable === true, constructible: node.constructible === true };
41316
+ if (node.kind === "intrinsic") return intrinsicCatalogue().get(String(node.id));
41317
+ if (node.kind === "guest-function" || node.kind === "module-function") return { callable: true };
41318
+ if (node.kind === "guest-class") return { callable: true, constructible: true };
41319
+ return { callable: [
41320
+ "guest-proxy-revoker",
41321
+ "async-generator-handler",
41322
+ "async-function-handler",
41323
+ "async-cleanup-handler",
41324
+ "thenable-resolver",
41325
+ "aggregate-handler",
41326
+ "adoption-resolver",
41327
+ "capability-executor",
41328
+ "promise-resolver"
41329
+ ].includes(String(node.kind)), constructible: false };
41330
+ }
41331
+ function validateProxyFlags(node, flags) {
41332
+ if (node.callable !== flags.callable || flags.constructible !== void 0 && node.constructible !== flags.constructible)
41333
+ throw new TypeError("Inconsistent Proxy callable flags.");
41334
+ }
41319
41335
  function record3(value) {
41320
41336
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Expected a guest heap record.");
41321
41337
  return value;
@@ -41336,7 +41352,7 @@ function absent(value) {
41336
41352
  const node = record3(value);
41337
41353
  return node.kind === "undefined" && Object.keys(node).length === 1;
41338
41354
  }
41339
- function validateGuestHeapNode(raw, heap, maxArrayLength = 4294967295) {
41355
+ function validateGuestHeapNode(raw, heap, maxArrayLength = Infinity) {
41340
41356
  if (record3(raw).kind === "guest-script") {
41341
41357
  const source = record3(raw);
41342
41358
  fields(source, ["kind", "body", "context"]);
@@ -41440,7 +41456,7 @@ function validateGuestHeapNode(raw, heap, maxArrayLength = 4294967295) {
41440
41456
  const target = reference(value, ["guest-proxy", "guest-proxy-revoker", "module-function", "async-generator-handler", "async-function-handler", "async-cleanup-handler", "thenable-resolver", "aggregate-handler", "capability-executor", "intrinsic", "bound-function", "promise-resolver", "guest-function", "guest-class"]);
41441
41457
  if (target.kind === "guest-proxy" && target.callable !== true)
41442
41458
  throw new TypeError("Guest accessor Proxy is not callable.");
41443
- if (target.kind === "intrinsic" && intrinsicCatalogue().get(String(target.id)) !== true)
41459
+ if (target.kind === "intrinsic" && intrinsicCatalogue().get(String(target.id))?.callable !== true)
41444
41460
  throw new TypeError("Guest accessor reference is not callable.");
41445
41461
  };
41446
41462
  if ((node.kind === "pending-promise" || node.kind === "guest-promise") && Object.hasOwn(node, "generatorOwner")) {
@@ -41531,17 +41547,9 @@ function validateGuestHeapNode(raw, heap, maxArrayLength = 4294967295) {
41531
41547
  if (node.target === null !== (node.handler === null)) throw new TypeError("Invalid revoked Proxy state.");
41532
41548
  if (node.target !== null) {
41533
41549
  reference(node.handler, objectKinds);
41534
- const seen = /* @__PURE__ */ new Set([node]);
41535
- let current = node;
41536
- while (current.kind === "guest-proxy" && current.target !== null) {
41537
- assertSnapshotDataDepth(seen.size, "Proxy target chain");
41538
- const target = reference(current.target, objectKinds);
41539
- if (seen.has(target)) throw new TypeError("Cyclic Proxy target chain.");
41540
- seen.add(target);
41541
- if (target.kind === "guest-proxy" && (target.callable !== current.callable || target.constructible !== current.constructible))
41542
- throw new TypeError("Inconsistent Proxy callable flags.");
41543
- current = target;
41544
- }
41550
+ const target = reference(node.target, objectKinds);
41551
+ const flags = targetFlags(target);
41552
+ if (flags !== void 0) validateProxyFlags(node, flags);
41545
41553
  }
41546
41554
  if (node.privateElements !== void 0) privateState(node.privateElements);
41547
41555
  } else if (node.kind === "guest-proxy-revoker") {
@@ -42318,15 +42326,8 @@ function validateGuestHeapNode(raw, heap, maxArrayLength = 4294967295) {
42318
42326
  if (array(node.args).length > maxArrayLength) throw new TypeError("Bound arguments exceed allocation limit.");
42319
42327
  if (!absent(node.length) && !(typeof node.length === "number" && node.length >= 0) && !(record3(node.length).kind === "number" && record3(node.length).value === "Infinity"))
42320
42328
  throw new TypeError("Invalid bound function length.");
42321
- const visited = /* @__PURE__ */ new Set([raw]);
42322
- let current = node;
42323
- while (current.kind === "bound-function") {
42324
- assertSnapshotDataDepth(visited.size, "<bound-target>");
42325
- callable(current.target);
42326
- current = reference(current.target);
42327
- if (visited.has(current)) throw new TypeError("Cyclic bound function target.");
42328
- visited.add(current);
42329
- }
42329
+ callable(node.target);
42330
+ reference(node.target);
42330
42331
  state(node.state);
42331
42332
  } else if (node.kind === "guest-function") {
42332
42333
  fields(node, ["kind", "astNodeId", "scope", "state"], ["name", "environment", "dynamicSource", "realm"]);
@@ -42681,20 +42682,47 @@ function validateGuestHeapGraphs(heap) {
42681
42682
  ["scope-frame", "parent", "Cyclic guest scope parent graph."],
42682
42683
  ["promise-reaction", "source", "Cyclic promise reaction source graph."]
42683
42684
  ]) {
42684
- const finished = /* @__PURE__ */ new Set();
42685
+ const finished2 = /* @__PURE__ */ new Set();
42685
42686
  for (const [id, raw] of Object.entries(heap)) {
42686
- if (record3(raw).kind !== kind || finished.has(id)) continue;
42687
+ if (record3(raw).kind !== kind || finished2.has(id)) continue;
42687
42688
  const path = /* @__PURE__ */ new Set();
42688
42689
  let current = id;
42689
- while (current !== void 0 && !finished.has(current)) {
42690
+ while (current !== void 0 && !finished2.has(current)) {
42690
42691
  if (path.has(current)) throw new TypeError(message);
42691
42692
  const node = record3(heap[current]);
42692
42693
  if (node.kind !== kind) break;
42693
42694
  path.add(current);
42694
42695
  const parent = node[edge];
42695
- current = absent(parent) ? void 0 : String(record3(parent).id);
42696
+ current = parent === null || absent(parent) ? void 0 : String(record3(parent).id);
42697
+ }
42698
+ for (const visited of path) finished2.add(visited);
42699
+ }
42700
+ }
42701
+ const finished = /* @__PURE__ */ new Map();
42702
+ for (const [id, raw] of Object.entries(heap)) {
42703
+ const root = record3(raw);
42704
+ if (root.kind !== "guest-proxy" && root.kind !== "bound-function" || finished.has(id)) continue;
42705
+ const path = /* @__PURE__ */ new Map();
42706
+ let current = id;
42707
+ let flags = finished.get(current);
42708
+ while (flags === void 0) {
42709
+ if (path.has(current)) throw new TypeError(root.kind === "guest-proxy" ? "Cyclic Proxy target chain." : "Cyclic bound function target.");
42710
+ const node = record3(heap[current]);
42711
+ if (node.kind !== "guest-proxy" && node.kind !== "bound-function" || node.target === null) {
42712
+ flags = targetFlags(node);
42713
+ if (flags === void 0) throw new TypeError("Invalid function target.");
42714
+ break;
42696
42715
  }
42697
- for (const visited of path) finished.add(visited);
42716
+ path.set(current, node);
42717
+ current = String(record3(node.target).id);
42718
+ flags = finished.get(current);
42719
+ }
42720
+ for (const [visited, node] of [...path].reverse()) {
42721
+ if (node.kind === "guest-proxy") {
42722
+ validateProxyFlags(node, flags);
42723
+ flags = targetFlags(node);
42724
+ }
42725
+ finished.set(visited, flags);
42698
42726
  }
42699
42727
  }
42700
42728
  }
@@ -42976,9 +43004,6 @@ function checkArray(properties, values, cooked) {
42976
43004
  }
42977
43005
 
42978
43006
  // packages/safe-js/src/snapshot/validation.ts
42979
- var DEFAULT_MAX_ENTRIES = 1e5;
42980
- var DEFAULT_MAX_STRING_LENGTH = 1e6;
42981
- var DEFAULT_MAX_DATA_SIZE = 16e6;
42982
43007
  var TAGGED_VALUE_KINDS = /* @__PURE__ */ new Set([
42983
43008
  "arguments",
42984
43009
  "array",
@@ -43009,23 +43034,21 @@ function validateSnapshotData(value) {
43009
43034
  validateGenericValue(value, "$", 0, {
43010
43035
  allowFunctions: false,
43011
43036
  allowUndefined: false,
43012
- entries: 0,
43013
43037
  dataSize: 0,
43014
- limits: defaultLimits(),
43038
+ limits: limitsFromBudget(),
43015
43039
  validateTaggedPayloads: false,
43016
43040
  dataPropertiesOnly: true,
43017
43041
  dataPrototypes: /* @__PURE__ */ new WeakSet()
43018
43042
  });
43019
43043
  }
43020
43044
  function validateDumpEnvelope(snapshot, options = {}) {
43021
- const limits = defaultLimits();
43045
+ const limits = limitsFromBudget();
43022
43046
  const root = requireRecord(snapshot, "$");
43023
43047
  const trusted = inMemoryRunSnapshots.has(root);
43024
43048
  const state = {
43025
43049
  allowHostFunctionState: trusted,
43026
43050
  allowFunctions: trusted,
43027
43051
  allowUndefined: true,
43028
- entries: 0,
43029
43052
  dataSize: 0,
43030
43053
  limits,
43031
43054
  validateTaggedPayloads: false,
@@ -43610,80 +43633,91 @@ function validateSnapshotProxy(value, path, dataPropertiesOnly = false) {
43610
43633
  }
43611
43634
  }
43612
43635
  function validateGenericValue(value, path, depth, state) {
43613
- validateSnapshotProxy(value, path, state.dataPropertiesOnly);
43614
- if (typeof value === "object" && value !== null && hasGuestObjectState(value) && !(state.allowHostFunctionState && (isSandboxModuleNamespace(value) || isSandboxClosure(value) && !isGuestClosure(value)))) {
43615
- fail("invalidState", path, "guest function properties, prototype links and custom descriptors cannot be restored");
43616
- }
43617
- if (depth > state.limits.maxDepth)
43618
- fail("budgetExceeded", path, `exceeds nesting limit ${state.limits.maxDepth}`);
43619
- state.entries += 1;
43620
- if (state.entries > state.limits.maxAggregateEntries)
43621
- fail(
43622
- "budgetExceeded",
43623
- path,
43624
- `exceeds aggregate entry limit ${state.limits.maxAggregateEntries}`
43625
- );
43626
- if (typeof value === "string") {
43627
- requireString(value, path, state.limits);
43628
- state.dataSize += value.length;
43629
- } else if (Array.isArray(value)) {
43630
- if (value.length > state.limits.maxEntries) fail("budgetExceeded", path, "array is too large");
43631
- if (state.dataPropertiesOnly) {
43632
- const entries = snapshotDataEntries(value, path, state.dataPrototypes).filter(([key]) => key !== "length");
43633
- if (entries.length !== value.length)
43634
- fail("invalidType", path, "snapshot arrays must be dense");
43635
- for (const [key, entry] of entries) {
43636
- const index = Number(key);
43637
- if (!Number.isInteger(index) || index < 0 || index >= value.length || String(index) !== key) {
43638
- fail("invalidType", path, "snapshot arrays cannot have named properties");
43636
+ const pending = [{ value, path, depth }];
43637
+ const ancestors = /* @__PURE__ */ new WeakSet();
43638
+ while (pending.length > 0) {
43639
+ const frame = pending.pop();
43640
+ if ("exit" in frame) {
43641
+ ancestors.delete(frame.exit);
43642
+ continue;
43643
+ }
43644
+ const { value: value2, path: path2, depth: depth2, key } = frame;
43645
+ if (key !== void 0) {
43646
+ requireString(key, path2, state.limits);
43647
+ state.dataSize += key.length;
43648
+ }
43649
+ validateSnapshotProxy(value2, path2, state.dataPropertiesOnly);
43650
+ if (typeof value2 === "object" && value2 !== null && hasGuestObjectState(value2) && !(state.allowHostFunctionState && (isSandboxModuleNamespace(value2) || isSandboxClosure(value2) && !isGuestClosure(value2)))) {
43651
+ fail("invalidState", path2, "guest function properties, prototype links and custom descriptors cannot be restored");
43652
+ }
43653
+ if (depth2 > state.limits.maxDepth)
43654
+ fail("budgetExceeded", path2, `exceeds nesting limit ${state.limits.maxDepth}`);
43655
+ if (typeof value2 === "object" && value2 !== null) {
43656
+ if (ancestors.has(value2)) {
43657
+ if (state.dataPropertiesOnly) fail("invalidCycle", path2, "snapshot data cannot contain cycles");
43658
+ continue;
43659
+ }
43660
+ ancestors.add(value2);
43661
+ pending.push({ exit: value2 });
43662
+ }
43663
+ if (typeof value2 === "string") {
43664
+ requireString(value2, path2, state.limits);
43665
+ state.dataSize += value2.length;
43666
+ } else if (Array.isArray(value2)) {
43667
+ if (value2.length > state.limits.maxEntries) fail("budgetExceeded", path2, "array is too large");
43668
+ if (state.dataPropertiesOnly) {
43669
+ const entries = snapshotDataEntries(value2, path2, state.dataPrototypes).filter(([key2]) => key2 !== "length");
43670
+ if (entries.length !== value2.length)
43671
+ fail("invalidType", path2, "snapshot arrays must be dense");
43672
+ for (const [key2, entry] of entries.reverse()) {
43673
+ const index = Number(key2);
43674
+ if (!Number.isInteger(index) || index < 0 || index >= value2.length || String(index) !== key2) {
43675
+ fail("invalidType", path2, "snapshot arrays cannot have named properties");
43676
+ }
43677
+ pending.push({ value: entry, path: `${path2}[${key2}]`, depth: depth2 + 1 });
43678
+ }
43679
+ } else {
43680
+ for (const [key2, entry] of ownSnapshotDataEntries(value2, path2, true).reverse()) {
43681
+ const index = Number(key2);
43682
+ if (Number.isInteger(index) && index >= 0 && index < value2.length && String(index) === key2)
43683
+ pending.push({ value: entry, path: `${path2}[${index}]`, depth: depth2 + 1 });
43639
43684
  }
43640
- validateGenericValue(entry, `${path}[${key}]`, depth + 1, state);
43641
43685
  }
43642
- } else {
43643
- for (const [key, entry] of ownSnapshotDataEntries(value, path, true)) {
43644
- const index = Number(key);
43645
- if (Number.isInteger(index) && index >= 0 && index < value.length && String(index) === key)
43646
- validateGenericValue(entry, `${path}[${index}]`, depth + 1, state);
43686
+ } else if (value2 !== null && typeof value2 === "object") {
43687
+ const record4 = value2;
43688
+ if (state.validateTaggedPayloads && isTaggedValueShape(record4)) {
43689
+ validateTaggedValue(record4, path2, state);
43647
43690
  }
43648
- }
43649
- } else if (value !== null && typeof value === "object") {
43650
- const record4 = value;
43651
- if (state.validateTaggedPayloads && isTaggedValueShape(record4)) {
43652
- validateTaggedValue(record4, path, state);
43653
- }
43654
- const entries = state.dataPropertiesOnly ? snapshotDataEntries(value, path, state.dataPrototypes) : ownSnapshotDataEntries(value, path, true);
43655
- if (state.dataPropertiesOnly) {
43656
- for (const [key, entry] of entries) {
43657
- if (typeof entry === "object" && entry !== null && getIntrinsicIdentity(entry) !== void 0 && hasGuestObjectState(entry))
43658
- fail("invalidState", `${path}${formatKey(key)}`, "mutated intrinsics require a serialized snapshot");
43691
+ const entries = state.dataPropertiesOnly ? snapshotDataEntries(value2, path2, state.dataPrototypes) : ownSnapshotDataEntries(value2, path2, true);
43692
+ if (state.dataPropertiesOnly) {
43693
+ for (const [key2, entry] of entries) {
43694
+ if (typeof entry === "object" && entry !== null && getIntrinsicIdentity(entry) !== void 0 && hasGuestObjectState(entry))
43695
+ fail("invalidState", `${path2}${formatKey(key2)}`, "mutated intrinsics require a serialized snapshot");
43696
+ }
43659
43697
  }
43698
+ for (const [key2, entry] of entries.reverse()) {
43699
+ const entryPath = `${path2}${formatKey(key2)}`;
43700
+ pending.push({ value: entry, path: entryPath, depth: depth2 + 1, key: key2 });
43701
+ }
43702
+ } else if (!["boolean", "number"].includes(typeof value2) && !(state.allowFunctions && typeof value2 === "function") && !(state.allowUndefined && value2 === void 0) && value2 !== null) {
43703
+ fail("invalidType", path2, "contains an unsupported value");
43660
43704
  }
43661
- for (const [key, entry] of entries) {
43662
- const entryPath = `${path}${formatKey(key)}`;
43663
- requireString(key, entryPath, state.limits);
43664
- state.dataSize += key.length;
43665
- validateGenericValue(entry, entryPath, depth + 1, state);
43666
- }
43667
- } else if (!["boolean", "number"].includes(typeof value) && !(state.allowFunctions && typeof value === "function") && !(state.allowUndefined && value === void 0) && value !== null) {
43668
- fail("invalidType", path, "contains an unsupported value");
43705
+ if (state.dataSize > state.limits.maxDataSize)
43706
+ fail("budgetExceeded", path2, `exceeds aggregate data limit ${state.limits.maxDataSize}`);
43669
43707
  }
43670
- if (state.dataSize > state.limits.maxDataSize)
43671
- fail("budgetExceeded", path, `exceeds aggregate data limit ${state.limits.maxDataSize}`);
43672
43708
  }
43673
- function validateRuntimeSnapshotDescriptors(snapshot) {
43709
+ function validateRuntimeSnapshotDescriptors(snapshot, budget) {
43674
43710
  const pending = [{ value: snapshot, path: "$", depth: 0 }];
43675
43711
  const seen = /* @__PURE__ */ new WeakSet();
43676
- let entries = 0;
43712
+ const limits = limitsFromBudget(budget);
43677
43713
  while (pending.length > 0) {
43678
43714
  const { value, path, depth } = pending.pop();
43679
43715
  validateSnapshotProxy(value, path);
43680
43716
  if (seen.has(value)) continue;
43681
43717
  seen.add(value);
43682
- if (depth > MAX_DATA_DEPTH)
43683
- fail("budgetExceeded", path, `exceeds nesting limit ${MAX_DATA_DEPTH}`);
43718
+ if (depth > limits.maxDepth)
43719
+ fail("budgetExceeded", path, `exceeds nesting limit ${limits.maxDepth}`);
43684
43720
  for (const [key, entry] of ownSnapshotDataEntries(value, path, true, true)) {
43685
- if (++entries > DEFAULT_MAX_ENTRIES)
43686
- fail("budgetExceeded", path, `exceeds aggregate entry limit ${DEFAULT_MAX_ENTRIES}`);
43687
43721
  if (entry !== null && typeof entry === "object")
43688
43722
  pending.push({ value: entry, path: `${path}${formatKey(key)}`, depth: depth + 1 });
43689
43723
  }
@@ -43726,14 +43760,13 @@ function ownSnapshotDataEntries(value, path, runtime = false, guestDescriptors =
43726
43760
  }
43727
43761
  return entries;
43728
43762
  }
43729
- function defaultLimits() {
43763
+ function limitsFromBudget(budget) {
43730
43764
  return {
43731
- maxAggregateEntries: DEFAULT_MAX_ENTRIES,
43732
- maxCallDepth: 1e4,
43733
- maxDepth: MAX_DATA_DEPTH,
43734
- maxEntries: DEFAULT_MAX_ENTRIES,
43735
- maxStringLength: DEFAULT_MAX_STRING_LENGTH,
43736
- maxDataSize: DEFAULT_MAX_DATA_SIZE
43765
+ maxCallDepth: budget?.limits.maxCallDepth ?? Infinity,
43766
+ maxDepth: budget?.limits.maxCallDepth ?? Infinity,
43767
+ maxEntries: budget?.limits.arrayLength ?? Infinity,
43768
+ maxStringLength: budget?.limits.stringLength ?? Infinity,
43769
+ maxDataSize: budget?.limits.dataSize ?? Infinity
43737
43770
  };
43738
43771
  }
43739
43772
  function requireArray(value, path, state) {
@@ -49333,4 +49366,4 @@ authorization of the copyright holder.
49333
49366
  SPDX-License-Identifier: Unicode-3.0
49334
49367
 
49335
49368
  */
49336
- //# sourceMappingURL=chunk-5X7TFA3E.js.map
49369
+ //# sourceMappingURL=chunk-SBFOCNNW.js.map