poe-code 11.0.18 → 11.0.19
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 +69 -10
- package/dist/index.js.map +4 -4
- package/dist/metafile.json +1 -1
- package/package.json +1 -1
- package/packages/safejs/dist/chunks/{chunk-BIGMX2WV.js → chunk-2USRJY3R.js} +2 -2
- package/packages/safejs/dist/chunks/{chunk-6BCUWJFF.js → chunk-TIKUUEG2.js} +62 -10
- package/packages/safejs/dist/chunks/{chunk-6BCUWJFF.js.map → chunk-TIKUUEG2.js.map} +3 -3
- package/packages/safejs/dist/cli.js +2 -2
- package/packages/safejs/dist/core.js +1 -1
- package/packages/safejs/dist/graph-depth.js +1 -3
- package/packages/safejs/dist/index.js +2 -2
- package/packages/safejs/dist/snapshot/arrays.d.ts +10 -0
- package/packages/safejs/dist/snapshot/arrays.js +24 -0
- package/packages/safejs/dist/snapshot/dump-format.js +7 -7
- package/packages/safejs/dist/snapshot/restore.js +9 -3
- package/packages/safejs/dist/snapshot/serialize.d.ts +2 -4
- package/packages/safejs/dist/snapshot/serialize.js +4 -7
- package/packages/safejs/dist/snapshot/validation.js +27 -2
- /package/packages/safejs/dist/chunks/{chunk-BIGMX2WV.js.map → chunk-2USRJY3R.js.map} +0 -0
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
parseMcpConfig,
|
|
21
21
|
splitFrontmatter,
|
|
22
22
|
withBrokenPipeGuard
|
|
23
|
-
} from "./chunks/chunk-
|
|
23
|
+
} from "./chunks/chunk-2USRJY3R.js";
|
|
24
24
|
import {
|
|
25
25
|
Budget,
|
|
26
26
|
SandboxError,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
replaceErrorStack,
|
|
33
33
|
restore,
|
|
34
34
|
run
|
|
35
|
-
} from "./chunks/chunk-
|
|
35
|
+
} from "./chunks/chunk-TIKUUEG2.js";
|
|
36
36
|
import "./chunks/chunk-4YIDX44G.js";
|
|
37
37
|
|
|
38
38
|
// packages/safejs/src/cli.ts
|
|
@@ -64,8 +64,6 @@ function graphEntries(value) {
|
|
|
64
64
|
if (isSandboxArguments(value)) {
|
|
65
65
|
return getSandboxArgumentEntries(value).map(([key, entry]) => [`.${key}`, entry]);
|
|
66
66
|
}
|
|
67
|
-
if (Array.isArray(value))
|
|
68
|
-
return value.map((entry, index) => [`[${index}]`, entry]);
|
|
69
67
|
if (value instanceof Map) {
|
|
70
68
|
return [...value.entries()].flatMap(([key, entry], index) => [
|
|
71
69
|
[`.<map>[${index}].key`, key],
|
|
@@ -79,7 +77,7 @@ function graphEntries(value) {
|
|
|
79
77
|
for (const key of Object.keys(value)) {
|
|
80
78
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
81
79
|
if (descriptor !== undefined && "value" in descriptor)
|
|
82
|
-
entries.push([`.${key}`, descriptor.value]);
|
|
80
|
+
entries.push([Array.isArray(value) ? `[${key}]` : `.${key}`, descriptor.value]);
|
|
83
81
|
}
|
|
84
82
|
return entries;
|
|
85
83
|
}
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
runWithSpawnUsageAccumulator,
|
|
28
28
|
splitFrontmatter,
|
|
29
29
|
supportsSpawnMode
|
|
30
|
-
} from "./chunks/chunk-
|
|
30
|
+
} from "./chunks/chunk-2USRJY3R.js";
|
|
31
31
|
import {
|
|
32
32
|
Budget,
|
|
33
33
|
FileSnapshotBackend,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
registerPendingHostCallPolicy,
|
|
50
50
|
restore,
|
|
51
51
|
run
|
|
52
|
-
} from "./chunks/chunk-
|
|
52
|
+
} from "./chunks/chunk-TIKUUEG2.js";
|
|
53
53
|
import "./chunks/chunk-4YIDX44G.js";
|
|
54
54
|
|
|
55
55
|
// packages/safejs/src/runner/run-harness.ts
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type SerializedArray<TValue> = {
|
|
2
|
+
kind: "array";
|
|
3
|
+
items: TValue[];
|
|
4
|
+
} | {
|
|
5
|
+
kind: "array";
|
|
6
|
+
length: number;
|
|
7
|
+
entries: Record<string, TValue>;
|
|
8
|
+
};
|
|
9
|
+
export declare function requiresArrayEntries(value: unknown[]): boolean;
|
|
10
|
+
export declare function serializeArray<TValue>(value: unknown[], serializeValue: (entry: unknown, key: string) => TValue): SerializedArray<TValue>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function requiresArrayEntries(value) {
|
|
2
|
+
const keys = Object.keys(value);
|
|
3
|
+
return keys.length !== value.length || keys.some((key, index) => key !== String(index));
|
|
4
|
+
}
|
|
5
|
+
export function serializeArray(value, serializeValue) {
|
|
6
|
+
if (!requiresArrayEntries(value)) {
|
|
7
|
+
return {
|
|
8
|
+
kind: "array",
|
|
9
|
+
items: Array.from({ length: value.length }, (_, index) => {
|
|
10
|
+
const key = String(index);
|
|
11
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
12
|
+
return serializeValue(descriptor !== undefined && "value" in descriptor ? descriptor.value : undefined, key);
|
|
13
|
+
})
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const entries = Object.create(null);
|
|
17
|
+
for (const key of Object.keys(value)) {
|
|
18
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
19
|
+
if (descriptor !== undefined && "value" in descriptor) {
|
|
20
|
+
entries[key] = serializeValue(descriptor.value, key);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return { kind: "array", length: value.length, entries };
|
|
24
|
+
}
|
|
@@ -4,6 +4,7 @@ import { assertSnapshotGraphDepth } from "../graph-depth.js";
|
|
|
4
4
|
import { sandboxErrorTypes } from "../error/shape.js";
|
|
5
5
|
import { getSandboxArgumentEntries, isSandboxArguments } from "../interp/arguments.js";
|
|
6
6
|
import { serializeArguments } from "./arguments.js";
|
|
7
|
+
import { requiresArrayEntries, serializeArray } from "./arrays.js";
|
|
7
8
|
const SKIP_VALUE = Symbol("SafeJS.skip-dump-value");
|
|
8
9
|
export function serializeSafeJSSnapshot(snapshot) {
|
|
9
10
|
const replayError = Object.getOwnPropertyDescriptor(snapshot, "replayError");
|
|
@@ -94,10 +95,10 @@ function serializeHeapReference(value, path, state) {
|
|
|
94
95
|
});
|
|
95
96
|
}
|
|
96
97
|
else if (Array.isArray(value)) {
|
|
97
|
-
state.heap[String(id)] = {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
};
|
|
98
|
+
state.heap[String(id)] = serializeArray(value, (entry, key) => {
|
|
99
|
+
const serialized = serializeDumpValue(entry, `${path}[${key}]`, state);
|
|
100
|
+
return serialized === SKIP_VALUE ? { kind: "undefined" } : serialized;
|
|
101
|
+
});
|
|
101
102
|
}
|
|
102
103
|
else {
|
|
103
104
|
const errorType = sandboxErrorTypes.get(value);
|
|
@@ -137,6 +138,7 @@ function indexHeapContainers(snapshot) {
|
|
|
137
138
|
for (const [value, stat] of stats.entries()) {
|
|
138
139
|
if (stat.count > 1 ||
|
|
139
140
|
stat.cyclic ||
|
|
141
|
+
(Array.isArray(value) && requiresArrayEntries(value)) ||
|
|
140
142
|
isSandboxArguments(value) ||
|
|
141
143
|
sandboxErrorTypes.has(value)) {
|
|
142
144
|
heapIds.set(value, nextId);
|
|
@@ -173,9 +175,7 @@ function collectContainerStats(value, stats, ancestors) {
|
|
|
173
175
|
ancestors.add(value);
|
|
174
176
|
const entries = isSandboxArguments(value)
|
|
175
177
|
? getSandboxArgumentEntries(value).map(([, entry]) => entry)
|
|
176
|
-
:
|
|
177
|
-
? getArrayDataItems(value)
|
|
178
|
-
: getEnumerableDataValues(value);
|
|
178
|
+
: getEnumerableDataValues(value);
|
|
179
179
|
for (const entry of entries) {
|
|
180
180
|
collectContainerStats(entry, stats, ancestors);
|
|
181
181
|
}
|
|
@@ -322,10 +322,16 @@ function restoreHeapValue(id, state) {
|
|
|
322
322
|
throw new Error(`Snapshot references unknown heap value ${id}.`);
|
|
323
323
|
}
|
|
324
324
|
if (serialized.kind === "array") {
|
|
325
|
-
const array =
|
|
325
|
+
const array = new Array("items" in serialized ? serialized.items.length : serialized.length);
|
|
326
326
|
state.heapValueById.set(id, array);
|
|
327
|
-
|
|
328
|
-
|
|
327
|
+
const entries = "items" in serialized ? Object.entries(serialized.items) : Object.entries(serialized.entries);
|
|
328
|
+
for (const [key, entry] of entries) {
|
|
329
|
+
Object.defineProperty(array, key, {
|
|
330
|
+
value: deserializeValue(entry, state),
|
|
331
|
+
configurable: true,
|
|
332
|
+
enumerable: true,
|
|
333
|
+
writable: true
|
|
334
|
+
});
|
|
329
335
|
}
|
|
330
336
|
return array;
|
|
331
337
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SandboxErrorName } from "../error/shape.js";
|
|
2
2
|
import { type SerializedArguments } from "./arguments.js";
|
|
3
|
+
import { type SerializedArray } from "./arrays.js";
|
|
3
4
|
import { type SandboxMap, type SandboxGenerator, type SandboxRegex, type SandboxSet } from "../interp/values.js";
|
|
4
5
|
type SnapshotId = number | string;
|
|
5
6
|
type SerializedUndefinedValue = {
|
|
@@ -38,10 +39,7 @@ export type SerializedReferenceValue = {
|
|
|
38
39
|
kind: "ref";
|
|
39
40
|
id: number;
|
|
40
41
|
};
|
|
41
|
-
export type SerializedHeapValue = SerializedArguments<SerializedSnapshotValue> | {
|
|
42
|
-
kind: "array";
|
|
43
|
-
items: SerializedSnapshotValue[];
|
|
44
|
-
} | {
|
|
42
|
+
export type SerializedHeapValue = SerializedArguments<SerializedSnapshotValue> | SerializedArray<SerializedSnapshotValue> | {
|
|
45
43
|
kind: "object";
|
|
46
44
|
entries: Record<string, SerializedSnapshotValue>;
|
|
47
45
|
errorType?: SandboxErrorName;
|
|
@@ -2,6 +2,7 @@ import { hashSource } from "../parse/hash.js";
|
|
|
2
2
|
import { sandboxErrorTypes } from "../error/shape.js";
|
|
3
3
|
import { assertSnapshotGraphDepth } from "../graph-depth.js";
|
|
4
4
|
import { serializeArguments } from "./arguments.js";
|
|
5
|
+
import { requiresArrayEntries, serializeArray } from "./arrays.js";
|
|
5
6
|
import { isSandboxArguments, isSandboxGenerator, isSandboxMap, isSandboxRegex, isSandboxSet } from "../interp/values.js";
|
|
6
7
|
export class UnsnapshotableValueError extends Error {
|
|
7
8
|
path;
|
|
@@ -201,10 +202,7 @@ function serializeHeapReference(value, path, state) {
|
|
|
201
202
|
};
|
|
202
203
|
}
|
|
203
204
|
else if (Array.isArray(value)) {
|
|
204
|
-
state.heap[String(id)] = {
|
|
205
|
-
kind: "array",
|
|
206
|
-
items: value.map((entry, index) => serializeValue(entry, `${path}[${index}]`, state))
|
|
207
|
-
};
|
|
205
|
+
state.heap[String(id)] = serializeArray(value, (entry, key) => serializeValue(entry, `${path}[${key}]`, state));
|
|
208
206
|
}
|
|
209
207
|
else {
|
|
210
208
|
const entries = Object.create(null);
|
|
@@ -282,6 +280,7 @@ function indexHeapContainers(input) {
|
|
|
282
280
|
for (const [value, stat] of stats.entries()) {
|
|
283
281
|
if (stat.count > 1 ||
|
|
284
282
|
stat.cyclic ||
|
|
283
|
+
(Array.isArray(value) && requiresArrayEntries(value)) ||
|
|
285
284
|
sandboxErrorTypes.has(value) ||
|
|
286
285
|
isSandboxArguments(value) ||
|
|
287
286
|
isSandboxMap(value) ||
|
|
@@ -331,9 +330,7 @@ function collectContainerStats(value, stats, ancestors) {
|
|
|
331
330
|
? [...value.entries].flatMap(([key, entry]) => [key, entry])
|
|
332
331
|
: isSandboxSet(value)
|
|
333
332
|
? [...value.values]
|
|
334
|
-
:
|
|
335
|
-
? value
|
|
336
|
-
: Object.values(value);
|
|
333
|
+
: Object.values(value);
|
|
337
334
|
for (const entry of entries) {
|
|
338
335
|
collectContainerStats(entry, stats, ancestors);
|
|
339
336
|
}
|
|
@@ -83,7 +83,7 @@ function validateDumpHeap(root, state) {
|
|
|
83
83
|
continue;
|
|
84
84
|
}
|
|
85
85
|
if (entry.kind === "array") {
|
|
86
|
-
|
|
86
|
+
validateArrayHeap(entry, path, state);
|
|
87
87
|
continue;
|
|
88
88
|
}
|
|
89
89
|
if (entry.kind === "object") {
|
|
@@ -401,7 +401,7 @@ function validateHeapValue(value, path, state) {
|
|
|
401
401
|
if (record.kind === "arguments")
|
|
402
402
|
validateArgumentsProperties(record, path);
|
|
403
403
|
if (record.kind === "array")
|
|
404
|
-
|
|
404
|
+
validateArrayHeap(record, path, state);
|
|
405
405
|
if (record.kind === "object")
|
|
406
406
|
requireRecord(record.entries, `${path}.entries`);
|
|
407
407
|
if (record.kind === "map") {
|
|
@@ -414,6 +414,31 @@ function validateHeapValue(value, path, state) {
|
|
|
414
414
|
if (record.kind === "set")
|
|
415
415
|
requireArray(record.values, `${path}.values`, state);
|
|
416
416
|
}
|
|
417
|
+
function validateArrayHeap(record, path, state) {
|
|
418
|
+
if (Object.hasOwn(record, "items")) {
|
|
419
|
+
requireArray(record.items, `${path}.items`, state);
|
|
420
|
+
if (Object.hasOwn(record, "length") || Object.hasOwn(record, "entries"))
|
|
421
|
+
fail("invalidValue", path, "array must use either items or length and entries");
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const length = requireSafeInteger(record.length, `${path}.length`, 0);
|
|
425
|
+
if (length > 0xffff_ffff)
|
|
426
|
+
fail("invalidValue", `${path}.length`, "exceeds maximum array length");
|
|
427
|
+
if (length > state.limits.maxEntries)
|
|
428
|
+
fail("budgetExceeded", `${path}.length`, `exceeds collection entry limit ${state.limits.maxEntries}`);
|
|
429
|
+
const entries = requireRecord(record.entries, `${path}.entries`);
|
|
430
|
+
for (const key of Object.keys(entries)) {
|
|
431
|
+
if (key === "length")
|
|
432
|
+
fail("invalidValue", `${path}.entries.length`, "array length is stored separately");
|
|
433
|
+
const index = Number(key);
|
|
434
|
+
if (String(index) === key &&
|
|
435
|
+
Number.isInteger(index) &&
|
|
436
|
+
index >= 0 &&
|
|
437
|
+
index < 0xffff_ffff &&
|
|
438
|
+
index >= length)
|
|
439
|
+
fail("invalidValue", `${path}.entries${formatKey(key)}`, "array index exceeds its length");
|
|
440
|
+
}
|
|
441
|
+
}
|
|
417
442
|
function validateErrorType(record, path) {
|
|
418
443
|
if (!Object.hasOwn(record, "errorType"))
|
|
419
444
|
return;
|
|
File without changes
|