@poe-platform/safe-js 0.1.171 → 0.1.172

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.
@@ -6717,6 +6717,23 @@ function nativeIterator(collection, method) {
6717
6717
  return collection.kind === "map" ? collection.entries[method]() : collection.values[method]();
6718
6718
  }
6719
6719
 
6720
+ // packages/safe-js/src/interp/regexp-iterator.ts
6721
+ var states2 = /* @__PURE__ */ new WeakMap();
6722
+ function isSandboxRegExpIterator(value) {
6723
+ return typeof value === "object" && value !== null && states2.has(value);
6724
+ }
6725
+ function restoreSandboxRegExpIterator(state, target = /* @__PURE__ */ Object.create(null)) {
6726
+ if (!state.exhausted && (state.matcher === void 0 || state.input === void 0))
6727
+ throw new TypeError("A live RegExp iterator requires its matcher and input.");
6728
+ states2.set(target, state.exhausted ? { matcher: void 0, input: void 0, exhausted: true } : { ...state });
6729
+ return target;
6730
+ }
6731
+ function regexpIteratorState(value) {
6732
+ const state = states2.get(value);
6733
+ if (state === void 0) throw new TypeError("Expected a RegExp string iterator.");
6734
+ return state;
6735
+ }
6736
+
6720
6737
  // packages/safe-js/src/interp/boxed.ts
6721
6738
  import { types as types3 } from "node:util";
6722
6739
  var boxes = /* @__PURE__ */ new WeakSet();
@@ -7463,6 +7480,7 @@ function graphEntries(value) {
7463
7480
  }
7464
7481
  const entries = [];
7465
7482
  if (isSandboxCollectionIterator(value)) entries.push([".<collection>", collectionIteratorState(value).collection]);
7483
+ if (isSandboxRegExpIterator(value)) entries.push([".<matcher>", regexpIteratorState(value).matcher]);
7466
7484
  for (const key of Object.keys(value)) {
7467
7485
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
7468
7486
  if (descriptor !== void 0 && "value" in descriptor)
@@ -7889,7 +7907,7 @@ function serializeDumpValue(value, path, state) {
7889
7907
  if (hasGuestObjectState(value)) {
7890
7908
  throw new TypeError("Guest function properties and prototype links cannot be serialized.");
7891
7909
  }
7892
- if (isSandboxRegex(value) && hasCustomRegexProperties(value) || isSandboxBox(value) || isSandboxDate(value) || isFloat32Array(value)) return serializeHeapReference(value, path, state);
7910
+ if (isSandboxRegExpIterator(value) || isSandboxRegex(value) && hasCustomRegexProperties(value) || isSandboxBox(value) || isSandboxDate(value) || isFloat32Array(value)) return serializeHeapReference(value, path, state);
7893
7911
  if (Array.isArray(value)) {
7894
7912
  const reference2 = serializeHeapReference(value, path, state);
7895
7913
  if (reference2 !== void 0) {
@@ -7913,7 +7931,28 @@ function serializeHeapReference(value, path, state) {
7913
7931
  }
7914
7932
  if (!state.serializedHeapIds.has(id)) {
7915
7933
  state.serializedHeapIds.add(id);
7916
- if (isSandboxRegex(value) && hasCustomRegexProperties(value)) {
7934
+ if (isSandboxRegExpIterator(value)) {
7935
+ const snapshot = regexpIteratorState(value);
7936
+ const matcher = snapshot.matcher;
7937
+ const entries = /* @__PURE__ */ Object.create(null);
7938
+ state.heap[String(id)] = {
7939
+ kind: "regexp-iterator",
7940
+ exhausted: snapshot.exhausted,
7941
+ matcher: matcher === void 0 ? { kind: "undefined" } : { kind: "regex", source: matcher.source, flags: matcher.flags, lastIndex: Number(matcher.lastIndex) },
7942
+ input: snapshot.input ?? { kind: "undefined" },
7943
+ entries,
7944
+ symbolEntries: serializeSymbolProperties(value, (entry) => {
7945
+ const serialized = serializeDumpValue(entry, `${path}.[symbol]`, state);
7946
+ if (serialized === SKIP_VALUE) throw new TypeError("Unsupported RegExp iterator symbol property in public dump.");
7947
+ return serialized;
7948
+ })
7949
+ };
7950
+ for (const [key, entry] of getEnumerableDataEntries(value)) {
7951
+ const serialized = serializeDumpValue(entry, `${path}.${key}`, state);
7952
+ if (serialized === SKIP_VALUE) throw new TypeError("Unsupported RegExp iterator property in public dump.");
7953
+ entries[key] = serialized;
7954
+ }
7955
+ } else if (isSandboxRegex(value) && hasCustomRegexProperties(value)) {
7917
7956
  const encode = (entry) => {
7918
7957
  const serialized = serializeDumpValue(entry, `${path}.<regex-property>`, state);
7919
7958
  if (serialized === SKIP_VALUE) throw new TypeError("Unsupported RegExp property in public dump.");
@@ -8005,7 +8044,7 @@ function indexHeapContainers(snapshot) {
8005
8044
  const heapIds = /* @__PURE__ */ new Map();
8006
8045
  let nextId = 1;
8007
8046
  for (const [value, stat2] of stats.entries()) {
8008
- if (stat2.count > 1 || stat2.cyclic || ownSerializableSymbolKeys(value).length > 0 || isSandboxBox(value) || isSandboxRegex(value) && hasCustomRegexProperties(value) || isSandboxDate(value) || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
8047
+ if (stat2.count > 1 || stat2.cyclic || ownSerializableSymbolKeys(value).length > 0 || isSandboxBox(value) || isSandboxRegExpIterator(value) || isSandboxRegex(value) && hasCustomRegexProperties(value) || isSandboxDate(value) || isFloat32Array(value) || Array.isArray(value) && requiresArrayEntries(value) || isSandboxArguments(value) || sandboxErrorTypes.has(value)) {
8009
8048
  heapIds.set(value, nextId);
8010
8049
  nextId += 1;
8011
8050
  }
@@ -8161,6 +8200,10 @@ function validateDumpHeap(root, state) {
8161
8200
  const entry = requireRecord(value, path);
8162
8201
  validateErrorType(entry, path);
8163
8202
  validateSymbolEntries(entry, path, state, heap);
8203
+ if (entry.kind === "regexp-iterator") {
8204
+ validateHeapValue(entry, path, state, heap);
8205
+ continue;
8206
+ }
8164
8207
  if (entry.kind === "regex-object") {
8165
8208
  validateTaggedValue(entry, path, state);
8166
8209
  continue;
@@ -8265,6 +8308,9 @@ function validatePosition(value, path) {
8265
8308
  requireSafeInteger(position.column, `${path}.column`, 0);
8266
8309
  return requireSafeInteger(position.offset, `${path}.offset`, 0);
8267
8310
  }
8311
+ function validateValue(value, path, depth, state) {
8312
+ validateGenericValue(value, path, depth, state);
8313
+ }
8268
8314
  function validateTaggedValue(record2, path, state) {
8269
8315
  switch (record2.kind) {
8270
8316
  case "undefined":
@@ -8308,6 +8354,7 @@ function validateTaggedValue(record2, path, state) {
8308
8354
  case "map":
8309
8355
  case "set":
8310
8356
  case "collection-iterator":
8357
+ case "regexp-iterator":
8311
8358
  return;
8312
8359
  }
8313
8360
  }
@@ -8348,9 +8395,47 @@ function validateGeneratorShape(record2, path, state) {
8348
8395
  }
8349
8396
  });
8350
8397
  }
8398
+ function validateHeapValue(value, path, state, heap) {
8399
+ const record2 = requireRecord(value, path);
8400
+ validateErrorType(record2, path);
8401
+ if (!["symbol", "arguments", "array", "object", "map", "set", "float32array", "date", "boxed", "collection-iterator", "regexp-iterator", "regex-object"].includes(String(record2.kind)))
8402
+ fail("unknownTag", `${path}.kind`, "unknown heap tag");
8403
+ validateValue(record2, path, 1, state);
8404
+ if (record2.kind === "symbol") validateSymbolRecord(record2, path, state);
8405
+ if (record2.kind === "arguments") validateArgumentsProperties(record2, path);
8406
+ if (record2.kind === "array") validateArrayHeap(record2, path, state);
8407
+ if (record2.kind === "object") requireRecord(record2.entries, `${path}.entries`);
8408
+ if (record2.kind === "boxed") validateBoxedRecord(record2, path, heap);
8409
+ if (record2.kind === "date") validateDateRecord(record2, path);
8410
+ if (record2.kind === "float32array") {
8411
+ validateFloat32Storage(record2);
8412
+ requireRecord(record2.entries, `${path}.entries`);
8413
+ }
8414
+ if (record2.kind === "map") {
8415
+ const entries = requireArray(record2.entries, `${path}.entries`, state);
8416
+ entries.forEach((entry, index) => {
8417
+ if (!Array.isArray(entry) || entry.length !== 2)
8418
+ fail("invalidValue", `${path}.entries[${index}]`, "map entry must contain two values");
8419
+ });
8420
+ }
8421
+ if (record2.kind === "set") requireArray(record2.values, `${path}.values`, state);
8422
+ if (record2.kind === "regexp-iterator") {
8423
+ if (typeof record2.exhausted !== "boolean") fail("invalidValue", `${path}.exhausted`, "invalid iterator exhaustion");
8424
+ if (!Object.hasOwn(record2, "matcher") || !Object.hasOwn(record2, "input")) fail("invalidValue", path, "missing RegExp iterator state");
8425
+ requireRecord(record2.entries, `${path}.entries`);
8426
+ }
8427
+ if (record2.kind === "collection-iterator") {
8428
+ if (record2.collectionKind !== "map" && record2.collectionKind !== "set") fail("invalidValue", `${path}.collectionKind`, "invalid iterator brand");
8429
+ if (record2.method !== "keys" && record2.method !== "values" && record2.method !== "entries") fail("invalidValue", `${path}.method`, "invalid iteration method");
8430
+ if (typeof record2.exhausted !== "boolean") fail("invalidValue", `${path}.exhausted`, "invalid iterator exhaustion");
8431
+ requireSafeInteger(record2.index, `${path}.index`, 0);
8432
+ if (!Object.hasOwn(record2, "collection")) fail("invalidValue", `${path}.collection`, "missing iterator source");
8433
+ requireRecord(record2.entries, `${path}.entries`);
8434
+ }
8435
+ }
8351
8436
  function validateSymbolEntries(record2, path, state, heap) {
8352
8437
  if (record2.symbolEntries === void 0) return;
8353
- if (record2.kind !== "object" && record2.kind !== "array" && record2.kind !== "date" && record2.kind !== "boxed" && record2.kind !== "regex-object")
8438
+ if (record2.kind !== "object" && record2.kind !== "array" && record2.kind !== "date" && record2.kind !== "boxed" && record2.kind !== "regex-object" && record2.kind !== "regexp-iterator")
8354
8439
  fail("invalidValue", `${path}.symbolEntries`, "symbol properties are unsupported for this heap kind");
8355
8440
  const entries = requireArray(record2.symbolEntries, `${path}.symbolEntries`, state);
8356
8441
  const keys = /* @__PURE__ */ new Set();
@@ -9181,1121 +9266,1164 @@ async function withRunResources(signal, execute) {
9181
9266
  return result;
9182
9267
  }
9183
9268
 
9184
- // packages/safe-js/src/interp/jobs.ts
9185
- import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
9186
- var activeJob = new AsyncLocalStorage4();
9187
- var SandboxJobQueue = class {
9188
- running = false;
9189
- pending = [];
9190
- ready = [];
9191
- idle = [];
9192
- generation = 0;
9193
- acquire(job) {
9194
- return new Promise((resolve) => {
9195
- this.pending.push(() => {
9196
- this.running = true;
9197
- this.generation += 1;
9198
- job.ownsExecution = true;
9199
- resolve();
9200
- });
9201
- this.advance();
9202
- });
9203
- }
9204
- release(job) {
9205
- job.prefixParent = void 0;
9206
- if (!job.ownsExecution) return;
9207
- job.ownsExecution = false;
9208
- this.running = false;
9209
- this.advance();
9210
- }
9211
- async run(task) {
9212
- const job = { queue: this, ownsExecution: false };
9213
- await this.acquire(job);
9214
- return activeJob.run(job, async () => {
9215
- try {
9216
- return await task();
9217
- } finally {
9218
- this.release(job);
9219
- }
9220
- });
9269
+ // packages/safe-js/src/interp/regex/engine.ts
9270
+ function matchRegex(pattern, input, lastIndex = 0) {
9271
+ const startIndex = pattern.flags.global ? normalizeLastIndex(lastIndex) : 0;
9272
+ return matchRegexFrom(pattern, input, startIndex);
9273
+ }
9274
+ function matchRegexFrom(pattern, input, startIndex) {
9275
+ if (startIndex > input.length) {
9276
+ return null;
9221
9277
  }
9222
- async drain() {
9223
- let idleTurns = 0;
9224
- while (idleTurns < 20) {
9225
- const generation = this.generation;
9226
- if (this.running) await new Promise((resolve) => this.idle.push(resolve));
9227
- await Promise.resolve();
9228
- idleTurns = generation === this.generation ? idleTurns + 1 : 0;
9278
+ for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
9279
+ const context = { input, flags: pattern.flags, steps: 0 };
9280
+ charge(context);
9281
+ const initialState = {
9282
+ position: attempt,
9283
+ captures: new Array(pattern.captureCount)
9284
+ };
9285
+ const result = matchNode(pattern.body, initialState, context).next();
9286
+ if (!result.done) {
9287
+ return toRegexMatch(input, attempt, result.value);
9229
9288
  }
9230
9289
  }
9231
- advance() {
9232
- if (this.running) return;
9233
- if (this.ready.length === 0 && this.pending.length > 0) {
9234
- const empty = this.ready;
9235
- this.ready = this.pending.reverse();
9236
- this.pending = empty;
9290
+ return null;
9291
+ }
9292
+ function* matchNode(node, state, context) {
9293
+ charge(context);
9294
+ switch (node.type) {
9295
+ case "empty":
9296
+ yield state;
9297
+ return;
9298
+ case "literal":
9299
+ if (charactersEqual(context.input[state.position], node.value, context.flags.ignoreCase)) {
9300
+ yield { ...state, position: state.position + 1 };
9301
+ }
9302
+ return;
9303
+ case "dot":
9304
+ if (state.position < context.input.length && (context.flags.dotAll || !isLineTerminator(context.input[state.position]))) {
9305
+ yield { ...state, position: state.position + 1 };
9306
+ }
9307
+ return;
9308
+ case "anchor":
9309
+ if (matchesAnchor(node.kind, state.position, context)) {
9310
+ yield state;
9311
+ }
9312
+ return;
9313
+ case "wordBoundary": {
9314
+ const previousWord = state.position > 0 && isWordCharacter(context.input[state.position - 1]);
9315
+ const nextWord = state.position < context.input.length && isWordCharacter(context.input[state.position]);
9316
+ if (previousWord !== nextWord !== node.negated) {
9317
+ yield state;
9318
+ }
9319
+ return;
9237
9320
  }
9238
- const next = this.ready.pop();
9239
- if (next !== void 0) {
9240
- next();
9241
- } else {
9242
- for (const resolve of this.idle.splice(0)) resolve();
9321
+ case "characterClass": {
9322
+ const character = context.input[state.position];
9323
+ if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context.flags.ignoreCase)) {
9324
+ yield { ...state, position: state.position + 1 };
9325
+ }
9326
+ return;
9243
9327
  }
9328
+ case "sequence":
9329
+ yield* matchSequence(node.elements, 0, state, context);
9330
+ return;
9331
+ case "alternation":
9332
+ for (const alternative of node.alternatives) {
9333
+ yield* matchNode(alternative, cloneState(state), context);
9334
+ }
9335
+ return;
9336
+ case "group":
9337
+ for (const result of matchNode(node.body, cloneState(state), context)) {
9338
+ if (!node.capturing || node.index === void 0) {
9339
+ yield result;
9340
+ continue;
9341
+ }
9342
+ const captures = result.captures.slice();
9343
+ captures[node.index - 1] = { start: state.position, end: result.position };
9344
+ yield { position: result.position, captures };
9345
+ }
9346
+ return;
9347
+ case "quantifier":
9348
+ yield* matchQuantifier(node, state, context, 0);
9244
9349
  }
9245
- };
9246
- function runPromiseJob(task) {
9247
- const job = activeJob.getStore();
9248
- return job === void 0 ? Promise.resolve().then(task) : job.queue.run(task);
9249
- }
9250
- function runAsyncPrefix(task) {
9251
- const parent = activeJob.getStore();
9252
- if (parent === void 0) return task();
9253
- let owner = parent;
9254
- while (owner !== void 0 && !owner.ownsExecution) owner = owner.prefixParent;
9255
- if (owner === void 0) return parent.queue.run(task);
9256
- const job = { queue: parent.queue, ownsExecution: false, prefixParent: parent };
9257
- return activeJob.run(job, async () => {
9258
- try {
9259
- return await task();
9260
- } finally {
9261
- job.queue.release(job);
9262
- }
9263
- });
9264
9350
  }
9265
- async function suspendJob(pending) {
9266
- const job = activeJob.getStore();
9267
- if (job === void 0) return pending;
9268
- job.queue.release(job);
9269
- try {
9270
- return await pending;
9271
- } finally {
9272
- await job.queue.acquire(job);
9351
+ function* matchSequence(elements, index, state, context) {
9352
+ charge(context);
9353
+ if (index === elements.length) {
9354
+ yield state;
9355
+ return;
9356
+ }
9357
+ for (const result of matchNode(elements[index], state, context)) {
9358
+ yield* matchSequence(elements, index + 1, result, context);
9273
9359
  }
9274
9360
  }
9275
-
9276
- // packages/safe-js/src/interp/iteration.ts
9277
- async function acquireSandboxIterator(value, budget, context, asyncProtocol = false, signal) {
9278
- const key = asyncProtocol ? Symbol.asyncIterator : Symbol.iterator;
9279
- if (context.getProperty === void 0 || isGuestHostObject(value))
9280
- return asyncProtocol ? getSandboxAsyncIterator(value, budget, context, signal) : getSandboxIterator(value, budget, context);
9281
- if (getSandboxPropertyDescriptor(value, key, budget) === void 0) {
9282
- if (!asyncProtocol) return getSandboxIterator(value, budget, context);
9283
- if (isSandboxGenerator(value) && value.async)
9284
- return getSandboxAsyncIterator(value, budget, context, signal);
9285
- const iterator2 = await acquireSandboxIterator(value, budget, context);
9286
- return iterator2 === void 0 ? void 0 : asyncFromSyncIterator(iterator2, budget, signal);
9361
+ function* matchQuantifier(node, state, context, count) {
9362
+ charge(context);
9363
+ const canRepeat = node.max === void 0 || count < node.max;
9364
+ if (!node.greedy && count >= node.min) {
9365
+ yield state;
9287
9366
  }
9288
- const factory = await context.getProperty(value, key);
9289
- if (factory === null || factory === void 0) {
9290
- if (!asyncProtocol) return void 0;
9291
- const iterator2 = await acquireSandboxIterator(value, budget, context);
9292
- return iterator2 === void 0 ? void 0 : asyncFromSyncIterator(iterator2, budget, signal);
9367
+ if (canRepeat) {
9368
+ for (const result of matchNode(node.body, clearCaptures(node.body, state), context)) {
9369
+ if (result.position === state.position) {
9370
+ if (count >= node.min) {
9371
+ continue;
9372
+ }
9373
+ if (count + 1 >= node.min) {
9374
+ yield result;
9375
+ } else {
9376
+ yield* matchQuantifier(node, result, context, count + 1);
9377
+ }
9378
+ continue;
9379
+ }
9380
+ yield* matchQuantifier(node, result, context, count + 1);
9381
+ }
9293
9382
  }
9294
- if (!isSandboxClosure(factory)) {
9295
- if (typeof factory !== "function") throw new TypeError("Iterator method must be callable.");
9296
- if (asyncProtocol) return nativeAsyncIterator(value, factory, signal);
9297
- const iterator2 = Reflect.apply(factory, value, []);
9298
- if (typeof iterator2 !== "object" && typeof iterator2 !== "function" || iterator2 === null)
9299
- throw new TypeError("Iterator must be an object.");
9300
- return syncIterator(iterator2);
9383
+ if (node.greedy && count >= node.min) {
9384
+ yield state;
9301
9385
  }
9302
- const iterator = await invokeBuiltinClosure(factory, [], budget, context, value);
9303
- if (typeof iterator !== "object" && typeof iterator !== "function" || iterator === null)
9304
- throw new TypeError("Iterator must be an object.");
9305
- const next = await context.getProperty(iterator, "next");
9306
- const invoke = async (operation, args) => {
9307
- if (!isSandboxClosure(operation)) throw new TypeError("Iterator operation must be callable.");
9308
- const returned = await invokeBuiltinClosure(operation, args, budget, context, iterator);
9309
- const result = asyncProtocol ? await awaitSandboxValue(returned, signal, budget) : returned;
9310
- if (typeof result !== "object" && typeof result !== "function" || result === null)
9311
- throw new TypeError("Iterator result must be an object.");
9312
- return result;
9313
- };
9314
- return {
9315
- ...asyncProtocol ? { asyncProtocol: true } : {},
9316
- asynchronous: true,
9317
- retainedValue: [value, iterator, next],
9318
- next: (...args) => invoke(next, args),
9319
- getOperation: async (method) => {
9320
- const operation = method === "next" ? next : await context.getProperty(iterator, method);
9321
- return method !== "next" && (operation === void 0 || operation === null) ? void 0 : (...args) => invoke(operation, args);
9322
- },
9323
- readResultProperty: async (result, property) => ({
9324
- value: await context.getProperty(result, property)
9325
- })
9326
- };
9327
9386
  }
9328
- async function readIteratorResult(iterator, result, property) {
9329
- return iterator.readResultProperty === void 0 ? { value: result[property] } : iterator.readResultProperty(result, property);
9330
- }
9331
- function getSandboxAsyncIterator(value, budget, context, signal) {
9332
- if (isSandboxGenerator(value) && value.async) {
9333
- return { ...generatorIterator(value, budget), asyncProtocol: true };
9334
- }
9335
- if (value !== null && (typeof value === "object" || typeof value === "function") && !isGuestHostObject(value)) {
9336
- const method = value[Symbol.asyncIterator];
9337
- if (method !== void 0 && method !== null) {
9338
- return nativeAsyncIterator(value, method, signal);
9339
- }
9387
+ function matchesAnchor(kind, position, context) {
9388
+ if (kind === "start") {
9389
+ return position === 0 || context.flags.multiline && position > 0 && isLineTerminator(context.input[position - 1]);
9340
9390
  }
9341
- const iterator = getSandboxIterator(value, budget, context);
9342
- return iterator === void 0 ? void 0 : asyncFromSyncIterator(iterator, budget, signal);
9391
+ return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
9343
9392
  }
9344
- function nativeAsyncIterator(value, method, signal) {
9345
- if (typeof method !== "function") throw new TypeError("Async iterator method must be callable.");
9346
- const iterator = Reflect.apply(method, value, []);
9347
- if (typeof iterator !== "object" && typeof iterator !== "function" || iterator === null) {
9348
- throw new TypeError("Async iterator must be an object.");
9393
+ function matchesCharacterClass(character, items, negated, ignoreCase) {
9394
+ const matched = items.some((item) => matchesCharacterClassItem(character, item, ignoreCase));
9395
+ return negated ? !matched : matched;
9396
+ }
9397
+ function matchesCharacterClassItem(character, item, ignoreCase) {
9398
+ if (item.type === "character") {
9399
+ return charactersEqual(character, item.value, ignoreCase);
9349
9400
  }
9350
- const next = iterator.next;
9351
- const invoke = async (operation, args) => {
9352
- if (typeof operation !== "function")
9353
- throw new TypeError("Async iterator operation must be callable.");
9354
- const pending = Promise.resolve(Reflect.apply(operation, iterator, args)).then((result2) => ({
9355
- result: result2
9356
- }));
9357
- const { result } = await awaitWithSignal(pending, signal);
9358
- if (typeof result !== "object" && typeof result !== "function" || result === null) {
9359
- throw new TypeError("Iterator result must be an object.");
9401
+ if (item.type === "range") {
9402
+ const candidate = character.charCodeAt(0);
9403
+ const from = item.from.charCodeAt(0);
9404
+ const to = item.to.charCodeAt(0);
9405
+ if (candidate >= from && candidate <= to) {
9406
+ return true;
9360
9407
  }
9361
- return {
9362
- get done() {
9363
- return result.done;
9364
- },
9365
- get value() {
9366
- return result.value;
9367
- }
9368
- };
9369
- };
9370
- return {
9371
- asyncProtocol: true,
9372
- retainedValue: value,
9373
- next: (...args) => invoke(next, args),
9374
- get return() {
9375
- const operation = iterator.return;
9376
- return operation === void 0 || operation === null ? void 0 : (...args) => invoke(operation, args);
9377
- },
9378
- get throw() {
9379
- const operation = iterator.throw;
9380
- return operation === void 0 || operation === null ? void 0 : (...args) => invoke(operation, args);
9408
+ if (!ignoreCase) {
9409
+ return false;
9381
9410
  }
9382
- };
9411
+ const foldedCandidate = foldCharacter(character, true).charCodeAt(0);
9412
+ const foldedFrom = foldCharacter(item.from, true).charCodeAt(0);
9413
+ const foldedTo = foldCharacter(item.to, true).charCodeAt(0);
9414
+ return foldedCandidate >= foldedFrom && foldedCandidate <= foldedTo;
9415
+ }
9416
+ const matched = item.kind === "digit" ? isDigit(character) : item.kind === "word" ? isWordCharacter(character) : isSpaceCharacter(character);
9417
+ return item.negated ? !matched : matched;
9383
9418
  }
9384
- function asyncFromSyncIterator(iterator, budget, signal) {
9385
- const invoke = async (method, args) => {
9386
- const operation = iterator.getOperation === void 0 ? iterator[method] : await iterator.getOperation(method);
9387
- if (operation === void 0) {
9388
- if (method === "throw") {
9389
- await closeIterator(iterator);
9390
- throw new TypeError("Delegated iterator does not provide a throw method.");
9391
- }
9392
- return { done: true, value: args[0] };
9393
- }
9394
- const returned = operation(...args);
9395
- const result = iterator.generator || iterator.asynchronous ? await returned : returned;
9396
- if (typeof result !== "object" && typeof result !== "function" || result === null) {
9397
- throw new TypeError("Iterator result must be an object.");
9398
- }
9399
- const done = Boolean((await readIteratorResult(iterator, result, "done")).value);
9400
- const resultValue = (await readIteratorResult(iterator, result, "value")).value;
9401
- try {
9402
- return { done, value: await awaitSandboxValue(resultValue, signal, budget) };
9403
- } catch (error) {
9404
- if (isFatalSandboxError(error) || error instanceof HostCallResumabilityError) throw error;
9405
- if (!done && method !== "return") await closeIterator(iterator, true);
9406
- throw error;
9407
- }
9408
- };
9419
+ function toRegexMatch(input, start, state) {
9409
9420
  return {
9410
- asyncProtocol: true,
9411
- snapshotIndex: iterator.snapshotIndex,
9412
- get retainedValue() {
9413
- return iterator.retainedValue;
9414
- },
9415
- next: (...args) => invoke("next", args),
9416
- return: (...args) => invoke("return", args),
9417
- throw: (...args) => invoke("throw", args)
9421
+ index: start,
9422
+ text: input.slice(start, state.position),
9423
+ captures: state.captures.map(
9424
+ (capture) => capture === void 0 ? void 0 : input.slice(capture.start, capture.end)
9425
+ )
9418
9426
  };
9419
9427
  }
9420
- async function closeIterator(iterator, preserveThrow = false) {
9421
- try {
9422
- const close = iterator.getOperation === void 0 ? iterator.return : await iterator.getOperation("return");
9423
- if (close === void 0) return;
9424
- const returned = close();
9425
- const result = iterator.asyncProtocol ? await suspendJob(Promise.resolve(returned)) : iterator.generator || iterator.asynchronous ? await returned : returned;
9426
- if (typeof result !== "object" && typeof result !== "function" || result === null) {
9427
- throw new TypeError("Iterator return result must be an object.");
9428
- }
9429
- } catch (error) {
9430
- if (!preserveThrow || isFatalSandboxError(error) || error instanceof HostCallResumabilityError)
9431
- throw error;
9432
- }
9428
+ function cloneState(state) {
9429
+ return { position: state.position, captures: state.captures.slice() };
9433
9430
  }
9434
- function getSandboxIterator(value, budget, context) {
9435
- if (isSandboxBox(value) && typeof boxedValue(value) === "string") {
9436
- const primitive = boxedValue(value);
9437
- let text;
9438
- let iterator2;
9439
- let initialized;
9440
- return {
9441
- asynchronous: true,
9442
- get retainedValue() {
9443
- return text === primitive ? void 0 : text;
9444
- },
9445
- next: async () => {
9446
- initialized ??= Promise.resolve(sandboxString(value, budget ?? new Budget(), context)).then(
9447
- (converted) => {
9448
- text = converted;
9449
- iterator2 = syncIterator(converted[Symbol.iterator]());
9450
- }
9451
- );
9452
- await initialized;
9453
- return iterator2.next();
9454
- }
9455
- };
9456
- }
9457
- if (isSandboxCollectionIterator(value))
9458
- return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
9459
- if (isGuestHostObject(value)) return getHostObjectIterator(value);
9460
- if (isFloat32Array(value)) {
9461
- return syncIterator(Float32Array.prototype.values.call(value));
9462
- }
9463
- if (isSandboxGenerator(value)) {
9464
- return value.async ? void 0 : generatorIterator(value);
9431
+ function clearCaptures(node, state) {
9432
+ const captures = state.captures.slice();
9433
+ clearNodeCaptures(node, captures);
9434
+ return { position: state.position, captures };
9435
+ }
9436
+ function clearNodeCaptures(node, captures) {
9437
+ if (node.type === "group") {
9438
+ if (node.capturing && node.index !== void 0) {
9439
+ captures[node.index - 1] = void 0;
9440
+ }
9441
+ clearNodeCaptures(node.body, captures);
9442
+ return;
9465
9443
  }
9466
- if (typeof value === "string") {
9467
- return syncIterator(value[Symbol.iterator]());
9444
+ if (node.type === "sequence") {
9445
+ for (const element of node.elements) {
9446
+ clearNodeCaptures(element, captures);
9447
+ }
9448
+ return;
9468
9449
  }
9469
- if (isSandboxMap(value)) {
9470
- return collectionIterator(value.entries);
9450
+ if (node.type === "alternation") {
9451
+ for (const alternative of node.alternatives) {
9452
+ clearNodeCaptures(alternative, captures);
9453
+ }
9454
+ return;
9471
9455
  }
9472
- if (isSandboxSet(value)) {
9473
- return collectionIterator(value.values);
9456
+ if (node.type === "quantifier") {
9457
+ clearNodeCaptures(node.body, captures);
9474
9458
  }
9475
- if (Array.isArray(value) && hasExplicitSandboxPrototype(value)) return void 0;
9476
- if (Array.isArray(value) && context?.getProperty !== void 0) {
9477
- let index = 0;
9478
- return {
9479
- asynchronous: true,
9480
- snapshotIndex: () => index,
9481
- next: async () => {
9482
- if (index >= value.length) return { done: true, value: void 0 };
9483
- budget?.visitNode();
9484
- return { done: false, value: await context.getProperty(value, index++) };
9485
- }
9486
- };
9459
+ }
9460
+ function charge(context) {
9461
+ context.steps += 1;
9462
+ allocateRegexSteps(context.steps);
9463
+ }
9464
+ function normalizeLastIndex(lastIndex) {
9465
+ if (Number.isNaN(lastIndex) || lastIndex <= 0) {
9466
+ return 0;
9487
9467
  }
9488
- if (typeof value !== "object" && typeof value !== "function" || value === null) {
9489
- return void 0;
9468
+ return Math.min(Math.floor(lastIndex), Number.MAX_SAFE_INTEGER);
9469
+ }
9470
+ function charactersEqual(left, right, ignoreCase) {
9471
+ return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
9472
+ }
9473
+ function foldCharacter(character, ignoreCase) {
9474
+ if (!ignoreCase) {
9475
+ return character;
9490
9476
  }
9491
- const iteratorMethod = value[Symbol.iterator];
9492
- if (iteratorMethod === void 0 || iteratorMethod === null) return void 0;
9493
- if (typeof iteratorMethod !== "function") {
9494
- throw new TypeError("Iterator method must be callable.");
9477
+ const folded = character.toUpperCase();
9478
+ if (folded.length !== 1) {
9479
+ return character;
9495
9480
  }
9496
- const iterator = Reflect.apply(iteratorMethod, value, []);
9497
- if (typeof iterator !== "object" && typeof iterator !== "function" || iterator === null) {
9498
- throw new TypeError("Iterator must be an object.");
9481
+ if (character.charCodeAt(0) >= 128 && folded.charCodeAt(0) < 128) {
9482
+ return character;
9499
9483
  }
9500
- return syncIterator(iterator);
9501
- }
9502
- function collectionIterator(collection) {
9503
- let iterator = collection[Symbol.iterator]();
9504
- let exhausted = false;
9505
- return {
9506
- ...syncIterator({
9507
- next: () => {
9508
- if (exhausted) return { done: true, value: void 0 };
9509
- const result = iterator.next();
9510
- exhausted = result.done === true;
9511
- return result;
9512
- }
9513
- }),
9514
- snapshotIndex: () => {
9515
- if (exhausted) return collection.size;
9516
- let remaining = 0;
9517
- while (!iterator.next().done) remaining += 1;
9518
- const index = collection.size - remaining;
9519
- iterator = collection[Symbol.iterator]();
9520
- for (let skipped = 0; skipped < index; skipped += 1) iterator.next();
9521
- return index;
9522
- }
9523
- };
9484
+ return folded;
9524
9485
  }
9525
- var asyncGeneratorRequests = /* @__PURE__ */ new WeakMap();
9526
- function generatorIterator(generator, budget) {
9527
- const invoke = async (method, value) => {
9528
- const leaveRunning = enterRunningState(generator);
9529
- const initialState = generator.state;
9530
- generator.state = "running";
9531
- try {
9532
- if (generator.async && method === "return" && (initialState === "start" || initialState === "done")) {
9533
- if (initialState === "start") await generator.channel.return();
9534
- value = await awaitSandboxValue(value, void 0, budget);
9535
- }
9536
- const result = await generator.channel[method](value);
9537
- generator.state = result.done ? "done" : "suspended";
9538
- return result;
9539
- } catch (error) {
9540
- generator.state = "done";
9541
- throw error;
9542
- } finally {
9543
- leaveRunning();
9544
- }
9545
- };
9546
- const request = (method, value) => {
9547
- if (!generator.async) return invoke(method, value);
9548
- const previous = asyncGeneratorRequests.get(generator) ?? Promise.resolve();
9549
- const result = previous.then(() => invoke(method, value));
9550
- asyncGeneratorRequests.set(
9551
- generator,
9552
- result.catch(() => void 0)
9553
- );
9554
- return result;
9555
- };
9556
- return {
9557
- generator: true,
9558
- next: (value) => request("next", value),
9559
- return: (value) => request("return", value),
9560
- throw: (error) => request("throw", error)
9561
- };
9486
+ function isDigit(character) {
9487
+ return character >= "0" && character <= "9";
9562
9488
  }
9563
- function syncIterator(iterator) {
9564
- const next = iterator.next;
9565
- const invoke = (method, args) => {
9566
- const leaveRunning = enterRunningState(iterator);
9567
- try {
9568
- return Reflect.apply(method, iterator, args);
9569
- } finally {
9570
- leaveRunning();
9571
- }
9572
- };
9573
- return {
9574
- next: (...args) => invoke(next, args),
9575
- get return() {
9576
- const method = iterator.return;
9577
- if (method === void 0 || method === null) return void 0;
9578
- if (typeof method !== "function") throw new TypeError("Iterator return must be callable.");
9579
- return (...args) => invoke(method, args);
9580
- },
9581
- get throw() {
9582
- const method = iterator.throw;
9583
- if (method === void 0 || method === null) return void 0;
9584
- if (typeof method !== "function") throw new TypeError("Iterator throw must be callable.");
9585
- return (...args) => invoke(method, args);
9586
- }
9587
- };
9489
+ function isWordCharacter(character) {
9490
+ return isDigit(character) || character >= "A" && character <= "Z" || character >= "a" && character <= "z" || character === "_";
9491
+ }
9492
+ function isSpaceCharacter(character) {
9493
+ return character === " " || character === "\f" || character === "\n" || character === "\r" || character === " " || character === "\v" || character === "\xA0" || character === "\u1680" || character >= "\u2000" && character <= "\u200A" || character === "\u2028" || character === "\u2029" || character === "\u202F" || character === "\u205F" || character === "\u3000" || character === "\uFEFF";
9494
+ }
9495
+ function isLineTerminator(character) {
9496
+ return character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029";
9588
9497
  }
9589
9498
 
9590
- // packages/safe-js/src/interp/patterns.ts
9591
- async function bindPattern(pattern, value, target, scope, context, reference) {
9592
- switch (pattern.type) {
9593
- case "Identifier":
9594
- bindIdentifier(pattern, value, target, scope);
9595
- return { ok: true };
9596
- case "MemberExpression":
9597
- if ("kind" in target) {
9598
- throw new TypeError("Destructuring declarations cannot bind to member expressions.");
9599
- }
9600
- return bindMemberExpression(pattern, value, context, reference);
9601
- case "AssignmentPattern":
9602
- return bindAssignmentPattern(pattern, value, target, scope, context, reference);
9603
- case "ArrayPattern":
9604
- return bindArrayPattern(pattern, value, target, scope, context);
9605
- case "ObjectPattern":
9606
- return bindObjectPattern(pattern, value, target, scope, context);
9607
- case "RestElement":
9608
- return bindPattern(pattern.argument, value, target, scope, context, reference);
9499
+ // packages/safe-js/src/interp/methods/regex.ts
9500
+ var regexMethodNames = /* @__PURE__ */ new Set(["exec", "test"]);
9501
+ var regexFlagProperties = {
9502
+ hasIndices: "d",
9503
+ global: "g",
9504
+ ignoreCase: "i",
9505
+ multiline: "m",
9506
+ dotAll: "s",
9507
+ unicode: "u",
9508
+ unicodeSets: "v",
9509
+ sticky: "y"
9510
+ };
9511
+ function isRegexMethodName(property) {
9512
+ return typeof property === "string" && regexMethodNames.has(property);
9513
+ }
9514
+ function getRegexMember(target, property, budget) {
9515
+ if (property === "source") return escapeRegexSource(target.source, budget);
9516
+ if (property === "flags") {
9517
+ const flags = [..."gims"].filter((flag) => target.flags.includes(flag)).join("");
9518
+ return budget === void 0 ? flags : budget.allocateString(flags);
9519
+ }
9520
+ if (property === "lastIndex") return target.lastIndex;
9521
+ if (Object.hasOwn(regexFlagProperties, property)) return target.flags.includes(regexFlagProperties[property]);
9522
+ if (!isRegexMethodName(property)) {
9523
+ return void 0;
9609
9524
  }
9525
+ return createSandboxClosure({
9526
+ sandbox: true,
9527
+ name: `RegExp#${property}`,
9528
+ call: (args, context) => callRegexMethod(context?.thisValue, property, args, budget, context)
9529
+ });
9610
9530
  }
9611
- function bindIdentifier(pattern, value, target, scope) {
9612
- if ("assign" in target || target.kind === "var" && target.initialize !== true) {
9613
- if ("assign" in target) {
9614
- const binding = scope.lookup(pattern.name);
9615
- if (!binding.found) {
9616
- throw new ReferenceError(`Cannot assign to undeclared binding '${pattern.name}'.`);
9617
- }
9618
- if (binding.kind === "const") {
9619
- throw new TypeError(`Cannot assign to const '${pattern.name}'`);
9620
- }
9531
+ function escapeRegexSource(source, budget) {
9532
+ let text = "";
9533
+ let escaped = false;
9534
+ let inClass = false;
9535
+ for (const character of source) {
9536
+ budget?.visitNode();
9537
+ if (character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029") {
9538
+ if (escaped) text = text.slice(0, -1);
9539
+ text += character === "\n" ? "\\n" : character === "\r" ? "\\r" : character === "\u2028" ? "\\u2028" : "\\u2029";
9540
+ escaped = false;
9541
+ } else {
9542
+ if (!escaped && character === "[") inClass = true;
9543
+ if (!escaped && character === "]") inClass = false;
9544
+ text += character === "/" && !escaped && !inClass ? "\\/" : character;
9545
+ escaped = character === "\\" && !escaped;
9621
9546
  }
9622
- scope.assign(pattern.name, value);
9623
- return;
9547
+ budget?.allocateString(text);
9624
9548
  }
9625
- scope.declare(pattern.name, target.kind, value);
9549
+ text = text === "" ? "(?:)" : text;
9550
+ return budget === void 0 ? text : budget.allocateString(text);
9626
9551
  }
9627
- async function bindAssignmentPattern(pattern, value, target, scope, context, reference) {
9628
- if (value !== void 0) {
9629
- return bindPattern(pattern.left, value, target, scope, context, reference);
9630
- }
9631
- const defaultValue = await context.evaluate(
9632
- pattern.right,
9633
- pattern.left.type === "Identifier" ? pattern.left.name : void 0
9634
- );
9635
- if (defaultValue.kind !== "normal") {
9636
- return { ok: false, result: defaultValue };
9552
+ function setRegexMember(target, property, value) {
9553
+ const properties = getRegexProperties(target);
9554
+ if (!Object.hasOwn(properties, property) && (property === "source" || property === "flags" || Object.hasOwn(regexFlagProperties, property))) {
9555
+ throw new TypeError(`RegExp#${String(property)} is not writable.`);
9637
9556
  }
9638
- return bindPattern(pattern.left, defaultValue.value, target, scope, context, reference);
9557
+ if (!Reflect.set(properties, property, value)) throw new TypeError(`RegExp#${String(property)} is not writable.`);
9639
9558
  }
9640
- async function bindPatternValue(pattern, readValue, target, scope, context) {
9641
- let member = pattern;
9642
- while (member.type === "AssignmentPattern" || member.type === "RestElement")
9643
- member = member.type === "AssignmentPattern" ? member.left : member.argument;
9644
- let reference;
9645
- if ("assign" in target && member.type === "MemberExpression") {
9646
- const prepared = await prepareMemberReference(member, context);
9647
- if (!prepared.ok) return prepared;
9648
- reference = prepared.reference;
9559
+ async function callRegexMethod(target, methodName, args, budget, context) {
9560
+ if (target === null || typeof target !== "object" || methodName === "exec" && !isSandboxRegex(target)) {
9561
+ throw new TypeError(`RegExp#${methodName} requires ${methodName === "exec" ? "a regex" : "an object"} receiver.`);
9649
9562
  }
9650
- let value;
9651
- const release = context.budget === void 0 ? () => void 0 : retainValues(context.budget, () => [reference?.object, reference?.key, value]);
9563
+ const retained = {};
9564
+ let cursor;
9565
+ let convertedInput;
9566
+ budget.setRetainedValues(retained, () => [target, ...args, cursor, convertedInput]);
9652
9567
  try {
9653
- value = (await readValue()).value;
9654
- return await bindPattern(pattern, value, target, scope, context, reference);
9568
+ const input = await sandboxString(args[0], budget, context);
9569
+ if (methodName === "test") {
9570
+ const exec = context?.getProperty === void 0 ? getSandboxDataProperty(target, "exec", budget) : await context.getProperty(target, "exec");
9571
+ if (isSandboxClosure(exec)) {
9572
+ const result = await invokeBuiltinClosure(exec, [input], budget, context, target);
9573
+ if (result !== null && typeof result !== "object") {
9574
+ throw new TypeError("RegExp#test exec must return an object or null.");
9575
+ }
9576
+ return result !== null;
9577
+ }
9578
+ }
9579
+ if (!isSandboxRegex(target)) throw new TypeError("RegExp execution requires a regex receiver.");
9580
+ if (typeof args[0] !== "string") convertedInput = input;
9581
+ cursor = target.lastIndex;
9582
+ const lastIndex = await sandboxNumber(cursor, budget, context);
9583
+ const match = executeRegex(target, input, lastIndex);
9584
+ return methodName === "test" ? match !== null : toMatchArray(match, input);
9655
9585
  } finally {
9656
- release();
9586
+ budget.setRetainedValues(retained, void 0);
9657
9587
  }
9658
9588
  }
9659
- async function bindArrayPattern(pattern, value, target, scope, context) {
9660
- const budget = context.budget ?? new Budget();
9661
- const iterator = await acquireSandboxIterator(
9662
- value,
9663
- budget,
9664
- context.callContext ?? {
9665
- stack: [],
9666
- thisValue: void 0,
9667
- getProperty: context.getProperty
9589
+ function executeRegex(target, input, lastIndex) {
9590
+ const pattern = getSandboxRegexPattern(target);
9591
+ const match = matchRegex(pattern, input, lastIndex);
9592
+ if (pattern.flags.global) {
9593
+ target.lastIndex = match === null ? 0 : match.index + match.text.length;
9594
+ }
9595
+ return match;
9596
+ }
9597
+ function toMatchArray(match, input) {
9598
+ if (match === null) {
9599
+ return null;
9600
+ }
9601
+ const result = [match.text, ...match.captures];
9602
+ Object.assign(result, { index: match.index, input, groups: void 0 });
9603
+ return result;
9604
+ }
9605
+
9606
+ // packages/safe-js/src/interp/methods/regexp-iterator.ts
9607
+ function nextRegExpIterator(iterator, budget) {
9608
+ const state = regexpIteratorState(iterator);
9609
+ budget?.visitNode();
9610
+ if (state.exhausted) return { value: void 0, done: true };
9611
+ const matcher = state.matcher;
9612
+ const input = state.input;
9613
+ const match = executeRegex(matcher, input, Number(matcher.lastIndex));
9614
+ if (match === null || !matcher.flags.includes("g")) {
9615
+ state.exhausted = true;
9616
+ state.matcher = void 0;
9617
+ state.input = void 0;
9618
+ }
9619
+ if (match === null) return { value: void 0, done: true };
9620
+ if (!state.exhausted && match.text.length === 0) {
9621
+ const index = Number(matcher.lastIndex);
9622
+ const unicode = matcher.flags.includes("u") || matcher.flags.includes("v");
9623
+ const codePoint = input.codePointAt(index);
9624
+ matcher.lastIndex = index + (unicode && codePoint !== void 0 && codePoint > 65535 ? 2 : 1);
9625
+ }
9626
+ budget?.allocateArrayLength(match.captures.length + 1);
9627
+ return { value: toMatchArray(match, input), done: false };
9628
+ }
9629
+ function getRegExpIteratorMember(property, budget) {
9630
+ if (property === Symbol.toStringTag) return "RegExp String Iterator";
9631
+ if (property === Symbol.iterator) return createSandboxClosure({
9632
+ sandbox: true,
9633
+ name: "[Symbol.iterator]",
9634
+ call: (_args, context) => context?.thisValue
9635
+ });
9636
+ if (property !== "next") return void 0;
9637
+ return createSandboxClosure({
9638
+ sandbox: true,
9639
+ name: "next",
9640
+ call: (_args, context) => {
9641
+ const receiver = context?.thisValue;
9642
+ if (!isSandboxRegExpIterator(receiver))
9643
+ throw new TypeError("RegExp string iterator next requires a matching receiver.");
9644
+ return nextRegExpIterator(receiver, budget);
9668
9645
  }
9669
- );
9670
- if (iterator === void 0) throw new TypeError("Array destructuring requires an iterable.");
9671
- let done = false;
9672
- const next = async (readValue = true) => {
9673
- if (done) return { value: void 0 };
9674
- try {
9675
- const result = await iterator.next();
9676
- if (typeof result !== "object" && typeof result !== "function" || result === null)
9677
- throw new TypeError("Iterator result must be an object.");
9678
- done = Boolean((await readIteratorResult(iterator, result, "done")).value);
9679
- return done || !readValue ? { value: void 0 } : await readIteratorResult(iterator, result, "value");
9680
- } catch (error) {
9681
- done = true;
9682
- throw error;
9683
- }
9684
- };
9685
- let retained;
9686
- const release = retainValues(budget, () => [value, iterator.retainedValue, retained]);
9687
- try {
9688
- for (let index = 0; index < pattern.elements.length; index += 1) {
9689
- const element = pattern.elements[index];
9690
- if (element === null) {
9691
- await next(false);
9692
- continue;
9693
- }
9694
- const binding = await bindPatternValue(
9695
- element,
9696
- async () => {
9697
- if (element.type !== "RestElement") return next();
9698
- const rest = [];
9699
- retained = rest;
9700
- for (let entry = await next(); !done; entry = await next()) {
9701
- budget.allocateArrayLength(rest.length + 1);
9702
- rest.push(entry.value);
9703
- }
9704
- return { value: rest };
9705
- },
9706
- target,
9707
- scope,
9708
- context
9709
- );
9710
- if (!binding.ok) {
9711
- if (!done) {
9712
- done = true;
9713
- await closeIterator(iterator, binding.result.kind === "throw");
9714
- }
9715
- return binding;
9716
- }
9717
- }
9718
- if (!done) {
9719
- done = true;
9720
- await closeIterator(iterator);
9721
- }
9722
- return { ok: true };
9723
- } catch (error) {
9724
- if (!done && !isFatalSandboxError(error)) await closeIterator(iterator, true);
9725
- throw error;
9726
- } finally {
9727
- release();
9728
- }
9646
+ });
9729
9647
  }
9730
- async function bindObjectPattern(pattern, value, target, scope, context) {
9731
- if (value === void 0 || value === null) {
9732
- throw new TypeError("Object destructuring requires a non-nullish value.");
9648
+
9649
+ // packages/safe-js/src/interp/jobs.ts
9650
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
9651
+ var activeJob = new AsyncLocalStorage4();
9652
+ var SandboxJobQueue = class {
9653
+ running = false;
9654
+ pending = [];
9655
+ ready = [];
9656
+ idle = [];
9657
+ generation = 0;
9658
+ acquire(job) {
9659
+ return new Promise((resolve) => {
9660
+ this.pending.push(() => {
9661
+ this.running = true;
9662
+ this.generation += 1;
9663
+ job.ownsExecution = true;
9664
+ resolve();
9665
+ });
9666
+ this.advance();
9667
+ });
9733
9668
  }
9734
- const excludedKeys = /* @__PURE__ */ new Set();
9735
- for (const property of pattern.properties) {
9736
- if (property.type === "RestElement") {
9737
- const binding2 = await bindPatternValue(
9738
- property,
9739
- async () => ({ value: await copyObjectRestValue(value, excludedKeys, context) }),
9740
- target,
9741
- scope,
9742
- context
9743
- );
9744
- if (!binding2.ok) {
9745
- return binding2;
9669
+ release(job) {
9670
+ job.prefixParent = void 0;
9671
+ if (!job.ownsExecution) return;
9672
+ job.ownsExecution = false;
9673
+ this.running = false;
9674
+ this.advance();
9675
+ }
9676
+ async run(task) {
9677
+ const job = { queue: this, ownsExecution: false };
9678
+ await this.acquire(job);
9679
+ return activeJob.run(job, async () => {
9680
+ try {
9681
+ return await task();
9682
+ } finally {
9683
+ this.release(job);
9746
9684
  }
9747
- continue;
9685
+ });
9686
+ }
9687
+ async drain() {
9688
+ let idleTurns = 0;
9689
+ while (idleTurns < 20) {
9690
+ const generation = this.generation;
9691
+ if (this.running) await new Promise((resolve) => this.idle.push(resolve));
9692
+ await Promise.resolve();
9693
+ idleTurns = generation === this.generation ? idleTurns + 1 : 0;
9748
9694
  }
9749
- const key = await evaluatePatternKey(property, context);
9750
- if (!key.ok) {
9751
- return key;
9695
+ }
9696
+ advance() {
9697
+ if (this.running) return;
9698
+ if (this.ready.length === 0 && this.pending.length > 0) {
9699
+ const empty = this.ready;
9700
+ this.ready = this.pending.reverse();
9701
+ this.pending = empty;
9752
9702
  }
9753
- excludedKeys.add(typeof key.value === "symbol" ? key.value : String(key.value));
9754
- const binding = await bindPatternValue(
9755
- property.value,
9756
- async () => ({ value: await context.getProperty(value, key.value) }),
9757
- target,
9758
- scope,
9759
- context
9760
- );
9761
- if (!binding.ok) {
9762
- return binding;
9703
+ const next = this.ready.pop();
9704
+ if (next !== void 0) {
9705
+ next();
9706
+ } else {
9707
+ for (const resolve of this.idle.splice(0)) resolve();
9763
9708
  }
9764
9709
  }
9765
- return { ok: true };
9710
+ };
9711
+ function runPromiseJob(task) {
9712
+ const job = activeJob.getStore();
9713
+ return job === void 0 ? Promise.resolve().then(task) : job.queue.run(task);
9766
9714
  }
9767
- async function bindMemberExpression(pattern, value, context, reference) {
9768
- if (reference === void 0) {
9769
- const prepared = await prepareMemberReference(pattern, context);
9770
- if (!prepared.ok) return prepared;
9771
- reference = prepared.reference;
9772
- }
9773
- if (reference.object === null || reference.object === void 0) {
9774
- throw new TypeError("Cannot assign properties of null or undefined.");
9775
- }
9776
- if (!isIndexableValue(reference.object)) {
9777
- throw new TypeError("Assignment expressions require a sandbox object property.");
9715
+ function runAsyncPrefix(task) {
9716
+ const parent = activeJob.getStore();
9717
+ if (parent === void 0) return task();
9718
+ let owner = parent;
9719
+ while (owner !== void 0 && !owner.ownsExecution) owner = owner.prefixParent;
9720
+ if (owner === void 0) return parent.queue.run(task);
9721
+ const job = { queue: parent.queue, ownsExecution: false, prefixParent: parent };
9722
+ return activeJob.run(job, async () => {
9723
+ try {
9724
+ return await task();
9725
+ } finally {
9726
+ job.queue.release(job);
9727
+ }
9728
+ });
9729
+ }
9730
+ async function suspendJob(pending) {
9731
+ const job = activeJob.getStore();
9732
+ if (job === void 0) return pending;
9733
+ job.queue.release(job);
9734
+ try {
9735
+ return await pending;
9736
+ } finally {
9737
+ await job.queue.acquire(job);
9778
9738
  }
9779
- await context.setProperty(reference.object, reference.key, value);
9780
- return { ok: true };
9781
9739
  }
9782
- async function prepareMemberReference(pattern, context) {
9783
- const object = await context.evaluate(pattern.object);
9784
- if (object.kind !== "normal") {
9785
- return { ok: false, result: object };
9740
+
9741
+ // packages/safe-js/src/interp/iteration.ts
9742
+ async function acquireSandboxIterator(value, budget, context, asyncProtocol = false, signal) {
9743
+ const key = asyncProtocol ? Symbol.asyncIterator : Symbol.iterator;
9744
+ if (context.getProperty === void 0 || isGuestHostObject(value))
9745
+ return asyncProtocol ? getSandboxAsyncIterator(value, budget, context, signal) : getSandboxIterator(value, budget, context);
9746
+ if (getSandboxPropertyDescriptor(value, key, budget) === void 0 && !(isSandboxRegExpIterator(value) && !asyncProtocol && getSandboxPropertyDescriptor(value, "next", budget) !== void 0)) {
9747
+ if (!asyncProtocol) return getSandboxIterator(value, budget, context);
9748
+ if (isSandboxGenerator(value) && value.async)
9749
+ return getSandboxAsyncIterator(value, budget, context, signal);
9750
+ const iterator2 = await acquireSandboxIterator(value, budget, context);
9751
+ return iterator2 === void 0 ? void 0 : asyncFromSyncIterator(iterator2, budget, signal);
9786
9752
  }
9787
- const property = pattern.computed ? await context.evaluate(pattern.property) : { kind: "normal", value: getStaticPropertyName(pattern.property) };
9788
- if (property.kind !== "normal") {
9789
- return { ok: false, result: property };
9753
+ const factory = await context.getProperty(value, key);
9754
+ if (factory === null || factory === void 0) {
9755
+ if (!asyncProtocol) return void 0;
9756
+ const iterator2 = await acquireSandboxIterator(value, budget, context);
9757
+ return iterator2 === void 0 ? void 0 : asyncFromSyncIterator(iterator2, budget, signal);
9758
+ }
9759
+ if (!isSandboxClosure(factory)) {
9760
+ if (typeof factory !== "function") throw new TypeError("Iterator method must be callable.");
9761
+ if (asyncProtocol) return nativeAsyncIterator(value, factory, signal);
9762
+ const iterator2 = Reflect.apply(factory, value, []);
9763
+ if (typeof iterator2 !== "object" && typeof iterator2 !== "function" || iterator2 === null)
9764
+ throw new TypeError("Iterator must be an object.");
9765
+ return syncIterator(iterator2);
9790
9766
  }
9767
+ const iterator = await invokeBuiltinClosure(factory, [], budget, context, value);
9768
+ if (typeof iterator !== "object" && typeof iterator !== "function" || iterator === null)
9769
+ throw new TypeError("Iterator must be an object.");
9770
+ const next = await context.getProperty(iterator, "next");
9771
+ const invoke = async (operation, args) => {
9772
+ if (!isSandboxClosure(operation)) throw new TypeError("Iterator operation must be callable.");
9773
+ const returned = await invokeBuiltinClosure(operation, args, budget, context, iterator);
9774
+ const result = asyncProtocol ? await awaitSandboxValue(returned, signal, budget) : returned;
9775
+ if (typeof result !== "object" && typeof result !== "function" || result === null)
9776
+ throw new TypeError("Iterator result must be an object.");
9777
+ return result;
9778
+ };
9791
9779
  return {
9792
- ok: true,
9793
- reference: { object: object.value, key: await context.toPropertyKey(property.value) }
9780
+ ...asyncProtocol ? { asyncProtocol: true } : {},
9781
+ asynchronous: true,
9782
+ retainedValue: [value, iterator, next],
9783
+ next: (...args) => invoke(next, args),
9784
+ getOperation: async (method) => {
9785
+ const operation = method === "next" ? next : await context.getProperty(iterator, method);
9786
+ return method !== "next" && (operation === void 0 || operation === null) ? void 0 : (...args) => invoke(operation, args);
9787
+ },
9788
+ readResultProperty: async (result, property) => ({
9789
+ value: await context.getProperty(result, property)
9790
+ })
9794
9791
  };
9795
9792
  }
9796
- async function evaluatePatternKey(property, context) {
9797
- return property.computed ? evaluateProperty(property.key, context) : { ok: true, value: getStaticPropertyName(property.key) };
9798
- }
9799
- async function evaluateProperty(property, context) {
9800
- const result = await context.evaluate(property);
9801
- if (result.kind !== "normal") {
9802
- return { ok: false, result };
9803
- }
9804
- return { ok: true, value: await context.toPropertyKey(result.value) };
9793
+ async function readIteratorResult(iterator, result, property) {
9794
+ return iterator.readResultProperty === void 0 ? { value: result[property] } : iterator.readResultProperty(result, property);
9805
9795
  }
9806
- function getStaticPropertyName(property) {
9807
- if (property.type === "Identifier") {
9808
- return property.name;
9796
+ function getSandboxAsyncIterator(value, budget, context, signal) {
9797
+ if (isSandboxGenerator(value) && value.async) {
9798
+ return { ...generatorIterator(value, budget), asyncProtocol: true };
9809
9799
  }
9810
- if (property.type === "StringLiteral" || property.type === "NumericLiteral") {
9811
- return property.value;
9800
+ if (value !== null && (typeof value === "object" || typeof value === "function") && !isGuestHostObject(value)) {
9801
+ const method = value[Symbol.asyncIterator];
9802
+ if (method !== void 0 && method !== null) {
9803
+ return nativeAsyncIterator(value, method, signal);
9804
+ }
9812
9805
  }
9813
- throw new TypeError(`Unsupported static property node '${property.type}'.`);
9806
+ const iterator = getSandboxIterator(value, budget, context);
9807
+ return iterator === void 0 ? void 0 : asyncFromSyncIterator(iterator, budget, signal);
9814
9808
  }
9815
- async function copyObjectRestValue(value, excludedKeys, context) {
9816
- const rest = /* @__PURE__ */ Object.create(null);
9817
- const release = context.budget === void 0 ? () => void 0 : retainValues(context.budget, () => [value, rest]);
9818
- try {
9819
- for (const key of ownEnumerableSandboxKeys(value, true)) {
9820
- if (excludedKeys.has(key) || !hasOwnSandboxProperty(value, key, true)) continue;
9821
- defineProperty(rest, key, await context.getProperty(value, key));
9822
- }
9823
- return rest;
9824
- } finally {
9825
- release();
9809
+ function nativeAsyncIterator(value, method, signal) {
9810
+ if (typeof method !== "function") throw new TypeError("Async iterator method must be callable.");
9811
+ const iterator = Reflect.apply(method, value, []);
9812
+ if (typeof iterator !== "object" && typeof iterator !== "function" || iterator === null) {
9813
+ throw new TypeError("Async iterator must be an object.");
9826
9814
  }
9827
- }
9828
- function isIndexableValue(value) {
9829
- return typeof value === "object" && value !== null;
9830
- }
9831
- function defineProperty(target, key, value) {
9832
- Object.defineProperty(target, key, {
9833
- configurable: true,
9834
- enumerable: true,
9835
- value,
9836
- writable: true
9837
- });
9838
- }
9839
-
9840
- // packages/safe-js/src/interp/var-hoist.ts
9841
- function hoistVarDeclarations(node, scope) {
9842
- for (const declaration of hoistedVarDeclarations([node])) {
9843
- for (const declarator of declaration.declarations) {
9844
- for (const identifier of boundIdentifiers(declarator.id)) {
9845
- scope.declareVar(identifier.name);
9815
+ const next = iterator.next;
9816
+ const invoke = async (operation, args) => {
9817
+ if (typeof operation !== "function")
9818
+ throw new TypeError("Async iterator operation must be callable.");
9819
+ const pending = Promise.resolve(Reflect.apply(operation, iterator, args)).then((result2) => ({
9820
+ result: result2
9821
+ }));
9822
+ const { result } = await awaitWithSignal(pending, signal);
9823
+ if (typeof result !== "object" && typeof result !== "function" || result === null) {
9824
+ throw new TypeError("Iterator result must be an object.");
9825
+ }
9826
+ return {
9827
+ get done() {
9828
+ return result.done;
9829
+ },
9830
+ get value() {
9831
+ return result.value;
9846
9832
  }
9833
+ };
9834
+ };
9835
+ return {
9836
+ asyncProtocol: true,
9837
+ retainedValue: value,
9838
+ next: (...args) => invoke(next, args),
9839
+ get return() {
9840
+ const operation = iterator.return;
9841
+ return operation === void 0 || operation === null ? void 0 : (...args) => invoke(operation, args);
9842
+ },
9843
+ get throw() {
9844
+ const operation = iterator.throw;
9845
+ return operation === void 0 || operation === null ? void 0 : (...args) => invoke(operation, args);
9847
9846
  }
9848
- }
9849
- }
9850
-
9851
- // packages/safe-js/src/interp/data-checkpoint.ts
9852
- function createDataCheckpoint(budget, context) {
9853
- let estimatedDataSize = 0;
9854
- return (value, growth = 0, force = false) => {
9855
- const limit = budget.limits.dataSize;
9856
- if (limit === void 0) return;
9857
- estimatedDataSize = Math.max(estimatedDataSize, budget.currentDataSize) + growth;
9858
- if (!force && estimatedDataSize <= limit) return;
9859
- if (context?.reconcileData !== void 0) context.reconcileData(value);
9860
- else reconcileCompiledValues(budget, [value], context?.compilation);
9861
- estimatedDataSize = budget.currentDataSize;
9862
9847
  };
9863
9848
  }
9864
-
9865
- // packages/safe-js/src/interp/globals/numeric-parsers.ts
9866
- function createNumericParsers(budget) {
9867
- return {
9868
- parseInt: createSandboxClosure({
9869
- sandbox: true,
9870
- name: "parseInt",
9871
- call: ([value, radix], context) => {
9872
- const parse2 = (text2) => {
9873
- const release = retainValues(budget, () => [text2]);
9874
- let convertedRadix;
9875
- try {
9876
- convertedRadix = sandboxNumber(radix, budget, context);
9877
- } catch (error) {
9878
- release();
9879
- throw error;
9880
- }
9881
- if (typeof convertedRadix === "number") {
9882
- try {
9883
- return globalThis.parseInt(text2, convertedRadix);
9884
- } finally {
9885
- release();
9886
- }
9887
- }
9888
- return convertedRadix.then((number) => globalThis.parseInt(text2, number)).finally(release);
9889
- };
9890
- const text = sandboxString(value, budget, context);
9891
- return typeof text === "string" ? parse2(text) : text.then(parse2);
9892
- }
9893
- }),
9894
- parseFloat: createSandboxClosure({
9895
- sandbox: true,
9896
- name: "parseFloat",
9897
- call: ([value], context) => {
9898
- const text = sandboxString(value, budget, context);
9899
- return typeof text === "string" ? globalThis.parseFloat(text) : text.then(globalThis.parseFloat);
9849
+ function asyncFromSyncIterator(iterator, budget, signal) {
9850
+ const invoke = async (method, args) => {
9851
+ const operation = iterator.getOperation === void 0 ? iterator[method] : await iterator.getOperation(method);
9852
+ if (operation === void 0) {
9853
+ if (method === "throw") {
9854
+ await closeIterator(iterator);
9855
+ throw new TypeError("Delegated iterator does not provide a throw method.");
9900
9856
  }
9901
- })
9857
+ return { done: true, value: args[0] };
9858
+ }
9859
+ const returned = operation(...args);
9860
+ const result = iterator.generator || iterator.asynchronous ? await returned : returned;
9861
+ if (typeof result !== "object" && typeof result !== "function" || result === null) {
9862
+ throw new TypeError("Iterator result must be an object.");
9863
+ }
9864
+ const done = Boolean((await readIteratorResult(iterator, result, "done")).value);
9865
+ const resultValue = (await readIteratorResult(iterator, result, "value")).value;
9866
+ try {
9867
+ return { done, value: await awaitSandboxValue(resultValue, signal, budget) };
9868
+ } catch (error) {
9869
+ if (isFatalSandboxError(error) || error instanceof HostCallResumabilityError) throw error;
9870
+ if (!done && method !== "return") await closeIterator(iterator, true);
9871
+ throw error;
9872
+ }
9873
+ };
9874
+ return {
9875
+ asyncProtocol: true,
9876
+ snapshotIndex: iterator.snapshotIndex,
9877
+ get retainedValue() {
9878
+ return iterator.retainedValue;
9879
+ },
9880
+ next: (...args) => invoke("next", args),
9881
+ return: (...args) => invoke("return", args),
9882
+ throw: (...args) => invoke("throw", args)
9902
9883
  };
9903
9884
  }
9904
-
9905
- // packages/safe-js/src/interp/methods/number.ts
9906
- var numberMethodNames = /* @__PURE__ */ new Set([
9907
- "toExponential",
9908
- "toFixed",
9909
- "toPrecision",
9910
- "toString"
9911
- ]);
9912
- function getNumberMember(property, budget) {
9913
- if (!isNumberMethodName(property)) {
9914
- return void 0;
9885
+ async function closeIterator(iterator, preserveThrow = false) {
9886
+ try {
9887
+ const close = iterator.getOperation === void 0 ? iterator.return : await iterator.getOperation("return");
9888
+ if (close === void 0) return;
9889
+ const returned = close();
9890
+ const result = iterator.asyncProtocol ? await suspendJob(Promise.resolve(returned)) : iterator.generator || iterator.asynchronous ? await returned : returned;
9891
+ if (typeof result !== "object" && typeof result !== "function" || result === null) {
9892
+ throw new TypeError("Iterator return result must be an object.");
9893
+ }
9894
+ } catch (error) {
9895
+ if (!preserveThrow || isFatalSandboxError(error) || error instanceof HostCallResumabilityError)
9896
+ throw error;
9915
9897
  }
9916
- return createSandboxClosure({
9917
- sandbox: true,
9918
- name: `Number#${property}`,
9919
- call: (args, context) => callNumberMethod(context?.thisValue, property, args, budget, context)
9920
- });
9921
- }
9922
- function isNumberMethodName(property) {
9923
- return typeof property === "string" && numberMethodNames.has(property);
9924
9898
  }
9925
- function callNumberMethod(value, methodName, args, budget, context) {
9926
- if (isSandboxBox(value)) value = boxedValue(value);
9927
- if (typeof value !== "number") {
9928
- throw new TypeError(`Number#${methodName} requires a number receiver.`);
9899
+ function getSandboxIterator(value, budget, context) {
9900
+ if (isSandboxBox(value) && typeof boxedValue(value) === "string") {
9901
+ const primitive = boxedValue(value);
9902
+ let text;
9903
+ let iterator2;
9904
+ let initialized;
9905
+ return {
9906
+ asynchronous: true,
9907
+ get retainedValue() {
9908
+ return text === primitive ? void 0 : text;
9909
+ },
9910
+ next: async () => {
9911
+ initialized ??= Promise.resolve(sandboxString(value, budget ?? new Budget(), context)).then(
9912
+ (converted) => {
9913
+ text = converted;
9914
+ iterator2 = syncIterator(converted[Symbol.iterator]());
9915
+ }
9916
+ );
9917
+ await initialized;
9918
+ return iterator2.next();
9919
+ }
9920
+ };
9929
9921
  }
9930
- const argument = args[0];
9931
- if (argument !== null && typeof argument === "object") {
9932
- return formatObjectArgument(value, methodName, argument, budget, context);
9922
+ if (isSandboxCollectionIterator(value))
9923
+ return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
9924
+ if (isSandboxRegExpIterator(value))
9925
+ return { next: () => nextRegExpIterator(value, budget), snapshotIndex: () => 0 };
9926
+ if (isGuestHostObject(value)) return getHostObjectIterator(value);
9927
+ if (isFloat32Array(value)) {
9928
+ return syncIterator(Float32Array.prototype.values.call(value));
9933
9929
  }
9934
- return formatNumber(value, methodName, argument === void 0 ? void 0 : Number(argument), budget);
9935
- }
9936
- async function formatObjectArgument(value, methodName, argument, budget, context) {
9937
- const retainedArgument = {};
9938
- budget.setRetainedValues(retainedArgument, () => [argument]);
9939
- try {
9940
- const number = await sandboxNumber(argument, budget, context);
9941
- return formatNumber(value, methodName, number, budget);
9942
- } finally {
9943
- budget.setRetainedValues(retainedArgument, void 0);
9930
+ if (isSandboxGenerator(value)) {
9931
+ return value.async ? void 0 : generatorIterator(value);
9944
9932
  }
9945
- }
9946
- function formatNumber(value, methodName, argument, budget) {
9947
- let result;
9948
- try {
9949
- result = value[methodName](argument);
9950
- } catch (error) {
9951
- if (!(error instanceof RangeError)) throw error;
9952
- const detail = methodName === "toString" ? "radix must be between 2 and 36." : methodName === "toPrecision" ? "precision must be between 1 and 100." : "digits must be between 0 and 100.";
9953
- throw new RangeError(`Number#${methodName} ${detail}`);
9933
+ if (typeof value === "string") {
9934
+ return syncIterator(value[Symbol.iterator]());
9954
9935
  }
9955
- return budget.allocateString(result);
9956
- }
9957
-
9958
- // packages/safe-js/src/interp/methods/string.ts
9959
- import { types as types6 } from "node:util";
9960
-
9961
- // packages/safe-js/src/interp/regex/engine.ts
9962
- function matchRegex(pattern, input, lastIndex = 0) {
9963
- const startIndex = pattern.flags.global ? normalizeLastIndex(lastIndex) : 0;
9964
- return matchRegexFrom(pattern, input, startIndex);
9965
- }
9966
- function matchRegexFrom(pattern, input, startIndex) {
9967
- if (startIndex > input.length) {
9968
- return null;
9936
+ if (isSandboxMap(value)) {
9937
+ return collectionIterator(value.entries);
9969
9938
  }
9970
- for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
9971
- const context = { input, flags: pattern.flags, steps: 0 };
9972
- charge(context);
9973
- const initialState = {
9974
- position: attempt,
9975
- captures: new Array(pattern.captureCount)
9939
+ if (isSandboxSet(value)) {
9940
+ return collectionIterator(value.values);
9941
+ }
9942
+ if (Array.isArray(value) && hasExplicitSandboxPrototype(value)) return void 0;
9943
+ if (Array.isArray(value) && context?.getProperty !== void 0) {
9944
+ let index = 0;
9945
+ return {
9946
+ asynchronous: true,
9947
+ snapshotIndex: () => index,
9948
+ next: async () => {
9949
+ if (index >= value.length) return { done: true, value: void 0 };
9950
+ budget?.visitNode();
9951
+ return { done: false, value: await context.getProperty(value, index++) };
9952
+ }
9976
9953
  };
9977
- const result = matchNode(pattern.body, initialState, context).next();
9978
- if (!result.done) {
9979
- return toRegexMatch(input, attempt, result.value);
9980
- }
9981
9954
  }
9982
- return null;
9955
+ if (typeof value !== "object" && typeof value !== "function" || value === null) {
9956
+ return void 0;
9957
+ }
9958
+ const iteratorMethod = value[Symbol.iterator];
9959
+ if (iteratorMethod === void 0 || iteratorMethod === null) return void 0;
9960
+ if (typeof iteratorMethod !== "function") {
9961
+ throw new TypeError("Iterator method must be callable.");
9962
+ }
9963
+ const iterator = Reflect.apply(iteratorMethod, value, []);
9964
+ if (typeof iterator !== "object" && typeof iterator !== "function" || iterator === null) {
9965
+ throw new TypeError("Iterator must be an object.");
9966
+ }
9967
+ return syncIterator(iterator);
9983
9968
  }
9984
- function* matchNode(node, state, context) {
9985
- charge(context);
9986
- switch (node.type) {
9987
- case "empty":
9988
- yield state;
9989
- return;
9990
- case "literal":
9991
- if (charactersEqual(context.input[state.position], node.value, context.flags.ignoreCase)) {
9992
- yield { ...state, position: state.position + 1 };
9993
- }
9994
- return;
9995
- case "dot":
9996
- if (state.position < context.input.length && (context.flags.dotAll || !isLineTerminator(context.input[state.position]))) {
9997
- yield { ...state, position: state.position + 1 };
9998
- }
9999
- return;
10000
- case "anchor":
10001
- if (matchesAnchor(node.kind, state.position, context)) {
10002
- yield state;
10003
- }
10004
- return;
10005
- case "wordBoundary": {
10006
- const previousWord = state.position > 0 && isWordCharacter(context.input[state.position - 1]);
10007
- const nextWord = state.position < context.input.length && isWordCharacter(context.input[state.position]);
10008
- if (previousWord !== nextWord !== node.negated) {
10009
- yield state;
9969
+ function collectionIterator(collection) {
9970
+ let iterator = collection[Symbol.iterator]();
9971
+ let exhausted = false;
9972
+ return {
9973
+ ...syncIterator({
9974
+ next: () => {
9975
+ if (exhausted) return { done: true, value: void 0 };
9976
+ const result = iterator.next();
9977
+ exhausted = result.done === true;
9978
+ return result;
10010
9979
  }
10011
- return;
9980
+ }),
9981
+ snapshotIndex: () => {
9982
+ if (exhausted) return collection.size;
9983
+ let remaining = 0;
9984
+ while (!iterator.next().done) remaining += 1;
9985
+ const index = collection.size - remaining;
9986
+ iterator = collection[Symbol.iterator]();
9987
+ for (let skipped = 0; skipped < index; skipped += 1) iterator.next();
9988
+ return index;
10012
9989
  }
10013
- case "characterClass": {
10014
- const character = context.input[state.position];
10015
- if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context.flags.ignoreCase)) {
10016
- yield { ...state, position: state.position + 1 };
9990
+ };
9991
+ }
9992
+ var asyncGeneratorRequests = /* @__PURE__ */ new WeakMap();
9993
+ function generatorIterator(generator, budget) {
9994
+ const invoke = async (method, value) => {
9995
+ const leaveRunning = enterRunningState(generator);
9996
+ const initialState = generator.state;
9997
+ generator.state = "running";
9998
+ try {
9999
+ if (generator.async && method === "return" && (initialState === "start" || initialState === "done")) {
10000
+ if (initialState === "start") await generator.channel.return();
10001
+ value = await awaitSandboxValue(value, void 0, budget);
10017
10002
  }
10018
- return;
10003
+ const result = await generator.channel[method](value);
10004
+ generator.state = result.done ? "done" : "suspended";
10005
+ return result;
10006
+ } catch (error) {
10007
+ generator.state = "done";
10008
+ throw error;
10009
+ } finally {
10010
+ leaveRunning();
10019
10011
  }
10020
- case "sequence":
10021
- yield* matchSequence(node.elements, 0, state, context);
10022
- return;
10023
- case "alternation":
10024
- for (const alternative of node.alternatives) {
10025
- yield* matchNode(alternative, cloneState(state), context);
10026
- }
10027
- return;
10028
- case "group":
10029
- for (const result of matchNode(node.body, cloneState(state), context)) {
10030
- if (!node.capturing || node.index === void 0) {
10031
- yield result;
10032
- continue;
10033
- }
10034
- const captures = result.captures.slice();
10035
- captures[node.index - 1] = { start: state.position, end: result.position };
10036
- yield { position: result.position, captures };
10037
- }
10038
- return;
10039
- case "quantifier":
10040
- yield* matchQuantifier(node, state, context, 0);
10041
- }
10012
+ };
10013
+ const request = (method, value) => {
10014
+ if (!generator.async) return invoke(method, value);
10015
+ const previous = asyncGeneratorRequests.get(generator) ?? Promise.resolve();
10016
+ const result = previous.then(() => invoke(method, value));
10017
+ asyncGeneratorRequests.set(
10018
+ generator,
10019
+ result.catch(() => void 0)
10020
+ );
10021
+ return result;
10022
+ };
10023
+ return {
10024
+ generator: true,
10025
+ next: (value) => request("next", value),
10026
+ return: (value) => request("return", value),
10027
+ throw: (error) => request("throw", error)
10028
+ };
10042
10029
  }
10043
- function* matchSequence(elements, index, state, context) {
10044
- charge(context);
10045
- if (index === elements.length) {
10046
- yield state;
10047
- return;
10048
- }
10049
- for (const result of matchNode(elements[index], state, context)) {
10050
- yield* matchSequence(elements, index + 1, result, context);
10051
- }
10030
+ function syncIterator(iterator) {
10031
+ const next = iterator.next;
10032
+ const invoke = (method, args) => {
10033
+ const leaveRunning = enterRunningState(iterator);
10034
+ try {
10035
+ return Reflect.apply(method, iterator, args);
10036
+ } finally {
10037
+ leaveRunning();
10038
+ }
10039
+ };
10040
+ return {
10041
+ next: (...args) => invoke(next, args),
10042
+ get return() {
10043
+ const method = iterator.return;
10044
+ if (method === void 0 || method === null) return void 0;
10045
+ if (typeof method !== "function") throw new TypeError("Iterator return must be callable.");
10046
+ return (...args) => invoke(method, args);
10047
+ },
10048
+ get throw() {
10049
+ const method = iterator.throw;
10050
+ if (method === void 0 || method === null) return void 0;
10051
+ if (typeof method !== "function") throw new TypeError("Iterator throw must be callable.");
10052
+ return (...args) => invoke(method, args);
10053
+ }
10054
+ };
10052
10055
  }
10053
- function* matchQuantifier(node, state, context, count) {
10054
- charge(context);
10055
- const canRepeat = node.max === void 0 || count < node.max;
10056
- if (!node.greedy && count >= node.min) {
10057
- yield state;
10056
+
10057
+ // packages/safe-js/src/interp/patterns.ts
10058
+ async function bindPattern(pattern, value, target, scope, context, reference) {
10059
+ switch (pattern.type) {
10060
+ case "Identifier":
10061
+ bindIdentifier(pattern, value, target, scope);
10062
+ return { ok: true };
10063
+ case "MemberExpression":
10064
+ if ("kind" in target) {
10065
+ throw new TypeError("Destructuring declarations cannot bind to member expressions.");
10066
+ }
10067
+ return bindMemberExpression(pattern, value, context, reference);
10068
+ case "AssignmentPattern":
10069
+ return bindAssignmentPattern(pattern, value, target, scope, context, reference);
10070
+ case "ArrayPattern":
10071
+ return bindArrayPattern(pattern, value, target, scope, context);
10072
+ case "ObjectPattern":
10073
+ return bindObjectPattern(pattern, value, target, scope, context);
10074
+ case "RestElement":
10075
+ return bindPattern(pattern.argument, value, target, scope, context, reference);
10058
10076
  }
10059
- if (canRepeat) {
10060
- for (const result of matchNode(node.body, clearCaptures(node.body, state), context)) {
10061
- if (result.position === state.position) {
10062
- if (count >= node.min) {
10063
- continue;
10064
- }
10065
- if (count + 1 >= node.min) {
10066
- yield result;
10067
- } else {
10068
- yield* matchQuantifier(node, result, context, count + 1);
10069
- }
10070
- continue;
10077
+ }
10078
+ function bindIdentifier(pattern, value, target, scope) {
10079
+ if ("assign" in target || target.kind === "var" && target.initialize !== true) {
10080
+ if ("assign" in target) {
10081
+ const binding = scope.lookup(pattern.name);
10082
+ if (!binding.found) {
10083
+ throw new ReferenceError(`Cannot assign to undeclared binding '${pattern.name}'.`);
10084
+ }
10085
+ if (binding.kind === "const") {
10086
+ throw new TypeError(`Cannot assign to const '${pattern.name}'`);
10071
10087
  }
10072
- yield* matchQuantifier(node, result, context, count + 1);
10073
10088
  }
10089
+ scope.assign(pattern.name, value);
10090
+ return;
10074
10091
  }
10075
- if (node.greedy && count >= node.min) {
10076
- yield state;
10092
+ scope.declare(pattern.name, target.kind, value);
10093
+ }
10094
+ async function bindAssignmentPattern(pattern, value, target, scope, context, reference) {
10095
+ if (value !== void 0) {
10096
+ return bindPattern(pattern.left, value, target, scope, context, reference);
10097
+ }
10098
+ const defaultValue = await context.evaluate(
10099
+ pattern.right,
10100
+ pattern.left.type === "Identifier" ? pattern.left.name : void 0
10101
+ );
10102
+ if (defaultValue.kind !== "normal") {
10103
+ return { ok: false, result: defaultValue };
10077
10104
  }
10105
+ return bindPattern(pattern.left, defaultValue.value, target, scope, context, reference);
10078
10106
  }
10079
- function matchesAnchor(kind, position, context) {
10080
- if (kind === "start") {
10081
- return position === 0 || context.flags.multiline && position > 0 && isLineTerminator(context.input[position - 1]);
10107
+ async function bindPatternValue(pattern, readValue, target, scope, context) {
10108
+ let member = pattern;
10109
+ while (member.type === "AssignmentPattern" || member.type === "RestElement")
10110
+ member = member.type === "AssignmentPattern" ? member.left : member.argument;
10111
+ let reference;
10112
+ if ("assign" in target && member.type === "MemberExpression") {
10113
+ const prepared = await prepareMemberReference(member, context);
10114
+ if (!prepared.ok) return prepared;
10115
+ reference = prepared.reference;
10116
+ }
10117
+ let value;
10118
+ const release = context.budget === void 0 ? () => void 0 : retainValues(context.budget, () => [reference?.object, reference?.key, value]);
10119
+ try {
10120
+ value = (await readValue()).value;
10121
+ return await bindPattern(pattern, value, target, scope, context, reference);
10122
+ } finally {
10123
+ release();
10082
10124
  }
10083
- return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
10084
10125
  }
10085
- function matchesCharacterClass(character, items, negated, ignoreCase) {
10086
- const matched = items.some((item) => matchesCharacterClassItem(character, item, ignoreCase));
10087
- return negated ? !matched : matched;
10126
+ async function bindArrayPattern(pattern, value, target, scope, context) {
10127
+ const budget = context.budget ?? new Budget();
10128
+ const iterator = await acquireSandboxIterator(
10129
+ value,
10130
+ budget,
10131
+ context.callContext ?? {
10132
+ stack: [],
10133
+ thisValue: void 0,
10134
+ getProperty: context.getProperty
10135
+ }
10136
+ );
10137
+ if (iterator === void 0) throw new TypeError("Array destructuring requires an iterable.");
10138
+ let done = false;
10139
+ const next = async (readValue = true) => {
10140
+ if (done) return { value: void 0 };
10141
+ try {
10142
+ const result = await iterator.next();
10143
+ if (typeof result !== "object" && typeof result !== "function" || result === null)
10144
+ throw new TypeError("Iterator result must be an object.");
10145
+ done = Boolean((await readIteratorResult(iterator, result, "done")).value);
10146
+ return done || !readValue ? { value: void 0 } : await readIteratorResult(iterator, result, "value");
10147
+ } catch (error) {
10148
+ done = true;
10149
+ throw error;
10150
+ }
10151
+ };
10152
+ let retained;
10153
+ const release = retainValues(budget, () => [value, iterator.retainedValue, retained]);
10154
+ try {
10155
+ for (let index = 0; index < pattern.elements.length; index += 1) {
10156
+ const element = pattern.elements[index];
10157
+ if (element === null) {
10158
+ await next(false);
10159
+ continue;
10160
+ }
10161
+ const binding = await bindPatternValue(
10162
+ element,
10163
+ async () => {
10164
+ if (element.type !== "RestElement") return next();
10165
+ const rest = [];
10166
+ retained = rest;
10167
+ for (let entry = await next(); !done; entry = await next()) {
10168
+ budget.allocateArrayLength(rest.length + 1);
10169
+ rest.push(entry.value);
10170
+ }
10171
+ return { value: rest };
10172
+ },
10173
+ target,
10174
+ scope,
10175
+ context
10176
+ );
10177
+ if (!binding.ok) {
10178
+ if (!done) {
10179
+ done = true;
10180
+ await closeIterator(iterator, binding.result.kind === "throw");
10181
+ }
10182
+ return binding;
10183
+ }
10184
+ }
10185
+ if (!done) {
10186
+ done = true;
10187
+ await closeIterator(iterator);
10188
+ }
10189
+ return { ok: true };
10190
+ } catch (error) {
10191
+ if (!done && !isFatalSandboxError(error)) await closeIterator(iterator, true);
10192
+ throw error;
10193
+ } finally {
10194
+ release();
10195
+ }
10088
10196
  }
10089
- function matchesCharacterClassItem(character, item, ignoreCase) {
10090
- if (item.type === "character") {
10091
- return charactersEqual(character, item.value, ignoreCase);
10197
+ async function bindObjectPattern(pattern, value, target, scope, context) {
10198
+ if (value === void 0 || value === null) {
10199
+ throw new TypeError("Object destructuring requires a non-nullish value.");
10092
10200
  }
10093
- if (item.type === "range") {
10094
- const candidate = character.charCodeAt(0);
10095
- const from = item.from.charCodeAt(0);
10096
- const to = item.to.charCodeAt(0);
10097
- if (candidate >= from && candidate <= to) {
10098
- return true;
10201
+ const excludedKeys = /* @__PURE__ */ new Set();
10202
+ for (const property of pattern.properties) {
10203
+ if (property.type === "RestElement") {
10204
+ const binding2 = await bindPatternValue(
10205
+ property,
10206
+ async () => ({ value: await copyObjectRestValue(value, excludedKeys, context) }),
10207
+ target,
10208
+ scope,
10209
+ context
10210
+ );
10211
+ if (!binding2.ok) {
10212
+ return binding2;
10213
+ }
10214
+ continue;
10099
10215
  }
10100
- if (!ignoreCase) {
10101
- return false;
10216
+ const key = await evaluatePatternKey(property, context);
10217
+ if (!key.ok) {
10218
+ return key;
10219
+ }
10220
+ excludedKeys.add(typeof key.value === "symbol" ? key.value : String(key.value));
10221
+ const binding = await bindPatternValue(
10222
+ property.value,
10223
+ async () => ({ value: await context.getProperty(value, key.value) }),
10224
+ target,
10225
+ scope,
10226
+ context
10227
+ );
10228
+ if (!binding.ok) {
10229
+ return binding;
10102
10230
  }
10103
- const foldedCandidate = foldCharacter(character, true).charCodeAt(0);
10104
- const foldedFrom = foldCharacter(item.from, true).charCodeAt(0);
10105
- const foldedTo = foldCharacter(item.to, true).charCodeAt(0);
10106
- return foldedCandidate >= foldedFrom && foldedCandidate <= foldedTo;
10107
10231
  }
10108
- const matched = item.kind === "digit" ? isDigit(character) : item.kind === "word" ? isWordCharacter(character) : isSpaceCharacter(character);
10109
- return item.negated ? !matched : matched;
10110
- }
10111
- function toRegexMatch(input, start, state) {
10112
- return {
10113
- index: start,
10114
- text: input.slice(start, state.position),
10115
- captures: state.captures.map(
10116
- (capture) => capture === void 0 ? void 0 : input.slice(capture.start, capture.end)
10117
- )
10118
- };
10119
- }
10120
- function cloneState(state) {
10121
- return { position: state.position, captures: state.captures.slice() };
10122
- }
10123
- function clearCaptures(node, state) {
10124
- const captures = state.captures.slice();
10125
- clearNodeCaptures(node, captures);
10126
- return { position: state.position, captures };
10232
+ return { ok: true };
10127
10233
  }
10128
- function clearNodeCaptures(node, captures) {
10129
- if (node.type === "group") {
10130
- if (node.capturing && node.index !== void 0) {
10131
- captures[node.index - 1] = void 0;
10132
- }
10133
- clearNodeCaptures(node.body, captures);
10134
- return;
10234
+ async function bindMemberExpression(pattern, value, context, reference) {
10235
+ if (reference === void 0) {
10236
+ const prepared = await prepareMemberReference(pattern, context);
10237
+ if (!prepared.ok) return prepared;
10238
+ reference = prepared.reference;
10135
10239
  }
10136
- if (node.type === "sequence") {
10137
- for (const element of node.elements) {
10138
- clearNodeCaptures(element, captures);
10139
- }
10140
- return;
10240
+ if (reference.object === null || reference.object === void 0) {
10241
+ throw new TypeError("Cannot assign properties of null or undefined.");
10141
10242
  }
10142
- if (node.type === "alternation") {
10143
- for (const alternative of node.alternatives) {
10144
- clearNodeCaptures(alternative, captures);
10145
- }
10146
- return;
10243
+ if (!isIndexableValue(reference.object)) {
10244
+ throw new TypeError("Assignment expressions require a sandbox object property.");
10147
10245
  }
10148
- if (node.type === "quantifier") {
10149
- clearNodeCaptures(node.body, captures);
10246
+ await context.setProperty(reference.object, reference.key, value);
10247
+ return { ok: true };
10248
+ }
10249
+ async function prepareMemberReference(pattern, context) {
10250
+ const object = await context.evaluate(pattern.object);
10251
+ if (object.kind !== "normal") {
10252
+ return { ok: false, result: object };
10253
+ }
10254
+ const property = pattern.computed ? await context.evaluate(pattern.property) : { kind: "normal", value: getStaticPropertyName(pattern.property) };
10255
+ if (property.kind !== "normal") {
10256
+ return { ok: false, result: property };
10150
10257
  }
10258
+ return {
10259
+ ok: true,
10260
+ reference: { object: object.value, key: await context.toPropertyKey(property.value) }
10261
+ };
10151
10262
  }
10152
- function charge(context) {
10153
- context.steps += 1;
10154
- allocateRegexSteps(context.steps);
10263
+ async function evaluatePatternKey(property, context) {
10264
+ return property.computed ? evaluateProperty(property.key, context) : { ok: true, value: getStaticPropertyName(property.key) };
10155
10265
  }
10156
- function normalizeLastIndex(lastIndex) {
10157
- if (Number.isNaN(lastIndex) || lastIndex <= 0) {
10158
- return 0;
10266
+ async function evaluateProperty(property, context) {
10267
+ const result = await context.evaluate(property);
10268
+ if (result.kind !== "normal") {
10269
+ return { ok: false, result };
10159
10270
  }
10160
- return Math.min(Math.floor(lastIndex), Number.MAX_SAFE_INTEGER);
10161
- }
10162
- function charactersEqual(left, right, ignoreCase) {
10163
- return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
10271
+ return { ok: true, value: await context.toPropertyKey(result.value) };
10164
10272
  }
10165
- function foldCharacter(character, ignoreCase) {
10166
- if (!ignoreCase) {
10167
- return character;
10273
+ function getStaticPropertyName(property) {
10274
+ if (property.type === "Identifier") {
10275
+ return property.name;
10168
10276
  }
10169
- const folded = character.toUpperCase();
10170
- if (folded.length !== 1) {
10171
- return character;
10277
+ if (property.type === "StringLiteral" || property.type === "NumericLiteral") {
10278
+ return property.value;
10172
10279
  }
10173
- if (character.charCodeAt(0) >= 128 && folded.charCodeAt(0) < 128) {
10174
- return character;
10280
+ throw new TypeError(`Unsupported static property node '${property.type}'.`);
10281
+ }
10282
+ async function copyObjectRestValue(value, excludedKeys, context) {
10283
+ const rest = /* @__PURE__ */ Object.create(null);
10284
+ const release = context.budget === void 0 ? () => void 0 : retainValues(context.budget, () => [value, rest]);
10285
+ try {
10286
+ for (const key of ownEnumerableSandboxKeys(value, true)) {
10287
+ if (excludedKeys.has(key) || !hasOwnSandboxProperty(value, key, true)) continue;
10288
+ defineProperty(rest, key, await context.getProperty(value, key));
10289
+ }
10290
+ return rest;
10291
+ } finally {
10292
+ release();
10175
10293
  }
10176
- return folded;
10177
10294
  }
10178
- function isDigit(character) {
10179
- return character >= "0" && character <= "9";
10295
+ function isIndexableValue(value) {
10296
+ return typeof value === "object" && value !== null;
10180
10297
  }
10181
- function isWordCharacter(character) {
10182
- return isDigit(character) || character >= "A" && character <= "Z" || character >= "a" && character <= "z" || character === "_";
10298
+ function defineProperty(target, key, value) {
10299
+ Object.defineProperty(target, key, {
10300
+ configurable: true,
10301
+ enumerable: true,
10302
+ value,
10303
+ writable: true
10304
+ });
10183
10305
  }
10184
- function isSpaceCharacter(character) {
10185
- return character === " " || character === "\f" || character === "\n" || character === "\r" || character === " " || character === "\v" || character === "\xA0" || character === "\u1680" || character >= "\u2000" && character <= "\u200A" || character === "\u2028" || character === "\u2029" || character === "\u202F" || character === "\u205F" || character === "\u3000" || character === "\uFEFF";
10306
+
10307
+ // packages/safe-js/src/interp/var-hoist.ts
10308
+ function hoistVarDeclarations(node, scope) {
10309
+ for (const declaration of hoistedVarDeclarations([node])) {
10310
+ for (const declarator of declaration.declarations) {
10311
+ for (const identifier of boundIdentifiers(declarator.id)) {
10312
+ scope.declareVar(identifier.name);
10313
+ }
10314
+ }
10315
+ }
10186
10316
  }
10187
- function isLineTerminator(character) {
10188
- return character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029";
10317
+
10318
+ // packages/safe-js/src/interp/data-checkpoint.ts
10319
+ function createDataCheckpoint(budget, context) {
10320
+ let estimatedDataSize = 0;
10321
+ return (value, growth = 0, force = false) => {
10322
+ const limit = budget.limits.dataSize;
10323
+ if (limit === void 0) return;
10324
+ estimatedDataSize = Math.max(estimatedDataSize, budget.currentDataSize) + growth;
10325
+ if (!force && estimatedDataSize <= limit) return;
10326
+ if (context?.reconcileData !== void 0) context.reconcileData(value);
10327
+ else reconcileCompiledValues(budget, [value], context?.compilation);
10328
+ estimatedDataSize = budget.currentDataSize;
10329
+ };
10189
10330
  }
10190
10331
 
10191
- // packages/safe-js/src/interp/methods/regex.ts
10192
- var regexMethodNames = /* @__PURE__ */ new Set(["exec", "test"]);
10193
- var regexFlagProperties = {
10194
- hasIndices: "d",
10195
- global: "g",
10196
- ignoreCase: "i",
10197
- multiline: "m",
10198
- dotAll: "s",
10199
- unicode: "u",
10200
- unicodeSets: "v",
10201
- sticky: "y"
10202
- };
10203
- function isRegexMethodName(property) {
10204
- return typeof property === "string" && regexMethodNames.has(property);
10332
+ // packages/safe-js/src/interp/globals/numeric-parsers.ts
10333
+ function createNumericParsers(budget) {
10334
+ return {
10335
+ parseInt: createSandboxClosure({
10336
+ sandbox: true,
10337
+ name: "parseInt",
10338
+ call: ([value, radix], context) => {
10339
+ const parse2 = (text2) => {
10340
+ const release = retainValues(budget, () => [text2]);
10341
+ let convertedRadix;
10342
+ try {
10343
+ convertedRadix = sandboxNumber(radix, budget, context);
10344
+ } catch (error) {
10345
+ release();
10346
+ throw error;
10347
+ }
10348
+ if (typeof convertedRadix === "number") {
10349
+ try {
10350
+ return globalThis.parseInt(text2, convertedRadix);
10351
+ } finally {
10352
+ release();
10353
+ }
10354
+ }
10355
+ return convertedRadix.then((number) => globalThis.parseInt(text2, number)).finally(release);
10356
+ };
10357
+ const text = sandboxString(value, budget, context);
10358
+ return typeof text === "string" ? parse2(text) : text.then(parse2);
10359
+ }
10360
+ }),
10361
+ parseFloat: createSandboxClosure({
10362
+ sandbox: true,
10363
+ name: "parseFloat",
10364
+ call: ([value], context) => {
10365
+ const text = sandboxString(value, budget, context);
10366
+ return typeof text === "string" ? globalThis.parseFloat(text) : text.then(globalThis.parseFloat);
10367
+ }
10368
+ })
10369
+ };
10205
10370
  }
10206
- function getRegexMember(target, property, budget) {
10207
- if (property === "source") return escapeRegexSource(target.source, budget);
10208
- if (property === "flags") {
10209
- const flags = [..."gims"].filter((flag) => target.flags.includes(flag)).join("");
10210
- return budget === void 0 ? flags : budget.allocateString(flags);
10211
- }
10212
- if (property === "lastIndex") return target.lastIndex;
10213
- if (Object.hasOwn(regexFlagProperties, property)) return target.flags.includes(regexFlagProperties[property]);
10214
- if (!isRegexMethodName(property)) {
10371
+
10372
+ // packages/safe-js/src/interp/methods/number.ts
10373
+ var numberMethodNames = /* @__PURE__ */ new Set([
10374
+ "toExponential",
10375
+ "toFixed",
10376
+ "toPrecision",
10377
+ "toString"
10378
+ ]);
10379
+ function getNumberMember(property, budget) {
10380
+ if (!isNumberMethodName(property)) {
10215
10381
  return void 0;
10216
10382
  }
10217
10383
  return createSandboxClosure({
10218
10384
  sandbox: true,
10219
- name: `RegExp#${property}`,
10220
- call: (args, context) => callRegexMethod(context?.thisValue, property, args, budget, context)
10385
+ name: `Number#${property}`,
10386
+ call: (args, context) => callNumberMethod(context?.thisValue, property, args, budget, context)
10221
10387
  });
10222
10388
  }
10223
- function escapeRegexSource(source, budget) {
10224
- let text = "";
10225
- let escaped = false;
10226
- let inClass = false;
10227
- for (const character of source) {
10228
- budget?.visitNode();
10229
- if (character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029") {
10230
- if (escaped) text = text.slice(0, -1);
10231
- text += character === "\n" ? "\\n" : character === "\r" ? "\\r" : character === "\u2028" ? "\\u2028" : "\\u2029";
10232
- escaped = false;
10233
- } else {
10234
- if (!escaped && character === "[") inClass = true;
10235
- if (!escaped && character === "]") inClass = false;
10236
- text += character === "/" && !escaped && !inClass ? "\\/" : character;
10237
- escaped = character === "\\" && !escaped;
10238
- }
10239
- budget?.allocateString(text);
10240
- }
10241
- text = text === "" ? "(?:)" : text;
10242
- return budget === void 0 ? text : budget.allocateString(text);
10389
+ function isNumberMethodName(property) {
10390
+ return typeof property === "string" && numberMethodNames.has(property);
10243
10391
  }
10244
- function setRegexMember(target, property, value) {
10245
- const properties = getRegexProperties(target);
10246
- if (!Object.hasOwn(properties, property) && (property === "source" || property === "flags" || Object.hasOwn(regexFlagProperties, property))) {
10247
- throw new TypeError(`RegExp#${String(property)} is not writable.`);
10392
+ function callNumberMethod(value, methodName, args, budget, context) {
10393
+ if (isSandboxBox(value)) value = boxedValue(value);
10394
+ if (typeof value !== "number") {
10395
+ throw new TypeError(`Number#${methodName} requires a number receiver.`);
10248
10396
  }
10249
- if (!Reflect.set(properties, property, value)) throw new TypeError(`RegExp#${String(property)} is not writable.`);
10250
- }
10251
- async function callRegexMethod(target, methodName, args, budget, context) {
10252
- if (target === null || typeof target !== "object" || methodName === "exec" && !isSandboxRegex(target)) {
10253
- throw new TypeError(`RegExp#${methodName} requires ${methodName === "exec" ? "a regex" : "an object"} receiver.`);
10397
+ const argument = args[0];
10398
+ if (argument !== null && typeof argument === "object") {
10399
+ return formatObjectArgument(value, methodName, argument, budget, context);
10254
10400
  }
10255
- const retained = {};
10256
- let cursor;
10257
- let convertedInput;
10258
- budget.setRetainedValues(retained, () => [target, ...args, cursor, convertedInput]);
10401
+ return formatNumber(value, methodName, argument === void 0 ? void 0 : Number(argument), budget);
10402
+ }
10403
+ async function formatObjectArgument(value, methodName, argument, budget, context) {
10404
+ const retainedArgument = {};
10405
+ budget.setRetainedValues(retainedArgument, () => [argument]);
10259
10406
  try {
10260
- const input = await sandboxString(args[0], budget, context);
10261
- if (methodName === "test") {
10262
- const exec = context?.getProperty === void 0 ? getSandboxDataProperty(target, "exec", budget) : await context.getProperty(target, "exec");
10263
- if (isSandboxClosure(exec)) {
10264
- const result = await invokeBuiltinClosure(exec, [input], budget, context, target);
10265
- if (result !== null && typeof result !== "object") {
10266
- throw new TypeError("RegExp#test exec must return an object or null.");
10267
- }
10268
- return result !== null;
10269
- }
10270
- }
10271
- if (!isSandboxRegex(target)) throw new TypeError("RegExp execution requires a regex receiver.");
10272
- if (typeof args[0] !== "string") convertedInput = input;
10273
- cursor = target.lastIndex;
10274
- const lastIndex = await sandboxNumber(cursor, budget, context);
10275
- const match = executeRegex(target, input, lastIndex);
10276
- return methodName === "test" ? match !== null : toMatchArray(match, input);
10407
+ const number = await sandboxNumber(argument, budget, context);
10408
+ return formatNumber(value, methodName, number, budget);
10277
10409
  } finally {
10278
- budget.setRetainedValues(retained, void 0);
10279
- }
10280
- }
10281
- function executeRegex(target, input, lastIndex) {
10282
- const pattern = getSandboxRegexPattern(target);
10283
- const match = matchRegex(pattern, input, lastIndex);
10284
- if (pattern.flags.global) {
10285
- target.lastIndex = match === null ? 0 : match.index + match.text.length;
10410
+ budget.setRetainedValues(retainedArgument, void 0);
10286
10411
  }
10287
- return match;
10288
10412
  }
10289
- function toMatchArray(match, input) {
10290
- if (match === null) {
10291
- return null;
10413
+ function formatNumber(value, methodName, argument, budget) {
10414
+ let result;
10415
+ try {
10416
+ result = value[methodName](argument);
10417
+ } catch (error) {
10418
+ if (!(error instanceof RangeError)) throw error;
10419
+ const detail = methodName === "toString" ? "radix must be between 2 and 36." : methodName === "toPrecision" ? "precision must be between 1 and 100." : "digits must be between 0 and 100.";
10420
+ throw new RangeError(`Number#${methodName} ${detail}`);
10292
10421
  }
10293
- const result = [match.text, ...match.captures];
10294
- Object.assign(result, { index: match.index, input, groups: void 0 });
10295
- return result;
10422
+ return budget.allocateString(result);
10296
10423
  }
10297
10424
 
10298
10425
  // packages/safe-js/src/interp/methods/string.ts
10426
+ import { types as types6 } from "node:util";
10299
10427
  var SPLIT_STRING_MESSAGE = "String#split only supports string separator values.";
10300
10428
  var stringMethodNames = /* @__PURE__ */ new Set([
10301
10429
  "at",
@@ -10811,9 +10939,10 @@ function callMatchLikeMethod(value, methodName, args, compilation, lastIndex) {
10811
10939
  return toMatchArray(executeRegex(regex, value, lastIndex ?? Number(regex.lastIndex)), value);
10812
10940
  if (methodName === "match") regex.lastIndex = 0;
10813
10941
  const matcher = methodName === "matchAll" ? createSandboxRegex(regex.source, regex.flags, normalizeLastIndex(lastIndex ?? Number(regex.lastIndex)), compilation) : regex;
10942
+ if (methodName === "matchAll")
10943
+ return restoreSandboxRegExpIterator({ matcher, input: value, exhausted: false });
10814
10944
  const matches = collectRegexMatches(matcher, value, matcher.flags.includes("g"), compilation.owner?.budget, Number(matcher.lastIndex));
10815
- if (methodName === "match" && matches.length === 0) return null;
10816
- return methodName === "match" ? matches.map((match) => match.text) : matches.map((match) => toMatchArray(match, value));
10945
+ return matches.length === 0 ? null : matches.map((match) => match.text);
10817
10946
  }
10818
10947
  function collectRegexMatches(regex, value, all, budget, lastIndex = 0) {
10819
10948
  const matches = [];
@@ -14711,6 +14840,7 @@ function isRestorableBindingValue(value, seen = /* @__PURE__ */ new WeakSet()) {
14711
14840
  }
14712
14841
  if (seen.has(value)) return true;
14713
14842
  seen.add(value);
14843
+ if (isSandboxRegExpIterator(value)) return isRestorableBindingValue(regexpIteratorState(value).matcher, seen);
14714
14844
  if (isSandboxCollectionIterator(value)) {
14715
14845
  return isRestorableBindingValue(collectionIteratorState(value).collection, seen);
14716
14846
  }
@@ -14965,7 +15095,7 @@ async function evaluateForOfStatement(node, context) {
14965
15095
  const restored = context.scope.consumeRestoredBinding(restoredIteration.values[0]);
14966
15096
  if (restored.found && Array.isArray(restored.value)) {
14967
15097
  restoredEntry = { done: false, value: restored.value[1] };
14968
- if (Array.isArray(restored.value[0]) || isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0]) || isSandboxCollectionIterator(restored.value[0])) {
15098
+ if (Array.isArray(restored.value[0]) || isSandboxMap(restored.value[0]) || isSandboxSet(restored.value[0]) || isSandboxCollectionIterator(restored.value[0]) || isSandboxRegExpIterator(restored.value[0])) {
14969
15099
  return evaluateForOfIterator(node, restored.value[0], context, restoredEntry);
14970
15100
  }
14971
15101
  }
@@ -15337,7 +15467,7 @@ function createLoopIterationContext(context, scope) {
15337
15467
  if (context.activeLoopIterations.size === 0) return snapshot;
15338
15468
  snapshot.loopIterations = {};
15339
15469
  for (const [nodeId, iteration] of context.activeLoopIterations) {
15340
- if (typeof iteration !== "number" && (Array.isArray(iteration.values[0]) || isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]) || isSandboxCollectionIterator(iteration.values[0]))) {
15470
+ if (typeof iteration !== "number" && (Array.isArray(iteration.values[0]) || isSandboxMap(iteration.values[0]) || isSandboxSet(iteration.values[0]) || isSandboxCollectionIterator(iteration.values[0]) || isSandboxRegExpIterator(iteration.values[0]))) {
15341
15471
  const bindingName = `#for-of:${nodeId}`;
15342
15472
  snapshot.bindings[bindingName] = iteration.values;
15343
15473
  snapshot.loopIterations[nodeId] = { index: iteration.index, values: [bindingName] };
@@ -15685,6 +15815,7 @@ function getPropertyValue(target, property, context, receiver = target) {
15685
15815
  const descriptor = getSandboxPropertyDescriptor(target, property, context.budget);
15686
15816
  if (descriptor !== void 0)
15687
15817
  return readPropertyDescriptor(descriptor, receiver, createCoercionContext(context), true);
15818
+ if (isSandboxRegExpIterator(target)) return getRegExpIteratorMember(property, context.budget);
15688
15819
  if (typeof target === "symbol") {
15689
15820
  const prototype = getBoxedPrototype(target, context.budget);
15690
15821
  return prototype === void 0 ? void 0 : getPropertyValue(prototype, property, context, receiver);
@@ -16267,7 +16398,7 @@ function hasSandboxProperty(value, key, context) {
16267
16398
  while (typeof current === "object" && current !== null) {
16268
16399
  if (isGuestHostObject(current)) return typeof key === "symbol" ? false : hasHostObjectMember(current, String(key));
16269
16400
  if (hasOwnSandboxProperty(current, key, false)) return true;
16270
- if (!((isGuestClosure(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) && (Array.isArray(current) || !isPlainSandboxObject(current) || isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current))) {
16401
+ if (!((isGuestClosure(current) || Array.isArray(current)) && hasExplicitSandboxPrototype(current)) && (Array.isArray(current) || !isPlainSandboxObject(current) || isSandboxDate(current) || isFloat32Array(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isSandboxRegExpIterator(current))) {
16271
16402
  return getPropertyValue(current, key, context) !== void 0;
16272
16403
  }
16273
16404
  current = getSandboxPrototype(current, context.budget);
@@ -16467,7 +16598,7 @@ function getMemberValue(target, property, context) {
16467
16598
  while (typeof current === "object" && current !== null) {
16468
16599
  if (isSandboxClosure(current)) return getClosureMemberValue(current, property, context);
16469
16600
  if (Array.isArray(current)) return getArrayMemberValue(current, property, context);
16470
- if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isFloat32Array(current)) {
16601
+ if (!isPlainSandboxObject(current) || isSandboxGenerator(current) || isSandboxCollectionIterator(current) || isSandboxRegExpIterator(current) || isFloat32Array(current)) {
16471
16602
  return getPropertyValue(current, property, context);
16472
16603
  }
16473
16604
  if (Object.hasOwn(current, String(property))) return current[String(property)];
@@ -17249,6 +17380,16 @@ function encodeReplayData(value, options = {}) {
17249
17380
  };
17250
17381
  }
17251
17382
  nodes[id] = { ...storage, properties, extensible: Object.isExtensible(entry) };
17383
+ } else if (isSandboxRegExpIterator(entry)) {
17384
+ const snapshot = regexpIteratorState(entry);
17385
+ const properties = /* @__PURE__ */ Object.create(null);
17386
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(entry))) {
17387
+ if (!("value" in descriptor)) throw new TypeError(`Cannot record replay data accessor '${key}'.`);
17388
+ properties[key] = { value: child(descriptor.value, JSON.stringify(["property", key])), configurable: descriptor.configurable === true, enumerable: descriptor.enumerable === true, writable: descriptor.writable === true };
17389
+ }
17390
+ let symbolIndex = 0;
17391
+ const symbolEntries = serializeSymbolProperties(entry, (value2) => encode(value2, depth + 1, [...path, { symbol: Math.floor(symbolIndex++ / 2) }]));
17392
+ nodes[id] = { kind: "regexp-iterator", matcher: child(snapshot.matcher, "<matcher>"), input: child(snapshot.input, "<input>"), exhausted: snapshot.exhausted, properties, extensible: Object.isExtensible(entry), symbolEntries };
17252
17393
  } else if (isSandboxCollectionIterator(entry)) {
17253
17394
  const snapshot = snapshotCollectionIterator(entry);
17254
17395
  const properties = /* @__PURE__ */ Object.create(null);
@@ -17439,6 +17580,20 @@ function decodeReplayData(input, options = {}, parent) {
17439
17580
  if (!node.extensible) Object.preventExtensions(result3);
17440
17581
  return result3;
17441
17582
  }
17583
+ if (kind === "regexp-iterator") {
17584
+ const exhausted = own(node, "exhausted");
17585
+ if (typeof exhausted !== "boolean" || typeof node.extensible !== "boolean") throw new TypeError("Invalid replay RegExp iterator.");
17586
+ const result3 = restoreSandboxRegExpIterator({ matcher: void 0, input: void 0, exhausted: true });
17587
+ restored.set(id, result3);
17588
+ const matcher = child(own(node, "matcher"));
17589
+ const input2 = child(own(node, "input"));
17590
+ if (matcher !== void 0 && !isSandboxRegex(matcher)) throw new TypeError("Invalid replay RegExp iterator matcher.");
17591
+ if (input2 !== void 0 && typeof input2 !== "string") throw new TypeError("Invalid replay RegExp iterator input.");
17592
+ restoreSandboxRegExpIterator({ matcher, input: input2, exhausted }, result3);
17593
+ defineProperties(result3, record(own(node, "properties")), child, node.symbolEntries);
17594
+ if (!node.extensible) Object.preventExtensions(result3);
17595
+ return result3;
17596
+ }
17442
17597
  if (kind === "collection-iterator") {
17443
17598
  const collectionKind = own(node, "collectionKind");
17444
17599
  const method = own(node, "method");
@@ -18754,7 +18909,7 @@ async function objectToPrimitive(value, budget, context, joining, hint, ordinary
18754
18909
  }
18755
18910
  }
18756
18911
  function conversionHook(value, name, budget, context) {
18757
- const implicitBuiltin = !hasExplicitSandboxPrototype(value) && (Array.isArray(value) || isSandboxDate(value) || isFloat32Array(value) || sandboxErrorTypes.has(value) || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxCollectionIterator(value) || isSandboxPromise(value) || isSandboxRegex(value) || isSandboxGenerator(value) || isGuestHostObject(value));
18912
+ const implicitBuiltin = !hasExplicitSandboxPrototype(value) && (Array.isArray(value) || isSandboxDate(value) || isFloat32Array(value) || sandboxErrorTypes.has(value) || isSandboxClosure(value) || isSandboxMap(value) || isSandboxSet(value) || isSandboxCollectionIterator(value) || isSandboxRegExpIterator(value) || isSandboxPromise(value) || isSandboxRegex(value) || isSandboxGenerator(value) || isGuestHostObject(value));
18758
18913
  let current = value;
18759
18914
  let depth = 0;
18760
18915
  while (current !== null) {
@@ -18783,6 +18938,7 @@ async function defaultToString(value, budget, context, joining) {
18783
18938
  if (isSandboxClosure(value)) return budget.allocateString(functionString(value));
18784
18939
  if (isSandboxMap(value)) return "[object Map]";
18785
18940
  if (isSandboxSet(value)) return "[object Set]";
18941
+ if (isSandboxRegExpIterator(value)) return "[object RegExp String Iterator]";
18786
18942
  if (isSandboxCollectionIterator(value))
18787
18943
  return collectionIteratorState(value).collectionKind === "map" ? "[object Map Iterator]" : "[object Set Iterator]";
18788
18944
  if (isSandboxGenerator(value)) return "[object Generator]";
@@ -18987,6 +19143,7 @@ function typeTag(value, builtinOnly = false) {
18987
19143
  if (builtinOnly) return "Object";
18988
19144
  if (isSandboxMap(value)) return "Map";
18989
19145
  if (isSandboxSet(value)) return "Set";
19146
+ if (isSandboxRegExpIterator(value)) return "RegExp String Iterator";
18990
19147
  if (isSandboxCollectionIterator(value)) return collectionIteratorState(value).collectionKind === "map" ? "Map Iterator" : "Set Iterator";
18991
19148
  if (isSandboxPromise(value)) return "Promise";
18992
19149
  if (isSandboxGenerator(value)) return "Generator";
@@ -20339,6 +20496,7 @@ function registerCancelablePromises(value, signal) {
20339
20496
  for (const entry of current.values) pending.push(entry);
20340
20497
  } else {
20341
20498
  if (isSandboxCollectionIterator(current)) pending.push(collectionIteratorState(current).collection);
20499
+ if (isSandboxRegExpIterator(current)) pending.push(regexpIteratorState(current).matcher);
20342
20500
  for (const descriptor of Object.values(Object.getOwnPropertyDescriptors(current))) {
20343
20501
  if ("value" in descriptor) pending.push(descriptor.value);
20344
20502
  }
@@ -20776,6 +20934,16 @@ function measureSandboxData(values, options = {}) {
20776
20934
  }
20777
20935
  return;
20778
20936
  }
20937
+ if (isSandboxRegExpIterator(value)) {
20938
+ const state = regexpIteratorState(value);
20939
+ visit(state.matcher, depth + 1);
20940
+ visit(state.input, depth + 1);
20941
+ for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
20942
+ usage += key.length + 1;
20943
+ if ("value" in descriptor) visit(descriptor.value, depth + 1);
20944
+ }
20945
+ return;
20946
+ }
20779
20947
  if (isSandboxCollectionIterator(value)) {
20780
20948
  visit(collectionIteratorState(value).collection, depth + 1);
20781
20949
  for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
@@ -20933,6 +21101,22 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
20933
21101
  if (isSandboxClosure(value) || isSandboxGenerator(value) || isSandboxPromise(value)) {
20934
21102
  return value;
20935
21103
  }
21104
+ if (isSandboxRegExpIterator(value)) {
21105
+ if (hasGuestObjectState(value)) throw new TypeError("Guest prototype links and custom descriptors cannot be copied as data.");
21106
+ if (!cloneSandboxCollections) return value;
21107
+ const existing = state.seen.get(value);
21108
+ if (existing !== void 0) return existing;
21109
+ const snapshot = regexpIteratorState(value);
21110
+ const copy = restoreSandboxRegExpIterator({ matcher: void 0, input: void 0, exhausted: true });
21111
+ state.seen.set(value, copy);
21112
+ const matcher = copyToSandbox(snapshot.matcher, state, `${path}.<matcher>`, true, depth + 1);
21113
+ if (matcher !== void 0 && !isSandboxRegex(matcher)) throw new TypeError("Invalid RegExp iterator matcher.");
21114
+ restoreSandboxRegExpIterator({ ...snapshot, matcher }, copy);
21115
+ for (const entry of getEnumerableObjectEntries(value, path)) {
21116
+ defineOwnDataProperty(copy, entry.key, copyToSandbox(entry.value, state, joinPath2(path, entry.key), true, depth + 1));
21117
+ }
21118
+ return copy;
21119
+ }
20936
21120
  if (isSandboxCollectionIterator(value)) {
20937
21121
  if (hasGuestObjectState(value)) throw new TypeError("Guest prototype links and custom descriptors cannot be copied as data.");
20938
21122
  if (!cloneSandboxCollections) return value;
@@ -21259,6 +21443,9 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
21259
21443
  if (isSandboxCollectionIterator(value)) {
21260
21444
  throw new TypeError("Sandbox collection iterators cannot cross into host values.");
21261
21445
  }
21446
+ if (isSandboxRegExpIterator(value)) {
21447
+ throw new TypeError("Sandbox RegExp iterators cannot cross into host values.");
21448
+ }
21262
21449
  if (isSandboxRegex(value)) {
21263
21450
  throw new TypeError("Invalid sandbox RegExp brand.");
21264
21451
  }
@@ -33923,7 +34110,7 @@ function structuredCloneSandboxValue(value, budget, parent) {
33923
34110
  }
33924
34111
  }
33925
34112
  function assertStructuredCloneable(value, seen) {
33926
- if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value)) {
34113
+ if (isSandboxClosure(value) || isSandboxPromise(value) || isSandboxCollectionIterator(value) || isSandboxRegExpIterator(value)) {
33927
34114
  throw new TypeError("structuredClone() cannot clone closures, promises, or collection iterators.");
33928
34115
  }
33929
34116
  if (typeof value !== "object" || value === null || seen.has(value)) {
@@ -35504,6 +35691,17 @@ function prepareReplayInputs(current, saved, preparePromise, onCapabilityRestore
35504
35691
  value = descriptor2.value;
35505
35692
  continue;
35506
35693
  }
35694
+ if (isSandboxRegExpIterator(value)) {
35695
+ if (key === "<matcher>") value = regexpIteratorState(value).matcher;
35696
+ else if (key === "<input>") value = regexpIteratorState(value).input;
35697
+ else {
35698
+ const property = JSON.parse(key);
35699
+ if (!Array.isArray(property) || property.length !== 2 || property[0] !== "property" || typeof property[1] !== "string") throw new TypeError("Invalid replay input iterator capability path.");
35700
+ const descriptor2 = Object.getOwnPropertyDescriptor(value, property[1]);
35701
+ value = descriptor2 !== void 0 && "value" in descriptor2 ? descriptor2.value : void 0;
35702
+ }
35703
+ continue;
35704
+ }
35507
35705
  if (isSandboxCollectionIterator(value)) {
35508
35706
  if (key === "<collection>") value = collectionIteratorState(value).collection;
35509
35707
  else {
@@ -35574,11 +35772,11 @@ function prepareReplayInputs(current, saved, preparePromise, onCapabilityRestore
35574
35772
  return { values: restored, snapshot: structuredClone(saved) };
35575
35773
  }
35576
35774
  function assertReplayInputShape(restored) {
35577
- if (restored === null || typeof restored !== "object" || Array.isArray(restored) || isSandboxClosure(restored) || isSandboxPromise(restored) || isSandboxCollectionIterator(restored) || isSandboxMap(restored) || isSandboxSet(restored))
35775
+ if (restored === null || typeof restored !== "object" || Array.isArray(restored) || isSandboxClosure(restored) || isSandboxPromise(restored) || isSandboxCollectionIterator(restored) || isSandboxRegExpIterator(restored) || isSandboxMap(restored) || isSandboxSet(restored))
35578
35776
  throw new TypeError("Invalid replay inputs.");
35579
35777
  const values = restored;
35580
35778
  for (const key of ["bindings", "imports"]) {
35581
- if (values[key] === null || typeof values[key] !== "object" || Array.isArray(values[key]) || isSandboxClosure(values[key]) || isSandboxPromise(values[key]) || isSandboxCollectionIterator(values[key]) || isSandboxMap(values[key]) || isSandboxSet(values[key]))
35779
+ if (values[key] === null || typeof values[key] !== "object" || Array.isArray(values[key]) || isSandboxClosure(values[key]) || isSandboxPromise(values[key]) || isSandboxCollectionIterator(values[key]) || isSandboxRegExpIterator(values[key]) || isSandboxMap(values[key]) || isSandboxSet(values[key]))
35582
35780
  throw new TypeError(`Invalid replay input ${key}.`);
35583
35781
  }
35584
35782
  if (values.entryPointArgs !== void 0 && !Array.isArray(values.entryPointArgs))
@@ -36179,4 +36377,4 @@ export {
36179
36377
  FileSnapshotBackend,
36180
36378
  run
36181
36379
  };
36182
- //# sourceMappingURL=chunk-XKCTB5FR.js.map
36380
+ //# sourceMappingURL=chunk-WVYGEWML.js.map