poe-code 14.0.72 → 14.0.74

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 (45) hide show
  1. package/dist/index.js +2674 -1760
  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-2J6W3YGB.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-6UY4Z7WY.js → chunk-YEZOXLY4.js} +6279 -5426
  7. package/packages/safe-js/dist/chunks/chunk-YEZOXLY4.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 +10 -0
  11. package/packages/safe-js/dist/index.js +2 -2
  12. package/packages/safe-js/dist/interp/cancel.js +3 -0
  13. package/packages/safe-js/dist/interp/globals/misc.js +2 -1
  14. package/packages/safe-js/dist/interp/globals/object-array.js +9 -7
  15. package/packages/safe-js/dist/interp/globals/object.js +5 -2
  16. package/packages/safe-js/dist/interp/globals/regex.js +88 -7
  17. package/packages/safe-js/dist/interp/interpreter.js +21 -14
  18. package/packages/safe-js/dist/interp/iteration.js +6 -1
  19. package/packages/safe-js/dist/interp/methods/regex.d.ts +7 -3
  20. package/packages/safe-js/dist/interp/methods/regex.js +132 -23
  21. package/packages/safe-js/dist/interp/methods/regexp-iterator.d.ts +8 -0
  22. package/packages/safe-js/dist/interp/methods/regexp-iterator.js +49 -0
  23. package/packages/safe-js/dist/interp/methods/string.d.ts +2 -0
  24. package/packages/safe-js/dist/interp/methods/string.js +460 -127
  25. package/packages/safe-js/dist/interp/object-model.d.ts +2 -0
  26. package/packages/safe-js/dist/interp/object-model.js +45 -12
  27. package/packages/safe-js/dist/interp/regexp-iterator.d.ts +14 -0
  28. package/packages/safe-js/dist/interp/regexp-iterator.js +18 -0
  29. package/packages/safe-js/dist/interp/regexp-properties.d.ts +3 -0
  30. package/packages/safe-js/dist/interp/regexp-properties.js +7 -0
  31. package/packages/safe-js/dist/interp/string-coercion.js +11 -7
  32. package/packages/safe-js/dist/interp/values.d.ts +3 -1
  33. package/packages/safe-js/dist/interp/values.js +111 -2
  34. package/packages/safe-js/dist/snapshot/dump-format.js +51 -9
  35. package/packages/safe-js/dist/snapshot/regexp-properties.d.ts +18 -0
  36. package/packages/safe-js/dist/snapshot/regexp-properties.js +58 -0
  37. package/packages/safe-js/dist/snapshot/replay-data.d.ts +12 -3
  38. package/packages/safe-js/dist/snapshot/replay-data.js +35 -1
  39. package/packages/safe-js/dist/snapshot/replay-inputs.js +17 -0
  40. package/packages/safe-js/dist/snapshot/restore.js +19 -1
  41. package/packages/safe-js/dist/snapshot/serialize.d.ts +12 -3
  42. package/packages/safe-js/dist/snapshot/serialize.js +40 -17
  43. package/packages/safe-js/dist/snapshot/validation.js +25 -2
  44. package/packages/safe-js/dist/chunks/chunk-6UY4Z7WY.js.map +0 -7
  45. /package/packages/safe-js/dist/chunks/{chunk-VYUHL33E.js.map → chunk-2J6W3YGB.js.map} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  resolveFsConfig,
23
23
  splitFrontmatter,
24
24
  withBrokenPipeGuard
25
- } from "./chunks/chunk-VYUHL33E.js";
25
+ } from "./chunks/chunk-2J6W3YGB.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-6UY4Z7WY.js";
37
+ } from "./chunks/chunk-YEZOXLY4.js";
38
38
  import "./chunks/chunk-ZWJ5BJUI.js";
39
39
  import "./chunks/chunk-3YTQEPZI.js";
40
40
  import "./chunks/chunk-4YIDX44G.js";
@@ -5,7 +5,7 @@ import {
5
5
  defineExtension,
6
6
  lint,
7
7
  run
8
- } from "./chunks/chunk-6UY4Z7WY.js";
8
+ } from "./chunks/chunk-YEZOXLY4.js";
9
9
  import "./chunks/chunk-4YIDX44G.js";
10
10
  export {
11
11
  Budget,
@@ -2,8 +2,10 @@ import { replaceErrorStack } from "./error/shape.js";
2
2
  import { SandboxError } from "./interp/budget.js";
3
3
  import { getSandboxArgumentEntries, isSandboxArguments } from "./interp/arguments.js";
4
4
  import { collectionIteratorState, isSandboxCollectionIterator } from "./interp/collection-iterator.js";
5
+ import { regexpIteratorState, isSandboxRegExpIterator } from "./interp/regexp-iterator.js";
5
6
  import { isSandboxMap, isSandboxSet } from "./interp/collection-brands.js";
6
7
  import { boxedDataProperties, isSandboxBox } from "./interp/boxed.js";
8
+ import { regexGuestProperties } from "./interp/regexp-properties.js";
7
9
  export const MAX_DATA_DEPTH = 1_024;
8
10
  export class SnapshotBudgetError extends Error {
9
11
  code = "budgetExceeded";
@@ -64,6 +66,12 @@ function walkGraphDepth(root, rootPath, assertDepth) {
64
66
  }
65
67
  }
66
68
  function graphEntries(value) {
69
+ const properties = regexGuestProperties.get(value);
70
+ if (properties !== undefined)
71
+ return Reflect.ownKeys(properties).flatMap(key => {
72
+ const descriptor = Object.getOwnPropertyDescriptor(properties, key);
73
+ return "value" in descriptor ? [[`.${String(key)}`, descriptor.value]] : [];
74
+ });
67
75
  if (isSandboxBox(value))
68
76
  return boxedDataProperties(value).map(([key, descriptor]) => [`.${key}`, descriptor.value]);
69
77
  if (isSandboxArguments(value)) {
@@ -83,6 +91,8 @@ function graphEntries(value) {
83
91
  const entries = [];
84
92
  if (isSandboxCollectionIterator(value))
85
93
  entries.push([".<collection>", collectionIteratorState(value).collection]);
94
+ if (isSandboxRegExpIterator(value))
95
+ entries.push([".<matcher>", regexpIteratorState(value).matcher]);
86
96
  for (const key of Object.keys(value)) {
87
97
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
88
98
  if (descriptor !== undefined && "value" in descriptor)
@@ -26,7 +26,7 @@ import {
26
26
  runWithSpawnUsageAccumulator,
27
27
  splitFrontmatter,
28
28
  supportsSpawnMode
29
- } from "./chunks/chunk-VYUHL33E.js";
29
+ } from "./chunks/chunk-2J6W3YGB.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-6UY4Z7WY.js";
53
+ } from "./chunks/chunk-YEZOXLY4.js";
54
54
  import "./chunks/chunk-ZWJ5BJUI.js";
55
55
  import "./chunks/chunk-3YTQEPZI.js";
56
56
  import "./chunks/chunk-4YIDX44G.js";
@@ -1,5 +1,6 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
3
+ import { regexpIteratorState, isSandboxRegExpIterator } from "./regexp-iterator.js";
3
4
  import { getSandboxPrototype } from "./object-model.js";
4
5
  import { createSandboxPromise, isSandboxClosure, isSandboxMap, isSandboxPromise, isSandboxSet } from "./values.js";
5
6
  import { assertPromiseExecutionAllowed, interruptOnFatalPromiseRejection, onFatalPromiseRejection, observeSandboxPromise, trackSandboxPromise } from "./promise-tracker.js";
@@ -100,6 +101,8 @@ function registerCancelablePromises(value, signal) {
100
101
  else {
101
102
  if (isSandboxCollectionIterator(current))
102
103
  pending.push(collectionIteratorState(current).collection);
104
+ if (isSandboxRegExpIterator(current))
105
+ pending.push(regexpIteratorState(current).matcher);
103
106
  for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(current))) {
104
107
  if ("value" in descriptor)
105
108
  pending.push(descriptor.value);
@@ -1,4 +1,5 @@
1
1
  import { isSandboxCollectionIterator } from "../collection-iterator.js";
2
+ import { isSandboxRegExpIterator } from "../regexp-iterator.js";
2
3
  import { assertSandboxGraphDepth } from "../../graph-depth.js";
3
4
  import { CompileScope } from "../regex/compile-guard.js";
4
5
  import { createNumericParsers } from "./numeric-parsers.js";
@@ -49,7 +50,7 @@ function structuredCloneSandboxValue(value, budget, parent) {
49
50
  }
50
51
  }
51
52
  function assertStructuredCloneable(value, seen) {
52
- if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value)) {
53
+ if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value) || isSandboxRegExpIterator(value)) {
53
54
  throw new TypeError("structuredClone() cannot clone closures, promises, or collection iterators.");
54
55
  }
55
56
  if (typeof value !== "object" || value === null || seen.has(value)) {
@@ -17,7 +17,7 @@ import { toPropertyKey } from "../property-key.js";
17
17
  import { createNumericParsers } from "./numeric-parsers.js";
18
18
  import { createPrimitiveConstructor } from "./primitives.js";
19
19
  import { getSandboxDataProperty, getSandboxPropertyDescriptor, getSandboxPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
20
- import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, measureSandboxData, ownEnumerableSandboxKeys as getOwnEnumerableKeys, ownSandboxSymbolKeys, ownEnumerableSandboxEntries as getDirectEntries } from "../values.js";
20
+ import { allocateProducedSandboxValue, createSandboxClosure, deepCopyToSandbox, defineOwnDataProperty, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, getRegexProperties, isSandboxSet, measureSandboxData, ownEnumerableSandboxKeys as getOwnEnumerableKeys, ownSandboxSymbolKeys, ownEnumerableSandboxEntries as getDirectEntries } from "../values.js";
21
21
  export function createObjectArrayGlobals(options) {
22
22
  return {
23
23
  Object: createObjectGlobal({
@@ -171,14 +171,14 @@ export function createObjectArrayGlobals(options) {
171
171
  call: ([value]) => {
172
172
  if (isGuestHostObject(value))
173
173
  throw new TypeError("Live host objects cannot be made non-extensible.");
174
- Object.preventExtensions(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
174
+ Object.preventExtensions(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value);
175
175
  return value;
176
176
  },
177
177
  name: "preventExtensions"
178
178
  }),
179
179
  isExtensible: createSandboxClosure({
180
180
  sandbox: true,
181
- call: ([value]) => Object.isExtensible(isGuestClosure(value) ? materializeFunctionProperties(value) : value),
181
+ call: ([value]) => Object.isExtensible(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value),
182
182
  name: "isExtensible"
183
183
  }),
184
184
  seal: createSandboxClosure({
@@ -186,14 +186,14 @@ export function createObjectArrayGlobals(options) {
186
186
  call: ([value]) => {
187
187
  if (isGuestHostObject(value))
188
188
  throw new TypeError("Live host objects cannot be sealed.");
189
- Object.seal(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
189
+ Object.seal(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value);
190
190
  return value;
191
191
  },
192
192
  name: "seal"
193
193
  }),
194
194
  isSealed: createSandboxClosure({
195
195
  sandbox: true,
196
- call: ([value]) => Object.isSealed(isGuestClosure(value) ? materializeFunctionProperties(value) : value),
196
+ call: ([value]) => Object.isSealed(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value),
197
197
  name: "isSealed"
198
198
  }),
199
199
  freeze: createSandboxClosure({
@@ -202,7 +202,7 @@ export function createObjectArrayGlobals(options) {
202
202
  if (isGuestHostObject(value))
203
203
  throw new TypeError("Live host objects cannot be frozen.");
204
204
  if (typeof value === "object" && value !== null) {
205
- Object.freeze(isGuestClosure(value) ? materializeFunctionProperties(value) : value);
205
+ Object.freeze(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value);
206
206
  }
207
207
  return value;
208
208
  },
@@ -210,7 +210,7 @@ export function createObjectArrayGlobals(options) {
210
210
  }),
211
211
  isFrozen: createSandboxClosure({
212
212
  sandbox: true,
213
- call: ([value]) => Object.isFrozen(isGuestClosure(value) ? materializeFunctionProperties(value) : value),
213
+ call: ([value]) => Object.isFrozen(isGuestClosure(value) ? materializeFunctionProperties(value) : isSandboxRegex(value) ? getRegexProperties(value) : value),
214
214
  name: "isFrozen"
215
215
  }),
216
216
  assign: createSandboxClosure({
@@ -425,6 +425,8 @@ function assignSandboxValues(target, sources, budget, context) {
425
425
  })();
426
426
  }
427
427
  function objectProperties(value, mutable = false) {
428
+ if (isSandboxRegex(value))
429
+ return getRegexProperties(value);
428
430
  if (isSandboxDate(value)) {
429
431
  return value;
430
432
  }
@@ -7,9 +7,10 @@ import { isSandboxErrorConstructorInstance } from "../exceptions.js";
7
7
  import { isFloat32Array } from "../float32.js";
8
8
  import { hasHostObjectMember, isGuestHostObject } from "../host-capabilities.js";
9
9
  import { collectionIteratorState, isSandboxCollectionIterator } from "../collection-iterator.js";
10
+ import { isSandboxRegExpIterator } from "../regexp-iterator.js";
10
11
  import { getSandboxPrototype, getSandboxPropertyDescriptor, hasExplicitSandboxPrototype, installObjectPrototype, isGuestClosure, markDescriptorObject, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
11
12
  import { toPropertyKey } from "../property-key.js";
12
- import { createSandboxClosure, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet } from "../values.js";
13
+ import { createSandboxClosure, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, getRegexProperties, isSandboxSet } from "../values.js";
13
14
  import { measureSandboxData } from "../values.js";
14
15
  export function createObjectGlobal(methods, budget) {
15
16
  const construct = ([value]) => {
@@ -138,7 +139,7 @@ export function hasOwnSandboxProperty(value, key, enumerable) {
138
139
  isSandboxGenerator(value))
139
140
  return false;
140
141
  else if (isSandboxRegex(value))
141
- return key === "lastIndex" && !enumerable;
142
+ properties = getRegexProperties(value);
142
143
  else
143
144
  properties = Object(value);
144
145
  const descriptor = Object.getOwnPropertyDescriptor(properties, key);
@@ -180,6 +181,8 @@ function typeTag(value, builtinOnly = false) {
180
181
  return "Map";
181
182
  if (isSandboxSet(value))
182
183
  return "Set";
184
+ if (isSandboxRegExpIterator(value))
185
+ return "RegExp String Iterator";
183
186
  if (isSandboxCollectionIterator(value))
184
187
  return collectionIteratorState(value).collectionKind === "map" ? "Map Iterator" : "Set Iterator";
185
188
  if (isSandboxPromise(value))
@@ -2,6 +2,11 @@ import { createSandboxClosure, createSandboxRegex, isSandboxRegex, reconcileComp
2
2
  import { CompileScope } from "../regex/compile-guard.js";
3
3
  import { SandboxError } from "../budget.js";
4
4
  import { sandboxString } from "../string-coercion.js";
5
+ import { getSandboxPropertyDescriptor, installRegexPrototype, materializeFunctionProperties, setSandboxPrototype } from "../object-model.js";
6
+ import { accessorAdapter, readPropertyDescriptor } from "../accessors.js";
7
+ import { callRegexMethod, getRegexMember, regexFlagProperties, regexSearch } from "../methods/regex.js";
8
+ import { regexMatch, regexReplace } from "../methods/string.js";
9
+ import { invokeBuiltinClosure } from "../builtin-call.js";
5
10
  export function createRegexGlobals(options) {
6
11
  const invoke = (construct) => async (args, context) => {
7
12
  const selected = options.compileOwner ?? context?.compilation?.owner;
@@ -12,18 +17,51 @@ export function createRegexGlobals(options) {
12
17
  const compilation = context?.compilation?.owner === operation.owner
13
18
  ? context.compilation : new CompileScope(operation.owner);
14
19
  let source = "";
20
+ let retainedSource;
21
+ let retainedFlags;
22
+ let retainedPrototype;
15
23
  const retained = {};
16
- options.budget.setRetainedValues(retained, () => [...args, source]);
24
+ options.budget.setRetainedValues(retained, () => [...args, source, retainedSource, retainedFlags, retainedPrototype]);
17
25
  try {
18
26
  const pattern = args[0];
19
27
  const flags = args[1];
20
- if (!construct && isSandboxRegex(pattern) && flags === undefined)
28
+ const read = (key) => {
29
+ const descriptor = getSandboxPropertyDescriptor(pattern, key, options.budget);
30
+ if (context?.getProperty !== undefined)
31
+ return context.getProperty(pattern, key);
32
+ return descriptor === undefined ? undefined : readPropertyDescriptor(descriptor, pattern, context);
33
+ };
34
+ let regexLike = false;
35
+ if (pattern !== null && typeof pattern === "object") {
36
+ const match = await read(Symbol.match);
37
+ regexLike = match === undefined ? isSandboxRegex(pattern) : Boolean(match);
38
+ }
39
+ if (!construct && regexLike && flags === undefined && await read("constructor") === constructor)
21
40
  return pattern;
22
- const sourceValue = isSandboxRegex(pattern) ? pattern.source : pattern;
23
- const flagsValue = isSandboxRegex(pattern) && flags === undefined ? pattern.flags : flags;
41
+ let sourceValue = pattern;
42
+ let flagsValue = flags;
43
+ if (isSandboxRegex(pattern)) {
44
+ sourceValue = pattern.source;
45
+ if (flags === undefined)
46
+ flagsValue = pattern.flags;
47
+ }
48
+ else if (regexLike) {
49
+ sourceValue = retainedSource = await read("source");
50
+ if (flags === undefined)
51
+ flagsValue = retainedFlags = await read("flags");
52
+ }
53
+ if (construct && context?.newTarget !== undefined && context.newTarget !== constructor) {
54
+ retainedPrototype = context.getProperty !== undefined
55
+ ? await context.getProperty(context.newTarget, "prototype")
56
+ : await readPropertyDescriptor(getSandboxPropertyDescriptor(context.newTarget, "prototype", options.budget) ?? { value: undefined }, context.newTarget, context);
57
+ }
24
58
  source = sourceValue === undefined ? "" : await sandboxString(sourceValue, options.budget, context);
59
+ retainedSource = undefined;
25
60
  const flagText = flagsValue === undefined ? "" : await sandboxString(flagsValue, options.budget, context);
61
+ retainedFlags = undefined;
26
62
  const regex = createSandboxRegex(source, flagText, 0, compilation);
63
+ if (typeof retainedPrototype === "object" && retainedPrototype !== null)
64
+ setSandboxPrototype(regex, retainedPrototype, options.budget);
27
65
  if (compilation !== context?.compilation) {
28
66
  reconcileCompiledValues(options.budget, [regex], compilation);
29
67
  }
@@ -36,7 +74,50 @@ export function createRegexGlobals(options) {
36
74
  operation.release();
37
75
  }
38
76
  };
39
- return {
40
- RegExp: createSandboxClosure({ sandbox: true, name: "RegExp", call: invoke(false), construct: invoke(true) })
41
- };
77
+ const constructor = createSandboxClosure({ guest: true, sandbox: true, name: "RegExp", length: 2, call: invoke(false), construct: invoke(true) });
78
+ const prototype = Object.create(null);
79
+ Object.defineProperty(materializeFunctionProperties(constructor), "prototype", { value: prototype, writable: false });
80
+ Object.defineProperty(prototype, "constructor", { value: constructor, writable: true, configurable: true });
81
+ Object.defineProperty(prototype, Symbol.search, {
82
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "[Symbol.search]", length: 1,
83
+ call: (args, context) => regexSearch(context?.thisValue, args[0], options.budget, context) }),
84
+ writable: true, configurable: true
85
+ });
86
+ Object.defineProperty(prototype, Symbol.match, {
87
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "[Symbol.match]", length: 1,
88
+ call: (args, context) => regexMatch(args[0], context?.thisValue, options.budget, context) }),
89
+ writable: true, configurable: true
90
+ });
91
+ Object.defineProperty(prototype, Symbol.replace, {
92
+ value: createSandboxClosure({ guest: true, sandbox: true, name: "[Symbol.replace]", length: 2,
93
+ call: (args, context) => regexReplace(args[0], context?.thisValue, args[1], options.budget, (closure, values) => invokeBuiltinClosure(closure, values, options.budget, context, undefined), context) }),
94
+ writable: true, configurable: true
95
+ });
96
+ for (const name of ["exec", "test", "toString"]) {
97
+ Object.defineProperty(prototype, name, {
98
+ value: createSandboxClosure({ sandbox: true, name, length: name === "toString" ? 0 : 1,
99
+ call: (args, context) => callRegexMethod(context?.thisValue, name, args, options.budget, context) }),
100
+ writable: true, configurable: true
101
+ });
102
+ }
103
+ for (const name of ["source", "flags", ...Object.keys(regexFlagProperties)]) {
104
+ const getter = createSandboxClosure({ sandbox: true, name: `get ${name}`, length: 0,
105
+ call: (_args, context) => {
106
+ const receiver = context?.thisValue;
107
+ if (name === "flags") {
108
+ if (receiver === null || typeof receiver !== "object")
109
+ throw new TypeError("RegExp flags requires an object receiver.");
110
+ return getRegexMember(receiver, name, options.budget, context);
111
+ }
112
+ if (receiver === prototype)
113
+ return name === "source" ? "(?:)" : undefined;
114
+ if (!isSandboxRegex(receiver))
115
+ throw new TypeError("RegExp accessor requires a regex receiver.");
116
+ return getRegexMember(receiver, name, options.budget, context);
117
+ }
118
+ });
119
+ Object.defineProperty(prototype, name, { get: accessorAdapter(getter, "get"), configurable: true });
120
+ }
121
+ installRegexPrototype(options.budget, prototype, constructor);
122
+ return { RegExp: constructor };
42
123
  }
@@ -26,7 +26,7 @@ import { getPromiseMember, isSandboxPromiseConstructor } from "./promise.js";
26
26
  import { acquireSandboxIterator, closeIterator, readIteratorResult } from "./iteration.js";
27
27
  import { assertCollectionMutable } from "./running-state.js";
28
28
  import { getGeneratorMember } from "./methods/generator.js";
29
- import { getRegexMember, isRegexMethodName, setRegexMember } from "./methods/regex.js";
29
+ import { getRegexMember, setRegexMember } from "./methods/regex.js";
30
30
  import { bindPattern } from "./patterns.js";
31
31
  import { callStringMethod, getStringMember, isStringMethodName, validateStringMethodArguments } from "./methods/string.js";
32
32
  import { callSetMethod, getSetMember, isSetMethodName } from "./methods/set.js";
@@ -35,11 +35,13 @@ import { hasOwnSandboxProperty } from "./globals/object.js";
35
35
  import { isSandboxMapConstructor, isSandboxSetConstructor } from "./globals/collections.js";
36
36
  import { collectionIteratorState, isSandboxCollectionIterator } from "./collection-iterator.js";
37
37
  import { getCollectionIteratorMember } from "./methods/collection-iterator.js";
38
+ import { isSandboxRegExpIterator, regexpIteratorState } from "./regexp-iterator.js";
39
+ import { getRegExpIteratorMember } from "./methods/regexp-iterator.js";
38
40
  import { getFloat32Member, isFloat32ArrayConstructor, setFloat32Member } from "./globals/float32array.js";
39
41
  import { isFloat32Array } from "./float32.js";
40
42
  import { dateString, dateTime, isSandboxDate } from "./date.js";
41
43
  import { getDateMember, getDatePrototype, isDateConstructor } from "./globals/date.js";
42
- import { createSandboxRegex, allocateProducedSandboxValue, ownEnumerableSandboxKeys, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, isSandboxSet, reconcileCompiledValues } from "./values.js";
44
+ import { createSandboxRegex, allocateProducedSandboxValue, ownEnumerableSandboxKeys, isSandboxClosure, isSandboxGenerator, isSandboxMap, isSandboxPromise, isSandboxRegex, getRegexProperties, isSandboxSet, reconcileCompiledValues } from "./values.js";
43
45
  import { Scope } from "./scope.js";
44
46
  import { hoistVarDeclarations } from "./var-hoist.js";
45
47
  const taggedTemplateRawArrays = new WeakMap();
@@ -857,6 +859,8 @@ function isRestorableBindingValue(value, seen = new WeakSet()) {
857
859
  if (seen.has(value))
858
860
  return true;
859
861
  seen.add(value);
862
+ if (isSandboxRegExpIterator(value))
863
+ return isRestorableBindingValue(regexpIteratorState(value).matcher, seen);
860
864
  if (isSandboxCollectionIterator(value)) {
861
865
  return isRestorableBindingValue(collectionIteratorState(value).collection, seen);
862
866
  }
@@ -1116,7 +1120,7 @@ async function evaluateForOfStatement(node, context) {
1116
1120
  const restored = context.scope.consumeRestoredBinding(restoredIteration.values[0]);
1117
1121
  if (restored.found && Array.isArray(restored.value)) {
1118
1122
  restoredEntry = { done: false, value: restored.value[1] };
1119
- if (Array.isArray(restored.value[0]) || isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0]) || isSandboxCollectionIterator(restored.value[0])) {
1123
+ if (Array.isArray(restored.value[0]) || isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0]) || isSandboxCollectionIterator(restored.value[0]) || isSandboxRegExpIterator(restored.value[0])) {
1120
1124
  return evaluateForOfIterator(node, restored.value[0], context, restoredEntry);
1121
1125
  }
1122
1126
  }
@@ -1510,7 +1514,7 @@ function createLoopIterationContext(context, scope) {
1510
1514
  snapshot.loopIterations = {};
1511
1515
  for (const [nodeId, iteration] of context.activeLoopIterations) {
1512
1516
  if (typeof iteration !== "number" &&
1513
- (Array.isArray(iteration.values[0]) || isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]) || isSandboxCollectionIterator(iteration.values[0]))) {
1517
+ (Array.isArray(iteration.values[0]) || isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]) || isSandboxCollectionIterator(iteration.values[0]) || isSandboxRegExpIterator(iteration.values[0]))) {
1514
1518
  const bindingName = `#for-of:${nodeId}`;
1515
1519
  snapshot.bindings[bindingName] = iteration.values;
1516
1520
  snapshot.loopIterations[nodeId] = { index: iteration.index, values: [bindingName] };
@@ -1772,7 +1776,7 @@ async function evaluateDeleteExpression(node, context) {
1772
1776
  }
1773
1777
  throw new TypeError("Cannot delete properties of null or undefined.");
1774
1778
  }
1775
- if (!isIndexableSandboxValue(member.object)) {
1779
+ if (!isIndexableSandboxValue(member.object) && !isSandboxRegex(member.object)) {
1776
1780
  throw new TypeError("Unary operator 'delete' requires a sandbox object property.");
1777
1781
  }
1778
1782
  const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
@@ -1852,6 +1856,8 @@ function getPropertyValue(target, property, context, receiver = target) {
1852
1856
  const descriptor = getSandboxPropertyDescriptor(target, property, context.budget);
1853
1857
  if (descriptor !== undefined)
1854
1858
  return readPropertyDescriptor(descriptor, receiver, createCoercionContext(context), true);
1859
+ if (isSandboxRegExpIterator(target))
1860
+ return getRegExpIteratorMember(property, context.budget);
1855
1861
  if (typeof target === "symbol") {
1856
1862
  const prototype = getBoxedPrototype(target, context.budget);
1857
1863
  return prototype === undefined ? undefined : getPropertyValue(prototype, property, context, receiver);
@@ -1892,7 +1898,8 @@ function getPropertyValue(target, property, context, receiver = target) {
1892
1898
  if (isSandboxPromise(target))
1893
1899
  return getPromiseMember(property, context.budget);
1894
1900
  if (isSandboxRegex(target))
1895
- return getRegexMember(target, property, context.budget);
1901
+ return hasExplicitSandboxPrototype(target) || getSandboxPrototype(target, context.budget) !== null
1902
+ ? undefined : getRegexMember(target, property, context.budget, createCoercionContext(context));
1896
1903
  if (!isIndexableSandboxValue(target)) {
1897
1904
  throw new TypeError("Attempted to read a property from a non-object value.");
1898
1905
  }
@@ -2132,8 +2139,8 @@ async function evaluateMemberCallExpression(node, context) {
2132
2139
  if (isSandboxPromise(member.object)) {
2133
2140
  return evaluateResolvedCallExpression(node, getPromiseMember(member.property, context.budget), context, member.object);
2134
2141
  }
2135
- if (isSandboxRegex(member.object) && isRegexMethodName(member.property)) {
2136
- return evaluateResolvedCallExpression(node, getRegexMember(member.object, member.property, context.budget), context, member.object);
2142
+ if (isSandboxRegex(member.object)) {
2143
+ return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
2137
2144
  }
2138
2145
  if (!isIndexableSandboxValue(member.object)) {
2139
2146
  throw new TypeError("Attempted to read a property from a non-object value.");
@@ -2381,9 +2388,9 @@ function hasSandboxProperty(value, key, context) {
2381
2388
  return typeof key === "symbol" ? false : hasHostObjectMember(current, String(key));
2382
2389
  if (hasOwnSandboxProperty(current, key, false))
2383
2390
  return true;
2384
- if (!((isGuestClosure(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) &&
2391
+ if (!isSandboxRegex(current) && !((isGuestClosure(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) &&
2385
2392
  (Array.isArray(current) || !isPlainSandboxObject(current) ||
2386
- isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current))) {
2393
+ isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isSandboxRegExpIterator(current))) {
2387
2394
  return getPropertyValue(current, key, context) !== undefined;
2388
2395
  }
2389
2396
  current = getSandboxPrototype(current, context.budget);
@@ -2603,7 +2610,7 @@ function getMemberValue(target, property, context) {
2603
2610
  return getClosureMemberValue(current, property, context);
2604
2611
  if (Array.isArray(current))
2605
2612
  return getArrayMemberValue(current, property, context);
2606
- if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isFloat32Array(current)) {
2613
+ if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isSandboxRegExpIterator(current) || isFloat32Array(current)) {
2607
2614
  return getPropertyValue(current, property, context);
2608
2615
  }
2609
2616
  if (Object.hasOwn(current, String(property)))
@@ -2646,9 +2653,7 @@ export function setSandboxProperty(target, property, value, budget, checkInherit
2646
2653
  return;
2647
2654
  }
2648
2655
  if (isSandboxRegex(target)) {
2649
- if (typeof property === "symbol")
2650
- throw new TypeError("RegExp symbol properties are not yet supported.");
2651
- setRegexMember(target, property, value);
2656
+ setRegexMember(target, property, value, budget);
2652
2657
  return;
2653
2658
  }
2654
2659
  if (!isIndexableSandboxValue(target)) {
@@ -2714,6 +2719,8 @@ function deleteSandboxProperty(target, property) {
2714
2719
  return deleteHostObjectMember(target, String(property));
2715
2720
  if (isGuestClosure(target))
2716
2721
  target = materializeFunctionProperties(target);
2722
+ if (isSandboxRegex(target))
2723
+ target = getRegexProperties(target);
2717
2724
  if (Array.isArray(target)) {
2718
2725
  assertCollectionMutable(target);
2719
2726
  }
@@ -4,6 +4,8 @@ import { isFloat32Array } from "./float32.js";
4
4
  import { boxedValue, isSandboxBox } from "./boxed.js";
5
5
  import { getHostObjectIterator, isGuestHostObject } from "./host-capabilities.js";
6
6
  import { isSandboxCollectionIterator, nextCollectionIterator } from "./collection-iterator.js";
7
+ import { isSandboxRegExpIterator } from "./regexp-iterator.js";
8
+ import { nextRegExpIterator } from "./methods/regexp-iterator.js";
7
9
  import { Budget, isFatalSandboxError } from "./budget.js";
8
10
  import { sandboxString } from "./string-coercion.js";
9
11
  import { awaitSandboxValue, awaitWithSignal } from "./cancel.js";
@@ -17,7 +19,8 @@ export async function acquireSandboxIterator(value, budget, context, asyncProtoc
17
19
  return asyncProtocol
18
20
  ? getSandboxAsyncIterator(value, budget, context, signal)
19
21
  : getSandboxIterator(value, budget, context);
20
- if (getSandboxPropertyDescriptor(value, key, budget) === undefined) {
22
+ if (getSandboxPropertyDescriptor(value, key, budget) === undefined &&
23
+ !(isSandboxRegExpIterator(value) && !asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== undefined)) {
21
24
  if (!asyncProtocol)
22
25
  return getSandboxIterator(value, budget, context);
23
26
  if (isSandboxGenerator(value) && value.async)
@@ -222,6 +225,8 @@ export function getSandboxIterator(value, budget, context) {
222
225
  }
223
226
  if (isSandboxCollectionIterator(value))
224
227
  return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
228
+ if (isSandboxRegExpIterator(value))
229
+ return { next: () => nextRegExpIterator(value, budget), snapshotIndex: () => 0 };
225
230
  if (isGuestHostObject(value))
226
231
  return getHostObjectIterator(value);
227
232
  if (isFloat32Array(value)) {
@@ -1,10 +1,14 @@
1
1
  import { type SandboxCallContext, type SandboxRegex, type SandboxValue } from "../values.js";
2
2
  import { type RegexMatch } from "../regex/engine.js";
3
3
  import type { Budget } from "../budget.js";
4
- export type RegexMethodName = "exec" | "test";
4
+ export declare function regexSearch(target: SandboxValue, input: SandboxValue, budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
5
+ export type RegexMethodName = "exec" | "test" | "toString";
6
+ export declare const regexFlagProperties: Readonly<Record<string, string>>;
5
7
  export declare function isRegexMethodName(property: string | number): property is RegexMethodName;
6
- export declare function getRegexMember(target: SandboxRegex, property: string | number, budget: Budget): SandboxValue | undefined;
7
- export declare function setRegexMember(target: SandboxRegex, property: string | number, value: SandboxValue): void;
8
+ export declare function getRegexMember(target: SandboxRegex, property: string | number, budget: Budget, context?: SandboxCallContext): SandboxValue | Promise<SandboxValue>;
9
+ export declare function setRegexMember(target: SandboxRegex, property: PropertyKey, value: SandboxValue, budget?: Budget): void;
8
10
  export declare function callRegexMethod(target: SandboxValue, methodName: RegexMethodName, args: readonly SandboxValue[], budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
11
+ export declare function regexExec(target: SandboxValue, input: string, budget: Budget, context?: SandboxCallContext): Promise<SandboxValue>;
12
+ export declare function regexToString(target: SandboxValue, budget: Budget, context?: SandboxCallContext): Promise<string>;
9
13
  export declare function executeRegex(target: SandboxRegex, input: string, lastIndex: number): RegexMatch | null;
10
14
  export declare function toMatchArray(match: RegexMatch | null, input: string): SandboxValue;