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.
- package/dist/index.js +451 -181
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-bash/dist/browser.js +35 -15
- package/packages/safe-bash/dist/browser.js.map +3 -3
- package/packages/safe-bash/dist/shell/arrays/state.d.ts +2 -1
- package/packages/safe-bash/dist/shell/arrays/state.d.ts.map +1 -1
- package/packages/safe-bash/dist/shell/arrays/state.js +23 -5
- package/packages/safe-bash/dist/shell/arrays/state.js.map +1 -1
- package/packages/safe-bash/dist/shell/cleanup.d.ts.map +1 -1
- package/packages/safe-bash/dist/shell/cleanup.js +11 -5
- package/packages/safe-bash/dist/shell/cleanup.js.map +1 -1
- package/packages/safe-bash/dist/shell/runtime.js +5 -5
- package/packages/safe-bash/dist/shell/runtime.js.map +1 -1
- package/packages/safe-js/dist/chunks/{chunk-MQU3AETK.js → chunk-4XYGVCOQ.js} +2 -2
- package/packages/safe-js/dist/chunks/{chunk-7AIY5C3F.js → chunk-VDFW3EKS.js} +368 -138
- package/packages/safe-js/dist/chunks/chunk-VDFW3EKS.js.map +7 -0
- package/packages/safe-js/dist/cli.js +2 -2
- package/packages/safe-js/dist/core.js +1 -1
- package/packages/safe-js/dist/graph-depth.js +10 -4
- package/packages/safe-js/dist/index.js +2 -2
- package/packages/safe-js/dist/interp/cancel.js +3 -0
- package/packages/safe-js/dist/interp/collection-brands.d.ts +5 -0
- package/packages/safe-js/dist/interp/collection-brands.js +8 -0
- package/packages/safe-js/dist/interp/collection-iterator.d.ts +27 -0
- package/packages/safe-js/dist/interp/collection-iterator.js +61 -0
- package/packages/safe-js/dist/interp/globals/collections.js +1 -1
- package/packages/safe-js/dist/interp/globals/misc.js +3 -2
- package/packages/safe-js/dist/interp/globals/object-array.js +2 -2
- package/packages/safe-js/dist/interp/globals/object.js +3 -0
- package/packages/safe-js/dist/interp/interpreter.js +20 -11
- package/packages/safe-js/dist/interp/iteration.d.ts +2 -1
- package/packages/safe-js/dist/interp/iteration.js +4 -1
- package/packages/safe-js/dist/interp/methods/array.d.ts +12 -3
- package/packages/safe-js/dist/interp/methods/array.js +164 -46
- package/packages/safe-js/dist/interp/methods/collection-iterator.d.ts +4 -0
- package/packages/safe-js/dist/interp/methods/collection-iterator.js +19 -0
- package/packages/safe-js/dist/interp/methods/map.js +3 -4
- package/packages/safe-js/dist/interp/methods/number.d.ts +2 -2
- package/packages/safe-js/dist/interp/methods/number.js +27 -46
- package/packages/safe-js/dist/interp/methods/set.js +3 -3
- package/packages/safe-js/dist/interp/patterns.d.ts +2 -0
- package/packages/safe-js/dist/interp/patterns.js +20 -2
- package/packages/safe-js/dist/interp/promise.js +1 -1
- package/packages/safe-js/dist/interp/string-coercion.js +4 -0
- package/packages/safe-js/dist/interp/values.d.ts +4 -5
- package/packages/safe-js/dist/interp/values.js +42 -10
- package/packages/safe-js/dist/snapshot/replay-data.d.ts +10 -0
- package/packages/safe-js/dist/snapshot/replay-data.js +32 -0
- package/packages/safe-js/dist/snapshot/replay-inputs.js +15 -0
- package/packages/safe-js/dist/snapshot/restore.js +16 -0
- package/packages/safe-js/dist/snapshot/serialize.d.ts +10 -1
- package/packages/safe-js/dist/snapshot/serialize.js +25 -9
- package/packages/safe-js/dist/snapshot/validation.js +14 -1
- package/packages/safe-js/dist/chunks/chunk-7AIY5C3F.js.map +0 -7
- /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-
|
|
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-
|
|
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";
|
|
@@ -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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
74
|
-
|
|
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-
|
|
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-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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:
|
|
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(
|
|
18
|
+
export declare function callArrayMethod(receiver: SandboxValue, methodName: ArrayMethodName, args: readonly SandboxValue[], options: ArrayMethodOptions, stack?: readonly string[]): Promise<SandboxValue>;
|
|
19
|
+
export {};
|