poe-code 14.0.74 → 14.0.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/index.js +1283 -144
  2. package/dist/index.js.map +4 -4
  3. package/dist/metafile.json +1 -1
  4. package/package.json +1 -1
  5. package/packages/safe-js/dist/chunks/{chunk-YEZOXLY4.js → chunk-UZYQWFMY.js} +1233 -143
  6. package/packages/safe-js/dist/chunks/chunk-UZYQWFMY.js.map +7 -0
  7. package/packages/safe-js/dist/chunks/{chunk-2J6W3YGB.js → chunk-VD2AS4E4.js} +2 -2
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.js +1 -1
  10. package/packages/safe-js/dist/index.js +2 -2
  11. package/packages/safe-js/dist/index.js.map +1 -1
  12. package/packages/safe-js/dist/interp/bigint-operators.d.ts +3 -0
  13. package/packages/safe-js/dist/interp/bigint-operators.js +62 -0
  14. package/packages/safe-js/dist/interp/boxed.d.ts +2 -2
  15. package/packages/safe-js/dist/interp/boxed.js +4 -1
  16. package/packages/safe-js/dist/interp/globals/bigint.d.ts +2 -0
  17. package/packages/safe-js/dist/interp/globals/bigint.js +85 -0
  18. package/packages/safe-js/dist/interp/globals/console-json.js +57 -24
  19. package/packages/safe-js/dist/interp/globals/object-array.js +1 -1
  20. package/packages/safe-js/dist/interp/globals/regex.js +108 -2
  21. package/packages/safe-js/dist/interp/globals.d.ts +1 -0
  22. package/packages/safe-js/dist/interp/globals.js +2 -0
  23. package/packages/safe-js/dist/interp/host-bridge.js +2 -0
  24. package/packages/safe-js/dist/interp/interpreter.js +59 -12
  25. package/packages/safe-js/dist/interp/iteration.js +5 -2
  26. package/packages/safe-js/dist/interp/methods/number.js +1 -1
  27. package/packages/safe-js/dist/interp/methods/regex-split.d.ts +3 -0
  28. package/packages/safe-js/dist/interp/methods/regex-split.js +102 -0
  29. package/packages/safe-js/dist/interp/methods/regex.d.ts +1 -1
  30. package/packages/safe-js/dist/interp/methods/regex.js +16 -5
  31. package/packages/safe-js/dist/interp/methods/regexp-iterator.d.ts +5 -1
  32. package/packages/safe-js/dist/interp/methods/regexp-iterator.js +59 -7
  33. package/packages/safe-js/dist/interp/methods/string.js +9 -9
  34. package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
  35. package/packages/safe-js/dist/interp/object-model.js +4 -1
  36. package/packages/safe-js/dist/interp/regex/compile-guard.js +26 -4
  37. package/packages/safe-js/dist/interp/regex/engine.d.ts +4 -0
  38. package/packages/safe-js/dist/interp/regex/engine.js +230 -30
  39. package/packages/safe-js/dist/interp/regex/parse.d.ts +42 -4
  40. package/packages/safe-js/dist/interp/regex/parse.js +429 -25
  41. package/packages/safe-js/dist/interp/regexp-iterator.d.ts +4 -2
  42. package/packages/safe-js/dist/interp/regexp-iterator.js +6 -1
  43. package/packages/safe-js/dist/interp/string-coercion.d.ts +1 -1
  44. package/packages/safe-js/dist/interp/string-coercion.js +8 -3
  45. package/packages/safe-js/dist/interp/values.d.ts +1 -1
  46. package/packages/safe-js/dist/interp/values.js +10 -3
  47. package/packages/safe-js/dist/lint/rules/AS-async-not-needed.js +2 -0
  48. package/packages/safe-js/dist/lint/rules/AS-missing-async.js +2 -0
  49. package/packages/safe-js/dist/lint/rules/known-globals.d.ts +1 -1
  50. package/packages/safe-js/dist/lint/rules/known-globals.js +1 -0
  51. package/packages/safe-js/dist/parse/parser.d.ts +6 -1
  52. package/packages/safe-js/dist/parse/parser.js +8 -0
  53. package/packages/safe-js/dist/parse/tokenizer.js +12 -4
  54. package/packages/safe-js/dist/parse.d.ts +1 -1
  55. package/packages/safe-js/dist/snapshot/bigint.d.ts +1 -0
  56. package/packages/safe-js/dist/snapshot/bigint.js +14 -0
  57. package/packages/safe-js/dist/snapshot/dump-format.js +12 -2
  58. package/packages/safe-js/dist/snapshot/replay-data.d.ts +6 -0
  59. package/packages/safe-js/dist/snapshot/replay-data.js +23 -5
  60. package/packages/safe-js/dist/snapshot/restore.js +10 -2
  61. package/packages/safe-js/dist/snapshot/serialize.d.ts +4 -1
  62. package/packages/safe-js/dist/snapshot/serialize.js +6 -1
  63. package/packages/safe-js/dist/snapshot/validation.js +27 -0
  64. package/packages/safe-js/dist/chunks/chunk-YEZOXLY4.js.map +0 -7
  65. /package/packages/safe-js/dist/chunks/{chunk-2J6W3YGB.js.map → chunk-VD2AS4E4.js.map} +0 -0
@@ -711,7 +711,7 @@ var RegexCompileGuard = class {
711
711
  this.work(flags.length);
712
712
  }
713
713
  retain(pattern, valueUnits = 0) {
714
- const units = 10 + pattern.source.length + measureNode(pattern.body);
714
+ const units = measurePattern(pattern);
715
715
  if (this.ticket !== void 0) {
716
716
  this.ticket.owner.budget.resizeCompileTicket(this.ticket, units + valueUnits);
717
717
  }
@@ -728,7 +728,15 @@ var RegexCompileGuard = class {
728
728
  }
729
729
  };
730
730
  function regexCompiledData(pattern) {
731
- return compiledData.get(pattern) ?? { units: 10 + pattern.source.length + measureNode(pattern.body) };
731
+ return compiledData.get(pattern) ?? { units: measurePattern(pattern) };
732
+ }
733
+ function measurePattern(pattern) {
734
+ let units = 10 + pattern.source.length + measureNode(pattern.body);
735
+ if (pattern.groups !== void 0) {
736
+ units += 1;
737
+ for (const [name, indices] of Object.entries(pattern.groups)) units += name.length + 2 + indices.length;
738
+ }
739
+ return units;
732
740
  }
733
741
  function measureNode(node) {
734
742
  switch (node.type) {
@@ -737,13 +745,18 @@ function measureNode(node) {
737
745
  return 2;
738
746
  case "literal":
739
747
  return 3 + node.value.length;
748
+ case "namedBackreference":
749
+ return 3 + node.name.length;
740
750
  case "anchor":
741
751
  case "wordBoundary":
752
+ case "backreference":
742
753
  return 3;
743
754
  case "characterClass": {
744
755
  let usage = 5 + node.items.length;
756
+ if (node.operation !== void 0) usage += 1 + node.operation.length;
757
+ if (node.strings !== void 0) usage += 1;
745
758
  for (const item of node.items) {
746
- usage += item.type === "character" ? 3 + item.value.length : item.type === "range" ? 4 + item.from.length + item.to.length : 4;
759
+ usage += item.type === "character" ? 3 + item.value.length : item.type === "range" ? 4 + item.from.length + item.to.length : item.type === "property" ? 4 + item.value.length + (item.strings === void 0 ? 0 : 1) : item.type === "set" ? 3 + measureNode({ type: "characterClass", ...item.value }) : item.type === "strings" ? 4 + item.values.reduce((total, value) => total + 1 + value.length, 0) : 4;
747
760
  }
748
761
  return usage;
749
762
  }
@@ -755,7 +768,10 @@ function measureNode(node) {
755
768
  return usage;
756
769
  }
757
770
  case "group":
758
- return 5 + measureNode(node.body);
771
+ return 5 + measureNode(node.body) + (node.name === void 0 ? 0 : 1 + node.name.length) + (node.modifiers === void 0 ? 0 : 2 + Object.keys(node.modifiers).length);
772
+ case "lookahead":
773
+ case "lookbehind":
774
+ return 4 + measureNode(node.body);
759
775
  case "quantifier":
760
776
  return (Object.hasOwn(node, "max") ? 6 : 5) + measureNode(node.body);
761
777
  }
@@ -1239,7 +1255,7 @@ var Lexer = class {
1239
1255
  this.advance();
1240
1256
  this.advance();
1241
1257
  this.consumeDigitsForBase(isHexDigit, "hexadecimal");
1242
- this.rejectBigIntSuffix();
1258
+ if (this.currentChar() === "n") this.advance();
1243
1259
  this.rejectInvalidNumericLiteralContinuation();
1244
1260
  return this.source.slice(start.offset, this.index);
1245
1261
  }
@@ -1247,7 +1263,7 @@ var Lexer = class {
1247
1263
  this.advance();
1248
1264
  this.advance();
1249
1265
  this.consumeDigitsForBase(isBinaryDigit, "binary");
1250
- this.rejectBigIntSuffix();
1266
+ if (this.currentChar() === "n") this.advance();
1251
1267
  this.rejectInvalidNumericLiteralContinuation();
1252
1268
  return this.source.slice(start.offset, this.index);
1253
1269
  }
@@ -1255,7 +1271,7 @@ var Lexer = class {
1255
1271
  this.advance();
1256
1272
  this.advance();
1257
1273
  this.consumeDigitsForBase(isOctalDigit, "octal");
1258
- this.rejectBigIntSuffix();
1274
+ if (this.currentChar() === "n") this.advance();
1259
1275
  this.rejectInvalidNumericLiteralContinuation();
1260
1276
  return this.source.slice(start.offset, this.index);
1261
1277
  }
@@ -1269,6 +1285,11 @@ var Lexer = class {
1269
1285
  }
1270
1286
  }
1271
1287
  this.consumeDecimalDigits();
1288
+ if (this.currentChar() === "n") {
1289
+ this.advance();
1290
+ this.rejectInvalidNumericLiteralContinuation();
1291
+ return this.source.slice(start.offset, this.index);
1292
+ }
1272
1293
  if (this.currentChar() === "." && (this.peekChar(1) !== "." || this.peekChar(2) !== ".")) {
1273
1294
  this.advance();
1274
1295
  this.consumeOptionalDecimalDigits();
@@ -1367,7 +1388,7 @@ var Lexer = class {
1367
1388
  }
1368
1389
  rejectBigIntSuffix() {
1369
1390
  if (this.currentChar() === "n") {
1370
- this.syntaxError("BigInt not supported", this.position());
1391
+ this.syntaxError("BigInt literals cannot contain a fraction or exponent", this.position());
1371
1392
  }
1372
1393
  }
1373
1394
  rejectInvalidNumericLiteralContinuation() {
@@ -2045,6 +2066,8 @@ function createIdentifier(token, name) {
2045
2066
  }
2046
2067
 
2047
2068
  // packages/safe-js/src/interp/regex/parse.ts
2069
+ var groupNameStart = /^[$_\p{ID_Start}]$/u;
2070
+ var groupNamePart = /^[$\u200c\u200d\p{ID_Continue}]$/u;
2048
2071
  function parseRegex(source, flags = "", compilation, valueUnits = 0) {
2049
2072
  const guard = new RegexCompileGuard(compilation);
2050
2073
  try {
@@ -2052,10 +2075,11 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
2052
2075
  guard.checkLength(flags.length, true);
2053
2076
  guard.allocate(5 + valueUnits);
2054
2077
  const parsedFlags = parseFlags(flags, guard);
2055
- const parser = new RegexParser(source, guard);
2078
+ const parser = new RegexParser(source, guard, parsedFlags.unicode || parsedFlags.unicodeSets, parsedFlags.unicodeSets);
2056
2079
  const body = parser.parse();
2057
2080
  guard.allocate(5 + source.length);
2058
2081
  const pattern = { source, flags: parsedFlags, captureCount: parser.captureCount, body };
2082
+ if (Object.keys(parser.namedGroups).length > 0) pattern.groups = parser.namedGroups;
2059
2083
  guard.retain(pattern, valueUnits);
2060
2084
  return pattern;
2061
2085
  } finally {
@@ -2063,14 +2087,21 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
2063
2087
  }
2064
2088
  }
2065
2089
  var RegexParser = class {
2066
- constructor(source, guard) {
2090
+ constructor(source, guard, unicode, unicodeSets) {
2067
2091
  this.source = source;
2068
2092
  this.guard = guard;
2093
+ this.unicode = unicode;
2094
+ this.unicodeSets = unicodeSets;
2069
2095
  }
2070
2096
  source;
2071
2097
  guard;
2098
+ unicode;
2099
+ unicodeSets;
2072
2100
  captureCount = 0;
2073
2101
  cursor = 0;
2102
+ totalCaptureCount;
2103
+ hasNamedCaptures = false;
2104
+ namedGroups = /* @__PURE__ */ Object.create(null);
2074
2105
  get position() {
2075
2106
  return this.cursor;
2076
2107
  }
@@ -2086,6 +2117,7 @@ var RegexParser = class {
2086
2117
  }
2087
2118
  this.fail(`Unexpected character '${this.peek()}'`);
2088
2119
  }
2120
+ if (this.unicode || Object.keys(this.namedGroups).length > 0) this.validateNamedGroups(body);
2089
2121
  return body;
2090
2122
  }
2091
2123
  parseAlternation() {
@@ -2119,15 +2151,20 @@ var RegexParser = class {
2119
2151
  parseQuantifiedAtom() {
2120
2152
  const quantifierStart = this.position;
2121
2153
  const current = this.peek();
2122
- if (current === "*" || current === "+" || current === "?" || current === "{") {
2154
+ if (current === "*" || current === "+" || current === "?" || current === "{" && this.unicode) {
2123
2155
  this.fail("Nothing to repeat", quantifierStart);
2124
2156
  }
2157
+ if (current === "{") {
2158
+ const quantifier2 = this.parseQuantifier();
2159
+ this.position = quantifierStart;
2160
+ if (quantifier2 !== void 0) this.fail("Nothing to repeat", quantifierStart);
2161
+ }
2125
2162
  const body = this.parseAtom();
2126
2163
  const quantifier = this.parseQuantifier();
2127
2164
  if (quantifier === void 0) {
2128
2165
  return body;
2129
2166
  }
2130
- if (body.type === "anchor" || body.type === "wordBoundary") {
2167
+ if (body.type === "anchor" || body.type === "wordBoundary" || body.type === "lookbehind" || this.unicode && body.type === "lookahead") {
2131
2168
  this.fail("Invalid quantifier target", quantifierStart);
2132
2169
  }
2133
2170
  const greedy = this.peek() !== "?";
@@ -2138,7 +2175,7 @@ var RegexParser = class {
2138
2175
  return { type: "quantifier", body, ...quantifier, greedy };
2139
2176
  }
2140
2177
  parseAtom() {
2141
- const character = this.take();
2178
+ const character = this.takeCharacter();
2142
2179
  switch (character) {
2143
2180
  case ".":
2144
2181
  this.guard.allocate(2);
@@ -2156,12 +2193,17 @@ var RegexParser = class {
2156
2193
  case "\\":
2157
2194
  return this.parseEscape(false, this.position - 1);
2158
2195
  default:
2196
+ if (this.unicode && (character === "]" || character === "}")) this.fail("Invalid Unicode pattern character");
2159
2197
  this.guard.allocate(3 + character.length);
2160
2198
  return { type: "literal", value: character };
2161
2199
  }
2162
2200
  }
2163
2201
  parseGroup(start) {
2164
2202
  let capturing = true;
2203
+ let name;
2204
+ let modifiers;
2205
+ let assertionNegated;
2206
+ let lookbehind = false;
2165
2207
  if (this.peek() === "?") {
2166
2208
  this.guard.allocate(Math.min(3, this.source.length - this.position));
2167
2209
  this.guard.work(Math.min(3, this.source.length - this.position));
@@ -2170,17 +2212,33 @@ var RegexParser = class {
2170
2212
  capturing = false;
2171
2213
  this.position += 2;
2172
2214
  } else if (extension.startsWith("?=") || extension.startsWith("?!")) {
2173
- this.fail("Lookahead is not supported", start);
2215
+ capturing = false;
2216
+ assertionNegated = extension.startsWith("?!");
2217
+ this.position += 2;
2174
2218
  } else if (extension.startsWith("?<=") || extension.startsWith("?<!")) {
2175
- this.fail("Lookbehind is not supported", start);
2219
+ capturing = false;
2220
+ assertionNegated = extension.startsWith("?<!");
2221
+ lookbehind = true;
2222
+ this.position += 3;
2176
2223
  } else if (extension.startsWith("?<")) {
2177
- this.fail("Named groups are not supported", start);
2224
+ this.position += 2;
2225
+ name = this.parseGroupName(start);
2226
+ } else if ("ims-".includes(extension[1] ?? "") && extension.length > 1) {
2227
+ capturing = false;
2228
+ this.position++;
2229
+ modifiers = this.parseModifiers(start);
2178
2230
  } else {
2179
2231
  this.fail("Unsupported group construct", start);
2180
2232
  }
2181
2233
  }
2182
2234
  if (capturing) this.guard.allocate(1);
2183
2235
  const index = capturing ? ++this.captureCount : void 0;
2236
+ if (name !== void 0) {
2237
+ this.guard.allocate(name.length + 2);
2238
+ const indices = this.namedGroups[name] ??= [];
2239
+ this.guard.array(indices.length + 1);
2240
+ indices.push(index);
2241
+ }
2184
2242
  this.guard.enterGroup();
2185
2243
  let body;
2186
2244
  try {
@@ -2192,10 +2250,40 @@ var RegexParser = class {
2192
2250
  this.fail("Unterminated group", start);
2193
2251
  }
2194
2252
  this.position += 1;
2253
+ if (assertionNegated !== void 0) {
2254
+ this.guard.allocate(4);
2255
+ return { type: lookbehind ? "lookbehind" : "lookahead", negated: assertionNegated, body };
2256
+ }
2195
2257
  this.guard.allocate(5);
2196
- return { type: "group", capturing, index, body };
2258
+ return {
2259
+ type: "group",
2260
+ capturing,
2261
+ index,
2262
+ body,
2263
+ ...name === void 0 ? {} : { name },
2264
+ ...modifiers === void 0 ? {} : { modifiers }
2265
+ };
2266
+ }
2267
+ parseModifiers(start) {
2268
+ this.guard.allocate(2);
2269
+ const modifiers = {};
2270
+ let enabled = true;
2271
+ while (!this.atEnd() && this.peek() !== ":") {
2272
+ const flag = this.take();
2273
+ if (flag === "-" && enabled) {
2274
+ enabled = false;
2275
+ continue;
2276
+ }
2277
+ const name = flag === "i" ? "ignoreCase" : flag === "m" ? "multiline" : flag === "s" ? "dotAll" : void 0;
2278
+ if (name === void 0 || Object.hasOwn(modifiers, name)) this.fail("Invalid regex modifiers", start);
2279
+ this.guard.allocate(1);
2280
+ modifiers[name] = enabled;
2281
+ }
2282
+ if (this.take() !== ":" || Object.keys(modifiers).length === 0) this.fail("Invalid regex modifiers", start);
2283
+ return modifiers;
2197
2284
  }
2198
2285
  parseCharacterClass(start) {
2286
+ if (this.unicodeSets) return { type: "characterClass", ...this.parseUnicodeSet(start) };
2199
2287
  const negated = this.peek() === "^";
2200
2288
  if (negated) {
2201
2289
  this.position += 1;
@@ -2215,9 +2303,13 @@ var RegexParser = class {
2215
2303
  this.position += 1;
2216
2304
  const right = this.parseClassItem(start);
2217
2305
  if (left.type !== "character" || right.type !== "character") {
2218
- this.fail("Character class ranges require literal endpoints", rangePosition);
2306
+ if (this.unicode) this.fail("Character class ranges require literal endpoints", rangePosition);
2307
+ this.guard.array(items.length + 3);
2308
+ this.guard.allocate(4);
2309
+ items.push(left, { type: "character", value: "-" }, right);
2310
+ continue;
2219
2311
  }
2220
- if (left.value.charCodeAt(0) > right.value.charCodeAt(0)) {
2312
+ if (left.value.codePointAt(0) > right.value.codePointAt(0)) {
2221
2313
  this.fail("Character class range is out of order", rangePosition);
2222
2314
  }
2223
2315
  this.guard.allocate(4 + left.value.length + right.value.length);
@@ -2246,26 +2338,193 @@ var RegexParser = class {
2246
2338
  this.fail("Unsupported character class escape", escapeStart);
2247
2339
  }
2248
2340
  this.guard.allocate(4);
2249
- return { type: "character", value: this.take() };
2341
+ return { type: "character", value: this.takeCharacter() };
2342
+ }
2343
+ parseUnicodeSet(start) {
2344
+ this.guard.enterGroup();
2345
+ try {
2346
+ const negated = this.peek() === "^";
2347
+ if (negated) this.position++;
2348
+ this.guard.allocate(5);
2349
+ const items = [];
2350
+ let operation;
2351
+ while (!this.atEnd() && this.peek() !== "]") {
2352
+ this.guard.array(items.length + 1);
2353
+ let item = this.parseUnicodeSetItem(start);
2354
+ if (this.peek() === "-" && this.source[this.position + 1] !== "-") {
2355
+ this.position++;
2356
+ const right = this.parseUnicodeSetItem(start);
2357
+ if (item.type !== "character" || right.type !== "character") this.fail("Invalid set range", start);
2358
+ if (item.value.codePointAt(0) > right.value.codePointAt(0)) this.fail("Set range is out of order", start);
2359
+ this.guard.allocate(4 + item.value.length + right.value.length);
2360
+ item = { type: "range", from: item.value, to: right.value };
2361
+ }
2362
+ if (operation !== void 0 && item.type === "range") this.fail("Set operations require nested ranges", start);
2363
+ items.push(item);
2364
+ const operator = this.source.slice(this.position, this.position + 2);
2365
+ if (operator === "&&" || operator === "--") {
2366
+ const next = operator === "&&" ? "intersection" : "subtraction";
2367
+ if (operation === void 0 && (items.length !== 1 || item.type === "range") || operation !== void 0 && operation !== next) this.fail("Mixed set operations", start);
2368
+ if (operation === void 0) this.guard.allocate(1 + next.length);
2369
+ operation = next;
2370
+ this.position += 2;
2371
+ if (this.peek() === "]" || this.atEnd()) this.fail("Missing set operand", start);
2372
+ } else if (operation !== void 0 && this.peek() !== "]") this.fail("Missing set operator", start);
2373
+ }
2374
+ if (this.take() !== "]") this.fail("Unterminated character set", start);
2375
+ const mayContainStrings = (item) => {
2376
+ if (item.type === "set") return item.value.strings === true;
2377
+ if (item.type === "property") return item.strings === true;
2378
+ if (item.type === "strings") return item.values.some((value) => value.length !== ((value.codePointAt(0) ?? 0) > 65535 ? 2 : 1));
2379
+ return false;
2380
+ };
2381
+ const strings = operation === "intersection" ? items.every(mayContainStrings) : operation === "subtraction" ? mayContainStrings(items[0]) : items.some(mayContainStrings);
2382
+ if (negated && strings) this.fail("Cannot complement a set containing strings", start);
2383
+ if (strings) this.guard.allocate(1);
2384
+ return { negated, items, ...operation === void 0 ? {} : { operation }, ...strings ? { strings: true } : {} };
2385
+ } finally {
2386
+ this.guard.leaveGroup();
2387
+ }
2388
+ }
2389
+ parseUnicodeSetItem(start) {
2390
+ if (this.peek() === "[") {
2391
+ this.position++;
2392
+ this.guard.allocate(3);
2393
+ return { type: "set", value: this.parseUnicodeSet(start) };
2394
+ }
2395
+ if (this.source.startsWith("\\q{", this.position)) {
2396
+ this.position += 3;
2397
+ this.guard.allocate(4);
2398
+ const values = [];
2399
+ let value2 = "";
2400
+ while (!this.atEnd()) {
2401
+ if (this.peek() === "|" || this.peek() === "}") {
2402
+ this.guard.array(values.length + 1);
2403
+ this.guard.allocate(1);
2404
+ values.push(value2);
2405
+ value2 = "";
2406
+ if (this.take() === "}") return { type: "strings", values };
2407
+ } else {
2408
+ const item = this.parseSetCharacter(start);
2409
+ this.guard.allocate(item.length);
2410
+ value2 += item;
2411
+ }
2412
+ }
2413
+ this.fail("Unterminated class string", start);
2414
+ }
2415
+ if (this.peek() === "\\") return this.parseClassItem(start);
2416
+ const value = this.parseSetCharacter(start);
2417
+ this.guard.allocate(3 + value.length);
2418
+ return { type: "character", value };
2419
+ }
2420
+ parseSetCharacter(start) {
2421
+ if (this.peek() === "\\") {
2422
+ this.position++;
2423
+ const node = this.parseEscape(true, start);
2424
+ if (node.type !== "literal") this.fail("Class strings require literal characters", start);
2425
+ return node.value;
2426
+ }
2427
+ const character = this.takeCharacter();
2428
+ if (!character || "()[]{}/-|".includes(character) || "!#$%&*+,.:;<=>?@^`~".includes(character) && this.peek() === character)
2429
+ this.fail("Invalid character in Unicode set", start);
2430
+ return character;
2250
2431
  }
2251
2432
  parseEscape(inCharacterClass, start) {
2252
2433
  if (this.atEnd()) {
2253
2434
  this.fail("Trailing escape", start);
2254
2435
  }
2255
2436
  const escaped = this.take();
2256
- if (escaped >= "1" && escaped <= "9") {
2257
- this.fail("Backreferences are not supported", start);
2258
- }
2259
- if (escaped === "p" || escaped === "P") {
2260
- this.fail("Unicode property escapes are not supported", start);
2437
+ if (escaped === "k") {
2438
+ this.totalCaptureCount ??= this.countAllCaptures();
2439
+ if (this.unicode || this.hasNamedCaptures) {
2440
+ if (inCharacterClass || this.take() !== "<") this.fail("Invalid named backreference", start);
2441
+ const name = this.parseGroupName(start);
2442
+ this.guard.allocate(3 + name.length);
2443
+ return { type: "namedBackreference", name };
2444
+ }
2445
+ }
2446
+ if (isDecimalDigit2(escaped)) {
2447
+ if (!inCharacterClass && escaped !== "0") {
2448
+ let end = this.position;
2449
+ let index = Number(escaped);
2450
+ while (isDecimalDigit2(this.source[end] ?? "")) {
2451
+ this.guard.work(1);
2452
+ index = index * 10 + Number(this.source[end++]);
2453
+ }
2454
+ this.totalCaptureCount ??= this.countAllCaptures();
2455
+ if (index <= this.totalCaptureCount) {
2456
+ this.position = end;
2457
+ this.guard.allocate(3);
2458
+ return { type: "backreference", index };
2459
+ }
2460
+ }
2461
+ if (this.unicode && (escaped !== "0" || isDecimalDigit2(this.peek())))
2462
+ this.fail("Invalid decimal escape", start);
2463
+ this.guard.allocate(4);
2464
+ if (escaped === "8" || escaped === "9") return { type: "literal", value: escaped };
2465
+ let code = Number(escaped);
2466
+ const maximum = escaped <= "3" ? 3 : 2;
2467
+ for (let digits = 1; digits < maximum && this.peek() >= "0" && this.peek() <= "7"; digits++) {
2468
+ code = code * 8 + Number(this.take());
2469
+ }
2470
+ return { type: "literal", value: String.fromCharCode(code) };
2471
+ }
2472
+ if (this.unicode && (escaped === "p" || escaped === "P")) {
2473
+ if (this.take() !== "{") this.fail("Invalid Unicode property escape", start);
2474
+ const begin = this.position;
2475
+ while (!this.atEnd() && this.peek() !== "}") {
2476
+ const character = this.take();
2477
+ if (!isDecimalDigit2(character) && !(character >= "a" && character <= "z") && !(character >= "A" && character <= "Z") && character !== "_" && character !== "=")
2478
+ this.fail("Invalid Unicode property escape", start);
2479
+ }
2480
+ this.guard.allocate(this.position - begin + 9);
2481
+ const value = this.source.slice(begin, this.position);
2482
+ if (this.take() !== "}") this.fail("Unterminated Unicode property escape", start);
2483
+ try {
2484
+ new RegExp(`\\${escaped}{${value}}`, this.unicodeSets ? "v" : "u");
2485
+ } catch {
2486
+ this.fail("Unknown Unicode property", start);
2487
+ }
2488
+ let strings = false;
2489
+ if (this.unicodeSets) {
2490
+ try {
2491
+ new RegExp(`\\p{${value}}`, "u");
2492
+ } catch {
2493
+ strings = true;
2494
+ }
2495
+ }
2496
+ this.guard.array(1);
2497
+ return { type: "characterClass", negated: false, items: [{ type: "property", value, negated: escaped === "P", ...strings ? { strings: true } : {} }] };
2261
2498
  }
2262
2499
  if (escaped === "x") {
2263
2500
  this.guard.allocate(4);
2264
- return { type: "literal", value: this.parseHexEscape(2, "hexadecimal", start) };
2501
+ return { type: "literal", value: this.parseHexEscape(2, "hexadecimal", start, this.unicode ? void 0 : "x") };
2265
2502
  }
2266
2503
  if (escaped === "u") {
2267
2504
  this.guard.allocate(4);
2268
- return { type: "literal", value: this.parseHexEscape(4, "Unicode", start) };
2505
+ if (this.unicode && this.peek() === "{") {
2506
+ this.position++;
2507
+ const begin = this.position;
2508
+ while (!this.atEnd() && this.peek() !== "}") this.position++;
2509
+ this.guard.allocate(this.position - begin);
2510
+ const digits = this.source.slice(begin, this.position);
2511
+ const point = Number.parseInt(digits, 16);
2512
+ if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
2513
+ this.fail("Invalid Unicode escape", start);
2514
+ return { type: "literal", value: String.fromCodePoint(point) };
2515
+ }
2516
+ let value = this.parseHexEscape(4, "Unicode", start, this.unicode ? void 0 : "u");
2517
+ if (this.unicode && value.charCodeAt(0) >= 55296 && value.charCodeAt(0) <= 56319 && this.source.startsWith("\\u", this.position)) {
2518
+ const digits = this.source.slice(this.position + 2, this.position + 6);
2519
+ const point = Number.parseInt(digits, 16);
2520
+ this.guard.work(digits.length);
2521
+ this.guard.allocate(digits.length);
2522
+ if (digits.length === 4 && allHexDigits(digits) && point >= 56320 && point <= 57343) {
2523
+ value += String.fromCharCode(point);
2524
+ this.position += 6;
2525
+ }
2526
+ }
2527
+ return { type: "literal", value };
2269
2528
  }
2270
2529
  this.guard.allocate(25);
2271
2530
  const kinds = {
@@ -2296,20 +2555,101 @@ var RegexParser = class {
2296
2555
  v: "\v",
2297
2556
  "0": "\0"
2298
2557
  };
2558
+ if (escaped === "c") {
2559
+ const letter = this.peek();
2560
+ this.guard.allocate(4);
2561
+ if (letter >= "a" && letter <= "z" || letter >= "A" && letter <= "Z" || !this.unicode && inCharacterClass && (isDecimalDigit2(letter) || letter === "_")) {
2562
+ this.position++;
2563
+ return { type: "literal", value: String.fromCharCode(letter.charCodeAt(0) % 32) };
2564
+ }
2565
+ if (this.unicode) this.fail("Invalid control escape", start);
2566
+ this.position--;
2567
+ return { type: "literal", value: "\\" };
2568
+ }
2569
+ if (this.unicode && controls[escaped] === void 0 && !"^$\\.*+?()[]{}|/".includes(escaped) && !(inCharacterClass && (escaped === "-" || this.unicodeSets && "!#$%&+,.:;<=>?@`~".includes(escaped))))
2570
+ this.fail("Invalid identity escape", start);
2299
2571
  this.guard.allocate(4);
2300
2572
  return { type: "literal", value: controls[escaped] ?? escaped };
2301
2573
  }
2302
- parseHexEscape(length, name, start) {
2574
+ parseHexEscape(length, name, start, identity) {
2303
2575
  const end = this.position + length;
2304
2576
  this.guard.allocate(Math.min(length, this.source.length - this.position));
2305
2577
  this.guard.work(Math.min(length, this.source.length - this.position));
2306
2578
  const digits = this.source.slice(this.position, end);
2307
2579
  if (digits.length !== length || !allHexDigits(digits)) {
2580
+ if (identity !== void 0) return identity;
2308
2581
  this.fail(`Invalid ${name} escape`, start);
2309
2582
  }
2310
2583
  this.position = end;
2311
2584
  return String.fromCharCode(Number.parseInt(digits, 16));
2312
2585
  }
2586
+ countAllCaptures() {
2587
+ let count = 0;
2588
+ let escaped = false;
2589
+ let characterClass = false;
2590
+ for (let index = 0; index < this.source.length; index++) {
2591
+ this.guard.work(1);
2592
+ const character = this.source[index];
2593
+ if (escaped) escaped = false;
2594
+ else if (character === "\\") escaped = true;
2595
+ else if (character === "[") characterClass = true;
2596
+ else if (character === "]") characterClass = false;
2597
+ else if (!characterClass && character === "(") {
2598
+ const named = this.source[index + 1] === "?" && this.source[index + 2] === "<" && this.source[index + 3] !== "=" && this.source[index + 3] !== "!";
2599
+ if (named) this.hasNamedCaptures = true;
2600
+ if (named || this.source[index + 1] !== "?") count++;
2601
+ }
2602
+ }
2603
+ return count;
2604
+ }
2605
+ parseGroupName(start) {
2606
+ let name = "";
2607
+ while (!this.atEnd() && this.peek() !== ">") {
2608
+ let character = this.take();
2609
+ if (character === "\\") {
2610
+ if (this.take() !== "u") this.fail("Invalid group name escape", start);
2611
+ if (this.peek() === "{") {
2612
+ this.position++;
2613
+ const begin = this.position;
2614
+ while (!this.atEnd() && this.peek() !== "}") this.position++;
2615
+ this.guard.allocate(this.position - begin);
2616
+ const digits = this.source.slice(begin, this.position);
2617
+ const point = Number.parseInt(digits, 16);
2618
+ if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
2619
+ this.fail("Invalid group name escape", start);
2620
+ character = String.fromCodePoint(point);
2621
+ } else character = this.parseHexEscape(4, "Unicode", start);
2622
+ }
2623
+ this.guard.allocate(character.length);
2624
+ name += character;
2625
+ }
2626
+ if (this.take() !== ">" || name.length === 0) this.fail("Invalid group name", start);
2627
+ let first = true;
2628
+ for (const character of name) {
2629
+ this.guard.work(1);
2630
+ if (!(first ? groupNameStart : groupNamePart).test(character)) this.fail("Invalid group name", start);
2631
+ first = false;
2632
+ }
2633
+ return name;
2634
+ }
2635
+ validateNamedGroups(node) {
2636
+ this.guard.work(1);
2637
+ this.guard.allocate(1);
2638
+ const names = /* @__PURE__ */ new Set();
2639
+ if (node.type === "namedBackreference" && !Object.hasOwn(this.namedGroups, node.name))
2640
+ this.fail("Unknown named backreference");
2641
+ if (node.type === "group" && node.name !== void 0) names.add(node.name);
2642
+ const children = node.type === "sequence" ? node.elements : node.type === "alternation" ? node.alternatives : node.type === "group" || node.type === "quantifier" || node.type === "lookahead" || node.type === "lookbehind" ? [node.body] : [];
2643
+ for (const child of children) {
2644
+ for (const name of this.validateNamedGroups(child)) {
2645
+ this.guard.work(1);
2646
+ if (names.has(name) && node.type !== "alternation") this.fail("Duplicate capture group name");
2647
+ this.guard.allocate(1);
2648
+ names.add(name);
2649
+ }
2650
+ }
2651
+ return names;
2652
+ }
2313
2653
  parseQuantifier() {
2314
2654
  const character = this.peek();
2315
2655
  if (character === "*") {
@@ -2339,18 +2679,29 @@ var RegexParser = class {
2339
2679
  }
2340
2680
  if (this.peek() === "}") {
2341
2681
  this.position += 1;
2682
+ if (!Number.isSafeInteger(min)) this.fail("Quantifier is too large", start);
2342
2683
  this.guard.allocate(3);
2343
2684
  return { min, max: min };
2344
2685
  }
2345
2686
  if (this.peek() !== ",") {
2687
+ if (!this.unicode) {
2688
+ this.position = start;
2689
+ return void 0;
2690
+ }
2346
2691
  this.fail("Invalid quantifier", start);
2347
2692
  }
2348
2693
  this.position += 1;
2349
2694
  const max = this.parseDecimal();
2350
2695
  if (this.peek() !== "}") {
2696
+ if (!this.unicode) {
2697
+ this.position = start;
2698
+ return void 0;
2699
+ }
2351
2700
  this.fail("Unterminated quantifier", start);
2352
2701
  }
2353
2702
  this.position += 1;
2703
+ if (!Number.isSafeInteger(min) || max !== void 0 && !Number.isSafeInteger(max))
2704
+ this.fail("Quantifier is too large", start);
2354
2705
  if (max !== void 0 && min > max) {
2355
2706
  this.fail("Quantifier range is out of order", start);
2356
2707
  }
@@ -2367,11 +2718,7 @@ var RegexParser = class {
2367
2718
  }
2368
2719
  this.guard.allocate(this.position - start);
2369
2720
  this.guard.work(this.position - start);
2370
- const value = Number(this.source.slice(start, this.position));
2371
- if (!Number.isSafeInteger(value)) {
2372
- this.fail("Quantifier is too large", start);
2373
- }
2374
- return value;
2721
+ return Number(this.source.slice(start, this.position));
2375
2722
  }
2376
2723
  peek() {
2377
2724
  return this.source[this.position] ?? "";
@@ -2381,6 +2728,12 @@ var RegexParser = class {
2381
2728
  this.position += 1;
2382
2729
  return character;
2383
2730
  }
2731
+ takeCharacter() {
2732
+ if (!this.unicode || this.atEnd()) return this.take();
2733
+ const character = String.fromCodePoint(this.source.codePointAt(this.position));
2734
+ this.position += character.length;
2735
+ return character;
2736
+ }
2384
2737
  atEnd() {
2385
2738
  return this.position >= this.source.length;
2386
2739
  }
@@ -2391,16 +2744,24 @@ var RegexParser = class {
2391
2744
  function parseFlags(flags, guard) {
2392
2745
  guard.allocate(10);
2393
2746
  const parsed = {
2747
+ hasIndices: false,
2394
2748
  global: false,
2749
+ sticky: false,
2750
+ unicode: false,
2751
+ unicodeSets: false,
2395
2752
  ignoreCase: false,
2396
2753
  multiline: false,
2397
2754
  dotAll: false
2398
2755
  };
2399
2756
  const names = {
2757
+ d: "hasIndices",
2400
2758
  g: "global",
2401
2759
  i: "ignoreCase",
2402
2760
  m: "multiline",
2403
- s: "dotAll"
2761
+ s: "dotAll",
2762
+ y: "sticky",
2763
+ u: "unicode",
2764
+ v: "unicodeSets"
2404
2765
  };
2405
2766
  for (let position = 0; position < flags.length; position += 1) {
2406
2767
  guard.work(1);
@@ -2414,6 +2775,7 @@ function parseFlags(flags, guard) {
2414
2775
  }
2415
2776
  parsed[name] = true;
2416
2777
  }
2778
+ if (parsed.unicode && parsed.unicodeSets) throw new SyntaxError("Unicode flags u and v cannot be combined");
2417
2779
  return parsed;
2418
2780
  }
2419
2781
  function isDecimalDigit2(character) {
@@ -5467,6 +5829,7 @@ function findImportMetaAssignmentInNode(node) {
5467
5829
  case "BooleanLiteral":
5468
5830
  case "NullLiteral":
5469
5831
  case "NumericLiteral":
5832
+ case "BigIntLiteral":
5470
5833
  case "StringLiteral":
5471
5834
  case "ThisExpression":
5472
5835
  case "RegexLiteral":
@@ -5545,6 +5908,12 @@ function isYieldArgumentTerminator(value) {
5545
5908
  return value === ";" || value === "}" || value === ")" || value === "]" || value === ",";
5546
5909
  }
5547
5910
  function createNumericLiteral(token) {
5911
+ if (token.value.endsWith("n")) return {
5912
+ type: "BigIntLiteral",
5913
+ raw: token.value,
5914
+ value: token.value.slice(0, -1).replaceAll("_", ""),
5915
+ span: createTokenSpan(token)
5916
+ };
5548
5917
  return {
5549
5918
  type: "NumericLiteral",
5550
5919
  raw: token.value,
@@ -6723,9 +7092,13 @@ function isSandboxRegExpIterator(value) {
6723
7092
  return typeof value === "object" && value !== null && states2.has(value);
6724
7093
  }
6725
7094
  function restoreSandboxRegExpIterator(state, target = /* @__PURE__ */ Object.create(null)) {
7095
+ if ((state.global !== void 0 || state.unicode !== void 0) && (typeof state.global !== "boolean" || typeof state.unicode !== "boolean"))
7096
+ throw new TypeError("Invalid RegExp iterator modes.");
7097
+ if (state.matcher !== void 0 && (state.matcher === null || typeof state.matcher !== "object"))
7098
+ throw new TypeError("Invalid RegExp iterator matcher.");
6726
7099
  if (!state.exhausted && (state.matcher === void 0 || state.input === void 0))
6727
7100
  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 });
7101
+ states2.set(target, state.exhausted ? { ...state, matcher: void 0, input: void 0, exhausted: true } : { ...state });
6729
7102
  return target;
6730
7103
  }
6731
7104
  function regexpIteratorState(value) {
@@ -6741,15 +7114,17 @@ var numberValue = Number.prototype.valueOf;
6741
7114
  var stringValue = String.prototype.valueOf;
6742
7115
  var booleanValue = Boolean.prototype.valueOf;
6743
7116
  var symbolValue = Symbol.prototype.valueOf;
7117
+ var bigintValue = BigInt.prototype.valueOf;
6744
7118
  function nativeBoxedValue(value) {
6745
7119
  if (types3.isNumberObject(value)) return Reflect.apply(numberValue, value, []);
6746
7120
  if (types3.isStringObject(value)) return Reflect.apply(stringValue, value, []);
6747
7121
  if (types3.isBooleanObject(value)) return Reflect.apply(booleanValue, value, []);
6748
7122
  if (types3.isSymbolObject(value)) return Reflect.apply(symbolValue, value, []);
7123
+ if (types3.isBigIntObject(value)) return Reflect.apply(bigintValue, value, []);
6749
7124
  return void 0;
6750
7125
  }
6751
7126
  function createSandboxBox(value) {
6752
- if (typeof value !== "number" && typeof value !== "string" && typeof value !== "boolean" && typeof value !== "symbol")
7127
+ if (typeof value !== "number" && typeof value !== "bigint" && typeof value !== "string" && typeof value !== "boolean" && typeof value !== "symbol")
6753
7128
  throw new TypeError("Invalid boxed primitive payload.");
6754
7129
  const box = Object(value);
6755
7130
  Object.setPrototypeOf(box, null);
@@ -7244,6 +7619,18 @@ async function flushPromiseJobs() {
7244
7619
  // packages/safe-js/src/interp/promise-replay.ts
7245
7620
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
7246
7621
 
7622
+ // packages/safe-js/src/snapshot/bigint.ts
7623
+ function validateBigIntData(value) {
7624
+ if (typeof value !== "string" || value.length === 0) throw new TypeError("Invalid BigInt snapshot value.");
7625
+ if (value === "0") return;
7626
+ const start = value[0] === "-" ? 1 : 0;
7627
+ if (start === value.length || value[start] === "0") throw new TypeError("Invalid BigInt snapshot value.");
7628
+ for (let index = start; index < value.length; index++) {
7629
+ const code = value.charCodeAt(index);
7630
+ if (code < 48 || code > 57) throw new TypeError("Invalid BigInt snapshot value.");
7631
+ }
7632
+ }
7633
+
7247
7634
  // packages/safe-js/src/interp/symbols.ts
7248
7635
  var wellKnownSymbols = Object.freeze({
7249
7636
  iterator: Symbol.iterator,
@@ -7634,6 +8021,9 @@ function getSandboxPrototype(value, budget) {
7634
8021
  function hasExplicitSandboxPrototype(value) {
7635
8022
  return prototypes.has(value);
7636
8023
  }
8024
+ function hasNullObjectPrototype(value) {
8025
+ return prototypes.get(value) === null && !Array.isArray(value) && !isSandboxClosure(value) && !isSandboxRegex(value);
8026
+ }
7637
8027
  function getSandboxPropertyDescriptor(value, key, budget) {
7638
8028
  const hostProperties = isSandboxClosure(value) ? value.properties : void 0;
7639
8029
  if (isSandboxClosure(value) && !isGuestClosure(value))
@@ -7715,7 +8105,7 @@ function hasGuestObjectState(value) {
7715
8105
  const intrinsicUnchanged = intrinsicConstructors.get(value);
7716
8106
  if (intrinsicUnchanged !== void 0) return !intrinsicUnchanged();
7717
8107
  if (isLiveCapability(value)) return true;
7718
- if (functionProperties.has(value) || prototypes.has(value)) return true;
8108
+ if (functionProperties.has(value) || prototypes.has(value) && !hasNullObjectPrototype(value)) return true;
7719
8109
  if (isSandboxBox(value) || isSandboxDate(value)) return false;
7720
8110
  return descriptorObjects.has(value) && Object.values(Object.getOwnPropertyDescriptors(value)).some(
7721
8111
  (descriptor) => !descriptor.enumerable || !descriptor.configurable || !descriptor.writable
@@ -7910,6 +8300,7 @@ function createDumpFile(snapshot) {
7910
8300
  return dumped;
7911
8301
  }
7912
8302
  function serializeDumpValue(value, path, state) {
8303
+ if (typeof value === "bigint") return { kind: "bigint", value: String(value) };
7913
8304
  if (typeof value === "symbol") return serializeSymbol(value, state.heapIds, state.heap);
7914
8305
  if (value === null || typeof value === "string" || typeof value === "boolean") {
7915
8306
  return value;
@@ -7956,11 +8347,14 @@ function serializeHeapReference(value, path, state) {
7956
8347
  if (isSandboxRegExpIterator(value)) {
7957
8348
  const snapshot = regexpIteratorState(value);
7958
8349
  const matcher = snapshot.matcher;
8350
+ const serializedMatcher = snapshot.global === void 0 && isSandboxRegex(matcher) ? { kind: "regex", source: matcher.source, flags: matcher.flags, lastIndex: Number(matcher.lastIndex) } : serializeDumpValue(matcher, `${path}.<matcher>`, state);
8351
+ if (serializedMatcher === SKIP_VALUE) throw new TypeError("Unsupported RegExp iterator matcher in public dump.");
7959
8352
  const entries = /* @__PURE__ */ Object.create(null);
7960
8353
  state.heap[String(id)] = {
7961
8354
  kind: "regexp-iterator",
7962
8355
  exhausted: snapshot.exhausted,
7963
- matcher: matcher === void 0 ? { kind: "undefined" } : { kind: "regex", source: matcher.source, flags: matcher.flags, lastIndex: Number(matcher.lastIndex) },
8356
+ matcher: serializedMatcher,
8357
+ ...snapshot.global === void 0 ? {} : { global: snapshot.global, unicode: snapshot.unicode },
7964
8358
  input: snapshot.input ?? { kind: "undefined" },
7965
8359
  entries,
7966
8360
  symbolEntries: serializeSymbolProperties(value, (entry) => {
@@ -8033,6 +8427,7 @@ function serializeHeapReference(value, path, state) {
8033
8427
  });
8034
8428
  state.heap[String(id)] = {
8035
8429
  kind: "object",
8430
+ ...hasNullObjectPrototype(value) ? { sandboxNullPrototype: true } : {},
8036
8431
  entries: serializeObjectEntries(value, path, state),
8037
8432
  ...symbolEntries.length === 0 ? {} : { symbolEntries },
8038
8433
  ...errorType === void 0 ? {} : { errorType }
@@ -8066,7 +8461,7 @@ function indexHeapContainers(snapshot) {
8066
8461
  const heapIds = /* @__PURE__ */ new Map();
8067
8462
  let nextId = 1;
8068
8463
  for (const [value, stat2] of stats.entries()) {
8069
- 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)) {
8464
+ if (stat2.count > 1 || stat2.cyclic || hasNullObjectPrototype(value) || 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)) {
8070
8465
  heapIds.set(value, nextId);
8071
8466
  nextId += 1;
8072
8467
  }
@@ -8252,6 +8647,8 @@ function validateDumpHeap(root, state) {
8252
8647
  continue;
8253
8648
  }
8254
8649
  if (entry.kind === "object") {
8650
+ if (Object.hasOwn(entry, "sandboxNullPrototype") && entry.sandboxNullPrototype !== true)
8651
+ fail("invalidValue", `${path}.sandboxNullPrototype`, "invalid object prototype");
8255
8652
  requireRecord(entry.entries, `${path}.entries`);
8256
8653
  continue;
8257
8654
  }
@@ -8335,6 +8732,14 @@ function validateValue(value, path, depth, state) {
8335
8732
  }
8336
8733
  function validateTaggedValue(record2, path, state) {
8337
8734
  switch (record2.kind) {
8735
+ case "bigint":
8736
+ requireString(record2.value, `${path}.value`, state.limits);
8737
+ try {
8738
+ validateBigIntData(record2.value);
8739
+ } catch {
8740
+ fail("invalidValue", `${path}.value`, "invalid BigInt value");
8741
+ }
8742
+ return;
8338
8743
  case "undefined":
8339
8744
  return;
8340
8745
  case "number":
@@ -8372,7 +8777,11 @@ function validateTaggedValue(record2, path, state) {
8372
8777
  return;
8373
8778
  case "array":
8374
8779
  case "arguments":
8780
+ return;
8375
8781
  case "object":
8782
+ if (Object.hasOwn(record2, "sandboxNullPrototype") && record2.sandboxNullPrototype !== true)
8783
+ fail("invalidValue", `${path}.sandboxNullPrototype`, "invalid object prototype");
8784
+ return;
8376
8785
  case "map":
8377
8786
  case "set":
8378
8787
  case "collection-iterator":
@@ -8442,6 +8851,8 @@ function validateHeapValue(value, path, state, heap) {
8442
8851
  }
8443
8852
  if (record2.kind === "set") requireArray(record2.values, `${path}.values`, state);
8444
8853
  if (record2.kind === "regexp-iterator") {
8854
+ if ((record2.global !== void 0 || record2.unicode !== void 0) && (typeof record2.global !== "boolean" || typeof record2.unicode !== "boolean"))
8855
+ fail("invalidValue", path, "invalid RegExp iterator modes");
8445
8856
  if (typeof record2.exhausted !== "boolean") fail("invalidValue", `${path}.exhausted`, "invalid iterator exhaustion");
8446
8857
  if (!Object.hasOwn(record2, "matcher") || !Object.hasOwn(record2, "input")) fail("invalidValue", path, "missing RegExp iterator state");
8447
8858
  requireRecord(record2.entries, `${path}.entries`);
@@ -8495,6 +8906,14 @@ function validateBoxedRecord(record2, path, heap) {
8495
8906
  const value = record2.value;
8496
8907
  if (typeof value === "number" || typeof value === "string" || typeof value === "boolean") return;
8497
8908
  const number = requireRecord(value, `${path}.value`);
8909
+ if (number.kind === "bigint") {
8910
+ try {
8911
+ validateBigIntData(number.value);
8912
+ } catch {
8913
+ fail("invalidValue", `${path}.value`, "invalid boxed BigInt payload");
8914
+ }
8915
+ return;
8916
+ }
8498
8917
  if (number.kind === "ref") {
8499
8918
  const id = requireSafeInteger(number.id, `${path}.value.id`, 1);
8500
8919
  const target = requireRecord(heap[String(id)], `${path}.value`);
@@ -9290,15 +9709,17 @@ async function withRunResources(signal, execute) {
9290
9709
 
9291
9710
  // packages/safe-js/src/interp/regex/engine.ts
9292
9711
  function matchRegex(pattern, input, lastIndex = 0) {
9293
- const startIndex = pattern.flags.global ? normalizeLastIndex(lastIndex) : 0;
9712
+ const startIndex = pattern.flags.global || pattern.flags.sticky ? normalizeLastIndex(lastIndex) : 0;
9294
9713
  return matchRegexFrom(pattern, input, startIndex);
9295
9714
  }
9296
9715
  function matchRegexFrom(pattern, input, startIndex) {
9297
9716
  if (startIndex > input.length) {
9298
9717
  return null;
9299
9718
  }
9300
- for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
9301
- const context = { input, flags: pattern.flags, steps: 0 };
9719
+ const unicode = pattern.flags.unicode || pattern.flags.unicodeSets;
9720
+ if (unicode && startIndex > 0 && startIndex < input.length && input.charCodeAt(startIndex) >= 56320 && input.charCodeAt(startIndex) <= 57343 && input.charCodeAt(startIndex - 1) >= 55296 && input.charCodeAt(startIndex - 1) <= 56319) startIndex--;
9721
+ for (let attempt = startIndex; attempt <= input.length; attempt = advanceStringIndex(input, attempt, unicode)) {
9722
+ const context = { input, flags: pattern.flags, groups: pattern.groups, direction: 1, work: { steps: 0 } };
9302
9723
  charge(context);
9303
9724
  const initialState = {
9304
9725
  position: attempt,
@@ -9306,25 +9727,59 @@ function matchRegexFrom(pattern, input, startIndex) {
9306
9727
  };
9307
9728
  const result = matchNode(pattern.body, initialState, context).next();
9308
9729
  if (!result.done) {
9309
- return toRegexMatch(input, attempt, result.value);
9730
+ return toRegexMatch(input, attempt, result.value, pattern.flags.hasIndices, pattern.groups);
9310
9731
  }
9732
+ if (pattern.flags.sticky) break;
9311
9733
  }
9312
9734
  return null;
9313
9735
  }
9314
9736
  function* matchNode(node, state, context) {
9315
9737
  charge(context);
9738
+ const unicode = context.flags.unicode || context.flags.unicodeSets;
9739
+ const character = readCharacter(context.input, state.position, context.direction, unicode);
9316
9740
  switch (node.type) {
9317
9741
  case "empty":
9318
9742
  yield state;
9319
9743
  return;
9320
9744
  case "literal":
9321
- if (charactersEqual(context.input[state.position], node.value, context.flags.ignoreCase)) {
9322
- yield { ...state, position: state.position + 1 };
9745
+ if (charactersEqual(character, node.value, context.flags.ignoreCase, unicode)) {
9746
+ yield { ...state, position: state.position + context.direction * character.length };
9323
9747
  }
9324
9748
  return;
9749
+ case "backreference":
9750
+ case "namedBackreference": {
9751
+ let capture;
9752
+ if (node.type === "backreference") capture = state.captures[node.index - 1];
9753
+ else {
9754
+ for (const index of context.groups?.[node.name] ?? []) {
9755
+ charge(context);
9756
+ if (state.captures[index - 1] !== void 0) {
9757
+ capture = state.captures[index - 1];
9758
+ break;
9759
+ }
9760
+ }
9761
+ }
9762
+ if (capture === void 0) {
9763
+ yield state;
9764
+ return;
9765
+ }
9766
+ let position = state.position;
9767
+ let reference = context.direction === 1 ? capture.start : capture.end;
9768
+ const end = context.direction === 1 ? capture.end : capture.start;
9769
+ while (reference !== end) {
9770
+ charge(context);
9771
+ const expected = readCharacter(context.input, reference, context.direction, unicode);
9772
+ const actual = readCharacter(context.input, position, context.direction, unicode);
9773
+ if (!charactersEqual(actual, expected, context.flags.ignoreCase, unicode)) return;
9774
+ reference += context.direction * expected.length;
9775
+ position += context.direction * actual.length;
9776
+ }
9777
+ yield { ...state, position };
9778
+ return;
9779
+ }
9325
9780
  case "dot":
9326
- if (state.position < context.input.length && (context.flags.dotAll || !isLineTerminator(context.input[state.position]))) {
9327
- yield { ...state, position: state.position + 1 };
9781
+ if (character !== void 0 && (context.flags.dotAll || !isLineTerminator(character))) {
9782
+ yield { ...state, position: state.position + context.direction * character.length };
9328
9783
  }
9329
9784
  return;
9330
9785
  case "anchor":
@@ -9333,17 +9788,24 @@ function* matchNode(node, state, context) {
9333
9788
  }
9334
9789
  return;
9335
9790
  case "wordBoundary": {
9336
- const previousWord = state.position > 0 && isWordCharacter(context.input[state.position - 1]);
9337
- const nextWord = state.position < context.input.length && isWordCharacter(context.input[state.position]);
9791
+ const previousWord = state.position > 0 && matchesCharacterClassItem(context.input[state.position - 1], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, unicode);
9792
+ const nextWord = state.position < context.input.length && matchesCharacterClassItem(context.input[state.position], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, unicode);
9338
9793
  if (previousWord !== nextWord !== node.negated) {
9339
9794
  yield state;
9340
9795
  }
9341
9796
  return;
9342
9797
  }
9343
9798
  case "characterClass": {
9344
- const character = context.input[state.position];
9345
- if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context.flags.ignoreCase)) {
9346
- yield { ...state, position: state.position + 1 };
9799
+ if (context.flags.unicodeSets) {
9800
+ const lengths = [...matchUnicodeSet(node, state.position, context)].sort((a, b) => b - a);
9801
+ for (const length of lengths) {
9802
+ charge(context);
9803
+ yield { ...state, position: state.position + context.direction * length };
9804
+ }
9805
+ return;
9806
+ }
9807
+ if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context)) {
9808
+ yield { ...state, position: state.position + context.direction * character.length };
9347
9809
  }
9348
9810
  return;
9349
9811
  }
@@ -9355,14 +9817,30 @@ function* matchNode(node, state, context) {
9355
9817
  yield* matchNode(alternative, cloneState(state), context);
9356
9818
  }
9357
9819
  return;
9820
+ case "lookahead":
9821
+ case "lookbehind": {
9822
+ const result = matchNode(node.body, cloneState(state), {
9823
+ ...context,
9824
+ direction: node.type === "lookbehind" ? -1 : 1
9825
+ }).next();
9826
+ if (node.negated) {
9827
+ if (result.done) yield state;
9828
+ } else if (!result.done) {
9829
+ yield { position: state.position, captures: result.value.captures };
9830
+ }
9831
+ return;
9832
+ }
9358
9833
  case "group":
9359
- for (const result of matchNode(node.body, cloneState(state), context)) {
9834
+ for (const result of matchNode(node.body, cloneState(state), node.modifiers === void 0 ? context : {
9835
+ ...context,
9836
+ flags: { ...context.flags, ...node.modifiers }
9837
+ })) {
9360
9838
  if (!node.capturing || node.index === void 0) {
9361
9839
  yield result;
9362
9840
  continue;
9363
9841
  }
9364
9842
  const captures = result.captures.slice();
9365
- captures[node.index - 1] = { start: state.position, end: result.position };
9843
+ captures[node.index - 1] = { start: Math.min(state.position, result.position), end: Math.max(state.position, result.position) };
9366
9844
  yield { position: result.position, captures };
9367
9845
  }
9368
9846
  return;
@@ -9376,7 +9854,8 @@ function* matchSequence(elements, index, state, context) {
9376
9854
  yield state;
9377
9855
  return;
9378
9856
  }
9379
- for (const result of matchNode(elements[index], state, context)) {
9857
+ const element = elements[context.direction === 1 ? index : elements.length - 1 - index];
9858
+ for (const result of matchNode(element, state, context)) {
9380
9859
  yield* matchSequence(elements, index + 1, result, context);
9381
9860
  }
9382
9861
  }
@@ -9412,11 +9891,28 @@ function matchesAnchor(kind, position, context) {
9412
9891
  }
9413
9892
  return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
9414
9893
  }
9415
- function matchesCharacterClass(character, items, negated, ignoreCase) {
9416
- const matched = items.some((item) => matchesCharacterClassItem(character, item, ignoreCase));
9894
+ function matchesCharacterClass(character, items, negated, context) {
9895
+ const matched = items.some((item) => {
9896
+ if (context.flags.unicode) charge(context);
9897
+ return matchesCharacterClassItem(character, item, context.flags.ignoreCase, context.flags.unicode);
9898
+ });
9417
9899
  return negated ? !matched : matched;
9418
9900
  }
9419
- function matchesCharacterClassItem(character, item, ignoreCase) {
9901
+ function matchesCharacterClassItem(character, item, ignoreCase, unicode, unicodeSets = false) {
9902
+ if (item.type === "strings" || item.type === "set") return false;
9903
+ if (unicode) {
9904
+ const hex = (value) => `\\u{${value.codePointAt(0).toString(16)}}`;
9905
+ let atom;
9906
+ if (item.type === "character") atom = hex(item.value);
9907
+ else if (item.type === "range") atom = `[${hex(item.from)}-${hex(item.to)}]`;
9908
+ else if (item.type === "property") atom = `\\${item.negated ? "P" : "p"}{${item.value}}`;
9909
+ else {
9910
+ const kind = item.kind === "digit" ? "d" : item.kind === "word" ? "w" : "s";
9911
+ atom = `\\${item.negated ? kind.toUpperCase() : kind}`;
9912
+ }
9913
+ return new RegExp(`^(?:${atom})$`, (ignoreCase ? "i" : "") + (unicodeSets ? "v" : "u")).test(character);
9914
+ }
9915
+ if (item.type === "property") return false;
9420
9916
  if (item.type === "character") {
9421
9917
  return charactersEqual(character, item.value, ignoreCase);
9422
9918
  }
@@ -9430,22 +9926,102 @@ function matchesCharacterClassItem(character, item, ignoreCase) {
9430
9926
  if (!ignoreCase) {
9431
9927
  return false;
9432
9928
  }
9433
- const foldedCandidate = foldCharacter(character, true).charCodeAt(0);
9434
- const foldedFrom = foldCharacter(item.from, true).charCodeAt(0);
9435
- const foldedTo = foldCharacter(item.to, true).charCodeAt(0);
9436
- return foldedCandidate >= foldedFrom && foldedCandidate <= foldedTo;
9929
+ return new RegExp(`^[\\u${from.toString(16).padStart(4, "0")}-\\u${to.toString(16).padStart(4, "0")}]$`, "i").test(character);
9437
9930
  }
9438
9931
  const matched = item.kind === "digit" ? isDigit(character) : item.kind === "word" ? isWordCharacter(character) : isSpaceCharacter(character);
9439
9932
  return item.negated ? !matched : matched;
9440
9933
  }
9441
- function toRegexMatch(input, start, state) {
9442
- return {
9934
+ function matchUnicodeSet(set, position, context) {
9935
+ charge(context);
9936
+ let lengths = /* @__PURE__ */ new Set();
9937
+ for (let index = 0; index < set.items.length; index++) {
9938
+ const next = matchUnicodeSetItem(set.items[index], position, context);
9939
+ if (index === 0) lengths = next;
9940
+ else if (set.operation === void 0) {
9941
+ for (const length of next) {
9942
+ charge(context);
9943
+ lengths.add(length);
9944
+ }
9945
+ } else {
9946
+ for (const length of lengths) {
9947
+ charge(context);
9948
+ if (set.operation === "intersection" ? !next.has(length) : next.has(length)) lengths.delete(length);
9949
+ }
9950
+ }
9951
+ }
9952
+ if (set.negated) {
9953
+ const character = readCharacter(context.input, position, context.direction, true);
9954
+ return new Set(character !== void 0 && !lengths.has(character.length) ? [character.length] : []);
9955
+ }
9956
+ return lengths;
9957
+ }
9958
+ function matchUnicodeSetItem(item, position, context) {
9959
+ charge(context);
9960
+ if (item.type === "set") return matchUnicodeSet(item.value, position, context);
9961
+ const lengths = /* @__PURE__ */ new Set();
9962
+ if (item.type === "strings") {
9963
+ for (const value of item.values) {
9964
+ charge(context);
9965
+ let reference = context.direction === 1 ? 0 : value.length;
9966
+ let cursor = position;
9967
+ const end = context.direction === 1 ? value.length : 0;
9968
+ while (reference !== end) {
9969
+ charge(context);
9970
+ const expected = readCharacter(value, reference, context.direction, true);
9971
+ const actual = readCharacter(context.input, cursor, context.direction, true);
9972
+ if (!charactersEqual(actual, expected, context.flags.ignoreCase, true)) break;
9973
+ reference += context.direction * expected.length;
9974
+ cursor += context.direction * actual.length;
9975
+ }
9976
+ if (reference === end) lengths.add(Math.abs(cursor - position));
9977
+ }
9978
+ return lengths;
9979
+ }
9980
+ if (item.type === "property" && item.strings) {
9981
+ const atom = `\\p{${item.value}}`;
9982
+ const flags = (context.flags.ignoreCase ? "i" : "") + "v";
9983
+ const matcher = new RegExp(context.direction === 1 ? atom : `(?<=(${atom}))`, flags + "y");
9984
+ matcher.lastIndex = position;
9985
+ const match = matcher.exec(context.input);
9986
+ if (match === null) return lengths;
9987
+ const longest = context.direction === 1 ? match[0] : match[1];
9988
+ const member = new RegExp(`^(?:${atom})$`, flags);
9989
+ let consumed = 0;
9990
+ while (consumed < longest.length) {
9991
+ charge(context);
9992
+ const cursor = context.direction === 1 ? consumed : longest.length - consumed;
9993
+ consumed += readCharacter(longest, cursor, context.direction, true).length;
9994
+ const candidate = context.direction === 1 ? longest.slice(0, consumed) : longest.slice(longest.length - consumed);
9995
+ if (member.test(candidate)) lengths.add(consumed);
9996
+ }
9997
+ return lengths;
9998
+ }
9999
+ const character = readCharacter(context.input, position, context.direction, true);
10000
+ if (character !== void 0 && matchesCharacterClassItem(character, item, context.flags.ignoreCase, true, true))
10001
+ lengths.add(character.length);
10002
+ return lengths;
10003
+ }
10004
+ function toRegexMatch(input, start, state, hasIndices, groups) {
10005
+ const match = {
9443
10006
  index: start,
9444
10007
  text: input.slice(start, state.position),
9445
10008
  captures: state.captures.map(
9446
10009
  (capture) => capture === void 0 ? void 0 : input.slice(capture.start, capture.end)
9447
10010
  )
9448
10011
  };
10012
+ if (hasIndices) {
10013
+ match.indices = [[start, state.position], ...state.captures.map((capture) => capture === void 0 ? void 0 : [capture.start, capture.end])];
10014
+ }
10015
+ if (groups !== void 0) {
10016
+ match.groups = /* @__PURE__ */ Object.create(null);
10017
+ if (hasIndices) match.indicesGroups = /* @__PURE__ */ Object.create(null);
10018
+ for (const [name, indices] of Object.entries(groups)) {
10019
+ const index = indices.find((index2) => state.captures[index2 - 1] !== void 0);
10020
+ match.groups[name] = index === void 0 ? void 0 : match.captures[index - 1];
10021
+ if (match.indicesGroups !== void 0) match.indicesGroups[name] = index === void 0 ? void 0 : match.indices[index];
10022
+ }
10023
+ }
10024
+ return match;
9449
10025
  }
9450
10026
  function cloneState(state) {
9451
10027
  return { position: state.position, captures: state.captures.slice() };
@@ -9475,13 +10051,13 @@ function clearNodeCaptures(node, captures) {
9475
10051
  }
9476
10052
  return;
9477
10053
  }
9478
- if (node.type === "quantifier") {
10054
+ if (node.type === "quantifier" || node.type === "lookahead" || node.type === "lookbehind") {
9479
10055
  clearNodeCaptures(node.body, captures);
9480
10056
  }
9481
10057
  }
9482
10058
  function charge(context) {
9483
- context.steps += 1;
9484
- allocateRegexSteps(context.steps);
10059
+ context.work.steps += 1;
10060
+ allocateRegexSteps(context.work.steps);
9485
10061
  }
9486
10062
  function normalizeLastIndex(lastIndex) {
9487
10063
  if (Number.isNaN(lastIndex) || lastIndex <= 0) {
@@ -9489,9 +10065,20 @@ function normalizeLastIndex(lastIndex) {
9489
10065
  }
9490
10066
  return Math.min(Math.floor(lastIndex), Number.MAX_SAFE_INTEGER);
9491
10067
  }
9492
- function charactersEqual(left, right, ignoreCase) {
10068
+ function charactersEqual(left, right, ignoreCase, unicode = false) {
10069
+ if (unicode && ignoreCase && left !== void 0)
10070
+ return new RegExp(`^\\u{${right.codePointAt(0).toString(16)}}$`, "iu").test(left);
9493
10071
  return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
9494
10072
  }
10073
+ function advanceStringIndex(input, index, unicode) {
10074
+ return index + (unicode && (input.codePointAt(index) ?? 0) > 65535 ? 2 : 1);
10075
+ }
10076
+ function readCharacter(input, position, direction, unicode) {
10077
+ let index = direction === 1 ? position : position - 1;
10078
+ if (index < 0 || index >= input.length) return void 0;
10079
+ if (unicode && direction === -1 && index > 0 && input.charCodeAt(index) >= 56320 && input.charCodeAt(index) <= 57343 && input.charCodeAt(index - 1) >= 55296 && input.charCodeAt(index - 1) <= 56319) index--;
10080
+ return unicode ? String.fromCodePoint(input.codePointAt(index)) : input[index];
10081
+ }
9495
10082
  function foldCharacter(character, ignoreCase) {
9496
10083
  if (!ignoreCase) {
9497
10084
  return character;
@@ -9518,6 +10105,69 @@ function isLineTerminator(character) {
9518
10105
  return character === "\n" || character === "\r" || character === "\u2028" || character === "\u2029";
9519
10106
  }
9520
10107
 
10108
+ // packages/safe-js/src/interp/bigint-operators.ts
10109
+ function bigIntOperation(operator, left, right, budget) {
10110
+ if (operator === ">>>") throw new TypeError("BigInts have no unsigned right shift.");
10111
+ if ((operator === "/" || operator === "%") && right === 0n) throw new RangeError("Division by zero.");
10112
+ if (operator === "**" && right < 0n) throw new RangeError("BigInt exponent must be nonnegative.");
10113
+ const leftSize = left.toString(16).length;
10114
+ const rightSize = right.toString(16).length;
10115
+ budget.visitNode(leftSize + rightSize);
10116
+ let size = Math.max(leftSize, rightSize) + 1;
10117
+ let work = leftSize + rightSize;
10118
+ if (operator === "*") {
10119
+ size = leftSize + rightSize;
10120
+ work = leftSize * rightSize;
10121
+ } else if (operator === "/" || operator === "%") {
10122
+ size = leftSize;
10123
+ work = leftSize * rightSize;
10124
+ } else if (operator === "**") {
10125
+ if (right === 0n) return 1n;
10126
+ if (left === 0n || left === 1n) return left;
10127
+ if (left === -1n) return right % 2n === 0n ? 1n : -1n;
10128
+ size = leftSize * Number(right);
10129
+ work = size * size;
10130
+ } else if (operator === "<<" || operator === ">>") {
10131
+ if (left === 0n) return 0n;
10132
+ const shift = operator === "<<" ? right : -right;
10133
+ size = shift > 0n ? leftSize + Math.ceil(Number(shift) / 4) : leftSize;
10134
+ work = size + rightSize;
10135
+ }
10136
+ if (!Number.isSafeInteger(size) || !Number.isSafeInteger(work))
10137
+ throw new SandboxError({ budget: "dataSize", current: Infinity, limit: Number.MAX_SAFE_INTEGER });
10138
+ budget.visitNode(work);
10139
+ const allocation = {};
10140
+ budget.setRetainedDataUsage(allocation, size);
10141
+ try {
10142
+ switch (operator) {
10143
+ case "+":
10144
+ return left + right;
10145
+ case "-":
10146
+ return left - right;
10147
+ case "*":
10148
+ return left * right;
10149
+ case "/":
10150
+ return left / right;
10151
+ case "%":
10152
+ return left % right;
10153
+ case "**":
10154
+ return left ** right;
10155
+ case "&":
10156
+ return left & right;
10157
+ case "|":
10158
+ return left | right;
10159
+ case "^":
10160
+ return left ^ right;
10161
+ case "<<":
10162
+ return left << right;
10163
+ case ">>":
10164
+ return left >> right;
10165
+ }
10166
+ } finally {
10167
+ budget.setRetainedDataUsage(allocation, 0);
10168
+ }
10169
+ }
10170
+
9521
10171
  // packages/safe-js/src/interp/jobs.ts
9522
10172
  import { AsyncLocalStorage as AsyncLocalStorage4 } from "node:async_hooks";
9523
10173
  var activeJob = new AsyncLocalStorage4();
@@ -9693,7 +10343,7 @@ function callNumberMethod(value, methodName, args, budget, context) {
9693
10343
  if (argument !== null && typeof argument === "object") {
9694
10344
  return formatObjectArgument(value, methodName, argument, budget, context);
9695
10345
  }
9696
- return formatNumber(value, methodName, argument === void 0 ? void 0 : Number(argument), budget);
10346
+ return formatNumber(value, methodName, argument === void 0 ? void 0 : +argument, budget);
9697
10347
  }
9698
10348
  async function formatObjectArgument(value, methodName, argument, budget, context) {
9699
10349
  const retainedArgument = {};
@@ -10067,7 +10717,7 @@ function callReplaceLikeMethod(value, methodName, args, budget, callClosure, use
10067
10717
  );
10068
10718
  }
10069
10719
  async function replaceRegex(value, regex, replacement, budget, callClosure, context) {
10070
- if (hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
10720
+ if (getSandboxRegexPattern(regex).groups !== void 0 || hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
10071
10721
  return regexReplace(value, regex, replacement, budget, callClosure, context);
10072
10722
  if (regex.flags.includes("g")) regex.lastIndex = 0;
10073
10723
  const cursor = regex.lastIndex;
@@ -10117,7 +10767,7 @@ async function regexReplace(input, regex, replacementInput, budget, callClosure,
10117
10767
  input = void 0;
10118
10768
  replacement = isSandboxClosure(replacementInput) ? replacementInput : await sandboxString(replacementInput, budget, context);
10119
10769
  replacementInput = void 0;
10120
- if (isSandboxRegex(regex) && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
10770
+ if (isSandboxRegex(regex) && getSandboxRegexPattern(regex).groups === void 0 && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
10121
10771
  release();
10122
10772
  return await replaceRegex(value, regex, replacement, budget, callClosure, context);
10123
10773
  }
@@ -10332,7 +10982,7 @@ function splitNormalized(value, separator, limit, budget, parent) {
10332
10982
  while (result2.length < limit) {
10333
10983
  const match = executeRegex(splitter, value, Number(splitter.lastIndex));
10334
10984
  if (match === null) break;
10335
- if (match.text.length === 0) splitter.lastIndex = match.index + 1;
10985
+ if (match.text.length === 0) splitter.lastIndex = advanceStringIndex(value, match.index, splitter.flags.includes("u") || splitter.flags.includes("v"));
10336
10986
  endedWithZeroWidthMatch = match.text.length === 0 && match.index === value.length;
10337
10987
  if (match.text.length === 0 && (match.index === copiedThrough || match.index === value.length))
10338
10988
  continue;
@@ -10491,7 +11141,7 @@ function callMatchLikeMethod(value, methodName, args, compilation, lastIndex) {
10491
11141
  return match?.index ?? -1;
10492
11142
  }
10493
11143
  if (methodName === "match" && !regex.flags.includes("g"))
10494
- return toMatchArray(executeRegex(regex, value, lastIndex ?? Number(regex.lastIndex)), value);
11144
+ return toMatchArray(executeRegex(regex, value, lastIndex ?? Number(regex.lastIndex)), value, compilation.owner?.budget);
10495
11145
  if (methodName === "match") regex.lastIndex = 0;
10496
11146
  const matcher = methodName === "matchAll" ? createSandboxRegex(regex.source, regex.flags, normalizeLastIndex(lastIndex ?? Number(regex.lastIndex)), compilation) : regex;
10497
11147
  if (methodName === "matchAll")
@@ -10507,7 +11157,7 @@ function collectRegexMatches(regex, value, all, budget, lastIndex = 0) {
10507
11157
  budget?.allocateArrayLength(matches.length + 1);
10508
11158
  matches.push(match);
10509
11159
  lastIndex = match.index + match.text.length;
10510
- if (all && match.text.length === 0) regex.lastIndex = ++lastIndex;
11160
+ if (all && match.text.length === 0) regex.lastIndex = lastIndex = advanceStringIndex(value, lastIndex, regex.flags.includes("u") || regex.flags.includes("v"));
10511
11161
  } while (all);
10512
11162
  return matches;
10513
11163
  }
@@ -10516,10 +11166,10 @@ function splitString(value, separator, limit) {
10516
11166
  return split.call(value, separator, limit);
10517
11167
  }
10518
11168
  function asNumber(value) {
10519
- return Number(value);
11169
+ return +value;
10520
11170
  }
10521
11171
  function asNumberOrUndefined(value) {
10522
- return value === void 0 ? void 0 : Number(value);
11172
+ return value === void 0 ? void 0 : +value;
10523
11173
  }
10524
11174
  function asStringOrUndefined(value) {
10525
11175
  return value === void 0 ? void 0 : String(value);
@@ -10869,7 +11519,7 @@ function createObjectArrayGlobals(options) {
10869
11519
  ),
10870
11520
  Number: createPrimitiveConstructor(
10871
11521
  {
10872
- call: (args, context) => sandboxNumber(args.length === 0 ? 0 : args[0], options.budget, context),
11522
+ call: (args, context) => sandboxNumber(args.length === 0 ? 0 : args[0], options.budget, context, true),
10873
11523
  name: "Number",
10874
11524
  properties: {
10875
11525
  isFinite: createSandboxClosure({
@@ -13553,6 +14203,16 @@ var dispatchTable = {
13553
14203
  ArrowFunctionExpression: evaluateArrowFunction,
13554
14204
  AwaitExpression: evaluateAwait,
13555
14205
  BinaryExpression: evaluateBinaryExpression,
14206
+ BigIntLiteral: async (node, context) => {
14207
+ const allocation = {};
14208
+ context.budget.visitNode(node.value.length);
14209
+ context.budget.setRetainedDataUsage(allocation, node.value.length);
14210
+ try {
14211
+ return { kind: "normal", hasValue: true, value: BigInt(node.value) };
14212
+ } finally {
14213
+ context.budget.setRetainedDataUsage(allocation, 0);
14214
+ }
14215
+ },
13556
14216
  BlockStatement: evaluateBlockStatement,
13557
14217
  BooleanLiteral: evaluatePrimitiveLiteral,
13558
14218
  CallExpression: evaluateCallExpression,
@@ -15327,8 +15987,9 @@ async function evaluateIdentifierUpdateExpression(node, context) {
15327
15987
  )
15328
15988
  };
15329
15989
  }
15330
- const current = toNumber(await toNumericPrimitive(binding.value, context));
15331
- const next = node.operator === "++" ? current + 1 : current - 1;
15990
+ const primitive = await toNumericPrimitive(binding.value, context);
15991
+ const current = typeof primitive === "bigint" ? primitive : toNumber(primitive);
15992
+ const next = typeof current === "bigint" ? bigIntOperation(node.operator === "++" ? "+" : "-", current, 1n, context.budget) : node.operator === "++" ? current + 1 : current - 1;
15332
15993
  context.scope.assign(node.argument.name, next);
15333
15994
  return {
15334
15995
  kind: "normal",
@@ -15345,10 +16006,9 @@ async function evaluateMemberUpdateExpression(node, context) {
15345
16006
  throw new TypeError("Cannot update properties of null or undefined.");
15346
16007
  }
15347
16008
  const property = await toPropertyKey(member.property, context.budget, createCoercionContext(context));
15348
- const current = toNumber(
15349
- await toNumericPrimitive(await getPropertyValue(member.object, property, context, member.superReceiver === void 0 ? member.object : member.superReceiver.value), context)
15350
- );
15351
- const next = node.operator === "++" ? current + 1 : current - 1;
16009
+ const primitive = await toNumericPrimitive(await getPropertyValue(member.object, property, context, member.superReceiver === void 0 ? member.object : member.superReceiver.value), context);
16010
+ const current = typeof primitive === "bigint" ? primitive : toNumber(primitive);
16011
+ const next = typeof current === "bigint" ? bigIntOperation(node.operator === "++" ? "+" : "-", current, 1n, context.budget) : node.operator === "++" ? current + 1 : current - 1;
15352
16012
  if (member.superReceiver === void 0) await setSandboxProperty(member.object, property, next, context.budget, true, createCoercionContext(context));
15353
16013
  else await setSuperProperty(member.object, member.superReceiver.value, property, next, context);
15354
16014
  return {
@@ -15382,7 +16042,7 @@ function getPropertyValue(target, property, context, receiver = target) {
15382
16042
  if (descriptor !== void 0)
15383
16043
  return readPropertyDescriptor(descriptor, receiver, createCoercionContext(context), true);
15384
16044
  if (isSandboxRegExpIterator(target)) return getRegExpIteratorMember(property, context.budget);
15385
- if (typeof target === "symbol") {
16045
+ if (typeof target === "symbol" || typeof target === "bigint") {
15386
16046
  const prototype = getBoxedPrototype(target, context.budget);
15387
16047
  return prototype === void 0 ? void 0 : getPropertyValue(prototype, property, context, receiver);
15388
16048
  }
@@ -15563,6 +16223,7 @@ async function evaluateObjectPropertyKey(node, context) {
15563
16223
  return evaluateMemberProperty(node.key, context);
15564
16224
  }
15565
16225
  function getStaticPropertyName(node) {
16226
+ if (node.type === "BigIntLiteral") return BigInt(node.value).toString();
15566
16227
  if (node.type === "Identifier") {
15567
16228
  return node.name;
15568
16229
  }
@@ -15596,7 +16257,7 @@ async function evaluateMemberCallExpression(node, context) {
15596
16257
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
15597
16258
  if (Array.isArray(member.object) && hasExplicitSandboxPrototype(member.object))
15598
16259
  return evaluateResolvedCallExpression(node, await getPropertyValue(member.object, member.property, context), context, member.object);
15599
- if ((typeof member.object === "string" || typeof member.object === "number" || typeof member.object === "boolean" || typeof member.object === "symbol") && getBoxedPrototype(member.object, context.budget) !== void 0) {
16260
+ if ((typeof member.object === "string" || typeof member.object === "number" || typeof member.object === "bigint" || typeof member.object === "boolean" || typeof member.object === "symbol") && getBoxedPrototype(member.object, context.budget) !== void 0) {
15600
16261
  if (isDefaultBoxedMethod(member.object, member.property, context.budget)) {
15601
16262
  if (typeof member.object === "string" && isStringMethodName(member.property))
15602
16263
  return evaluateStringMethodCall(node, member.object, member.property, context);
@@ -15846,10 +16507,14 @@ async function applyUnaryOperator(operator, value, context) {
15846
16507
  return void 0;
15847
16508
  case "+":
15848
16509
  return toNumber(await toNumericPrimitive(value, context));
15849
- case "-":
15850
- return -toNumber(await toNumericPrimitive(value, context));
15851
- case "~":
15852
- return ~toNumber(await toNumericPrimitive(value, context));
16510
+ case "-": {
16511
+ const primitive = await toNumericPrimitive(value, context);
16512
+ return typeof primitive === "bigint" ? bigIntOperation("-", 0n, primitive, context.budget) : -toNumber(primitive);
16513
+ }
16514
+ case "~": {
16515
+ const primitive = await toNumericPrimitive(value, context);
16516
+ return typeof primitive === "bigint" ? bigIntOperation("^", primitive, -1n, context.budget) : ~toNumber(primitive);
16517
+ }
15853
16518
  }
15854
16519
  }
15855
16520
  function describeTypeofValue(value) {
@@ -15865,6 +16530,10 @@ function isTruthy(value) {
15865
16530
  return Boolean(value);
15866
16531
  }
15867
16532
  function applyBinaryOperator(node, left, right, context) {
16533
+ if ((typeof left === "bigint" || typeof right === "bigint") && ["-", "*", "/", "%", "**", "&", "|", "^", "<<", ">>", ">>>"].includes(node.operator)) {
16534
+ if (typeof left !== "bigint" || typeof right !== "bigint") throw new TypeError("Cannot mix BigInt and other numeric types.");
16535
+ return bigIntOperation(node.operator, left, right, context.budget);
16536
+ }
15868
16537
  switch (node.operator) {
15869
16538
  case "+":
15870
16539
  return applyAdditionOperator(left, right, context);
@@ -15983,6 +16652,10 @@ async function applyCompoundAssignmentOperator(operator, left, right, context) {
15983
16652
  left = await toNumericPrimitive(left, context, operator === "+=" ? "default" : "number");
15984
16653
  if (convertingObject) convertedLeft = left;
15985
16654
  right = await toNumericPrimitive(right, context, operator === "+=" ? "default" : "number");
16655
+ if (operator !== "+=" && (typeof left === "bigint" || typeof right === "bigint")) {
16656
+ if (typeof left !== "bigint" || typeof right !== "bigint") throw new TypeError("Cannot mix BigInt and other numeric types.");
16657
+ return bigIntOperation(operator.slice(0, -1), left, right, context.budget);
16658
+ }
15986
16659
  switch (operator) {
15987
16660
  case "+=":
15988
16661
  return applyAdditionOperator(left, right, context);
@@ -16019,6 +16692,10 @@ function applyAdditionOperator(left, right, context) {
16019
16692
  if (typeof leftPrimitive === "string" || typeof rightPrimitive === "string") {
16020
16693
  return context.budget.allocateString(toString(leftPrimitive) + toString(rightPrimitive));
16021
16694
  }
16695
+ if (typeof leftPrimitive === "bigint" || typeof rightPrimitive === "bigint") {
16696
+ if (typeof leftPrimitive !== "bigint" || typeof rightPrimitive !== "bigint") throw new TypeError("Cannot mix BigInt and other numeric types.");
16697
+ return bigIntOperation("+", leftPrimitive, rightPrimitive, context.budget);
16698
+ }
16022
16699
  return toNumber(leftPrimitive) + toNumber(rightPrimitive);
16023
16700
  }
16024
16701
  function compareRelational(left, right, operator) {
@@ -16036,8 +16713,9 @@ function compareRelational(left, right, operator) {
16036
16713
  return leftPrimitive >= rightPrimitive;
16037
16714
  }
16038
16715
  }
16039
- const leftNumber = toNumber(leftPrimitive);
16040
- const rightNumber = toNumber(rightPrimitive);
16716
+ const hasBigInt = typeof leftPrimitive === "bigint" || typeof rightPrimitive === "bigint";
16717
+ const leftNumber = typeof leftPrimitive === "bigint" || hasBigInt && typeof leftPrimitive === "string" ? leftPrimitive : toNumber(leftPrimitive);
16718
+ const rightNumber = typeof rightPrimitive === "bigint" || hasBigInt && typeof rightPrimitive === "string" ? rightPrimitive : toNumber(rightPrimitive);
16041
16719
  switch (operator) {
16042
16720
  case "<":
16043
16721
  return leftNumber < rightNumber;
@@ -16050,6 +16728,7 @@ function compareRelational(left, right, operator) {
16050
16728
  }
16051
16729
  }
16052
16730
  function isLooselyEqual(left, right) {
16731
+ if (typeof left === "bigint" || typeof right === "bigint") return left == right;
16053
16732
  const leftType = getCoercionType(left);
16054
16733
  const rightType = getCoercionType(right);
16055
16734
  if (leftType === rightType) {
@@ -16082,6 +16761,7 @@ function isPrimitiveCoercionType(type) {
16082
16761
  return type !== "object";
16083
16762
  }
16084
16763
  function getCoercionType(value) {
16764
+ if (typeof value === "bigint") return "bigint";
16085
16765
  if (typeof value === "symbol") return "symbol";
16086
16766
  if (value === null) {
16087
16767
  return "null";
@@ -16115,6 +16795,7 @@ async function toNumericPrimitive(value, context, hint = "number") {
16115
16795
  throw new TypeError("Expected a sandbox value.");
16116
16796
  }
16117
16797
  function toNumber(value) {
16798
+ if (typeof value === "bigint") throw new TypeError("Cannot convert a BigInt value to a number");
16118
16799
  if (typeof value === "symbol") throw new TypeError("Cannot convert a Symbol value to a number");
16119
16800
  if (isSandboxDate(value)) return dateTime(value);
16120
16801
  if (typeof value === "number") {
@@ -16656,7 +17337,7 @@ async function callRegexMethod(target, methodName, args, budget, context) {
16656
17337
  cursor = target.lastIndex;
16657
17338
  const lastIndex = await sandboxNumber(cursor, budget, context);
16658
17339
  const match = executeRegex(target, input, lastIndex);
16659
- return toMatchArray(match, input);
17340
+ return toMatchArray(match, input, budget);
16660
17341
  } finally {
16661
17342
  budget.setRetainedValues(retained, void 0);
16662
17343
  }
@@ -16707,17 +17388,26 @@ async function regexToString(target, budget, context) {
16707
17388
  function executeRegex(target, input, lastIndex) {
16708
17389
  const pattern = getSandboxRegexPattern(target);
16709
17390
  const match = matchRegex(pattern, input, lastIndex);
16710
- if (pattern.flags.global) {
17391
+ if (pattern.flags.global || pattern.flags.sticky) {
16711
17392
  target.lastIndex = match === null ? 0 : match.index + match.text.length;
16712
17393
  }
16713
17394
  return match;
16714
17395
  }
16715
- function toMatchArray(match, input) {
17396
+ function toMatchArray(match, input, budget) {
16716
17397
  if (match === null) {
16717
17398
  return null;
16718
17399
  }
17400
+ budget?.allocateArrayLength(match.captures.length + 1);
16719
17401
  const result = [match.text, ...match.captures];
16720
- Object.assign(result, { index: match.index, input, groups: void 0 });
17402
+ if (match.groups !== void 0) setSandboxPrototype(match.groups, null, budget);
17403
+ if (match.indicesGroups !== void 0) setSandboxPrototype(match.indicesGroups, null, budget);
17404
+ Object.assign(result, { index: match.index, input, groups: match.groups });
17405
+ if (match.indices !== void 0) {
17406
+ budget?.allocateArrayLength(match.indices.length);
17407
+ budget?.allocateArrayLength(2);
17408
+ Object.assign(match.indices, { groups: match.indicesGroups });
17409
+ Object.assign(result, { indices: match.indices });
17410
+ }
16721
17411
  return result;
16722
17412
  }
16723
17413
 
@@ -16727,9 +17417,10 @@ function nextRegExpIterator(iterator, budget) {
16727
17417
  budget?.visitNode();
16728
17418
  if (state.exhausted) return { value: void 0, done: true };
16729
17419
  const matcher = state.matcher;
17420
+ if (!isSandboxRegex(matcher)) throw new TypeError("Custom RegExp iterator execution requires a sandbox context.");
16730
17421
  const input = state.input;
16731
17422
  const match = executeRegex(matcher, input, Number(matcher.lastIndex));
16732
- if (match === null || !matcher.flags.includes("g")) {
17423
+ if (match === null || !(state.global ?? matcher.flags.includes("g"))) {
16733
17424
  state.exhausted = true;
16734
17425
  state.matcher = void 0;
16735
17426
  state.input = void 0;
@@ -16737,12 +17428,52 @@ function nextRegExpIterator(iterator, budget) {
16737
17428
  if (match === null) return { value: void 0, done: true };
16738
17429
  if (!state.exhausted && match.text.length === 0) {
16739
17430
  const index = Number(matcher.lastIndex);
16740
- const unicode = matcher.flags.includes("u") || matcher.flags.includes("v");
17431
+ const unicode = state.unicode ?? (matcher.flags.includes("u") || matcher.flags.includes("v"));
16741
17432
  const codePoint = input.codePointAt(index);
16742
17433
  matcher.lastIndex = index + (unicode && codePoint !== void 0 && codePoint > 65535 ? 2 : 1);
16743
17434
  }
16744
- budget?.allocateArrayLength(match.captures.length + 1);
16745
- return { value: toMatchArray(match, input), done: false };
17435
+ return { value: toMatchArray(match, input, budget), done: false };
17436
+ }
17437
+ async function nextObservableRegExpIterator(iterator, budget, context) {
17438
+ const state = regexpIteratorState(iterator);
17439
+ if (state.exhausted) return { value: void 0, done: true };
17440
+ const matcher = state.matcher;
17441
+ if (isSandboxRegex(matcher) && !hasRegexPropertyOverride(matcher, ["exec"], budget) && (matcher.lastIndex === null || typeof matcher.lastIndex !== "object"))
17442
+ return nextRegExpIterator(iterator, budget);
17443
+ const input = state.input;
17444
+ let result;
17445
+ let field;
17446
+ const release = retainValues(budget, () => [iterator, matcher, input, result, field]);
17447
+ const read = (value, key) => {
17448
+ if (context.getProperty !== void 0) return context.getProperty(value, key);
17449
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
17450
+ return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
17451
+ };
17452
+ try {
17453
+ budget.visitNode();
17454
+ result = await regexExec(matcher, input, budget, context);
17455
+ const global = state.global ?? (isSandboxRegex(matcher) && matcher.flags.includes("g"));
17456
+ if (result === null || !global) {
17457
+ state.exhausted = true;
17458
+ state.matcher = void 0;
17459
+ state.input = void 0;
17460
+ return result === null ? { value: void 0, done: true } : { value: result, done: false };
17461
+ }
17462
+ field = await read(result, "0");
17463
+ const text = await sandboxString(field, budget, context);
17464
+ field = void 0;
17465
+ if (text.length === 0) {
17466
+ field = await read(matcher, "lastIndex");
17467
+ const index = normalizeLastIndex(await sandboxNumber(field, budget, context));
17468
+ field = void 0;
17469
+ const unicode = state.unicode ?? (isSandboxRegex(matcher) && (matcher.flags.includes("u") || matcher.flags.includes("v")));
17470
+ const point = input.codePointAt(index);
17471
+ await setSandboxProperty(matcher, "lastIndex", index + (unicode && point !== void 0 && point > 65535 ? 2 : 1), budget, true, context);
17472
+ }
17473
+ return { value: result, done: false };
17474
+ } finally {
17475
+ release();
17476
+ }
16746
17477
  }
16747
17478
  function getRegExpIteratorMember(property, budget) {
16748
17479
  if (property === Symbol.toStringTag) return "RegExp String Iterator";
@@ -16759,7 +17490,7 @@ function getRegExpIteratorMember(property, budget) {
16759
17490
  const receiver = context?.thisValue;
16760
17491
  if (!isSandboxRegExpIterator(receiver))
16761
17492
  throw new TypeError("RegExp string iterator next requires a matching receiver.");
16762
- return nextRegExpIterator(receiver, budget);
17493
+ return context === void 0 ? nextRegExpIterator(receiver, budget) : nextObservableRegExpIterator(receiver, budget, context);
16763
17494
  }
16764
17495
  });
16765
17496
  }
@@ -16947,8 +17678,11 @@ function getSandboxIterator(value, budget, context) {
16947
17678
  }
16948
17679
  if (isSandboxCollectionIterator(value))
16949
17680
  return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
16950
- if (isSandboxRegExpIterator(value))
17681
+ if (isSandboxRegExpIterator(value)) {
17682
+ if (context !== void 0 && budget !== void 0)
17683
+ return { asynchronous: true, next: () => nextObservableRegExpIterator(value, budget, context), snapshotIndex: () => 0 };
16951
17684
  return { next: () => nextRegExpIterator(value, budget), snapshotIndex: () => 0 };
17685
+ }
16952
17686
  if (isGuestHostObject(value)) return getHostObjectIterator(value);
16953
17687
  if (isFloat32Array(value)) {
16954
17688
  return syncIterator(Float32Array.prototype.values.call(value));
@@ -17659,6 +18393,7 @@ function encodeReplayData(value, options = {}) {
17659
18393
  if (depth > MAX_DATA_DEPTH) throw new TypeError("Replay data exceeds the nesting limit.");
17660
18394
  if (entry === null || typeof entry === "boolean" || typeof entry === "string") return entry;
17661
18395
  if (entry === void 0) return { tag: "undefined" };
18396
+ if (typeof entry === "bigint") return { tag: "bigint", value: String(entry) };
17662
18397
  if (typeof entry === "symbol") {
17663
18398
  let id2 = symbols.get(entry);
17664
18399
  if (id2 === void 0) {
@@ -17755,7 +18490,16 @@ function encodeReplayData(value, options = {}) {
17755
18490
  }
17756
18491
  let symbolIndex = 0;
17757
18492
  const symbolEntries = serializeSymbolProperties(entry, (value2) => encode(value2, depth + 1, [...path, { symbol: Math.floor(symbolIndex++ / 2) }]));
17758
- nodes[id] = { kind: "regexp-iterator", matcher: child(snapshot.matcher, "<matcher>"), input: child(snapshot.input, "<input>"), exhausted: snapshot.exhausted, properties, extensible: Object.isExtensible(entry), symbolEntries };
18493
+ nodes[id] = {
18494
+ kind: "regexp-iterator",
18495
+ matcher: child(snapshot.matcher, "<matcher>"),
18496
+ input: child(snapshot.input, "<input>"),
18497
+ exhausted: snapshot.exhausted,
18498
+ properties,
18499
+ extensible: Object.isExtensible(entry),
18500
+ symbolEntries,
18501
+ ...snapshot.global === void 0 ? {} : { global: snapshot.global, unicode: snapshot.unicode }
18502
+ };
17759
18503
  } else if (isSandboxCollectionIterator(entry)) {
17760
18504
  const snapshot = snapshotCollectionIterator(entry);
17761
18505
  const properties = /* @__PURE__ */ Object.create(null);
@@ -17809,6 +18553,7 @@ function encodeReplayData(value, options = {}) {
17809
18553
  nodes[id] = {
17810
18554
  kind: Array.isArray(entry) ? "array" : "object",
17811
18555
  nullPrototype: prototype === null,
18556
+ ...hasNullObjectPrototype(entry) ? { sandboxNullPrototype: true } : {},
17812
18557
  ...errorType === void 0 ? {} : { errorType },
17813
18558
  extensible: Object.isExtensible(entry),
17814
18559
  properties,
@@ -17851,6 +18596,11 @@ function decodeReplayData(input, options = {}, parent) {
17851
18596
  return capability;
17852
18597
  }
17853
18598
  if (own(atom, "tag") === "undefined") return void 0;
18599
+ if (own(atom, "tag") === "bigint") {
18600
+ const value = own(atom, "value");
18601
+ validateBigIntData(value);
18602
+ return BigInt(value);
18603
+ }
17854
18604
  if (atom.tag === "number") {
17855
18605
  switch (own(atom, "value")) {
17856
18606
  case "NaN":
@@ -17920,7 +18670,7 @@ function decodeReplayData(input, options = {}, parent) {
17920
18670
  const payload = own(node, "value");
17921
18671
  const payloadRecord = payload !== null && typeof payload === "object" ? record(payload) : void 0;
17922
18672
  const symbolReference = payloadRecord !== void 0 && own(payloadRecord, "tag") === "ref" && Number.isSafeInteger(payloadRecord.id) && Number(payloadRecord.id) >= 0 && Number(payloadRecord.id) < nodes.length && own(record(nodes[Number(payloadRecord.id)]), "kind") === "symbol";
17923
- if (typeof payload !== "number" && typeof payload !== "string" && typeof payload !== "boolean" && !symbolReference && (payload === null || typeof payload !== "object" || own(record(payload), "tag") !== "number"))
18673
+ if (typeof payload !== "number" && typeof payload !== "string" && typeof payload !== "boolean" && !symbolReference && (payload === null || typeof payload !== "object" || !["number", "bigint"].includes(String(own(record(payload), "tag")))))
17924
18674
  throw new TypeError("Invalid boxed primitive payload.");
17925
18675
  const result3 = createSandboxBox(child(payload));
17926
18676
  restored.set(id, result3);
@@ -17953,9 +18703,15 @@ function decodeReplayData(input, options = {}, parent) {
17953
18703
  restored.set(id, result3);
17954
18704
  const matcher = child(own(node, "matcher"));
17955
18705
  const input2 = child(own(node, "input"));
17956
- if (matcher !== void 0 && !isSandboxRegex(matcher)) throw new TypeError("Invalid replay RegExp iterator matcher.");
18706
+ if ((node.global !== void 0 || node.unicode !== void 0) && (typeof node.global !== "boolean" || typeof node.unicode !== "boolean")) throw new TypeError("Invalid replay RegExp iterator modes.");
18707
+ if (matcher !== void 0 && (node.global === void 0 ? !isSandboxRegex(matcher) : matcher === null || typeof matcher !== "object")) throw new TypeError("Invalid replay RegExp iterator matcher.");
17957
18708
  if (input2 !== void 0 && typeof input2 !== "string") throw new TypeError("Invalid replay RegExp iterator input.");
17958
- restoreSandboxRegExpIterator({ matcher, input: input2, exhausted }, result3);
18709
+ restoreSandboxRegExpIterator({
18710
+ matcher,
18711
+ input: input2,
18712
+ exhausted,
18713
+ ...node.global === void 0 ? {} : { global: node.global, unicode: node.unicode }
18714
+ }, result3);
17959
18715
  defineProperties(result3, record(own(node, "properties")), child, node.symbolEntries);
17960
18716
  if (!node.extensible) Object.preventExtensions(result3);
17961
18717
  return result3;
@@ -18025,6 +18781,10 @@ function decodeReplayData(input, options = {}, parent) {
18025
18781
  throw new TypeError("Invalid replay object metadata.");
18026
18782
  }
18027
18783
  const result2 = kind === "array" ? [] : Object.create(node.nullPrototype ? null : Object.prototype);
18784
+ if (Object.hasOwn(node, "sandboxNullPrototype")) {
18785
+ if (kind !== "object" || node.sandboxNullPrototype !== true) throw new TypeError("Invalid replay object prototype.");
18786
+ setSandboxPrototype(result2, null);
18787
+ }
18028
18788
  if (Object.hasOwn(node, "errorType")) {
18029
18789
  sandboxErrorTypes.set(result2, node.errorType);
18030
18790
  }
@@ -18661,7 +19421,7 @@ function wrapSandboxClosureForHost(closure, stackFrames, budget, compileOwner, c
18661
19421
  return wrapped;
18662
19422
  }
18663
19423
  function isSandboxLikeValue(value) {
18664
- if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
19424
+ if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
18665
19425
  return true;
18666
19426
  }
18667
19427
  if (isSandboxClosure(value) || isSandboxPromise(value)) {
@@ -18726,7 +19486,7 @@ function copyHostValueToSandbox(value, stackFrames, options, state, path) {
18726
19486
  if (options.realm === void 0 || options.errorData || options.hostCalls !== void 0) throw new TypeError("Live capabilities are not portable replay or error data.");
18727
19487
  return importHostCapability(value, options.realm.owner);
18728
19488
  }
18729
- if (value === null || value === void 0 || typeof value === "number" || typeof value === "boolean") {
19489
+ if (value === null || value === void 0 || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
18730
19490
  return value;
18731
19491
  }
18732
19492
  if (typeof value === "string") {
@@ -19205,12 +19965,16 @@ function getDatePrototype(value, budget, owner) {
19205
19965
  var defaultStringHook = /* @__PURE__ */ Symbol("defaultStringHook");
19206
19966
  var defaultValueHook = /* @__PURE__ */ Symbol("defaultValueHook");
19207
19967
  var joiningArrays = /* @__PURE__ */ new WeakSet();
19208
- function sandboxNumber(value, budget, context) {
19968
+ function sandboxNumber(value, budget, context, allowBigInt = false) {
19969
+ const convert = (primitive) => {
19970
+ if (typeof primitive === "bigint" && !allowBigInt) throw new TypeError("Cannot convert a BigInt value to a number");
19971
+ return Number(primitive);
19972
+ };
19209
19973
  if (value === null || typeof value !== "object") {
19210
19974
  if (typeof value === "function") throw new TypeError("Expected a sandbox value.");
19211
- return Number(value);
19975
+ return convert(value);
19212
19976
  }
19213
- return objectToPrimitive(value, budget, context, /* @__PURE__ */ new Set(), "number").then(Number);
19977
+ return objectToPrimitive(value, budget, context, /* @__PURE__ */ new Set(), "number").then(convert);
19214
19978
  }
19215
19979
  function sandboxString(value, budget, context, joining = /* @__PURE__ */ new Set()) {
19216
19980
  if (typeof value === "symbol") throw new TypeError("Cannot convert a Symbol value to a string");
@@ -21214,6 +21978,10 @@ function measureSandboxData(values, options = {}) {
21214
21978
  const seenSymbols = /* @__PURE__ */ new Set();
21215
21979
  let usage = 0;
21216
21980
  const visit = (value, depth = 0) => {
21981
+ if (typeof value === "bigint") {
21982
+ usage += value.toString(16).length;
21983
+ return;
21984
+ }
21217
21985
  if (typeof value === "symbol") {
21218
21986
  if (!seenSymbols.has(value)) {
21219
21987
  seenSymbols.add(value);
@@ -21472,7 +22240,7 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
21472
22240
  const copy = restoreSandboxRegExpIterator({ matcher: void 0, input: void 0, exhausted: true });
21473
22241
  state.seen.set(value, copy);
21474
22242
  const matcher = copyToSandbox(snapshot.matcher, state, `${path}.<matcher>`, true, depth + 1);
21475
- if (matcher !== void 0 && !isSandboxRegex(matcher)) throw new TypeError("Invalid RegExp iterator matcher.");
22243
+ if (matcher !== void 0 && (snapshot.global === void 0 ? !isSandboxRegex(matcher) : matcher === null || typeof matcher !== "object")) throw new TypeError("Invalid RegExp iterator matcher.");
21476
22244
  restoreSandboxRegExpIterator({ ...snapshot, matcher }, copy);
21477
22245
  for (const entry of getEnumerableObjectEntries(value, path)) {
21478
22246
  defineOwnDataProperty(copy, entry.key, copyToSandbox(entry.value, state, joinPath2(path, entry.key), true, depth + 1));
@@ -21660,6 +22428,7 @@ function copyToSandbox(value, state, path = "<root>", cloneSandboxCollections =
21660
22428
  const copy = createPlainObject(
21661
22429
  !cloneSandboxCollections || Object.getPrototypeOf(value) === null
21662
22430
  );
22431
+ if (!state.structuredClone && hasNullObjectPrototype(value)) setSandboxPrototype(copy, null);
21663
22432
  state.seen.set(value, copy);
21664
22433
  const errorType = sandboxErrorTypes.get(value);
21665
22434
  if (errorType !== void 0) sandboxErrorTypes.set(copy, errorType);
@@ -21871,7 +22640,7 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
21871
22640
  if (existing !== void 0) {
21872
22641
  return existing;
21873
22642
  }
21874
- const copy = createPlainObject(Object.getPrototypeOf(value) === null);
22643
+ const copy = createPlainObject(hasNullObjectPrototype(value) || Object.getPrototypeOf(value) === null);
21875
22644
  state.seen.set(value, copy);
21876
22645
  for (const entry of getEnumerableObjectEntries(value, path)) {
21877
22646
  defineOwnDataProperty(
@@ -21885,7 +22654,7 @@ function copyFromSandbox(value, state, path = "<root>", options, depth = 0) {
21885
22654
  throw new TypeError(`Unsupported sandbox value at ${path}: ${describeValue2(value)}`);
21886
22655
  }
21887
22656
  function isSandboxPrimitive(value) {
21888
- return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "symbol";
22657
+ return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol";
21889
22658
  }
21890
22659
  function isHostPromise(value) {
21891
22660
  return value instanceof Promise;
@@ -23609,6 +24378,7 @@ var KNOWN_RUNTIME_GLOBALS = [
23609
24378
  "AggregateError",
23610
24379
  "Array",
23611
24380
  "Boolean",
24381
+ "BigInt",
23612
24382
  "Date",
23613
24383
  "Error",
23614
24384
  "Infinity",
@@ -26880,6 +27650,7 @@ var ASAsyncNotNeededScanner = class {
26880
27650
  case "MetaProperty":
26881
27651
  case "NullLiteral":
26882
27652
  case "NumericLiteral":
27653
+ case "BigIntLiteral":
26883
27654
  case "RegexLiteral":
26884
27655
  case "StringLiteral":
26885
27656
  case "UndefinedLiteral":
@@ -27161,6 +27932,7 @@ function expressionContainsAwait(node) {
27161
27932
  case "MetaProperty":
27162
27933
  case "NullLiteral":
27163
27934
  case "NumericLiteral":
27935
+ case "BigIntLiteral":
27164
27936
  case "RegexLiteral":
27165
27937
  case "StringLiteral":
27166
27938
  case "ThisExpression":
@@ -30574,6 +31346,7 @@ var ASMissingAsyncScanner = class {
30574
31346
  case "MetaProperty":
30575
31347
  case "NullLiteral":
30576
31348
  case "NumericLiteral":
31349
+ case "BigIntLiteral":
30577
31350
  case "RegexLiteral":
30578
31351
  case "StringLiteral":
30579
31352
  case "UndefinedLiteral":
@@ -30844,6 +31617,7 @@ function expressionContainsAwait2(node) {
30844
31617
  case "MetaProperty":
30845
31618
  case "NullLiteral":
30846
31619
  case "NumericLiteral":
31620
+ case "BigIntLiteral":
30847
31621
  case "RegexLiteral":
30848
31622
  case "StringLiteral":
30849
31623
  case "ThisExpression":
@@ -34162,29 +34936,53 @@ function createConsoleJsonGlobals(options) {
34162
34936
  };
34163
34937
  }
34164
34938
  async function stringifyJson(value, replacer, indent, budget, context) {
34165
- if (replacer !== void 0 && replacer !== null && !isSandboxClosure(replacer)) {
34166
- throw new TypeError(
34167
- "JSON.stringify(value, replacer, indent) only supports function, null, or undefined replacers."
34168
- );
34169
- }
34170
- if (indent !== void 0 && typeof indent !== "number" && typeof indent !== "string") {
34171
- throw new TypeError(
34172
- "JSON.stringify(value, replacer, indent) requires indent to be a string, number, or undefined."
34173
- );
34174
- }
34175
- const holder = {};
34176
- defineDataProperty2(holder, "", value);
34177
- const output = await stringifyProperty("", holder, {
34178
- budget,
34179
- context,
34180
- gap: normalizeStringifyGap(indent),
34181
- replacer: isSandboxClosure(replacer) ? replacer : void 0,
34182
- stack: []
34183
- });
34184
- if (output === void 0) {
34185
- return void 0;
34939
+ const allocation = {};
34940
+ let propertyList;
34941
+ const release = retainValues(budget, () => [value, replacer, indent]);
34942
+ try {
34943
+ if (Array.isArray(replacer)) {
34944
+ propertyList = [];
34945
+ const seen = /* @__PURE__ */ new Set();
34946
+ let size = 0;
34947
+ const state = { budget, context, gap: "", stack: [] };
34948
+ const length = replacer.length;
34949
+ for (let index = 0; index < length; index++) {
34950
+ budget.visitNode();
34951
+ const entry = await getStringifyProperty(replacer, String(index), state);
34952
+ const primitive = isSandboxBox(entry) ? boxedValue(entry) : entry;
34953
+ if (typeof primitive !== "string" && typeof primitive !== "number") continue;
34954
+ const key = await sandboxString(entry, budget, context);
34955
+ if (seen.has(key)) continue;
34956
+ budget.allocateArrayLength(propertyList.length + 1);
34957
+ size += key.length + 2;
34958
+ budget.setRetainedDataUsage(allocation, size);
34959
+ propertyList.push(key);
34960
+ seen.add(key);
34961
+ }
34962
+ }
34963
+ if (isSandboxBox(indent)) {
34964
+ const primitive = boxedValue(indent);
34965
+ if (typeof primitive === "number") indent = await sandboxNumber(indent, budget, context);
34966
+ else if (typeof primitive === "string") indent = await sandboxString(indent, budget, context);
34967
+ }
34968
+ const holder = {};
34969
+ defineDataProperty2(holder, "", value);
34970
+ const output = await stringifyProperty("", holder, {
34971
+ budget,
34972
+ context,
34973
+ gap: normalizeStringifyGap(indent),
34974
+ replacer: isSandboxClosure(replacer) ? replacer : void 0,
34975
+ propertyList,
34976
+ stack: []
34977
+ });
34978
+ if (output === void 0) {
34979
+ return void 0;
34980
+ }
34981
+ return budget.allocateString(output);
34982
+ } finally {
34983
+ budget.setRetainedDataUsage(allocation, 0);
34984
+ release();
34186
34985
  }
34187
- return budget.allocateString(output);
34188
34986
  }
34189
34987
  async function stringifyProperty(key, holder, state, indent = "") {
34190
34988
  let value = await getStringifyProperty(holder, key, state);
@@ -34192,7 +34990,7 @@ async function stringifyProperty(key, holder, state, indent = "") {
34192
34990
  try {
34193
34991
  if (isSandboxDate(value) && getSandboxPropertyDescriptor(value, "toJSON", state.budget) === void 0) {
34194
34992
  value = await dateToJSON(value, state.budget, state.context);
34195
- } else if (isStringifyContainer(value)) {
34993
+ } else if (typeof value === "bigint" || isSandboxClosure(value) || isStringifyContainer(value)) {
34196
34994
  const toJSON = await getStringifyProperty(value, "toJSON", state);
34197
34995
  if (isSandboxClosure(toJSON)) {
34198
34996
  value = await callStringifyClosure(toJSON, [key], value, state);
@@ -34274,7 +35072,7 @@ async function stringifyObject(value, state, indent) {
34274
35072
  const release = retainValues(state.budget, () => entries);
34275
35073
  try {
34276
35074
  const nextIndent = indent + state.gap;
34277
- for (const key of Object.keys(value)) {
35075
+ for (const key of state.propertyList ?? Object.keys(value)) {
34278
35076
  const serialized = await stringifyProperty(key, value, state, nextIndent);
34279
35077
  if (serialized !== void 0) {
34280
35078
  entries.push(`${quoteJsonString(key)}:${state.gap === "" ? "" : " "}${serialized}`);
@@ -34337,19 +35135,17 @@ function isStringifyObject(value) {
34337
35135
  return isStringifyContainer(value) && !Array.isArray(value);
34338
35136
  }
34339
35137
  function toSandboxValue(value) {
34340
- if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || isSandboxClosure(value) || isSandboxPromise(value) || Array.isArray(value) || isStringifyContainer(value)) {
35138
+ if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "symbol" || typeof value === "boolean" || isSandboxClosure(value) || isSandboxPromise(value) || Array.isArray(value) || isStringifyContainer(value)) {
34341
35139
  return value;
34342
35140
  }
34343
- if (typeof value === "bigint") {
34344
- throw new TypeError("Do not know how to serialize a BigInt.");
34345
- }
34346
35141
  throw new TypeError(
34347
35142
  `JSON.stringify(value) produced an unsupported value of type ${typeof value}.`
34348
35143
  );
34349
35144
  }
34350
35145
  function getStringifyProperty(target, key, state) {
34351
35146
  if (state.context?.getProperty !== void 0) return state.context.getProperty(target, key);
34352
- const descriptor = getSandboxPropertyDescriptor(target, key, state.budget);
35147
+ const object = typeof target === "bigint" ? getBoxedPrototype(target, state.budget) : target;
35148
+ const descriptor = object === void 0 ? void 0 : getSandboxPropertyDescriptor(object, key, state.budget);
34353
35149
  return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, target, state.context);
34354
35150
  }
34355
35151
  function copyJsonToSandbox(value, budget) {
@@ -34388,6 +35184,90 @@ function defineDataProperty2(target, key, value) {
34388
35184
  });
34389
35185
  }
34390
35186
 
35187
+ // packages/safe-js/src/interp/methods/regex-split.ts
35188
+ async function regexSplit(target, input, limit, constructor, budget, context) {
35189
+ if (target === null || typeof target !== "object") throw new TypeError("RegExp split requires an object receiver.");
35190
+ let string;
35191
+ let species;
35192
+ let field;
35193
+ let flags;
35194
+ let matcher;
35195
+ let match;
35196
+ const result = [];
35197
+ const release = retainValues(budget, () => [target, input, limit, string, species, field, flags, matcher, match, result]);
35198
+ const read = (value, key) => {
35199
+ if (context?.getProperty !== void 0) return context.getProperty(value, key);
35200
+ const descriptor = getSandboxPropertyDescriptor(value, key, budget);
35201
+ return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
35202
+ };
35203
+ const append = (value) => {
35204
+ budget.allocateArrayLength(result.length + 1);
35205
+ result.push(value);
35206
+ };
35207
+ try {
35208
+ string = await sandboxString(input, budget, context);
35209
+ input = void 0;
35210
+ field = await read(target, "constructor");
35211
+ species = constructor;
35212
+ if (field !== void 0) {
35213
+ if (field === null || typeof field !== "object") throw new TypeError("Invalid RegExp species constructor.");
35214
+ species = await read(field, Symbol.species);
35215
+ if (species === null || species === void 0) species = constructor;
35216
+ }
35217
+ field = void 0;
35218
+ if (!isSandboxClosure(species) || species.construct === void 0) throw new TypeError("RegExp species must be a constructor.");
35219
+ field = await read(target, "flags");
35220
+ flags = await sandboxString(field, budget, context);
35221
+ field = void 0;
35222
+ const unicode = flags.includes("u") || flags.includes("v");
35223
+ if (!flags.includes("y")) flags = budget.allocateString(flags + "y");
35224
+ matcher = await invokeBuiltinClosure(species, [target, flags], budget, context, void 0, true);
35225
+ const maximum = limit === void 0 ? 2 ** 32 - 1 : await sandboxNumber(limit, budget, context) >>> 0;
35226
+ limit = void 0;
35227
+ if (maximum === 0) return result;
35228
+ if (string.length === 0) {
35229
+ match = await regexExec(matcher, string, budget, context);
35230
+ if (match === null) append(string);
35231
+ return result;
35232
+ }
35233
+ let end = 0;
35234
+ let index = 0;
35235
+ while (index < string.length) {
35236
+ budget.visitNode();
35237
+ match = void 0;
35238
+ await setSandboxProperty(matcher, "lastIndex", index, budget, true, context);
35239
+ match = await regexExec(matcher, string, budget, context);
35240
+ if (match !== null) {
35241
+ field = await read(matcher, "lastIndex");
35242
+ const next = Math.min(normalizeLastIndex(await sandboxNumber(field, budget, context)), string.length);
35243
+ field = void 0;
35244
+ if (next !== end) {
35245
+ append(budget.allocateString(string.slice(end, index)));
35246
+ if (result.length === maximum) return result;
35247
+ end = next;
35248
+ field = await read(match, "length");
35249
+ const length = normalizeLastIndex(await sandboxNumber(field, budget, context));
35250
+ field = void 0;
35251
+ for (let capture = 1; capture < length; capture++) {
35252
+ budget.visitNode();
35253
+ field = await read(match, String(capture));
35254
+ append(field);
35255
+ field = void 0;
35256
+ if (result.length === maximum) return result;
35257
+ }
35258
+ index = end;
35259
+ continue;
35260
+ }
35261
+ }
35262
+ index += unicode && (string.codePointAt(index) ?? 0) > 65535 ? 2 : 1;
35263
+ }
35264
+ append(budget.allocateString(string.slice(end)));
35265
+ return result;
35266
+ } finally {
35267
+ release();
35268
+ }
35269
+ }
35270
+
34391
35271
  // packages/safe-js/src/interp/globals/regex.ts
34392
35272
  function createRegexGlobals(options) {
34393
35273
  const invoke = (construct) => async (args, context) => {
@@ -34452,7 +35332,55 @@ function createRegexGlobals(options) {
34452
35332
  }
34453
35333
  };
34454
35334
  const constructor = createSandboxClosure({ guest: true, sandbox: true, name: "RegExp", length: 2, call: invoke(false), construct: invoke(true) });
35335
+ Object.defineProperty(materializeFunctionProperties(constructor), "escape", {
35336
+ value: createSandboxClosure({
35337
+ guest: true,
35338
+ sandbox: true,
35339
+ name: "escape",
35340
+ length: 1,
35341
+ call: (args) => {
35342
+ const input = args[0];
35343
+ if (typeof input !== "string") throw new TypeError("RegExp.escape requires a string.");
35344
+ const allocation = {};
35345
+ let escaped = "";
35346
+ try {
35347
+ for (const character of input) {
35348
+ options.budget.visitNode();
35349
+ const point = character.codePointAt(0);
35350
+ let part = character;
35351
+ if (escaped.length === 0 && (point >= 48 && point <= 57 || point >= 65 && point <= 90 || point >= 97 && point <= 122)) {
35352
+ part = `\\x${point.toString(16)}`;
35353
+ } else if ("^$\\.*+?()[]{}|/".includes(character)) {
35354
+ part = "\\" + character;
35355
+ } else {
35356
+ const control = "\f\n\r \v".indexOf(character);
35357
+ if (control !== -1) part = "\\" + "fnrtv"[control];
35358
+ else if (",-=<>#&!%:;@~'`\"".includes(character) || character.trim() === "" || point >= 55296 && point <= 57343) {
35359
+ part = point <= 255 ? `\\x${point.toString(16).padStart(2, "0")}` : `\\u${point.toString(16).padStart(4, "0")}`;
35360
+ }
35361
+ }
35362
+ options.budget.setRetainedDataUsage(allocation, escaped.length + part.length);
35363
+ escaped = options.budget.allocateString(escaped + part);
35364
+ }
35365
+ return escaped;
35366
+ } finally {
35367
+ options.budget.setRetainedDataUsage(allocation, 0);
35368
+ }
35369
+ }
35370
+ }),
35371
+ writable: true,
35372
+ configurable: true
35373
+ });
34455
35374
  const prototype = /* @__PURE__ */ Object.create(null);
35375
+ Object.defineProperty(materializeFunctionProperties(constructor), Symbol.species, {
35376
+ get: accessorAdapter(createSandboxClosure({
35377
+ sandbox: true,
35378
+ name: "get [Symbol.species]",
35379
+ length: 0,
35380
+ call: (_args, context) => context?.thisValue
35381
+ }), "get"),
35382
+ configurable: true
35383
+ });
34456
35384
  Object.defineProperty(materializeFunctionProperties(constructor), "prototype", { value: prototype, writable: false });
34457
35385
  Object.defineProperty(prototype, "constructor", { value: constructor, writable: true, configurable: true });
34458
35386
  Object.defineProperty(prototype, Symbol.search, {
@@ -34495,6 +35423,73 @@ function createRegexGlobals(options) {
34495
35423
  writable: true,
34496
35424
  configurable: true
34497
35425
  });
35426
+ Object.defineProperty(prototype, Symbol.matchAll, {
35427
+ value: createSandboxClosure({
35428
+ guest: true,
35429
+ sandbox: true,
35430
+ name: "[Symbol.matchAll]",
35431
+ length: 1,
35432
+ call: async (args, context) => {
35433
+ const target = context?.thisValue;
35434
+ if (target === null || typeof target !== "object") throw new TypeError("RegExp matchAll requires an object receiver.");
35435
+ let input = args[0];
35436
+ let string;
35437
+ let species;
35438
+ let field;
35439
+ let flags;
35440
+ let matcher;
35441
+ const release = retainValues(options.budget, () => [target, input, string, species, field, flags, matcher]);
35442
+ const read = (value, key) => {
35443
+ if (context?.getProperty !== void 0) return context.getProperty(value, key);
35444
+ const descriptor = getSandboxPropertyDescriptor(value, key, options.budget);
35445
+ return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
35446
+ };
35447
+ try {
35448
+ string = await sandboxString(input, options.budget, context);
35449
+ input = void 0;
35450
+ field = await read(target, "constructor");
35451
+ species = constructor;
35452
+ if (field !== void 0) {
35453
+ if (field === null || typeof field !== "object") throw new TypeError("Invalid RegExp species constructor.");
35454
+ species = await read(field, Symbol.species);
35455
+ if (species === null || species === void 0) species = constructor;
35456
+ }
35457
+ field = void 0;
35458
+ if (!isSandboxClosure(species) || species.construct === void 0) throw new TypeError("RegExp species must be a constructor.");
35459
+ field = await read(target, "flags");
35460
+ flags = await sandboxString(field, options.budget, context);
35461
+ field = void 0;
35462
+ matcher = await invokeBuiltinClosure(species, [target, flags], options.budget, context, void 0, true);
35463
+ field = await read(target, "lastIndex");
35464
+ const cursor = normalizeLastIndex(await sandboxNumber(field, options.budget, context));
35465
+ field = void 0;
35466
+ await setSandboxProperty(matcher, "lastIndex", cursor, options.budget, true, context);
35467
+ return restoreSandboxRegExpIterator({
35468
+ matcher,
35469
+ input: string,
35470
+ exhausted: false,
35471
+ global: flags.includes("g"),
35472
+ unicode: flags.includes("u") || flags.includes("v")
35473
+ });
35474
+ } finally {
35475
+ release();
35476
+ }
35477
+ }
35478
+ }),
35479
+ writable: true,
35480
+ configurable: true
35481
+ });
35482
+ Object.defineProperty(prototype, Symbol.split, {
35483
+ value: createSandboxClosure({
35484
+ guest: true,
35485
+ sandbox: true,
35486
+ name: "[Symbol.split]",
35487
+ length: 2,
35488
+ call: (args, context) => regexSplit(context?.thisValue, args[0], args[1], constructor, options.budget, context)
35489
+ }),
35490
+ writable: true,
35491
+ configurable: true
35492
+ });
34498
35493
  for (const name of ["exec", "test", "toString"]) {
34499
35494
  Object.defineProperty(prototype, name, {
34500
35495
  value: createSandboxClosure({
@@ -34705,6 +35700,100 @@ function createSymbolGlobal(budget) {
34705
35700
  return constructor;
34706
35701
  }
34707
35702
 
35703
+ // packages/safe-js/src/interp/globals/bigint.ts
35704
+ function createBigIntGlobal(budget) {
35705
+ const convert = async (value, context, allowNumber = false) => {
35706
+ const primitive = value !== null && typeof value === "object" ? await objectToPrimitive(value, budget, context, /* @__PURE__ */ new Set(), "number") : value;
35707
+ if (typeof primitive === "bigint") return primitive;
35708
+ if (typeof primitive !== "string" && typeof primitive !== "boolean" && !(allowNumber && typeof primitive === "number"))
35709
+ throw new TypeError("Cannot convert value to BigInt.");
35710
+ const size = typeof primitive === "string" ? primitive.length : 256;
35711
+ budget.visitNode(size);
35712
+ const allocation = {};
35713
+ budget.setRetainedDataUsage(allocation, size);
35714
+ try {
35715
+ return BigInt(primitive);
35716
+ } finally {
35717
+ budget.setRetainedDataUsage(allocation, 0);
35718
+ }
35719
+ };
35720
+ const constructor = createSandboxClosure({
35721
+ guest: true,
35722
+ sandbox: true,
35723
+ name: "BigInt",
35724
+ length: 1,
35725
+ call: ([value], context) => convert(value, context, true)
35726
+ });
35727
+ const prototype = /* @__PURE__ */ Object.create(null);
35728
+ Object.defineProperties(prototype, {
35729
+ constructor: { value: constructor, writable: true, configurable: true },
35730
+ valueOf: {
35731
+ value: createSandboxClosure({
35732
+ sandbox: true,
35733
+ name: "valueOf",
35734
+ length: 0,
35735
+ call: (_args, context) => primitiveReceiver(context?.thisValue, "bigint")
35736
+ }),
35737
+ writable: true,
35738
+ configurable: true
35739
+ },
35740
+ toString: {
35741
+ value: createSandboxClosure({
35742
+ sandbox: true,
35743
+ name: "toString",
35744
+ length: 1,
35745
+ call: async ([radix], context) => {
35746
+ const value = primitiveReceiver(context?.thisValue, "bigint");
35747
+ const base = radix === void 0 ? 10 : await sandboxNumber(radix, budget, context);
35748
+ const allocation = {};
35749
+ const size = value.toString(16).length * 4;
35750
+ budget.visitNode(size);
35751
+ budget.setRetainedDataUsage(allocation, size);
35752
+ try {
35753
+ return budget.allocateString(value.toString(base));
35754
+ } finally {
35755
+ budget.setRetainedDataUsage(allocation, 0);
35756
+ }
35757
+ }
35758
+ }),
35759
+ writable: true,
35760
+ configurable: true
35761
+ },
35762
+ [Symbol.toStringTag]: { value: "BigInt", configurable: true }
35763
+ });
35764
+ const properties = materializeFunctionProperties(constructor);
35765
+ Object.defineProperty(properties, "prototype", { value: prototype });
35766
+ for (const name of ["asIntN", "asUintN"]) {
35767
+ Object.defineProperty(properties, name, {
35768
+ writable: true,
35769
+ configurable: true,
35770
+ value: createSandboxClosure({
35771
+ sandbox: true,
35772
+ name,
35773
+ length: 2,
35774
+ call: async ([bits, input], context) => {
35775
+ const number = await sandboxNumber(bits, budget, context);
35776
+ const width = Number.isNaN(number) ? 0 : Math.trunc(number);
35777
+ if (width < 0 || !Number.isSafeInteger(width)) throw new RangeError("Invalid BigInt width.");
35778
+ const value = await convert(input, context);
35779
+ const size = value.toString(16).length;
35780
+ budget.visitNode(size);
35781
+ if (width >= size * 4 + 1 && (name === "asIntN" || value >= 0n)) return value;
35782
+ const allocation = {};
35783
+ budget.setRetainedDataUsage(allocation, Math.ceil(width / 4) + 1);
35784
+ try {
35785
+ return BigInt[name](width, value);
35786
+ } finally {
35787
+ budget.setRetainedDataUsage(allocation, 0);
35788
+ }
35789
+ }
35790
+ })
35791
+ });
35792
+ }
35793
+ installBoxedPrototype(budget, prototype, constructor, "bigint");
35794
+ return constructor;
35795
+ }
35796
+
34708
35797
  // packages/safe-js/src/interp/globals.ts
34709
35798
  function createBuiltinBindings(options) {
34710
35799
  return {
@@ -34713,6 +35802,7 @@ function createBuiltinBindings(options) {
34713
35802
  Float32Array: createFloat32ArrayGlobal(options.budget),
34714
35803
  Date: createDateGlobal(options),
34715
35804
  Symbol: createSymbolGlobal(options.budget),
35805
+ BigInt: createBigIntGlobal(options.budget),
34716
35806
  ...createErrorGlobals(options),
34717
35807
  ...createMathGlobals({ random: options.random }),
34718
35808
  ...createObjectArrayGlobals(options),
@@ -36839,4 +37929,4 @@ export {
36839
37929
  FileSnapshotBackend,
36840
37930
  run
36841
37931
  };
36842
- //# sourceMappingURL=chunk-YEZOXLY4.js.map
37932
+ //# sourceMappingURL=chunk-UZYQWFMY.js.map