poe-code 14.0.72 → 14.0.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/index.js +850 -638
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-js/dist/chunks/{chunk-VYUHL33E.js → chunk-I2Z37MKZ.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-6UY4Z7WY.js → chunk-XKCTB5FR.js} +351 -158
  7. package/packages/safe-js/dist/chunks/chunk-XKCTB5FR.js.map +7 -0
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.js +1 -1
  10. package/packages/safe-js/dist/graph-depth.js +7 -0
  11. package/packages/safe-js/dist/index.js +2 -2
  12. package/packages/safe-js/dist/interp/globals/object-array.js +9 -7
  13. package/packages/safe-js/dist/interp/globals/object.js +2 -2
  14. package/packages/safe-js/dist/interp/interpreter.js +7 -7
  15. package/packages/safe-js/dist/interp/methods/regex.d.ts +1 -1
  16. package/packages/safe-js/dist/interp/methods/regex.js +6 -3
  17. package/packages/safe-js/dist/interp/methods/string.js +57 -18
  18. package/packages/safe-js/dist/interp/object-model.js +6 -3
  19. package/packages/safe-js/dist/interp/regexp-properties.d.ts +3 -0
  20. package/packages/safe-js/dist/interp/regexp-properties.js +7 -0
  21. package/packages/safe-js/dist/interp/values.d.ts +1 -0
  22. package/packages/safe-js/dist/interp/values.js +76 -2
  23. package/packages/safe-js/dist/snapshot/dump-format.js +27 -9
  24. package/packages/safe-js/dist/snapshot/regexp-properties.d.ts +18 -0
  25. package/packages/safe-js/dist/snapshot/regexp-properties.js +58 -0
  26. package/packages/safe-js/dist/snapshot/replay-data.d.ts +3 -2
  27. package/packages/safe-js/dist/snapshot/replay-data.js +4 -1
  28. package/packages/safe-js/dist/snapshot/restore.js +2 -0
  29. package/packages/safe-js/dist/snapshot/serialize.d.ts +3 -2
  30. package/packages/safe-js/dist/snapshot/serialize.js +23 -16
  31. package/packages/safe-js/dist/snapshot/validation.js +12 -1
  32. package/packages/safe-js/dist/chunks/chunk-6UY4Z7WY.js.map +0 -7
  33. /package/packages/safe-js/dist/chunks/{chunk-VYUHL33E.js.map → chunk-I2Z37MKZ.js.map} +0 -0
@@ -1,4 +1,6 @@
1
1
  export const DUMP_FORMAT_VERSION = 1;
2
+ import { getRegexProperties, isSandboxRegex } from "../interp/values.js";
3
+ import { hasCustomRegexProperties, serializeRegexProperties } from "./regexp-properties.js";
2
4
  export const EXECUTION_SEMANTICS = "jobs-v8";
3
5
  import { assertSnapshotGraphDepth } from "../graph-depth.js";
4
6
  import { hasGuestObjectState } from "../interp/object-model.js";
@@ -79,7 +81,7 @@ function serializeDumpValue(value, path, state) {
79
81
  if (hasGuestObjectState(value)) {
80
82
  throw new TypeError("Guest function properties and prototype links cannot be serialized.");
81
83
  }
82
- if (isSandboxBox(value) || isSandboxDate(value) || isFloat32Array(value))
84
+ if ((isSandboxRegex(value) && hasCustomRegexProperties(value)) || isSandboxBox(value) || isSandboxDate(value) || isFloat32Array(value))
83
85
  return serializeHeapReference(value, path, state);
84
86
  if (Array.isArray(value)) {
85
87
  const reference = serializeHeapReference(value, path, state);
@@ -104,7 +106,17 @@ function serializeHeapReference(value, path, state) {
104
106
  }
105
107
  if (!state.serializedHeapIds.has(id)) {
106
108
  state.serializedHeapIds.add(id);
107
- if (isSandboxBox(value)) {
109
+ if (isSandboxRegex(value) && hasCustomRegexProperties(value)) {
110
+ const encode = (entry) => {
111
+ const serialized = serializeDumpValue(entry, `${path}.<regex-property>`, state);
112
+ if (serialized === SKIP_VALUE)
113
+ throw new TypeError("Unsupported RegExp property in public dump.");
114
+ return serialized;
115
+ };
116
+ state.heap[String(id)] = { kind: "regex-object", source: value.source, flags: value.flags,
117
+ lastIndex: encode(value.lastIndex), ...serializeRegexProperties(value, encode) };
118
+ }
119
+ else if (isSandboxBox(value)) {
108
120
  state.heap[String(id)] = encodeBoxedData(value, (entry, key) => {
109
121
  if (Object.is(entry, -0))
110
122
  return { kind: "number", value: "-0" };
@@ -194,6 +206,7 @@ function indexHeapContainers(snapshot) {
194
206
  stat.cyclic ||
195
207
  ownSerializableSymbolKeys(value).length > 0 ||
196
208
  isSandboxBox(value) ||
209
+ (isSandboxRegex(value) && hasCustomRegexProperties(value)) ||
197
210
  isSandboxDate(value) ||
198
211
  isFloat32Array(value) ||
199
212
  (Array.isArray(value) && requiresArrayEntries(value)) ||
@@ -231,13 +244,18 @@ function collectContainerStats(value, stats, ancestors) {
231
244
  }
232
245
  stat.expanded = true;
233
246
  ancestors.add(value);
234
- const entries = isSandboxDate(value)
235
- ? dateDataProperties(value).flatMap(([key, descriptor]) => typeof key === "string" ? [descriptor.value] : [])
236
- : isSandboxBox(value)
237
- ? boxedDataProperties(value).map(([, descriptor]) => descriptor.value)
238
- : isSandboxArguments(value)
239
- ? getSandboxArgumentEntries(value).map(([, entry]) => entry)
240
- : getEnumerableDataValues(value);
247
+ const entries = isSandboxRegex(value)
248
+ ? Reflect.ownKeys(getRegexProperties(value)).flatMap(key => {
249
+ const descriptor = Object.getOwnPropertyDescriptor(getRegexProperties(value), key);
250
+ return "value" in descriptor ? [descriptor.value] : [];
251
+ })
252
+ : isSandboxDate(value)
253
+ ? dateDataProperties(value).flatMap(([key, descriptor]) => typeof key === "string" ? [descriptor.value] : [])
254
+ : isSandboxBox(value)
255
+ ? boxedDataProperties(value).map(([, descriptor]) => descriptor.value)
256
+ : isSandboxArguments(value)
257
+ ? getSandboxArgumentEntries(value).map(([, entry]) => entry)
258
+ : getEnumerableDataValues(value);
241
259
  for (const entry of entries) {
242
260
  collectContainerStats(entry, stats, ancestors);
243
261
  }
@@ -0,0 +1,18 @@
1
+ import { type SandboxRegex } from "../interp/values.js";
2
+ import { type SerializedSymbolProperty } from "./symbols.js";
3
+ type DataProperty<T> = {
4
+ value: T;
5
+ enumerable: boolean;
6
+ writable: boolean;
7
+ configurable: boolean;
8
+ };
9
+ export type RegexPropertyData<T> = {
10
+ properties?: Record<string, DataProperty<T>>;
11
+ symbolEntries?: Array<SerializedSymbolProperty<T>>;
12
+ extensible?: boolean;
13
+ };
14
+ export declare function hasCustomRegexProperties(value: SandboxRegex): boolean;
15
+ export declare function serializeRegexProperties<T>(value: SandboxRegex, encode: (entry: unknown) => T): RegexPropertyData<T>;
16
+ export declare function validateRegexProperties(data: RegexPropertyData<unknown>): void;
17
+ export declare function restoreRegexProperties<T>(value: SandboxRegex, data: RegexPropertyData<T>, decode: (entry: T) => unknown): void;
18
+ export {};
@@ -0,0 +1,58 @@
1
+ import { getRegexProperties } from "../interp/values.js";
2
+ import { restoreSymbolProperties, serializeSymbolProperties } from "./symbols.js";
3
+ export function hasCustomRegexProperties(value) {
4
+ const properties = getRegexProperties(value);
5
+ return Reflect.ownKeys(properties).length !== 1 || !Object.isExtensible(properties) ||
6
+ Object.getOwnPropertyDescriptor(properties, "lastIndex")?.writable !== true;
7
+ }
8
+ export function serializeRegexProperties(value, encode) {
9
+ if (!hasCustomRegexProperties(value))
10
+ return {};
11
+ const source = getRegexProperties(value);
12
+ const properties = Object.create(null);
13
+ for (const key of Object.getOwnPropertyNames(source)) {
14
+ const descriptor = Object.getOwnPropertyDescriptor(source, key);
15
+ if (!("value" in descriptor))
16
+ throw new TypeError("RegExp accessor properties cannot be serialized as data.");
17
+ properties[key] = { value: encode(descriptor.value), enumerable: descriptor.enumerable === true,
18
+ configurable: descriptor.configurable === true, writable: descriptor.writable === true };
19
+ }
20
+ const symbolEntries = serializeSymbolProperties(source, encode);
21
+ return { properties, ...(symbolEntries.length === 0 ? {} : { symbolEntries }),
22
+ ...(Object.isExtensible(source) ? {} : { extensible: false }) };
23
+ }
24
+ export function validateRegexProperties(data) {
25
+ const descriptor = (value) => {
26
+ if (typeof value !== "object" || value === null || Array.isArray(value) ||
27
+ !Object.hasOwn(value, "value") ||
28
+ !["enumerable", "configurable", "writable"].every(key => Object.hasOwn(value, key) && typeof value[key] === "boolean") ||
29
+ Object.keys(value).some(key => !["value", "enumerable", "configurable", "writable"].includes(key)))
30
+ throw new TypeError("Invalid RegExp data property descriptor.");
31
+ };
32
+ if (data.extensible !== undefined && typeof data.extensible !== "boolean")
33
+ throw new TypeError("Invalid RegExp extensibility.");
34
+ if (data.properties !== undefined) {
35
+ if (typeof data.properties !== "object" || data.properties === null || Array.isArray(data.properties))
36
+ throw new TypeError("Invalid RegExp property data.");
37
+ for (const entry of Object.values(data.properties))
38
+ descriptor(entry);
39
+ }
40
+ if (data.symbolEntries !== undefined) {
41
+ if (!Array.isArray(data.symbolEntries))
42
+ throw new TypeError("Invalid RegExp symbol properties.");
43
+ for (const entry of data.symbolEntries) {
44
+ if (!Array.isArray(entry) || entry.length !== 2)
45
+ throw new TypeError("Invalid RegExp symbol property.");
46
+ descriptor(entry[1]);
47
+ }
48
+ }
49
+ }
50
+ export function restoreRegexProperties(value, data, decode) {
51
+ validateRegexProperties(data);
52
+ const properties = getRegexProperties(value);
53
+ for (const [key, descriptor] of Object.entries(data.properties ?? {}))
54
+ Object.defineProperty(properties, key, { ...descriptor, value: decode(descriptor.value) });
55
+ restoreSymbolProperties(properties, data.symbolEntries, decode);
56
+ if (data.extensible === false)
57
+ Object.preventExtensions(properties);
58
+ }
@@ -1,3 +1,4 @@
1
+ import { type RegexPropertyData } from "./regexp-properties.js";
1
2
  import { type SerializedSymbol, type SerializedSymbolProperty } from "./symbols.js";
2
3
  import { type CollectionIterationMethod } from "../interp/collection-iterator.js";
3
4
  import { CompileScope } from "../interp/regex/compile-guard.js";
@@ -70,12 +71,12 @@ type DataNode = SerializedSymbol | {
70
71
  } | {
71
72
  kind: "set";
72
73
  values: Atom[];
73
- } | {
74
+ } | ({
74
75
  kind: "regex";
75
76
  source: string;
76
77
  flags: string;
77
78
  lastIndex: Atom;
78
- };
79
+ } & RegexPropertyData<Atom>);
79
80
  export type ReplayData = {
80
81
  root: Atom;
81
82
  nodes: DataNode[];
@@ -1,4 +1,5 @@
1
1
  import { MAX_DATA_DEPTH } from "../graph-depth.js";
2
+ import { serializeRegexProperties, restoreRegexProperties } from "./regexp-properties.js";
2
3
  import { wellKnownSymbols } from "../interp/symbols.js";
3
4
  import { symbolData, serializeSymbolProperties } from "./symbols.js";
4
5
  import { isSandboxCollectionIterator, restoreSandboxCollectionIterator, snapshotCollectionIterator } from "../interp/collection-iterator.js";
@@ -152,7 +153,8 @@ export function encodeReplayData(value, options = {}) {
152
153
  kind: "regex",
153
154
  source: entry.source,
154
155
  flags: entry.flags,
155
- lastIndex: child(entry.lastIndex, "lastIndex")
156
+ lastIndex: child(entry.lastIndex, "lastIndex"),
157
+ ...serializeRegexProperties(entry, value => child(value, "<regex-property>"))
156
158
  };
157
159
  }
158
160
  else if (isSandboxArguments(entry)) {
@@ -387,6 +389,7 @@ export function decodeReplayData(input, options = {}, parent) {
387
389
  const result = createSandboxRegex(node.source, node.flags, 0, compilation);
388
390
  restored.set(id, result);
389
391
  result.lastIndex = child(own(node, "lastIndex"));
392
+ restoreRegexProperties(result, node, child);
390
393
  return result;
391
394
  }
392
395
  if (kind === "arguments") {
@@ -1,4 +1,5 @@
1
1
  import { Budget, SandboxError } from "../interp/budget.js";
2
+ import { restoreRegexProperties } from "./regexp-properties.js";
2
3
  import { executeAsyncFunction } from "../interp/async.js";
3
4
  import { toPropertyKey } from "../interp/property-key.js";
4
5
  import { CompileScope } from "../interp/regex/compile-guard.js";
@@ -377,6 +378,7 @@ function restoreHeapValue(id, state) {
377
378
  const value = createSandboxRegex(serialized.source, serialized.flags, 0, state.compilation);
378
379
  state.heapValueById.set(id, value);
379
380
  value.lastIndex = deserializeValue(serialized.lastIndex, state);
381
+ restoreRegexProperties(value, serialized, entry => deserializeValue(entry, state));
380
382
  return value;
381
383
  }
382
384
  if (serialized.kind === "float32array") {
@@ -1,3 +1,4 @@
1
+ import { type RegexPropertyData } from "./regexp-properties.js";
1
2
  import { type SerializedSymbol, type SerializedSymbolProperty } from "./symbols.js";
2
3
  import { type CollectionIterationMethod, type SandboxCollectionIterator } from "../interp/collection-iterator.js";
3
4
  import { type SandboxErrorName } from "../error/shape.js";
@@ -47,12 +48,12 @@ export type SerializedReferenceValue = {
47
48
  kind: "ref";
48
49
  id: number;
49
50
  };
50
- export type SerializedHeapValue = SerializedSymbol | BoxedData<SerializedSnapshotValue> | {
51
+ export type SerializedHeapValue = SerializedSymbol | BoxedData<SerializedSnapshotValue> | ({
51
52
  kind: "regex-object";
52
53
  source: string;
53
54
  flags: string;
54
55
  lastIndex: SerializedSnapshotValue;
55
- } | {
56
+ } & RegexPropertyData<SerializedSnapshotValue>) | {
56
57
  kind: "collection-iterator";
57
58
  collectionKind: "map" | "set";
58
59
  method: CollectionIterationMethod;
@@ -1,4 +1,5 @@
1
1
  import { hashSource } from "../parse/hash.js";
2
+ import { hasCustomRegexProperties, serializeRegexProperties } from "./regexp-properties.js";
2
3
  import { ownSerializableSymbolKeys, serializeSymbol, serializeSymbolProperties } from "./symbols.js";
3
4
  import { collectionIteratorState, isSandboxCollectionIterator, snapshotCollectionIterator } from "../interp/collection-iterator.js";
4
5
  import { hasGuestObjectState } from "../interp/object-model.js";
@@ -12,7 +13,7 @@ import { dateDataProperties, isSandboxDate } from "../interp/date.js";
12
13
  import { serializeDate } from "./date-properties.js";
13
14
  import { boxedDataProperties, isSandboxBox } from "../interp/boxed.js";
14
15
  import { encodeBoxedData } from "./boxed.js";
15
- import { isSandboxArguments, isSandboxGenerator, isSandboxMap, isSandboxRegex, isSandboxSet } from "../interp/values.js";
16
+ import { isSandboxArguments, isSandboxGenerator, isSandboxMap, isSandboxRegex, getRegexProperties, isSandboxSet } from "../interp/values.js";
16
17
  export class UnsnapshotableValueError extends Error {
17
18
  path;
18
19
  constructor(path) {
@@ -210,7 +211,8 @@ function serializeHeapReference(value, path, state) {
210
211
  state.serializedHeapIds.add(id);
211
212
  if (isSandboxRegex(value)) {
212
213
  state.heap[String(id)] = { kind: "regex-object", source: value.source, flags: value.flags,
213
- lastIndex: serializeValue(value.lastIndex, `${path}.lastIndex`, state) };
214
+ lastIndex: serializeValue(value.lastIndex, `${path}.lastIndex`, state),
215
+ ...serializeRegexProperties(value, entry => serializeValue(entry, `${path}.<regex-property>`, state)) };
214
216
  }
215
217
  else if (isSandboxCollectionIterator(value)) {
216
218
  const snapshot = snapshotCollectionIterator(value);
@@ -346,7 +348,7 @@ function indexHeapContainers(input) {
346
348
  if (stat.count > 1 ||
347
349
  stat.cyclic ||
348
350
  ownSerializableSymbolKeys(value).length > 0 ||
349
- (isSandboxRegex(value) && (!Number.isSafeInteger(value.lastIndex) ||
351
+ (isSandboxRegex(value) && (hasCustomRegexProperties(value) || !Number.isSafeInteger(value.lastIndex) ||
350
352
  (typeof value.lastIndex === "number" && value.lastIndex < 0) || Object.is(value.lastIndex, -0))) ||
351
353
  isSandboxBox(value) ||
352
354
  isSandboxDate(value) ||
@@ -399,19 +401,24 @@ function collectContainerStats(value, stats, ancestors) {
399
401
  }
400
402
  stat.expanded = true;
401
403
  ancestors.add(value);
402
- const entries = isSandboxDate(value)
403
- ? dateDataProperties(value).flatMap(([key, descriptor]) => typeof key === "string" ? [descriptor.value] : [])
404
- : isSandboxBox(value)
405
- ? boxedDataProperties(value).map(([, descriptor]) => descriptor.value)
406
- : isSandboxCollectionIterator(value)
407
- ? [collectionIteratorState(value).collection, ...Object.values(value)]
408
- : isSandboxArguments(value)
409
- ? Object.values(Object.getOwnPropertyDescriptors(value)).flatMap((descriptor) => "value" in descriptor ? [descriptor.value] : [])
410
- : isSandboxMap(value)
411
- ? [...value.entries].flatMap(([key, entry]) => [key, entry])
412
- : isSandboxSet(value)
413
- ? [...value.values]
414
- : Object.values(value);
404
+ const entries = isSandboxRegex(value)
405
+ ? Reflect.ownKeys(getRegexProperties(value)).flatMap(key => {
406
+ const descriptor = Object.getOwnPropertyDescriptor(getRegexProperties(value), key);
407
+ return "value" in descriptor ? [descriptor.value] : [];
408
+ })
409
+ : isSandboxDate(value)
410
+ ? dateDataProperties(value).flatMap(([key, descriptor]) => typeof key === "string" ? [descriptor.value] : [])
411
+ : isSandboxBox(value)
412
+ ? boxedDataProperties(value).map(([, descriptor]) => descriptor.value)
413
+ : isSandboxCollectionIterator(value)
414
+ ? [collectionIteratorState(value).collection, ...Object.values(value)]
415
+ : isSandboxArguments(value)
416
+ ? Object.values(Object.getOwnPropertyDescriptors(value)).flatMap((descriptor) => "value" in descriptor ? [descriptor.value] : [])
417
+ : isSandboxMap(value)
418
+ ? [...value.entries].flatMap(([key, entry]) => [key, entry])
419
+ : isSandboxSet(value)
420
+ ? [...value.values]
421
+ : Object.values(value);
415
422
  for (const entry of entries) {
416
423
  collectContainerStats(entry, stats, ancestors);
417
424
  }
@@ -1,4 +1,5 @@
1
1
  import { replaceErrorStack, sandboxErrorNames } from "../error/shape.js";
2
+ import { validateRegexProperties } from "./regexp-properties.js";
2
3
  import { wellKnownSymbols } from "../interp/symbols.js";
3
4
  import { types } from "node:util";
4
5
  import { DUMP_FORMAT_VERSION } from "./dump-format.js";
@@ -84,6 +85,10 @@ function validateDumpHeap(root, state) {
84
85
  const entry = requireRecord(value, path);
85
86
  validateErrorType(entry, path);
86
87
  validateSymbolEntries(entry, path, state, heap);
88
+ if (entry.kind === "regex-object") {
89
+ validateTaggedValue(entry, path, state);
90
+ continue;
91
+ }
87
92
  if (entry.kind === "boxed") {
88
93
  validateBoxedRecord(entry, path, heap);
89
94
  continue;
@@ -376,6 +381,12 @@ function validateTaggedValue(record, path, state) {
376
381
  requireString(record.flags, `${path}.flags`, state.limits);
377
382
  if (!Object.hasOwn(record, "lastIndex"))
378
383
  fail("invalidValue", `${path}.lastIndex`, "missing regex cursor");
384
+ try {
385
+ validateRegexProperties(record);
386
+ }
387
+ catch {
388
+ fail("invalidValue", path, "invalid RegExp property data");
389
+ }
379
390
  return;
380
391
  case "array":
381
392
  case "arguments":
@@ -473,7 +484,7 @@ function validateHeapValue(value, path, state, heap) {
473
484
  function validateSymbolEntries(record, path, state, heap) {
474
485
  if (record.symbolEntries === undefined)
475
486
  return;
476
- if (record.kind !== "object" && record.kind !== "array" && record.kind !== "date" && record.kind !== "boxed")
487
+ if (record.kind !== "object" && record.kind !== "array" && record.kind !== "date" && record.kind !== "boxed" && record.kind !== "regex-object")
477
488
  fail("invalidValue", `${path}.symbolEntries`, "symbol properties are unsupported for this heap kind");
478
489
  const entries = requireArray(record.symbolEntries, `${path}.symbolEntries`, state);
479
490
  const keys = new Set();