poe-code 14.0.51 → 14.0.53

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 (57) hide show
  1. package/dist/index.js +451 -181
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-bash/dist/browser.js +35 -15
  6. package/packages/safe-bash/dist/browser.js.map +3 -3
  7. package/packages/safe-bash/dist/shell/arrays/state.d.ts +2 -1
  8. package/packages/safe-bash/dist/shell/arrays/state.d.ts.map +1 -1
  9. package/packages/safe-bash/dist/shell/arrays/state.js +23 -5
  10. package/packages/safe-bash/dist/shell/arrays/state.js.map +1 -1
  11. package/packages/safe-bash/dist/shell/cleanup.d.ts.map +1 -1
  12. package/packages/safe-bash/dist/shell/cleanup.js +11 -5
  13. package/packages/safe-bash/dist/shell/cleanup.js.map +1 -1
  14. package/packages/safe-bash/dist/shell/runtime.js +5 -5
  15. package/packages/safe-bash/dist/shell/runtime.js.map +1 -1
  16. package/packages/safe-js/dist/chunks/{chunk-MQU3AETK.js → chunk-4XYGVCOQ.js} +2 -2
  17. package/packages/safe-js/dist/chunks/{chunk-7AIY5C3F.js → chunk-VDFW3EKS.js} +368 -138
  18. package/packages/safe-js/dist/chunks/chunk-VDFW3EKS.js.map +7 -0
  19. package/packages/safe-js/dist/cli.js +2 -2
  20. package/packages/safe-js/dist/core.js +1 -1
  21. package/packages/safe-js/dist/graph-depth.js +10 -4
  22. package/packages/safe-js/dist/index.js +2 -2
  23. package/packages/safe-js/dist/interp/cancel.js +3 -0
  24. package/packages/safe-js/dist/interp/collection-brands.d.ts +5 -0
  25. package/packages/safe-js/dist/interp/collection-brands.js +8 -0
  26. package/packages/safe-js/dist/interp/collection-iterator.d.ts +27 -0
  27. package/packages/safe-js/dist/interp/collection-iterator.js +61 -0
  28. package/packages/safe-js/dist/interp/globals/collections.js +1 -1
  29. package/packages/safe-js/dist/interp/globals/misc.js +3 -2
  30. package/packages/safe-js/dist/interp/globals/object-array.js +2 -2
  31. package/packages/safe-js/dist/interp/globals/object.js +3 -0
  32. package/packages/safe-js/dist/interp/interpreter.js +20 -11
  33. package/packages/safe-js/dist/interp/iteration.d.ts +2 -1
  34. package/packages/safe-js/dist/interp/iteration.js +4 -1
  35. package/packages/safe-js/dist/interp/methods/array.d.ts +12 -3
  36. package/packages/safe-js/dist/interp/methods/array.js +164 -46
  37. package/packages/safe-js/dist/interp/methods/collection-iterator.d.ts +4 -0
  38. package/packages/safe-js/dist/interp/methods/collection-iterator.js +19 -0
  39. package/packages/safe-js/dist/interp/methods/map.js +3 -4
  40. package/packages/safe-js/dist/interp/methods/number.d.ts +2 -2
  41. package/packages/safe-js/dist/interp/methods/number.js +27 -46
  42. package/packages/safe-js/dist/interp/methods/set.js +3 -3
  43. package/packages/safe-js/dist/interp/patterns.d.ts +2 -0
  44. package/packages/safe-js/dist/interp/patterns.js +20 -2
  45. package/packages/safe-js/dist/interp/promise.js +1 -1
  46. package/packages/safe-js/dist/interp/string-coercion.js +4 -0
  47. package/packages/safe-js/dist/interp/values.d.ts +4 -5
  48. package/packages/safe-js/dist/interp/values.js +42 -10
  49. package/packages/safe-js/dist/snapshot/replay-data.d.ts +10 -0
  50. package/packages/safe-js/dist/snapshot/replay-data.js +32 -0
  51. package/packages/safe-js/dist/snapshot/replay-inputs.js +15 -0
  52. package/packages/safe-js/dist/snapshot/restore.js +16 -0
  53. package/packages/safe-js/dist/snapshot/serialize.d.ts +10 -1
  54. package/packages/safe-js/dist/snapshot/serialize.js +25 -9
  55. package/packages/safe-js/dist/snapshot/validation.js +14 -1
  56. package/packages/safe-js/dist/chunks/chunk-7AIY5C3F.js.map +0 -7
  57. /package/packages/safe-js/dist/chunks/{chunk-MQU3AETK.js.map → chunk-4XYGVCOQ.js.map} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  resolveFsConfig,
23
23
  splitFrontmatter,
24
24
  withBrokenPipeGuard
25
- } from "./chunks/chunk-MQU3AETK.js";
25
+ } from "./chunks/chunk-4XYGVCOQ.js";
26
26
  import {
27
27
  Budget,
28
28
  SandboxError,
@@ -34,7 +34,7 @@ import {
34
34
  replaceErrorStack,
35
35
  restore,
36
36
  run
37
- } from "./chunks/chunk-7AIY5C3F.js";
37
+ } from "./chunks/chunk-VDFW3EKS.js";
38
38
  import "./chunks/chunk-UXMKEUH3.js";
39
39
  import "./chunks/chunk-5DYEOCT5.js";
40
40
  import "./chunks/chunk-4YIDX44G.js";
@@ -5,7 +5,7 @@ import {
5
5
  defineExtension,
6
6
  lint,
7
7
  run
8
- } from "./chunks/chunk-7AIY5C3F.js";
8
+ } from "./chunks/chunk-VDFW3EKS.js";
9
9
  import "./chunks/chunk-4YIDX44G.js";
10
10
  export {
11
11
  Budget,
@@ -1,6 +1,8 @@
1
1
  import { replaceErrorStack } from "./error/shape.js";
2
2
  import { SandboxError } from "./interp/budget.js";
3
3
  import { getSandboxArgumentEntries, isSandboxArguments } from "./interp/arguments.js";
4
+ import { collectionIteratorState, isSandboxCollectionIterator } from "./interp/collection-iterator.js";
5
+ import { isSandboxMap, isSandboxSet } from "./interp/collection-brands.js";
4
6
  export const MAX_DATA_DEPTH = 1_024;
5
7
  export class SnapshotBudgetError extends Error {
6
8
  code = "budgetExceeded";
@@ -64,16 +66,20 @@ function graphEntries(value) {
64
66
  if (isSandboxArguments(value)) {
65
67
  return getSandboxArgumentEntries(value).map(([key, entry]) => [`.${key}`, entry]);
66
68
  }
67
- if (value instanceof Map) {
68
- return [...value.entries()].flatMap(([key, entry], index) => [
69
+ const map = isSandboxMap(value) ? value.entries : value instanceof Map ? value : undefined;
70
+ if (map !== undefined) {
71
+ return [...map.entries()].flatMap(([key, entry], index) => [
69
72
  [`.<map>[${index}].key`, key],
70
73
  [`.<map>[${index}].value`, entry]
71
74
  ]);
72
75
  }
73
- if (value instanceof Set) {
74
- return [...value.values()].map((entry, index) => [`.<set>[${index}]`, entry]);
76
+ const set = isSandboxSet(value) ? value.values : value instanceof Set ? value : undefined;
77
+ if (set !== undefined) {
78
+ return [...set.values()].map((entry, index) => [`.<set>[${index}]`, entry]);
75
79
  }
76
80
  const entries = [];
81
+ if (isSandboxCollectionIterator(value))
82
+ entries.push([".<collection>", collectionIteratorState(value).collection]);
77
83
  for (const key of Object.keys(value)) {
78
84
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
79
85
  if (descriptor !== undefined && "value" in descriptor)
@@ -26,7 +26,7 @@ import {
26
26
  runWithSpawnUsageAccumulator,
27
27
  splitFrontmatter,
28
28
  supportsSpawnMode
29
- } from "./chunks/chunk-MQU3AETK.js";
29
+ } from "./chunks/chunk-4XYGVCOQ.js";
30
30
  import {
31
31
  Budget,
32
32
  FileSnapshotBackend,
@@ -50,7 +50,7 @@ import {
50
50
  registerPendingHostCallPolicy,
51
51
  restore,
52
52
  run
53
- } from "./chunks/chunk-7AIY5C3F.js";
53
+ } from "./chunks/chunk-VDFW3EKS.js";
54
54
  import "./chunks/chunk-UXMKEUH3.js";
55
55
  import "./chunks/chunk-5DYEOCT5.js";
56
56
  import "./chunks/chunk-4YIDX44G.js";
@@ -1,4 +1,5 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
2
3
  import { getSandboxPrototype } from "./object-model.js";
3
4
  import { createSandboxPromise, isSandboxClosure, isSandboxMap, isSandboxPromise, isSandboxSet } from "./values.js";
4
5
  import { assertPromiseExecutionAllowed, interruptOnFatalPromiseRejection, onFatalPromiseRejection, observeSandboxPromise, trackSandboxPromise } from "./promise-tracker.js";
@@ -97,6 +98,8 @@ function registerCancelablePromises(value, signal) {
97
98
  pending.push(entry);
98
99
  }
99
100
  else {
101
+ if (isSandboxCollectionIterator(current))
102
+ pending.push(collectionIteratorState(current).collection);
100
103
  for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(current))) {
101
104
  if ("value" in descriptor)
102
105
  pending.push(descriptor.value);
@@ -0,0 +1,5 @@
1
+ import type { SandboxMap, SandboxSet } from "./values.js";
2
+ export declare const sandboxMapBrand: unique symbol;
3
+ export declare const sandboxSetBrand: unique symbol;
4
+ export declare function isSandboxMap(value: unknown): value is SandboxMap;
5
+ export declare function isSandboxSet(value: unknown): value is SandboxSet;
@@ -0,0 +1,8 @@
1
+ export const sandboxMapBrand = Symbol("SandboxMap");
2
+ export const sandboxSetBrand = Symbol("SandboxSet");
3
+ export function isSandboxMap(value) {
4
+ return typeof value === "object" && value !== null && sandboxMapBrand in value;
5
+ }
6
+ export function isSandboxSet(value) {
7
+ return typeof value === "object" && value !== null && sandboxSetBrand in value;
8
+ }
@@ -0,0 +1,27 @@
1
+ import type { Budget } from "./budget.js";
2
+ import type { SandboxMap, SandboxSet, SandboxValue } from "./values.js";
3
+ declare const collectionIteratorBrand: unique symbol;
4
+ export type SandboxCollectionIterator = {
5
+ readonly [collectionIteratorBrand]: true;
6
+ };
7
+ export type CollectionIterationMethod = "keys" | "values" | "entries";
8
+ export type CollectionIteratorSnapshot = {
9
+ collection: SandboxMap | SandboxSet | undefined;
10
+ collectionKind: "map" | "set";
11
+ method: CollectionIterationMethod;
12
+ index: number;
13
+ exhausted: boolean;
14
+ };
15
+ type IteratorState = Omit<CollectionIteratorSnapshot, "index"> & {
16
+ iterator: Iterator<SandboxValue> | undefined;
17
+ };
18
+ export declare function isSandboxCollectionIterator(value: unknown): value is SandboxCollectionIterator;
19
+ export declare function createSandboxCollectionIterator(collection: SandboxMap | SandboxSet, method: CollectionIterationMethod): SandboxCollectionIterator;
20
+ export declare function restoreSandboxCollectionIterator(snapshot: CollectionIteratorSnapshot, target?: SandboxCollectionIterator): SandboxCollectionIterator;
21
+ export declare function collectionIteratorState(value: SandboxCollectionIterator): Readonly<IteratorState>;
22
+ export declare function snapshotCollectionIterator(value: SandboxCollectionIterator): CollectionIteratorSnapshot;
23
+ export declare function nextCollectionIterator(value: SandboxCollectionIterator, budget?: Budget): {
24
+ value: SandboxValue;
25
+ done: boolean;
26
+ };
27
+ export {};
@@ -0,0 +1,61 @@
1
+ const states = new WeakMap();
2
+ export function isSandboxCollectionIterator(value) {
3
+ return typeof value === "object" && value !== null && states.has(value);
4
+ }
5
+ export function createSandboxCollectionIterator(collection, method) {
6
+ return restoreSandboxCollectionIterator({ collection, collectionKind: collection.kind, method, index: 0, exhausted: false });
7
+ }
8
+ // A registered placeholder lets snapshot readers resolve collection/iterator cycles.
9
+ // Initialize its cursor only after the source collection has been fully restored.
10
+ export function restoreSandboxCollectionIterator(snapshot, target = Object.create(null)) {
11
+ const { collection, collectionKind, method, index, exhausted } = snapshot;
12
+ if (collection !== undefined && collection.kind !== collectionKind)
13
+ throw new TypeError("Collection iterator source has the wrong brand.");
14
+ if (!exhausted && collection === undefined)
15
+ throw new TypeError("Live collection iterator requires its source collection.");
16
+ const iterator = exhausted ? undefined : nativeIterator(collection, method);
17
+ for (let skipped = 0; skipped < index; skipped += 1) {
18
+ if (iterator === undefined || iterator.next().done)
19
+ throw new TypeError("Collection iterator cursor exceeds its source.");
20
+ }
21
+ states.set(target, { collection: exhausted ? undefined : collection, collectionKind, method, exhausted, iterator });
22
+ return target;
23
+ }
24
+ export function collectionIteratorState(value) {
25
+ const state = states.get(value);
26
+ if (state === undefined)
27
+ throw new TypeError("Expected a collection iterator.");
28
+ return state;
29
+ }
30
+ export function snapshotCollectionIterator(value) {
31
+ const state = collectionIteratorState(value);
32
+ if (state.exhausted)
33
+ return { ...state, index: 0 };
34
+ const collection = state.collection;
35
+ const size = collection.kind === "map" ? collection.entries.size : collection.values.size;
36
+ let remaining = 0;
37
+ while (!state.iterator.next().done)
38
+ remaining += 1;
39
+ const snapshot = { ...state, index: size - remaining };
40
+ restoreSandboxCollectionIterator(snapshot, value);
41
+ return snapshot;
42
+ }
43
+ export function nextCollectionIterator(value, budget) {
44
+ const state = states.get(value);
45
+ budget?.visitNode();
46
+ if (state.exhausted)
47
+ return { value: undefined, done: true };
48
+ const result = state.iterator.next();
49
+ if (result.done) {
50
+ state.exhausted = true;
51
+ state.collection = undefined;
52
+ state.iterator = undefined;
53
+ return { value: undefined, done: true };
54
+ }
55
+ if (state.method === "entries")
56
+ budget?.allocateArrayLength(2);
57
+ return { value: result.value, done: false };
58
+ }
59
+ function nativeIterator(collection, method) {
60
+ return collection.kind === "map" ? collection.entries[method]() : collection.values[method]();
61
+ }
@@ -71,7 +71,7 @@ function populateCollection(source, collection, { name, budget, context, append,
71
71
  budget.allocateCollectionEntries(0);
72
72
  if (source === undefined || source === null)
73
73
  return collection;
74
- const iterator = getSandboxIterator(source);
74
+ const iterator = getSandboxIterator(source, budget);
75
75
  if (iterator === undefined)
76
76
  throw new TypeError(`${name} constructor requires an iterable.`);
77
77
  let entry;
@@ -1,3 +1,4 @@
1
+ import { isSandboxCollectionIterator } from "../collection-iterator.js";
1
2
  import { assertSandboxGraphDepth } from "../../graph-depth.js";
2
3
  import { allocateProducedSandboxValue, cloneSandboxValue, createSandboxClosure, isSandboxClosure, isSandboxMap, isSandboxPromise, isSandboxSet } from "../values.js";
3
4
  export function createMiscGlobals(options) {
@@ -36,8 +37,8 @@ function structuredCloneSandboxValue(value, budget) {
36
37
  return allocateProducedSandboxValue(clone, budget);
37
38
  }
38
39
  function assertStructuredCloneable(value, seen) {
39
- if (isSandboxClosure(value) || isSandboxPromise(value)) {
40
- throw new TypeError("structuredClone() cannot clone closures or promises.");
40
+ if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value)) {
41
+ throw new TypeError("structuredClone() cannot clone closures, promises, or collection iterators.");
41
42
  }
42
43
  if (typeof value !== "object" || value === null || seen.has(value)) {
43
44
  return;
@@ -122,7 +122,7 @@ export function createObjectArrayGlobals(options) {
122
122
  fromEntries: createSandboxClosure({
123
123
  sandbox: true,
124
124
  call: ([value], context) => {
125
- const iterator = getSandboxIterator(value);
125
+ const iterator = getSandboxIterator(value, options.budget);
126
126
  if (iterator === undefined) {
127
127
  throw new TypeError("Object.fromEntries requires an iterable.");
128
128
  }
@@ -411,7 +411,7 @@ async function arrayFromSandboxValues(args, budget, context) {
411
411
  const read = (property) => context?.getProperty !== undefined
412
412
  ? context.getProperty(items, property)
413
413
  : getSandboxDataProperty(items, property, budget);
414
- const iterator = getSandboxIterator(items);
414
+ const iterator = getSandboxIterator(items, budget);
415
415
  const constructor = context?.thisValue;
416
416
  let result;
417
417
  let currentValue;
@@ -3,6 +3,7 @@ import { isSandboxDate } from "../date.js";
3
3
  import { isSandboxErrorConstructorInstance } from "../exceptions.js";
4
4
  import { isFloat32Array } from "../float32.js";
5
5
  import { hasHostObjectMember, isGuestHostObject } from "../host-capabilities.js";
6
+ import { collectionIteratorState, isSandboxCollectionIterator } from "../collection-iterator.js";
6
7
  import { getSandboxPrototype, installObjectPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties } from "../object-model.js";
7
8
  import { sandboxString } from "../string-coercion.js";
8
9
  import { createSandboxClosure, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "../values.js";
@@ -143,6 +144,8 @@ function typeTag(value) {
143
144
  return "Map";
144
145
  if (isSandboxSet(value))
145
146
  return "Set";
147
+ if (isSandboxCollectionIterator(value))
148
+ return collectionIteratorState(value).collectionKind === "map" ? "Map Iterator" : "Set Iterator";
146
149
  if (isSandboxPromise(value))
147
150
  return "Promise";
148
151
  if (isSandboxGenerator(value))
@@ -27,6 +27,8 @@ import { callSetMethod, getSetMember, isSetMethodName } from "./methods/set.js";
27
27
  import { isSandboxErrorConstructorInstance } from "./globals/error.js";
28
28
  import { hasOwnSandboxProperty } from "./globals/object.js";
29
29
  import { isSandboxMapConstructor, isSandboxSetConstructor } from "./globals/collections.js";
30
+ import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
31
+ import { getCollectionIteratorMember } from "./methods/collection-iterator.js";
30
32
  import { getFloat32Member, isFloat32ArrayConstructor, setFloat32Member } from "./globals/float32array.js";
31
33
  import { isFloat32Array } from "./float32.js";
32
34
  import { dateString, dateTime, isSandboxDate } from "./date.js";
@@ -734,6 +736,9 @@ function isRestorableBindingValue(value, seen = new WeakSet()) {
734
736
  if (seen.has(value))
735
737
  return true;
736
738
  seen.add(value);
739
+ if (isSandboxCollectionIterator(value)) {
740
+ return isRestorableBindingValue(collectionIteratorState(value).collection, seen);
741
+ }
737
742
  if (isSandboxMap(value)) {
738
743
  for (const [key, entry] of value.entries) {
739
744
  if (!isRestorableBindingValue(key, seen) || !isRestorableBindingValue(entry, seen)) {
@@ -977,7 +982,7 @@ async function evaluateForOfStatement(node, context) {
977
982
  const restored = context.scope.consumeRestoredBinding(restoredIteration.values[0]);
978
983
  if (restored.found && Array.isArray(restored.value)) {
979
984
  restoredEntry = { done: false, value: restored.value[1] };
980
- if (isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0])) {
985
+ if (isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0]) || isSandboxCollectionIterator(restored.value[0])) {
981
986
  return evaluateForOfIterator(node, restored.value[0], context, restoredEntry);
982
987
  }
983
988
  }
@@ -1025,7 +1030,7 @@ async function evaluateForOfStatement(node, context) {
1025
1030
  };
1026
1031
  }
1027
1032
  async function evaluateForOfIterator(node, value, context, restoredEntry) {
1028
- const iterator = getSandboxIterator(value);
1033
+ const iterator = getSandboxIterator(value, context.budget);
1029
1034
  if (iterator === undefined) {
1030
1035
  throw new TypeError(`${String(value)} is not a supported iterable`);
1031
1036
  }
@@ -1341,7 +1346,7 @@ function createLoopIterationContext(context, scope) {
1341
1346
  snapshot.loopIterations = {};
1342
1347
  for (const [nodeId, iteration] of context.activeLoopIterations) {
1343
1348
  if (typeof iteration !== "number" &&
1344
- (isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]))) {
1349
+ (isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]) || isSandboxCollectionIterator(iteration.values[0]))) {
1345
1350
  const bindingName = `#for-of:${nodeId}`;
1346
1351
  snapshot.bindings[bindingName] = iteration.values;
1347
1352
  snapshot.loopIterations[nodeId] = { index: iteration.index, values: [bindingName] };
@@ -1469,7 +1474,7 @@ async function evaluateYieldDelegate(node, context) {
1469
1474
  if (argument.kind !== "normal") {
1470
1475
  return argument;
1471
1476
  }
1472
- const iterator = getSandboxIterator(argument.value);
1477
+ const iterator = getSandboxIterator(argument.value, context.budget);
1473
1478
  if (iterator === undefined) {
1474
1479
  throw new TypeError(`${String(argument.value)} is not a supported iterable`);
1475
1480
  }
@@ -1679,6 +1684,8 @@ function getPropertyValue(target, property, context) {
1679
1684
  return getMapMember(target, property, createMapMethodOptions(context));
1680
1685
  if (isSandboxSet(target))
1681
1686
  return getSetMember(target, property, createSetMethodOptions(context));
1687
+ if (isSandboxCollectionIterator(target))
1688
+ return getCollectionIteratorMember(target, property, context.budget);
1682
1689
  if (isSandboxGenerator(target))
1683
1690
  return getGeneratorMember(target, property, context.budget);
1684
1691
  if (isSandboxClosure(target))
@@ -1695,6 +1702,7 @@ function getPropertyValue(target, property, context) {
1695
1702
  export function createPatternContext(context, scope = context.scope, evaluate = evaluateNode) {
1696
1703
  const evaluationContext = { ...context, scope };
1697
1704
  return {
1705
+ budget: context.budget,
1698
1706
  evaluate: node => evaluate(node, evaluationContext),
1699
1707
  toPropertyKey: value => toPropertyKey(value, context.budget, createCoercionContext(evaluationContext)),
1700
1708
  getProperty: (value, key) => getPropertyValue(value, key, evaluationContext),
@@ -2141,7 +2149,7 @@ function hasSandboxProperty(value, key, context) {
2141
2149
  if (hasOwnSandboxProperty(current, key, false))
2142
2150
  return true;
2143
2151
  if (Array.isArray(current) || !isPlainSandboxObject(current) ||
2144
- isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current)) {
2152
+ isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current)) {
2145
2153
  return getPropertyValue(current, key, context) !== undefined;
2146
2154
  }
2147
2155
  current = getSandboxPrototype(current, context.budget);
@@ -2359,7 +2367,7 @@ function getMemberValue(target, property, context) {
2359
2367
  return getClosureMemberValue(current, property, context);
2360
2368
  if (Array.isArray(current))
2361
2369
  return getArrayMemberValue(current, property, context);
2362
- if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isFloat32Array(current)) {
2370
+ if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isFloat32Array(current)) {
2363
2371
  return getPropertyValue(current, property, context);
2364
2372
  }
2365
2373
  if (Object.hasOwn(current, String(property)))
@@ -2475,7 +2483,7 @@ async function evaluateNumberMethodCall(node, target, methodName, context) {
2475
2483
  return {
2476
2484
  kind: "normal",
2477
2485
  hasValue: true,
2478
- value: callNumberMethod(target, methodName, args.value, context.budget)
2486
+ value: await callNumberMethod(target, methodName, args.value, context.budget, createCoercionContext(context))
2479
2487
  };
2480
2488
  }
2481
2489
  catch (error) {
@@ -2488,6 +2496,10 @@ async function evaluateNumberMethodCall(node, target, methodName, context) {
2488
2496
  function createArrayMethodOptions(context) {
2489
2497
  return {
2490
2498
  budget: context.budget,
2499
+ context: createCoercionContext(context),
2500
+ hasProperty: (value, property) => hasSandboxProperty(value, property, context),
2501
+ setProperty: (value, property, entry) => setSandboxProperty(value, property, entry, context.budget),
2502
+ deleteProperty: deleteSandboxProperty,
2491
2503
  callClosure: (closure, args, stack, thisValue) => invokeSandboxClosure(closure, args, context, stack, undefined, thisValue)
2492
2504
  };
2493
2505
  }
@@ -2578,7 +2590,7 @@ async function evaluateSpreadElement(node, context) {
2578
2590
  result: value
2579
2591
  };
2580
2592
  }
2581
- const iterator = getSpreadIterator(value.value);
2593
+ const iterator = getSandboxIterator(value.value, context.budget);
2582
2594
  if (iterator === undefined) {
2583
2595
  throw new TypeError("Spread arguments must evaluate to an iterable.");
2584
2596
  }
@@ -2647,9 +2659,6 @@ function describeObjectSpreadValue(value) {
2647
2659
  }
2648
2660
  return typeof value;
2649
2661
  }
2650
- function getSpreadIterator(value) {
2651
- return getSandboxIterator(value);
2652
- }
2653
2662
  async function closeIterator(iterator) {
2654
2663
  if (iterator.generator && iterator.return !== undefined) {
2655
2664
  await iterator.return();
@@ -1,4 +1,5 @@
1
1
  import { type SandboxValue } from "./values.js";
2
+ import type { Budget } from "./budget.js";
2
3
  export type SandboxIterator = {
3
4
  readonly generator?: true;
4
5
  snapshotIndex?(): number;
@@ -6,4 +7,4 @@ export type SandboxIterator = {
6
7
  return?(value?: SandboxValue): IteratorResult<SandboxValue> | Promise<IteratorResult<SandboxValue>>;
7
8
  throw?(error?: SandboxValue): IteratorResult<SandboxValue> | Promise<IteratorResult<SandboxValue>>;
8
9
  };
9
- export declare function getSandboxIterator(value: SandboxValue): SandboxIterator | undefined;
10
+ export declare function getSandboxIterator(value: SandboxValue, budget?: Budget): SandboxIterator | undefined;
@@ -2,7 +2,10 @@ import { isSandboxGenerator, isSandboxMap, isSandboxSet } from "./values.js";
2
2
  import { enterRunningState } from "./running-state.js";
3
3
  import { isFloat32Array } from "./float32.js";
4
4
  import { getHostObjectIterator, isGuestHostObject } from "./host-capabilities.js";
5
- export function getSandboxIterator(value) {
5
+ import { isSandboxCollectionIterator, nextCollectionIterator } from "./collection-iterator.js";
6
+ export function getSandboxIterator(value, budget) {
7
+ if (isSandboxCollectionIterator(value))
8
+ return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
6
9
  if (isGuestHostObject(value))
7
10
  return getHostObjectIterator(value);
8
11
  if (isFloat32Array(value)) {
@@ -1,10 +1,19 @@
1
1
  import { Budget } from "../budget.js";
2
- import { type SandboxArray, type SandboxClosure, type SandboxValue } from "../values.js";
2
+ import { type SandboxArray, type SandboxCallContext, type SandboxClosure, type SandboxObject, type SandboxValue } from "../values.js";
3
+ type ArrayLikeValue = SandboxArray | (SandboxObject & {
4
+ [index: number]: SandboxValue;
5
+ length: number;
6
+ });
3
7
  export type ArrayMethodName = "map" | "filter" | "find" | "findIndex" | "findLast" | "findLastIndex" | "some" | "every" | "reduce" | "reduceRight" | "forEach" | "flatMap" | "flat" | "includes" | "indexOf" | "lastIndexOf" | "join" | "slice" | "concat" | "splice" | "fill" | "copyWithin" | "at" | "sort" | "reverse" | "toSorted" | "toReversed" | "toSpliced" | "with" | "push" | "pop" | "shift" | "unshift";
4
8
  export type ArrayMethodOptions = {
5
9
  budget: Budget;
10
+ context?: SandboxCallContext;
11
+ hasProperty?: (value: SandboxValue, property: string) => boolean;
12
+ setProperty?: (value: SandboxValue, property: string, entry: SandboxValue) => void;
13
+ deleteProperty?: (value: SandboxValue, property: string | number) => boolean;
6
14
  callClosure: (closure: SandboxClosure, args: readonly SandboxValue[], stack: readonly string[], thisValue?: SandboxValue) => Promise<SandboxValue>;
7
15
  };
8
- export declare function getArrayMember(value: SandboxArray, property: string | number, options: ArrayMethodOptions): SandboxValue | undefined;
16
+ export declare function getArrayMember(value: ArrayLikeValue, property: string | number, options: ArrayMethodOptions): SandboxValue | undefined;
9
17
  export declare function isArrayMethodName(property: string | number): property is ArrayMethodName;
10
- export declare function callArrayMethod(value: SandboxArray, methodName: ArrayMethodName, args: readonly SandboxValue[], options: ArrayMethodOptions, stack?: readonly string[]): Promise<SandboxValue>;
18
+ export declare function callArrayMethod(receiver: SandboxValue, methodName: ArrayMethodName, args: readonly SandboxValue[], options: ArrayMethodOptions, stack?: readonly string[]): Promise<SandboxValue>;
19
+ export {};