poe-code 11.0.18 → 11.0.20

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.
@@ -27,7 +27,7 @@ import {
27
27
  validateMigrationSemantics,
28
28
  validateSnapshotData,
29
29
  validateSnapshotMigration
30
- } from "./chunk-6BCUWJFF.js";
30
+ } from "./chunk-7IOZFASL.js";
31
31
 
32
32
  // packages/safejs/src/migrate.ts
33
33
  import { createHash } from "node:crypto";
@@ -8055,4 +8055,4 @@ export {
8055
8055
  parseMcpConfig,
8056
8056
  makeMcpModule
8057
8057
  };
8058
- //# sourceMappingURL=chunk-BIGMX2WV.js.map
8058
+ //# sourceMappingURL=chunk-JFP4YVY2.js.map
@@ -20,7 +20,7 @@ import {
20
20
  parseMcpConfig,
21
21
  splitFrontmatter,
22
22
  withBrokenPipeGuard
23
- } from "./chunks/chunk-BIGMX2WV.js";
23
+ } from "./chunks/chunk-JFP4YVY2.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-6BCUWJFF.js";
35
+ } from "./chunks/chunk-7IOZFASL.js";
36
36
  import "./chunks/chunk-4YIDX44G.js";
37
37
 
38
38
  // packages/safejs/src/cli.ts
@@ -3,7 +3,7 @@ import {
3
3
  createReplayableRandom,
4
4
  lint,
5
5
  run
6
- } from "./chunks/chunk-6BCUWJFF.js";
6
+ } from "./chunks/chunk-7IOZFASL.js";
7
7
  import "./chunks/chunk-4YIDX44G.js";
8
8
  export {
9
9
  Budget,
@@ -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-BIGMX2WV.js";
30
+ } from "./chunks/chunk-JFP4YVY2.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-6BCUWJFF.js";
52
+ } from "./chunks/chunk-7IOZFASL.js";
53
53
  import "./chunks/chunk-4YIDX44G.js";
54
54
 
55
55
  // packages/safejs/src/runner/run-harness.ts
@@ -291,6 +291,8 @@ function callMatchLikeMethod(value, methodName, args) {
291
291
  ? createSandboxRegex(regex.source, regex.flags, regex.lastIndex)
292
292
  : regex;
293
293
  const matches = collectRegexMatches(matcher, value, true);
294
+ if (methodName === "match" && matches.length === 0)
295
+ return null;
294
296
  return methodName === "match"
295
297
  ? matches.map((match) => match.text)
296
298
  : matches.map((match) => toMatchArray(match, value));
@@ -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
- kind: "array",
99
- items: serializeArrayItems(value, path, state)
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
- : Array.isArray(value)
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
- for (const entry of serialized.items) {
328
- array.push(deserializeValue(entry, state));
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
- : Array.isArray(value)
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
- requireArray(entry.items, `${path}.items`, state);
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
- requireArray(record.items, `${path}.items`, state);
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;