poe-code 14.0.51 → 14.0.52
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 +287 -90
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safe-js/dist/chunks/{chunk-7AIY5C3F.js → chunk-DVWTNFTV.js} +208 -48
- package/packages/safe-js/dist/chunks/chunk-DVWTNFTV.js.map +7 -0
- package/packages/safe-js/dist/chunks/{chunk-MQU3AETK.js → chunk-XIBH4BH2.js} +2 -2
- 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 +15 -10
- 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/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/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-XIBH4BH2.js.map} +0 -0
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
validateMigrationSemantics,
|
|
28
28
|
validateSnapshotData,
|
|
29
29
|
validateSnapshotMigration
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-DVWTNFTV.js";
|
|
31
31
|
import {
|
|
32
32
|
createFileSystem,
|
|
33
33
|
createNodeFileSystemAdapterRegistry,
|
|
@@ -8245,4 +8245,4 @@ export {
|
|
|
8245
8245
|
parseMcpConfig,
|
|
8246
8246
|
makeMcpModule
|
|
8247
8247
|
};
|
|
8248
|
-
//# sourceMappingURL=chunk-
|
|
8248
|
+
//# sourceMappingURL=chunk-XIBH4BH2.js.map
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
resolveFsConfig,
|
|
23
23
|
splitFrontmatter,
|
|
24
24
|
withBrokenPipeGuard
|
|
25
|
-
} from "./chunks/chunk-
|
|
25
|
+
} from "./chunks/chunk-XIBH4BH2.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-DVWTNFTV.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-XIBH4BH2.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-DVWTNFTV.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)))
|
|
@@ -2578,7 +2586,7 @@ async function evaluateSpreadElement(node, context) {
|
|
|
2578
2586
|
result: value
|
|
2579
2587
|
};
|
|
2580
2588
|
}
|
|
2581
|
-
const iterator =
|
|
2589
|
+
const iterator = getSandboxIterator(value.value, context.budget);
|
|
2582
2590
|
if (iterator === undefined) {
|
|
2583
2591
|
throw new TypeError("Spread arguments must evaluate to an iterable.");
|
|
2584
2592
|
}
|
|
@@ -2647,9 +2655,6 @@ function describeObjectSpreadValue(value) {
|
|
|
2647
2655
|
}
|
|
2648
2656
|
return typeof value;
|
|
2649
2657
|
}
|
|
2650
|
-
function getSpreadIterator(value) {
|
|
2651
|
-
return getSandboxIterator(value);
|
|
2652
|
-
}
|
|
2653
2658
|
async function closeIterator(iterator) {
|
|
2654
2659
|
if (iterator.generator && iterator.return !== undefined) {
|
|
2655
2660
|
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)) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Budget } from "../budget.js";
|
|
2
|
+
import { type SandboxCollectionIterator } from "../collection-iterator.js";
|
|
3
|
+
import { type SandboxValue } from "../values.js";
|
|
4
|
+
export declare function getCollectionIteratorMember(target: SandboxCollectionIterator, property: string | number, budget: Budget): SandboxValue;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { collectionIteratorState, isSandboxCollectionIterator, nextCollectionIterator } from "../collection-iterator.js";
|
|
2
|
+
import { createSandboxClosure } from "../values.js";
|
|
3
|
+
export function getCollectionIteratorMember(target, property, budget) {
|
|
4
|
+
if (Object.hasOwn(target, property))
|
|
5
|
+
return target[property];
|
|
6
|
+
if (property !== "next")
|
|
7
|
+
return undefined;
|
|
8
|
+
const { collectionKind } = collectionIteratorState(target);
|
|
9
|
+
return createSandboxClosure({
|
|
10
|
+
sandbox: true,
|
|
11
|
+
name: "next",
|
|
12
|
+
call: (_args, context) => {
|
|
13
|
+
const receiver = context?.thisValue;
|
|
14
|
+
if (!isSandboxCollectionIterator(receiver) || collectionIteratorState(receiver).collectionKind !== collectionKind)
|
|
15
|
+
throw new TypeError("Iterator next requires a matching collection iterator receiver.");
|
|
16
|
+
return nextCollectionIterator(receiver, budget);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSandboxClosure, isSandboxClosure, isSandboxMap } from "../values.js";
|
|
2
2
|
import { assertCollectionMutable } from "../running-state.js";
|
|
3
3
|
import { enterKeyedCollectionCallback, updateKeyedCollectionCallbacks } from "./collection-callback.js";
|
|
4
|
+
import { createSandboxCollectionIterator } from "../collection-iterator.js";
|
|
4
5
|
const mapMethodNames = new Set([
|
|
5
6
|
"get",
|
|
6
7
|
"set",
|
|
@@ -80,10 +81,8 @@ export async function callMapMethod(target, methodName, args, options, stack = [
|
|
|
80
81
|
return undefined;
|
|
81
82
|
}
|
|
82
83
|
case "keys":
|
|
83
|
-
return allocateProducedSandboxValue([...target.entries.keys()], options.budget);
|
|
84
84
|
case "values":
|
|
85
|
-
return allocateProducedSandboxValue([...target.entries.values()], options.budget);
|
|
86
85
|
case "entries":
|
|
87
|
-
return
|
|
86
|
+
return createSandboxCollectionIterator(target, methodName);
|
|
88
87
|
}
|
|
89
88
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createSandboxClosure, isSandboxClosure, isSandboxSet } from "../values.js";
|
|
2
2
|
import { assertCollectionMutable } from "../running-state.js";
|
|
3
3
|
import { enterKeyedCollectionCallback, updateKeyedCollectionCallbacks } from "./collection-callback.js";
|
|
4
|
+
import { createSandboxCollectionIterator } from "../collection-iterator.js";
|
|
4
5
|
const setMethodNames = new Set([
|
|
5
6
|
"add",
|
|
6
7
|
"has",
|
|
@@ -77,8 +78,7 @@ export async function callSetMethod(target, methodName, args, options, stack = [
|
|
|
77
78
|
}
|
|
78
79
|
case "keys":
|
|
79
80
|
case "values":
|
|
80
|
-
return allocateProducedSandboxValue([...target.values], options.budget);
|
|
81
81
|
case "entries":
|
|
82
|
-
return
|
|
82
|
+
return createSandboxCollectionIterator(target, methodName);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AssignmentPattern, MemberExpression, ParseResult, RestElement, VariableDeclarationKind, VariableDeclarator } from "../parse.js";
|
|
2
2
|
import type { AsyncEvaluationResult } from "./async.js";
|
|
3
3
|
import type { Scope } from "./scope.js";
|
|
4
|
+
import type { Budget } from "./budget.js";
|
|
4
5
|
import { type SandboxValue } from "./values.js";
|
|
5
6
|
type Pattern = VariableDeclarator["id"] | AssignmentPattern | MemberExpression | RestElement;
|
|
6
7
|
export type PatternTarget = {
|
|
@@ -10,6 +11,7 @@ export type PatternTarget = {
|
|
|
10
11
|
assign: true;
|
|
11
12
|
};
|
|
12
13
|
export type PatternContext = {
|
|
14
|
+
budget?: Budget;
|
|
13
15
|
evaluate(node: ParseResult): Promise<AsyncEvaluationResult>;
|
|
14
16
|
toPropertyKey(value: SandboxValue): Promise<string>;
|
|
15
17
|
getProperty(value: SandboxValue, key: string | number): SandboxValue;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSandboxCollectionIterator, nextCollectionIterator } from "./collection-iterator.js";
|
|
1
2
|
import { isSandboxMap, isSandboxSet, ownEnumerableSandboxEntries } from "./values.js";
|
|
2
3
|
export async function bindPattern(pattern, value, target, scope, context) {
|
|
3
4
|
switch (pattern.type) {
|
|
@@ -46,13 +47,30 @@ async function bindAssignmentPattern(pattern, value, target, scope, context) {
|
|
|
46
47
|
return bindPattern(pattern.left, defaultValue.value, target, scope, context);
|
|
47
48
|
}
|
|
48
49
|
async function bindArrayPattern(pattern, value, target, scope, context) {
|
|
49
|
-
const
|
|
50
|
+
const iterator = isSandboxCollectionIterator(value) ? value : undefined;
|
|
51
|
+
const values = iterator === undefined ? getArrayPatternValues(value) : undefined;
|
|
50
52
|
for (let index = 0; index < pattern.elements.length; index += 1) {
|
|
51
53
|
const element = pattern.elements[index];
|
|
52
54
|
if (element === null) {
|
|
55
|
+
if (iterator !== undefined)
|
|
56
|
+
nextCollectionIterator(iterator, context.budget);
|
|
53
57
|
continue;
|
|
54
58
|
}
|
|
55
|
-
|
|
59
|
+
let elementValue;
|
|
60
|
+
if (iterator === undefined) {
|
|
61
|
+
elementValue = element.type === "RestElement" ? values.slice(index) : values[index];
|
|
62
|
+
}
|
|
63
|
+
else if (element.type === "RestElement") {
|
|
64
|
+
const rest = [];
|
|
65
|
+
for (let entry = nextCollectionIterator(iterator, context.budget); !entry.done; entry = nextCollectionIterator(iterator, context.budget)) {
|
|
66
|
+
context.budget?.allocateArrayLength(rest.length + 1);
|
|
67
|
+
rest.push(entry.value);
|
|
68
|
+
}
|
|
69
|
+
elementValue = rest;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
elementValue = nextCollectionIterator(iterator, context.budget).value;
|
|
73
|
+
}
|
|
56
74
|
const binding = await bindPattern(element, elementValue, target, scope, context);
|
|
57
75
|
if (!binding.ok) {
|
|
58
76
|
return binding;
|
|
@@ -337,7 +337,7 @@ async function settleIterable(iterable, method, budget, constructor, context) {
|
|
|
337
337
|
const promiseResolve = readPromiseReceiverProperty(constructor, "resolve", prototype);
|
|
338
338
|
if (!isSandboxClosure(promiseResolve))
|
|
339
339
|
throw new TypeError("Promise constructor requires a callable resolve.");
|
|
340
|
-
const iterator = getSandboxIterator(iterable);
|
|
340
|
+
const iterator = getSandboxIterator(iterable, budget);
|
|
341
341
|
if (iterator === undefined)
|
|
342
342
|
throw new TypeError("Promise helpers require an iterable.");
|
|
343
343
|
let index = 0;
|
|
@@ -4,6 +4,7 @@ import { invokeBuiltinClosure } from "./builtin-call.js";
|
|
|
4
4
|
import { float32Storage, isFloat32Array } from "./float32.js";
|
|
5
5
|
import { assertSandboxDataDepth } from "../graph-depth.js";
|
|
6
6
|
import { isGuestHostObject } from "./host-capabilities.js";
|
|
7
|
+
import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
|
|
7
8
|
import { getGuestFunctionProperties, getSandboxPrototype, hasExplicitSandboxPrototype, isGuestClosure } from "./object-model.js";
|
|
8
9
|
import { getRegexMember } from "./methods/regex.js";
|
|
9
10
|
import { isSandboxClosure, isSandboxPromise, isSandboxMap, isSandboxSet, isSandboxRegex, isSandboxGenerator } from "./values.js";
|
|
@@ -65,6 +66,7 @@ function conversionHook(value, name, budget) {
|
|
|
65
66
|
isSandboxClosure(value) ||
|
|
66
67
|
isSandboxMap(value) ||
|
|
67
68
|
isSandboxSet(value) ||
|
|
69
|
+
isSandboxCollectionIterator(value) ||
|
|
68
70
|
isSandboxPromise(value) ||
|
|
69
71
|
isSandboxRegex(value) ||
|
|
70
72
|
isSandboxGenerator(value) ||
|
|
@@ -97,6 +99,8 @@ async function defaultToString(value, budget, context, joining) {
|
|
|
97
99
|
return "[object Map]";
|
|
98
100
|
if (isSandboxSet(value))
|
|
99
101
|
return "[object Set]";
|
|
102
|
+
if (isSandboxCollectionIterator(value))
|
|
103
|
+
return collectionIteratorState(value).collectionKind === "map" ? "[object Map Iterator]" : "[object Set Iterator]";
|
|
100
104
|
if (isSandboxGenerator(value))
|
|
101
105
|
return "[object Generator]";
|
|
102
106
|
if (isSandboxRegex(value)) {
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
import { sandboxMapBrand, sandboxSetBrand } from "./collection-brands.js";
|
|
2
|
+
import { type SandboxCollectionIterator } from "./collection-iterator.js";
|
|
1
3
|
import type { Budget, CompileTicket } from "./budget.js";
|
|
2
4
|
import { CompileScope } from "./regex/compile-guard.js";
|
|
3
5
|
import type { GeneratorChannel } from "./generator.js";
|
|
4
6
|
import { type RegexPattern } from "./regex/parse.js";
|
|
5
7
|
export { createSandboxArguments, isSandboxArguments } from "./arguments.js";
|
|
8
|
+
export { isSandboxMap, isSandboxSet } from "./collection-brands.js";
|
|
6
9
|
declare const sandboxClosureBrand: unique symbol;
|
|
7
10
|
declare const sandboxGeneratorBrand: unique symbol;
|
|
8
|
-
declare const sandboxMapBrand: unique symbol;
|
|
9
11
|
declare const sandboxPromiseBrand: unique symbol;
|
|
10
12
|
declare const sandboxRegexBrand: unique symbol;
|
|
11
13
|
declare const sandboxRegexPattern: unique symbol;
|
|
12
|
-
declare const sandboxSetBrand: unique symbol;
|
|
13
14
|
declare const sandboxRetainedValues: unique symbol;
|
|
14
15
|
export type SandboxPrimitive = string | number | boolean | null | undefined;
|
|
15
|
-
export type SandboxValue = SandboxPrimitive | Date | Float32Array | SandboxObject | SandboxArray | SandboxClosure | SandboxGenerator | SandboxMap | SandboxSet | SandboxPromise | SandboxRegex;
|
|
16
|
+
export type SandboxValue = SandboxPrimitive | Date | Float32Array | SandboxObject | SandboxArray | SandboxClosure | SandboxGenerator | SandboxCollectionIterator | SandboxMap | SandboxSet | SandboxPromise | SandboxRegex;
|
|
16
17
|
export type SandboxObject = {
|
|
17
18
|
[key: string]: SandboxValue;
|
|
18
19
|
};
|
|
@@ -123,9 +124,7 @@ export declare function createSandboxSet(values?: Iterable<SandboxValue>): Sandb
|
|
|
123
124
|
export declare function createSandboxRegex(source: string, flags?: string, lastIndex?: number, compilation?: CompileScope): SandboxRegex;
|
|
124
125
|
export declare function getSandboxRegexPattern(regex: SandboxRegex): RegexPattern;
|
|
125
126
|
export declare function isSandboxClosure(value: unknown): value is SandboxClosure;
|
|
126
|
-
export declare function isSandboxMap(value: unknown): value is SandboxMap;
|
|
127
127
|
export declare function isSandboxPromise(value: unknown): value is SandboxPromise;
|
|
128
|
-
export declare function isSandboxSet(value: unknown): value is SandboxSet;
|
|
129
128
|
export declare function isSandboxGenerator(value: unknown): value is SandboxGenerator;
|
|
130
129
|
export declare function isSandboxRegex(value: unknown): value is SandboxRegex;
|
|
131
130
|
export declare function deepCopyToSandbox(value: unknown): SandboxValue;
|