poe-code 14.0.74 → 14.0.75

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 (38) hide show
  1. package/dist/index.js +926 -84
  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-2J6W3YGB.js → chunk-BAJI3K4B.js} +2 -2
  6. package/packages/safe-js/dist/chunks/{chunk-YEZOXLY4.js → chunk-EOTY4PCT.js} +901 -84
  7. package/packages/safe-js/dist/chunks/chunk-EOTY4PCT.js.map +7 -0
  8. package/packages/safe-js/dist/cli.js +2 -2
  9. package/packages/safe-js/dist/core.js +1 -1
  10. package/packages/safe-js/dist/index.js +2 -2
  11. package/packages/safe-js/dist/interp/globals/regex.js +108 -2
  12. package/packages/safe-js/dist/interp/iteration.js +5 -2
  13. package/packages/safe-js/dist/interp/methods/regex-split.d.ts +3 -0
  14. package/packages/safe-js/dist/interp/methods/regex-split.js +102 -0
  15. package/packages/safe-js/dist/interp/methods/regex.d.ts +1 -1
  16. package/packages/safe-js/dist/interp/methods/regex.js +16 -5
  17. package/packages/safe-js/dist/interp/methods/regexp-iterator.d.ts +5 -1
  18. package/packages/safe-js/dist/interp/methods/regexp-iterator.js +59 -7
  19. package/packages/safe-js/dist/interp/methods/string.js +7 -7
  20. package/packages/safe-js/dist/interp/object-model.d.ts +1 -0
  21. package/packages/safe-js/dist/interp/object-model.js +4 -1
  22. package/packages/safe-js/dist/interp/regex/compile-guard.js +26 -4
  23. package/packages/safe-js/dist/interp/regex/engine.d.ts +4 -0
  24. package/packages/safe-js/dist/interp/regex/engine.js +230 -30
  25. package/packages/safe-js/dist/interp/regex/parse.d.ts +42 -4
  26. package/packages/safe-js/dist/interp/regex/parse.js +429 -25
  27. package/packages/safe-js/dist/interp/regexp-iterator.d.ts +4 -2
  28. package/packages/safe-js/dist/interp/regexp-iterator.js +6 -1
  29. package/packages/safe-js/dist/interp/values.js +5 -3
  30. package/packages/safe-js/dist/snapshot/dump-format.js +10 -2
  31. package/packages/safe-js/dist/snapshot/replay-data.d.ts +3 -0
  32. package/packages/safe-js/dist/snapshot/replay-data.js +14 -4
  33. package/packages/safe-js/dist/snapshot/restore.js +8 -2
  34. package/packages/safe-js/dist/snapshot/serialize.d.ts +3 -0
  35. package/packages/safe-js/dist/snapshot/serialize.js +4 -1
  36. package/packages/safe-js/dist/snapshot/validation.js +8 -0
  37. package/packages/safe-js/dist/chunks/chunk-YEZOXLY4.js.map +0 -7
  38. /package/packages/safe-js/dist/chunks/{chunk-2J6W3YGB.js.map → chunk-BAJI3K4B.js.map} +0 -0
package/dist/index.js CHANGED
@@ -120228,7 +120228,15 @@ var init_budget2 = __esm({
120228
120228
 
120229
120229
  // packages/safe-js/src/interp/regex/compile-guard.ts
120230
120230
  function regexCompiledData(pattern) {
120231
- return compiledData.get(pattern) ?? { units: 10 + pattern.source.length + measureNode(pattern.body) };
120231
+ return compiledData.get(pattern) ?? { units: measurePattern(pattern) };
120232
+ }
120233
+ function measurePattern(pattern) {
120234
+ let units = 10 + pattern.source.length + measureNode(pattern.body);
120235
+ if (pattern.groups !== void 0) {
120236
+ units += 1;
120237
+ for (const [name, indices] of Object.entries(pattern.groups)) units += name.length + 2 + indices.length;
120238
+ }
120239
+ return units;
120232
120240
  }
120233
120241
  function measureNode(node) {
120234
120242
  switch (node.type) {
@@ -120237,13 +120245,18 @@ function measureNode(node) {
120237
120245
  return 2;
120238
120246
  case "literal":
120239
120247
  return 3 + node.value.length;
120248
+ case "namedBackreference":
120249
+ return 3 + node.name.length;
120240
120250
  case "anchor":
120241
120251
  case "wordBoundary":
120252
+ case "backreference":
120242
120253
  return 3;
120243
120254
  case "characterClass": {
120244
120255
  let usage = 5 + node.items.length;
120256
+ if (node.operation !== void 0) usage += 1 + node.operation.length;
120257
+ if (node.strings !== void 0) usage += 1;
120245
120258
  for (const item of node.items) {
120246
- usage += item.type === "character" ? 3 + item.value.length : item.type === "range" ? 4 + item.from.length + item.to.length : 4;
120259
+ 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((total2, value) => total2 + 1 + value.length, 0) : 4;
120247
120260
  }
120248
120261
  return usage;
120249
120262
  }
@@ -120255,7 +120268,10 @@ function measureNode(node) {
120255
120268
  return usage;
120256
120269
  }
120257
120270
  case "group":
120258
- return 5 + measureNode(node.body);
120271
+ 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);
120272
+ case "lookahead":
120273
+ case "lookbehind":
120274
+ return 4 + measureNode(node.body);
120259
120275
  case "quantifier":
120260
120276
  return (Object.hasOwn(node, "max") ? 6 : 5) + measureNode(node.body);
120261
120277
  }
@@ -120374,7 +120390,7 @@ var init_compile_guard = __esm({
120374
120390
  this.work(flags.length);
120375
120391
  }
120376
120392
  retain(pattern, valueUnits = 0) {
120377
- const units = 10 + pattern.source.length + measureNode(pattern.body);
120393
+ const units = measurePattern(pattern);
120378
120394
  if (this.ticket !== void 0) {
120379
120395
  this.ticket.owner.budget.resizeCompileTicket(this.ticket, units + valueUnits);
120380
120396
  }
@@ -121719,10 +121735,11 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
121719
121735
  guard.checkLength(flags.length, true);
121720
121736
  guard.allocate(5 + valueUnits);
121721
121737
  const parsedFlags = parseFlags(flags, guard);
121722
- const parser = new RegexParser(source, guard);
121738
+ const parser = new RegexParser(source, guard, parsedFlags.unicode || parsedFlags.unicodeSets, parsedFlags.unicodeSets);
121723
121739
  const body = parser.parse();
121724
121740
  guard.allocate(5 + source.length);
121725
121741
  const pattern = { source, flags: parsedFlags, captureCount: parser.captureCount, body };
121742
+ if (Object.keys(parser.namedGroups).length > 0) pattern.groups = parser.namedGroups;
121726
121743
  guard.retain(pattern, valueUnits);
121727
121744
  return pattern;
121728
121745
  } finally {
@@ -121732,16 +121749,24 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
121732
121749
  function parseFlags(flags, guard) {
121733
121750
  guard.allocate(10);
121734
121751
  const parsed = {
121752
+ hasIndices: false,
121735
121753
  global: false,
121754
+ sticky: false,
121755
+ unicode: false,
121756
+ unicodeSets: false,
121736
121757
  ignoreCase: false,
121737
121758
  multiline: false,
121738
121759
  dotAll: false
121739
121760
  };
121740
121761
  const names = {
121762
+ d: "hasIndices",
121741
121763
  g: "global",
121742
121764
  i: "ignoreCase",
121743
121765
  m: "multiline",
121744
- s: "dotAll"
121766
+ s: "dotAll",
121767
+ y: "sticky",
121768
+ u: "unicode",
121769
+ v: "unicodeSets"
121745
121770
  };
121746
121771
  for (let position = 0; position < flags.length; position += 1) {
121747
121772
  guard.work(1);
@@ -121755,6 +121780,7 @@ function parseFlags(flags, guard) {
121755
121780
  }
121756
121781
  parsed[name] = true;
121757
121782
  }
121783
+ if (parsed.unicode && parsed.unicodeSets) throw new SyntaxError("Unicode flags u and v cannot be combined");
121758
121784
  return parsed;
121759
121785
  }
121760
121786
  function isDecimalDigit2(character2) {
@@ -121768,20 +121794,29 @@ function allHexDigits(value) {
121768
121794
  }
121769
121795
  return true;
121770
121796
  }
121771
- var RegexParser;
121797
+ var groupNameStart, groupNamePart, RegexParser;
121772
121798
  var init_parse5 = __esm({
121773
121799
  "packages/safe-js/src/interp/regex/parse.ts"() {
121774
121800
  "use strict";
121775
121801
  init_compile_guard();
121802
+ groupNameStart = /^[$_\p{ID_Start}]$/u;
121803
+ groupNamePart = /^[$\u200c\u200d\p{ID_Continue}]$/u;
121776
121804
  RegexParser = class {
121777
- constructor(source, guard) {
121805
+ constructor(source, guard, unicode, unicodeSets) {
121778
121806
  this.source = source;
121779
121807
  this.guard = guard;
121808
+ this.unicode = unicode;
121809
+ this.unicodeSets = unicodeSets;
121780
121810
  }
121781
121811
  source;
121782
121812
  guard;
121813
+ unicode;
121814
+ unicodeSets;
121783
121815
  captureCount = 0;
121784
121816
  cursor = 0;
121817
+ totalCaptureCount;
121818
+ hasNamedCaptures = false;
121819
+ namedGroups = /* @__PURE__ */ Object.create(null);
121785
121820
  get position() {
121786
121821
  return this.cursor;
121787
121822
  }
@@ -121797,6 +121832,7 @@ var init_parse5 = __esm({
121797
121832
  }
121798
121833
  this.fail(`Unexpected character '${this.peek()}'`);
121799
121834
  }
121835
+ if (this.unicode || Object.keys(this.namedGroups).length > 0) this.validateNamedGroups(body);
121800
121836
  return body;
121801
121837
  }
121802
121838
  parseAlternation() {
@@ -121830,15 +121866,20 @@ var init_parse5 = __esm({
121830
121866
  parseQuantifiedAtom() {
121831
121867
  const quantifierStart = this.position;
121832
121868
  const current = this.peek();
121833
- if (current === "*" || current === "+" || current === "?" || current === "{") {
121869
+ if (current === "*" || current === "+" || current === "?" || current === "{" && this.unicode) {
121834
121870
  this.fail("Nothing to repeat", quantifierStart);
121835
121871
  }
121872
+ if (current === "{") {
121873
+ const quantifier2 = this.parseQuantifier();
121874
+ this.position = quantifierStart;
121875
+ if (quantifier2 !== void 0) this.fail("Nothing to repeat", quantifierStart);
121876
+ }
121836
121877
  const body = this.parseAtom();
121837
121878
  const quantifier = this.parseQuantifier();
121838
121879
  if (quantifier === void 0) {
121839
121880
  return body;
121840
121881
  }
121841
- if (body.type === "anchor" || body.type === "wordBoundary") {
121882
+ if (body.type === "anchor" || body.type === "wordBoundary" || body.type === "lookbehind" || this.unicode && body.type === "lookahead") {
121842
121883
  this.fail("Invalid quantifier target", quantifierStart);
121843
121884
  }
121844
121885
  const greedy = this.peek() !== "?";
@@ -121849,7 +121890,7 @@ var init_parse5 = __esm({
121849
121890
  return { type: "quantifier", body, ...quantifier, greedy };
121850
121891
  }
121851
121892
  parseAtom() {
121852
- const character2 = this.take();
121893
+ const character2 = this.takeCharacter();
121853
121894
  switch (character2) {
121854
121895
  case ".":
121855
121896
  this.guard.allocate(2);
@@ -121867,12 +121908,17 @@ var init_parse5 = __esm({
121867
121908
  case "\\":
121868
121909
  return this.parseEscape(false, this.position - 1);
121869
121910
  default:
121911
+ if (this.unicode && (character2 === "]" || character2 === "}")) this.fail("Invalid Unicode pattern character");
121870
121912
  this.guard.allocate(3 + character2.length);
121871
121913
  return { type: "literal", value: character2 };
121872
121914
  }
121873
121915
  }
121874
121916
  parseGroup(start) {
121875
121917
  let capturing = true;
121918
+ let name;
121919
+ let modifiers;
121920
+ let assertionNegated;
121921
+ let lookbehind = false;
121876
121922
  if (this.peek() === "?") {
121877
121923
  this.guard.allocate(Math.min(3, this.source.length - this.position));
121878
121924
  this.guard.work(Math.min(3, this.source.length - this.position));
@@ -121881,17 +121927,33 @@ var init_parse5 = __esm({
121881
121927
  capturing = false;
121882
121928
  this.position += 2;
121883
121929
  } else if (extension.startsWith("?=") || extension.startsWith("?!")) {
121884
- this.fail("Lookahead is not supported", start);
121930
+ capturing = false;
121931
+ assertionNegated = extension.startsWith("?!");
121932
+ this.position += 2;
121885
121933
  } else if (extension.startsWith("?<=") || extension.startsWith("?<!")) {
121886
- this.fail("Lookbehind is not supported", start);
121934
+ capturing = false;
121935
+ assertionNegated = extension.startsWith("?<!");
121936
+ lookbehind = true;
121937
+ this.position += 3;
121887
121938
  } else if (extension.startsWith("?<")) {
121888
- this.fail("Named groups are not supported", start);
121939
+ this.position += 2;
121940
+ name = this.parseGroupName(start);
121941
+ } else if ("ims-".includes(extension[1] ?? "") && extension.length > 1) {
121942
+ capturing = false;
121943
+ this.position++;
121944
+ modifiers = this.parseModifiers(start);
121889
121945
  } else {
121890
121946
  this.fail("Unsupported group construct", start);
121891
121947
  }
121892
121948
  }
121893
121949
  if (capturing) this.guard.allocate(1);
121894
121950
  const index = capturing ? ++this.captureCount : void 0;
121951
+ if (name !== void 0) {
121952
+ this.guard.allocate(name.length + 2);
121953
+ const indices = this.namedGroups[name] ??= [];
121954
+ this.guard.array(indices.length + 1);
121955
+ indices.push(index);
121956
+ }
121895
121957
  this.guard.enterGroup();
121896
121958
  let body;
121897
121959
  try {
@@ -121903,10 +121965,40 @@ var init_parse5 = __esm({
121903
121965
  this.fail("Unterminated group", start);
121904
121966
  }
121905
121967
  this.position += 1;
121968
+ if (assertionNegated !== void 0) {
121969
+ this.guard.allocate(4);
121970
+ return { type: lookbehind ? "lookbehind" : "lookahead", negated: assertionNegated, body };
121971
+ }
121906
121972
  this.guard.allocate(5);
121907
- return { type: "group", capturing, index, body };
121973
+ return {
121974
+ type: "group",
121975
+ capturing,
121976
+ index,
121977
+ body,
121978
+ ...name === void 0 ? {} : { name },
121979
+ ...modifiers === void 0 ? {} : { modifiers }
121980
+ };
121981
+ }
121982
+ parseModifiers(start) {
121983
+ this.guard.allocate(2);
121984
+ const modifiers = {};
121985
+ let enabled = true;
121986
+ while (!this.atEnd() && this.peek() !== ":") {
121987
+ const flag = this.take();
121988
+ if (flag === "-" && enabled) {
121989
+ enabled = false;
121990
+ continue;
121991
+ }
121992
+ const name = flag === "i" ? "ignoreCase" : flag === "m" ? "multiline" : flag === "s" ? "dotAll" : void 0;
121993
+ if (name === void 0 || Object.hasOwn(modifiers, name)) this.fail("Invalid regex modifiers", start);
121994
+ this.guard.allocate(1);
121995
+ modifiers[name] = enabled;
121996
+ }
121997
+ if (this.take() !== ":" || Object.keys(modifiers).length === 0) this.fail("Invalid regex modifiers", start);
121998
+ return modifiers;
121908
121999
  }
121909
122000
  parseCharacterClass(start) {
122001
+ if (this.unicodeSets) return { type: "characterClass", ...this.parseUnicodeSet(start) };
121910
122002
  const negated = this.peek() === "^";
121911
122003
  if (negated) {
121912
122004
  this.position += 1;
@@ -121926,9 +122018,13 @@ var init_parse5 = __esm({
121926
122018
  this.position += 1;
121927
122019
  const right = this.parseClassItem(start);
121928
122020
  if (left.type !== "character" || right.type !== "character") {
121929
- this.fail("Character class ranges require literal endpoints", rangePosition);
122021
+ if (this.unicode) this.fail("Character class ranges require literal endpoints", rangePosition);
122022
+ this.guard.array(items.length + 3);
122023
+ this.guard.allocate(4);
122024
+ items.push(left, { type: "character", value: "-" }, right);
122025
+ continue;
121930
122026
  }
121931
- if (left.value.charCodeAt(0) > right.value.charCodeAt(0)) {
122027
+ if (left.value.codePointAt(0) > right.value.codePointAt(0)) {
121932
122028
  this.fail("Character class range is out of order", rangePosition);
121933
122029
  }
121934
122030
  this.guard.allocate(4 + left.value.length + right.value.length);
@@ -121957,26 +122053,193 @@ var init_parse5 = __esm({
121957
122053
  this.fail("Unsupported character class escape", escapeStart);
121958
122054
  }
121959
122055
  this.guard.allocate(4);
121960
- return { type: "character", value: this.take() };
122056
+ return { type: "character", value: this.takeCharacter() };
122057
+ }
122058
+ parseUnicodeSet(start) {
122059
+ this.guard.enterGroup();
122060
+ try {
122061
+ const negated = this.peek() === "^";
122062
+ if (negated) this.position++;
122063
+ this.guard.allocate(5);
122064
+ const items = [];
122065
+ let operation;
122066
+ while (!this.atEnd() && this.peek() !== "]") {
122067
+ this.guard.array(items.length + 1);
122068
+ let item = this.parseUnicodeSetItem(start);
122069
+ if (this.peek() === "-" && this.source[this.position + 1] !== "-") {
122070
+ this.position++;
122071
+ const right = this.parseUnicodeSetItem(start);
122072
+ if (item.type !== "character" || right.type !== "character") this.fail("Invalid set range", start);
122073
+ if (item.value.codePointAt(0) > right.value.codePointAt(0)) this.fail("Set range is out of order", start);
122074
+ this.guard.allocate(4 + item.value.length + right.value.length);
122075
+ item = { type: "range", from: item.value, to: right.value };
122076
+ }
122077
+ if (operation !== void 0 && item.type === "range") this.fail("Set operations require nested ranges", start);
122078
+ items.push(item);
122079
+ const operator = this.source.slice(this.position, this.position + 2);
122080
+ if (operator === "&&" || operator === "--") {
122081
+ const next = operator === "&&" ? "intersection" : "subtraction";
122082
+ if (operation === void 0 && (items.length !== 1 || item.type === "range") || operation !== void 0 && operation !== next) this.fail("Mixed set operations", start);
122083
+ if (operation === void 0) this.guard.allocate(1 + next.length);
122084
+ operation = next;
122085
+ this.position += 2;
122086
+ if (this.peek() === "]" || this.atEnd()) this.fail("Missing set operand", start);
122087
+ } else if (operation !== void 0 && this.peek() !== "]") this.fail("Missing set operator", start);
122088
+ }
122089
+ if (this.take() !== "]") this.fail("Unterminated character set", start);
122090
+ const mayContainStrings = (item) => {
122091
+ if (item.type === "set") return item.value.strings === true;
122092
+ if (item.type === "property") return item.strings === true;
122093
+ if (item.type === "strings") return item.values.some((value) => value.length !== ((value.codePointAt(0) ?? 0) > 65535 ? 2 : 1));
122094
+ return false;
122095
+ };
122096
+ const strings = operation === "intersection" ? items.every(mayContainStrings) : operation === "subtraction" ? mayContainStrings(items[0]) : items.some(mayContainStrings);
122097
+ if (negated && strings) this.fail("Cannot complement a set containing strings", start);
122098
+ if (strings) this.guard.allocate(1);
122099
+ return { negated, items, ...operation === void 0 ? {} : { operation }, ...strings ? { strings: true } : {} };
122100
+ } finally {
122101
+ this.guard.leaveGroup();
122102
+ }
122103
+ }
122104
+ parseUnicodeSetItem(start) {
122105
+ if (this.peek() === "[") {
122106
+ this.position++;
122107
+ this.guard.allocate(3);
122108
+ return { type: "set", value: this.parseUnicodeSet(start) };
122109
+ }
122110
+ if (this.source.startsWith("\\q{", this.position)) {
122111
+ this.position += 3;
122112
+ this.guard.allocate(4);
122113
+ const values = [];
122114
+ let value2 = "";
122115
+ while (!this.atEnd()) {
122116
+ if (this.peek() === "|" || this.peek() === "}") {
122117
+ this.guard.array(values.length + 1);
122118
+ this.guard.allocate(1);
122119
+ values.push(value2);
122120
+ value2 = "";
122121
+ if (this.take() === "}") return { type: "strings", values };
122122
+ } else {
122123
+ const item = this.parseSetCharacter(start);
122124
+ this.guard.allocate(item.length);
122125
+ value2 += item;
122126
+ }
122127
+ }
122128
+ this.fail("Unterminated class string", start);
122129
+ }
122130
+ if (this.peek() === "\\") return this.parseClassItem(start);
122131
+ const value = this.parseSetCharacter(start);
122132
+ this.guard.allocate(3 + value.length);
122133
+ return { type: "character", value };
122134
+ }
122135
+ parseSetCharacter(start) {
122136
+ if (this.peek() === "\\") {
122137
+ this.position++;
122138
+ const node = this.parseEscape(true, start);
122139
+ if (node.type !== "literal") this.fail("Class strings require literal characters", start);
122140
+ return node.value;
122141
+ }
122142
+ const character2 = this.takeCharacter();
122143
+ if (!character2 || "()[]{}/-|".includes(character2) || "!#$%&*+,.:;<=>?@^`~".includes(character2) && this.peek() === character2)
122144
+ this.fail("Invalid character in Unicode set", start);
122145
+ return character2;
121961
122146
  }
121962
122147
  parseEscape(inCharacterClass, start) {
121963
122148
  if (this.atEnd()) {
121964
122149
  this.fail("Trailing escape", start);
121965
122150
  }
121966
122151
  const escaped = this.take();
121967
- if (escaped >= "1" && escaped <= "9") {
121968
- this.fail("Backreferences are not supported", start);
121969
- }
121970
- if (escaped === "p" || escaped === "P") {
121971
- this.fail("Unicode property escapes are not supported", start);
122152
+ if (escaped === "k") {
122153
+ this.totalCaptureCount ??= this.countAllCaptures();
122154
+ if (this.unicode || this.hasNamedCaptures) {
122155
+ if (inCharacterClass || this.take() !== "<") this.fail("Invalid named backreference", start);
122156
+ const name = this.parseGroupName(start);
122157
+ this.guard.allocate(3 + name.length);
122158
+ return { type: "namedBackreference", name };
122159
+ }
122160
+ }
122161
+ if (isDecimalDigit2(escaped)) {
122162
+ if (!inCharacterClass && escaped !== "0") {
122163
+ let end = this.position;
122164
+ let index = Number(escaped);
122165
+ while (isDecimalDigit2(this.source[end] ?? "")) {
122166
+ this.guard.work(1);
122167
+ index = index * 10 + Number(this.source[end++]);
122168
+ }
122169
+ this.totalCaptureCount ??= this.countAllCaptures();
122170
+ if (index <= this.totalCaptureCount) {
122171
+ this.position = end;
122172
+ this.guard.allocate(3);
122173
+ return { type: "backreference", index };
122174
+ }
122175
+ }
122176
+ if (this.unicode && (escaped !== "0" || isDecimalDigit2(this.peek())))
122177
+ this.fail("Invalid decimal escape", start);
122178
+ this.guard.allocate(4);
122179
+ if (escaped === "8" || escaped === "9") return { type: "literal", value: escaped };
122180
+ let code = Number(escaped);
122181
+ const maximum = escaped <= "3" ? 3 : 2;
122182
+ for (let digits = 1; digits < maximum && this.peek() >= "0" && this.peek() <= "7"; digits++) {
122183
+ code = code * 8 + Number(this.take());
122184
+ }
122185
+ return { type: "literal", value: String.fromCharCode(code) };
122186
+ }
122187
+ if (this.unicode && (escaped === "p" || escaped === "P")) {
122188
+ if (this.take() !== "{") this.fail("Invalid Unicode property escape", start);
122189
+ const begin = this.position;
122190
+ while (!this.atEnd() && this.peek() !== "}") {
122191
+ const character2 = this.take();
122192
+ if (!isDecimalDigit2(character2) && !(character2 >= "a" && character2 <= "z") && !(character2 >= "A" && character2 <= "Z") && character2 !== "_" && character2 !== "=")
122193
+ this.fail("Invalid Unicode property escape", start);
122194
+ }
122195
+ this.guard.allocate(this.position - begin + 9);
122196
+ const value = this.source.slice(begin, this.position);
122197
+ if (this.take() !== "}") this.fail("Unterminated Unicode property escape", start);
122198
+ try {
122199
+ new RegExp(`\\${escaped}{${value}}`, this.unicodeSets ? "v" : "u");
122200
+ } catch {
122201
+ this.fail("Unknown Unicode property", start);
122202
+ }
122203
+ let strings = false;
122204
+ if (this.unicodeSets) {
122205
+ try {
122206
+ new RegExp(`\\p{${value}}`, "u");
122207
+ } catch {
122208
+ strings = true;
122209
+ }
122210
+ }
122211
+ this.guard.array(1);
122212
+ return { type: "characterClass", negated: false, items: [{ type: "property", value, negated: escaped === "P", ...strings ? { strings: true } : {} }] };
121972
122213
  }
121973
122214
  if (escaped === "x") {
121974
122215
  this.guard.allocate(4);
121975
- return { type: "literal", value: this.parseHexEscape(2, "hexadecimal", start) };
122216
+ return { type: "literal", value: this.parseHexEscape(2, "hexadecimal", start, this.unicode ? void 0 : "x") };
121976
122217
  }
121977
122218
  if (escaped === "u") {
121978
122219
  this.guard.allocate(4);
121979
- return { type: "literal", value: this.parseHexEscape(4, "Unicode", start) };
122220
+ if (this.unicode && this.peek() === "{") {
122221
+ this.position++;
122222
+ const begin = this.position;
122223
+ while (!this.atEnd() && this.peek() !== "}") this.position++;
122224
+ this.guard.allocate(this.position - begin);
122225
+ const digits = this.source.slice(begin, this.position);
122226
+ const point = Number.parseInt(digits, 16);
122227
+ if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
122228
+ this.fail("Invalid Unicode escape", start);
122229
+ return { type: "literal", value: String.fromCodePoint(point) };
122230
+ }
122231
+ let value = this.parseHexEscape(4, "Unicode", start, this.unicode ? void 0 : "u");
122232
+ if (this.unicode && value.charCodeAt(0) >= 55296 && value.charCodeAt(0) <= 56319 && this.source.startsWith("\\u", this.position)) {
122233
+ const digits = this.source.slice(this.position + 2, this.position + 6);
122234
+ const point = Number.parseInt(digits, 16);
122235
+ this.guard.work(digits.length);
122236
+ this.guard.allocate(digits.length);
122237
+ if (digits.length === 4 && allHexDigits(digits) && point >= 56320 && point <= 57343) {
122238
+ value += String.fromCharCode(point);
122239
+ this.position += 6;
122240
+ }
122241
+ }
122242
+ return { type: "literal", value };
121980
122243
  }
121981
122244
  this.guard.allocate(25);
121982
122245
  const kinds = {
@@ -122007,20 +122270,101 @@ var init_parse5 = __esm({
122007
122270
  v: "\v",
122008
122271
  "0": "\0"
122009
122272
  };
122273
+ if (escaped === "c") {
122274
+ const letter = this.peek();
122275
+ this.guard.allocate(4);
122276
+ if (letter >= "a" && letter <= "z" || letter >= "A" && letter <= "Z" || !this.unicode && inCharacterClass && (isDecimalDigit2(letter) || letter === "_")) {
122277
+ this.position++;
122278
+ return { type: "literal", value: String.fromCharCode(letter.charCodeAt(0) % 32) };
122279
+ }
122280
+ if (this.unicode) this.fail("Invalid control escape", start);
122281
+ this.position--;
122282
+ return { type: "literal", value: "\\" };
122283
+ }
122284
+ if (this.unicode && controls[escaped] === void 0 && !"^$\\.*+?()[]{}|/".includes(escaped) && !(inCharacterClass && (escaped === "-" || this.unicodeSets && "!#$%&+,.:;<=>?@`~".includes(escaped))))
122285
+ this.fail("Invalid identity escape", start);
122010
122286
  this.guard.allocate(4);
122011
122287
  return { type: "literal", value: controls[escaped] ?? escaped };
122012
122288
  }
122013
- parseHexEscape(length, name, start) {
122289
+ parseHexEscape(length, name, start, identity) {
122014
122290
  const end = this.position + length;
122015
122291
  this.guard.allocate(Math.min(length, this.source.length - this.position));
122016
122292
  this.guard.work(Math.min(length, this.source.length - this.position));
122017
122293
  const digits = this.source.slice(this.position, end);
122018
122294
  if (digits.length !== length || !allHexDigits(digits)) {
122295
+ if (identity !== void 0) return identity;
122019
122296
  this.fail(`Invalid ${name} escape`, start);
122020
122297
  }
122021
122298
  this.position = end;
122022
122299
  return String.fromCharCode(Number.parseInt(digits, 16));
122023
122300
  }
122301
+ countAllCaptures() {
122302
+ let count = 0;
122303
+ let escaped = false;
122304
+ let characterClass = false;
122305
+ for (let index = 0; index < this.source.length; index++) {
122306
+ this.guard.work(1);
122307
+ const character2 = this.source[index];
122308
+ if (escaped) escaped = false;
122309
+ else if (character2 === "\\") escaped = true;
122310
+ else if (character2 === "[") characterClass = true;
122311
+ else if (character2 === "]") characterClass = false;
122312
+ else if (!characterClass && character2 === "(") {
122313
+ const named = this.source[index + 1] === "?" && this.source[index + 2] === "<" && this.source[index + 3] !== "=" && this.source[index + 3] !== "!";
122314
+ if (named) this.hasNamedCaptures = true;
122315
+ if (named || this.source[index + 1] !== "?") count++;
122316
+ }
122317
+ }
122318
+ return count;
122319
+ }
122320
+ parseGroupName(start) {
122321
+ let name = "";
122322
+ while (!this.atEnd() && this.peek() !== ">") {
122323
+ let character2 = this.take();
122324
+ if (character2 === "\\") {
122325
+ if (this.take() !== "u") this.fail("Invalid group name escape", start);
122326
+ if (this.peek() === "{") {
122327
+ this.position++;
122328
+ const begin = this.position;
122329
+ while (!this.atEnd() && this.peek() !== "}") this.position++;
122330
+ this.guard.allocate(this.position - begin);
122331
+ const digits = this.source.slice(begin, this.position);
122332
+ const point = Number.parseInt(digits, 16);
122333
+ if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
122334
+ this.fail("Invalid group name escape", start);
122335
+ character2 = String.fromCodePoint(point);
122336
+ } else character2 = this.parseHexEscape(4, "Unicode", start);
122337
+ }
122338
+ this.guard.allocate(character2.length);
122339
+ name += character2;
122340
+ }
122341
+ if (this.take() !== ">" || name.length === 0) this.fail("Invalid group name", start);
122342
+ let first = true;
122343
+ for (const character2 of name) {
122344
+ this.guard.work(1);
122345
+ if (!(first ? groupNameStart : groupNamePart).test(character2)) this.fail("Invalid group name", start);
122346
+ first = false;
122347
+ }
122348
+ return name;
122349
+ }
122350
+ validateNamedGroups(node) {
122351
+ this.guard.work(1);
122352
+ this.guard.allocate(1);
122353
+ const names = /* @__PURE__ */ new Set();
122354
+ if (node.type === "namedBackreference" && !Object.hasOwn(this.namedGroups, node.name))
122355
+ this.fail("Unknown named backreference");
122356
+ if (node.type === "group" && node.name !== void 0) names.add(node.name);
122357
+ const children2 = node.type === "sequence" ? node.elements : node.type === "alternation" ? node.alternatives : node.type === "group" || node.type === "quantifier" || node.type === "lookahead" || node.type === "lookbehind" ? [node.body] : [];
122358
+ for (const child of children2) {
122359
+ for (const name of this.validateNamedGroups(child)) {
122360
+ this.guard.work(1);
122361
+ if (names.has(name) && node.type !== "alternation") this.fail("Duplicate capture group name");
122362
+ this.guard.allocate(1);
122363
+ names.add(name);
122364
+ }
122365
+ }
122366
+ return names;
122367
+ }
122024
122368
  parseQuantifier() {
122025
122369
  const character2 = this.peek();
122026
122370
  if (character2 === "*") {
@@ -122050,18 +122394,29 @@ var init_parse5 = __esm({
122050
122394
  }
122051
122395
  if (this.peek() === "}") {
122052
122396
  this.position += 1;
122397
+ if (!Number.isSafeInteger(min)) this.fail("Quantifier is too large", start);
122053
122398
  this.guard.allocate(3);
122054
122399
  return { min, max: min };
122055
122400
  }
122056
122401
  if (this.peek() !== ",") {
122402
+ if (!this.unicode) {
122403
+ this.position = start;
122404
+ return void 0;
122405
+ }
122057
122406
  this.fail("Invalid quantifier", start);
122058
122407
  }
122059
122408
  this.position += 1;
122060
122409
  const max = this.parseDecimal();
122061
122410
  if (this.peek() !== "}") {
122411
+ if (!this.unicode) {
122412
+ this.position = start;
122413
+ return void 0;
122414
+ }
122062
122415
  this.fail("Unterminated quantifier", start);
122063
122416
  }
122064
122417
  this.position += 1;
122418
+ if (!Number.isSafeInteger(min) || max !== void 0 && !Number.isSafeInteger(max))
122419
+ this.fail("Quantifier is too large", start);
122065
122420
  if (max !== void 0 && min > max) {
122066
122421
  this.fail("Quantifier range is out of order", start);
122067
122422
  }
@@ -122078,11 +122433,7 @@ var init_parse5 = __esm({
122078
122433
  }
122079
122434
  this.guard.allocate(this.position - start);
122080
122435
  this.guard.work(this.position - start);
122081
- const value = Number(this.source.slice(start, this.position));
122082
- if (!Number.isSafeInteger(value)) {
122083
- this.fail("Quantifier is too large", start);
122084
- }
122085
- return value;
122436
+ return Number(this.source.slice(start, this.position));
122086
122437
  }
122087
122438
  peek() {
122088
122439
  return this.source[this.position] ?? "";
@@ -122092,6 +122443,12 @@ var init_parse5 = __esm({
122092
122443
  this.position += 1;
122093
122444
  return character2;
122094
122445
  }
122446
+ takeCharacter() {
122447
+ if (!this.unicode || this.atEnd()) return this.take();
122448
+ const character2 = String.fromCodePoint(this.source.codePointAt(this.position));
122449
+ this.position += character2.length;
122450
+ return character2;
122451
+ }
122095
122452
  atEnd() {
122096
122453
  return this.position >= this.source.length;
122097
122454
  }
@@ -126228,9 +126585,13 @@ function isSandboxRegExpIterator(value) {
126228
126585
  return typeof value === "object" && value !== null && states2.has(value);
126229
126586
  }
126230
126587
  function restoreSandboxRegExpIterator(state, target = /* @__PURE__ */ Object.create(null)) {
126588
+ if ((state.global !== void 0 || state.unicode !== void 0) && (typeof state.global !== "boolean" || typeof state.unicode !== "boolean"))
126589
+ throw new TypeError("Invalid RegExp iterator modes.");
126590
+ if (state.matcher !== void 0 && (state.matcher === null || typeof state.matcher !== "object"))
126591
+ throw new TypeError("Invalid RegExp iterator matcher.");
126231
126592
  if (!state.exhausted && (state.matcher === void 0 || state.input === void 0))
126232
126593
  throw new TypeError("A live RegExp iterator requires its matcher and input.");
126233
- states2.set(target, state.exhausted ? { matcher: void 0, input: void 0, exhausted: true } : { ...state });
126594
+ states2.set(target, state.exhausted ? { ...state, matcher: void 0, input: void 0, exhausted: true } : { ...state });
126234
126595
  return target;
126235
126596
  }
126236
126597
  function regexpIteratorState(value) {
@@ -127671,6 +128032,9 @@ function getSandboxPrototype(value, budget) {
127671
128032
  function hasExplicitSandboxPrototype(value) {
127672
128033
  return prototypes.has(value);
127673
128034
  }
128035
+ function hasNullObjectPrototype(value) {
128036
+ return prototypes.get(value) === null && !Array.isArray(value) && !isSandboxClosure(value) && !isSandboxRegex(value);
128037
+ }
127674
128038
  function getSandboxPropertyDescriptor(value, key3, budget) {
127675
128039
  const hostProperties = isSandboxClosure(value) ? value.properties : void 0;
127676
128040
  if (isSandboxClosure(value) && !isGuestClosure(value))
@@ -127752,7 +128116,7 @@ function hasGuestObjectState(value) {
127752
128116
  const intrinsicUnchanged = intrinsicConstructors.get(value);
127753
128117
  if (intrinsicUnchanged !== void 0) return !intrinsicUnchanged();
127754
128118
  if (isLiveCapability(value)) return true;
127755
- if (functionProperties.has(value) || prototypes.has(value)) return true;
128119
+ if (functionProperties.has(value) || prototypes.has(value) && !hasNullObjectPrototype(value)) return true;
127756
128120
  if (isSandboxBox(value) || isSandboxDate(value)) return false;
127757
128121
  return descriptorObjects.has(value) && Object.values(Object.getOwnPropertyDescriptors(value)).some(
127758
128122
  (descriptor) => !descriptor.enumerable || !descriptor.configurable || !descriptor.writable
@@ -128070,7 +128434,16 @@ function encodeReplayData(value, options = {}) {
128070
128434
  }
128071
128435
  let symbolIndex = 0;
128072
128436
  const symbolEntries = serializeSymbolProperties(entry, (value2) => encode(value2, depth + 1, [...path193, { symbol: Math.floor(symbolIndex++ / 2) }]));
128073
- nodes[id] = { kind: "regexp-iterator", matcher: child(snapshot2.matcher, "<matcher>"), input: child(snapshot2.input, "<input>"), exhausted: snapshot2.exhausted, properties, extensible: Object.isExtensible(entry), symbolEntries };
128437
+ nodes[id] = {
128438
+ kind: "regexp-iterator",
128439
+ matcher: child(snapshot2.matcher, "<matcher>"),
128440
+ input: child(snapshot2.input, "<input>"),
128441
+ exhausted: snapshot2.exhausted,
128442
+ properties,
128443
+ extensible: Object.isExtensible(entry),
128444
+ symbolEntries,
128445
+ ...snapshot2.global === void 0 ? {} : { global: snapshot2.global, unicode: snapshot2.unicode }
128446
+ };
128074
128447
  } else if (isSandboxCollectionIterator(entry)) {
128075
128448
  const snapshot2 = snapshotCollectionIterator(entry);
128076
128449
  const properties = /* @__PURE__ */ Object.create(null);
@@ -128124,6 +128497,7 @@ function encodeReplayData(value, options = {}) {
128124
128497
  nodes[id] = {
128125
128498
  kind: Array.isArray(entry) ? "array" : "object",
128126
128499
  nullPrototype: prototype === null,
128500
+ ...hasNullObjectPrototype(entry) ? { sandboxNullPrototype: true } : {},
128127
128501
  ...errorType === void 0 ? {} : { errorType },
128128
128502
  extensible: Object.isExtensible(entry),
128129
128503
  properties,
@@ -128268,9 +128642,15 @@ function decodeReplayData(input, options = {}, parent) {
128268
128642
  restored.set(id, result3);
128269
128643
  const matcher = child(own(node, "matcher"));
128270
128644
  const input2 = child(own(node, "input"));
128271
- if (matcher !== void 0 && !isSandboxRegex(matcher)) throw new TypeError("Invalid replay RegExp iterator matcher.");
128645
+ 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.");
128646
+ if (matcher !== void 0 && (node.global === void 0 ? !isSandboxRegex(matcher) : matcher === null || typeof matcher !== "object")) throw new TypeError("Invalid replay RegExp iterator matcher.");
128272
128647
  if (input2 !== void 0 && typeof input2 !== "string") throw new TypeError("Invalid replay RegExp iterator input.");
128273
- restoreSandboxRegExpIterator({ matcher, input: input2, exhausted }, result3);
128648
+ restoreSandboxRegExpIterator({
128649
+ matcher,
128650
+ input: input2,
128651
+ exhausted,
128652
+ ...node.global === void 0 ? {} : { global: node.global, unicode: node.unicode }
128653
+ }, result3);
128274
128654
  defineProperties(result3, record(own(node, "properties")), child, node.symbolEntries);
128275
128655
  if (!node.extensible) Object.preventExtensions(result3);
128276
128656
  return result3;
@@ -128340,6 +128720,10 @@ function decodeReplayData(input, options = {}, parent) {
128340
128720
  throw new TypeError("Invalid replay object metadata.");
128341
128721
  }
128342
128722
  const result2 = kind === "array" ? [] : Object.create(node.nullPrototype ? null : Object.prototype);
128723
+ if (Object.hasOwn(node, "sandboxNullPrototype")) {
128724
+ if (kind !== "object" || node.sandboxNullPrototype !== true) throw new TypeError("Invalid replay object prototype.");
128725
+ setSandboxPrototype(result2, null);
128726
+ }
128343
128727
  if (Object.hasOwn(node, "errorType")) {
128344
128728
  sandboxErrorTypes.set(result2, node.errorType);
128345
128729
  }
@@ -129345,15 +129729,17 @@ var init_resources = __esm({
129345
129729
 
129346
129730
  // packages/safe-js/src/interp/regex/engine.ts
129347
129731
  function matchRegex(pattern, input, lastIndex = 0) {
129348
- const startIndex = pattern.flags.global ? normalizeLastIndex(lastIndex) : 0;
129732
+ const startIndex = pattern.flags.global || pattern.flags.sticky ? normalizeLastIndex(lastIndex) : 0;
129349
129733
  return matchRegexFrom(pattern, input, startIndex);
129350
129734
  }
129351
129735
  function matchRegexFrom(pattern, input, startIndex) {
129352
129736
  if (startIndex > input.length) {
129353
129737
  return null;
129354
129738
  }
129355
- for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
129356
- const context = { input, flags: pattern.flags, steps: 0 };
129739
+ const unicode = pattern.flags.unicode || pattern.flags.unicodeSets;
129740
+ 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--;
129741
+ for (let attempt = startIndex; attempt <= input.length; attempt = advanceStringIndex(input, attempt, unicode)) {
129742
+ const context = { input, flags: pattern.flags, groups: pattern.groups, direction: 1, work: { steps: 0 } };
129357
129743
  charge(context);
129358
129744
  const initialState = {
129359
129745
  position: attempt,
@@ -129361,25 +129747,59 @@ function matchRegexFrom(pattern, input, startIndex) {
129361
129747
  };
129362
129748
  const result = matchNode(pattern.body, initialState, context).next();
129363
129749
  if (!result.done) {
129364
- return toRegexMatch(input, attempt, result.value);
129750
+ return toRegexMatch(input, attempt, result.value, pattern.flags.hasIndices, pattern.groups);
129365
129751
  }
129752
+ if (pattern.flags.sticky) break;
129366
129753
  }
129367
129754
  return null;
129368
129755
  }
129369
129756
  function* matchNode(node, state, context) {
129370
129757
  charge(context);
129758
+ const unicode = context.flags.unicode || context.flags.unicodeSets;
129759
+ const character2 = readCharacter(context.input, state.position, context.direction, unicode);
129371
129760
  switch (node.type) {
129372
129761
  case "empty":
129373
129762
  yield state;
129374
129763
  return;
129375
129764
  case "literal":
129376
- if (charactersEqual(context.input[state.position], node.value, context.flags.ignoreCase)) {
129377
- yield { ...state, position: state.position + 1 };
129765
+ if (charactersEqual(character2, node.value, context.flags.ignoreCase, unicode)) {
129766
+ yield { ...state, position: state.position + context.direction * character2.length };
129767
+ }
129768
+ return;
129769
+ case "backreference":
129770
+ case "namedBackreference": {
129771
+ let capture;
129772
+ if (node.type === "backreference") capture = state.captures[node.index - 1];
129773
+ else {
129774
+ for (const index of context.groups?.[node.name] ?? []) {
129775
+ charge(context);
129776
+ if (state.captures[index - 1] !== void 0) {
129777
+ capture = state.captures[index - 1];
129778
+ break;
129779
+ }
129780
+ }
129781
+ }
129782
+ if (capture === void 0) {
129783
+ yield state;
129784
+ return;
129378
129785
  }
129786
+ let position = state.position;
129787
+ let reference = context.direction === 1 ? capture.start : capture.end;
129788
+ const end = context.direction === 1 ? capture.end : capture.start;
129789
+ while (reference !== end) {
129790
+ charge(context);
129791
+ const expected = readCharacter(context.input, reference, context.direction, unicode);
129792
+ const actual = readCharacter(context.input, position, context.direction, unicode);
129793
+ if (!charactersEqual(actual, expected, context.flags.ignoreCase, unicode)) return;
129794
+ reference += context.direction * expected.length;
129795
+ position += context.direction * actual.length;
129796
+ }
129797
+ yield { ...state, position };
129379
129798
  return;
129799
+ }
129380
129800
  case "dot":
129381
- if (state.position < context.input.length && (context.flags.dotAll || !isLineTerminator(context.input[state.position]))) {
129382
- yield { ...state, position: state.position + 1 };
129801
+ if (character2 !== void 0 && (context.flags.dotAll || !isLineTerminator(character2))) {
129802
+ yield { ...state, position: state.position + context.direction * character2.length };
129383
129803
  }
129384
129804
  return;
129385
129805
  case "anchor":
@@ -129388,17 +129808,24 @@ function* matchNode(node, state, context) {
129388
129808
  }
129389
129809
  return;
129390
129810
  case "wordBoundary": {
129391
- const previousWord = state.position > 0 && isWordCharacter(context.input[state.position - 1]);
129392
- const nextWord = state.position < context.input.length && isWordCharacter(context.input[state.position]);
129811
+ const previousWord = state.position > 0 && matchesCharacterClassItem(context.input[state.position - 1], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, unicode);
129812
+ const nextWord = state.position < context.input.length && matchesCharacterClassItem(context.input[state.position], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, unicode);
129393
129813
  if (previousWord !== nextWord !== node.negated) {
129394
129814
  yield state;
129395
129815
  }
129396
129816
  return;
129397
129817
  }
129398
129818
  case "characterClass": {
129399
- const character2 = context.input[state.position];
129400
- if (character2 !== void 0 && matchesCharacterClass(character2, node.items, node.negated, context.flags.ignoreCase)) {
129401
- yield { ...state, position: state.position + 1 };
129819
+ if (context.flags.unicodeSets) {
129820
+ const lengths = [...matchUnicodeSet(node, state.position, context)].sort((a, b) => b - a);
129821
+ for (const length of lengths) {
129822
+ charge(context);
129823
+ yield { ...state, position: state.position + context.direction * length };
129824
+ }
129825
+ return;
129826
+ }
129827
+ if (character2 !== void 0 && matchesCharacterClass(character2, node.items, node.negated, context)) {
129828
+ yield { ...state, position: state.position + context.direction * character2.length };
129402
129829
  }
129403
129830
  return;
129404
129831
  }
@@ -129410,14 +129837,30 @@ function* matchNode(node, state, context) {
129410
129837
  yield* matchNode(alternative, cloneState(state), context);
129411
129838
  }
129412
129839
  return;
129840
+ case "lookahead":
129841
+ case "lookbehind": {
129842
+ const result = matchNode(node.body, cloneState(state), {
129843
+ ...context,
129844
+ direction: node.type === "lookbehind" ? -1 : 1
129845
+ }).next();
129846
+ if (node.negated) {
129847
+ if (result.done) yield state;
129848
+ } else if (!result.done) {
129849
+ yield { position: state.position, captures: result.value.captures };
129850
+ }
129851
+ return;
129852
+ }
129413
129853
  case "group":
129414
- for (const result of matchNode(node.body, cloneState(state), context)) {
129854
+ for (const result of matchNode(node.body, cloneState(state), node.modifiers === void 0 ? context : {
129855
+ ...context,
129856
+ flags: { ...context.flags, ...node.modifiers }
129857
+ })) {
129415
129858
  if (!node.capturing || node.index === void 0) {
129416
129859
  yield result;
129417
129860
  continue;
129418
129861
  }
129419
129862
  const captures = result.captures.slice();
129420
- captures[node.index - 1] = { start: state.position, end: result.position };
129863
+ captures[node.index - 1] = { start: Math.min(state.position, result.position), end: Math.max(state.position, result.position) };
129421
129864
  yield { position: result.position, captures };
129422
129865
  }
129423
129866
  return;
@@ -129431,7 +129874,8 @@ function* matchSequence(elements, index, state, context) {
129431
129874
  yield state;
129432
129875
  return;
129433
129876
  }
129434
- for (const result of matchNode(elements[index], state, context)) {
129877
+ const element = elements[context.direction === 1 ? index : elements.length - 1 - index];
129878
+ for (const result of matchNode(element, state, context)) {
129435
129879
  yield* matchSequence(elements, index + 1, result, context);
129436
129880
  }
129437
129881
  }
@@ -129467,11 +129911,28 @@ function matchesAnchor(kind, position, context) {
129467
129911
  }
129468
129912
  return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
129469
129913
  }
129470
- function matchesCharacterClass(character2, items, negated, ignoreCase) {
129471
- const matched = items.some((item) => matchesCharacterClassItem(character2, item, ignoreCase));
129914
+ function matchesCharacterClass(character2, items, negated, context) {
129915
+ const matched = items.some((item) => {
129916
+ if (context.flags.unicode) charge(context);
129917
+ return matchesCharacterClassItem(character2, item, context.flags.ignoreCase, context.flags.unicode);
129918
+ });
129472
129919
  return negated ? !matched : matched;
129473
129920
  }
129474
- function matchesCharacterClassItem(character2, item, ignoreCase) {
129921
+ function matchesCharacterClassItem(character2, item, ignoreCase, unicode, unicodeSets = false) {
129922
+ if (item.type === "strings" || item.type === "set") return false;
129923
+ if (unicode) {
129924
+ const hex = (value) => `\\u{${value.codePointAt(0).toString(16)}}`;
129925
+ let atom;
129926
+ if (item.type === "character") atom = hex(item.value);
129927
+ else if (item.type === "range") atom = `[${hex(item.from)}-${hex(item.to)}]`;
129928
+ else if (item.type === "property") atom = `\\${item.negated ? "P" : "p"}{${item.value}}`;
129929
+ else {
129930
+ const kind = item.kind === "digit" ? "d" : item.kind === "word" ? "w" : "s";
129931
+ atom = `\\${item.negated ? kind.toUpperCase() : kind}`;
129932
+ }
129933
+ return new RegExp(`^(?:${atom})$`, (ignoreCase ? "i" : "") + (unicodeSets ? "v" : "u")).test(character2);
129934
+ }
129935
+ if (item.type === "property") return false;
129475
129936
  if (item.type === "character") {
129476
129937
  return charactersEqual(character2, item.value, ignoreCase);
129477
129938
  }
@@ -129485,22 +129946,102 @@ function matchesCharacterClassItem(character2, item, ignoreCase) {
129485
129946
  if (!ignoreCase) {
129486
129947
  return false;
129487
129948
  }
129488
- const foldedCandidate = foldCharacter(character2, true).charCodeAt(0);
129489
- const foldedFrom = foldCharacter(item.from, true).charCodeAt(0);
129490
- const foldedTo = foldCharacter(item.to, true).charCodeAt(0);
129491
- return foldedCandidate >= foldedFrom && foldedCandidate <= foldedTo;
129949
+ return new RegExp(`^[\\u${from.toString(16).padStart(4, "0")}-\\u${to.toString(16).padStart(4, "0")}]$`, "i").test(character2);
129492
129950
  }
129493
129951
  const matched = item.kind === "digit" ? isDigit5(character2) : item.kind === "word" ? isWordCharacter(character2) : isSpaceCharacter(character2);
129494
129952
  return item.negated ? !matched : matched;
129495
129953
  }
129496
- function toRegexMatch(input, start, state) {
129497
- return {
129954
+ function matchUnicodeSet(set, position, context) {
129955
+ charge(context);
129956
+ let lengths = /* @__PURE__ */ new Set();
129957
+ for (let index = 0; index < set.items.length; index++) {
129958
+ const next = matchUnicodeSetItem(set.items[index], position, context);
129959
+ if (index === 0) lengths = next;
129960
+ else if (set.operation === void 0) {
129961
+ for (const length of next) {
129962
+ charge(context);
129963
+ lengths.add(length);
129964
+ }
129965
+ } else {
129966
+ for (const length of lengths) {
129967
+ charge(context);
129968
+ if (set.operation === "intersection" ? !next.has(length) : next.has(length)) lengths.delete(length);
129969
+ }
129970
+ }
129971
+ }
129972
+ if (set.negated) {
129973
+ const character2 = readCharacter(context.input, position, context.direction, true);
129974
+ return new Set(character2 !== void 0 && !lengths.has(character2.length) ? [character2.length] : []);
129975
+ }
129976
+ return lengths;
129977
+ }
129978
+ function matchUnicodeSetItem(item, position, context) {
129979
+ charge(context);
129980
+ if (item.type === "set") return matchUnicodeSet(item.value, position, context);
129981
+ const lengths = /* @__PURE__ */ new Set();
129982
+ if (item.type === "strings") {
129983
+ for (const value of item.values) {
129984
+ charge(context);
129985
+ let reference = context.direction === 1 ? 0 : value.length;
129986
+ let cursor2 = position;
129987
+ const end = context.direction === 1 ? value.length : 0;
129988
+ while (reference !== end) {
129989
+ charge(context);
129990
+ const expected = readCharacter(value, reference, context.direction, true);
129991
+ const actual = readCharacter(context.input, cursor2, context.direction, true);
129992
+ if (!charactersEqual(actual, expected, context.flags.ignoreCase, true)) break;
129993
+ reference += context.direction * expected.length;
129994
+ cursor2 += context.direction * actual.length;
129995
+ }
129996
+ if (reference === end) lengths.add(Math.abs(cursor2 - position));
129997
+ }
129998
+ return lengths;
129999
+ }
130000
+ if (item.type === "property" && item.strings) {
130001
+ const atom = `\\p{${item.value}}`;
130002
+ const flags = (context.flags.ignoreCase ? "i" : "") + "v";
130003
+ const matcher = new RegExp(context.direction === 1 ? atom : `(?<=(${atom}))`, flags + "y");
130004
+ matcher.lastIndex = position;
130005
+ const match = matcher.exec(context.input);
130006
+ if (match === null) return lengths;
130007
+ const longest = context.direction === 1 ? match[0] : match[1];
130008
+ const member = new RegExp(`^(?:${atom})$`, flags);
130009
+ let consumed = 0;
130010
+ while (consumed < longest.length) {
130011
+ charge(context);
130012
+ const cursor2 = context.direction === 1 ? consumed : longest.length - consumed;
130013
+ consumed += readCharacter(longest, cursor2, context.direction, true).length;
130014
+ const candidate = context.direction === 1 ? longest.slice(0, consumed) : longest.slice(longest.length - consumed);
130015
+ if (member.test(candidate)) lengths.add(consumed);
130016
+ }
130017
+ return lengths;
130018
+ }
130019
+ const character2 = readCharacter(context.input, position, context.direction, true);
130020
+ if (character2 !== void 0 && matchesCharacterClassItem(character2, item, context.flags.ignoreCase, true, true))
130021
+ lengths.add(character2.length);
130022
+ return lengths;
130023
+ }
130024
+ function toRegexMatch(input, start, state, hasIndices, groups) {
130025
+ const match = {
129498
130026
  index: start,
129499
130027
  text: input.slice(start, state.position),
129500
130028
  captures: state.captures.map(
129501
130029
  (capture) => capture === void 0 ? void 0 : input.slice(capture.start, capture.end)
129502
130030
  )
129503
130031
  };
130032
+ if (hasIndices) {
130033
+ match.indices = [[start, state.position], ...state.captures.map((capture) => capture === void 0 ? void 0 : [capture.start, capture.end])];
130034
+ }
130035
+ if (groups !== void 0) {
130036
+ match.groups = /* @__PURE__ */ Object.create(null);
130037
+ if (hasIndices) match.indicesGroups = /* @__PURE__ */ Object.create(null);
130038
+ for (const [name, indices] of Object.entries(groups)) {
130039
+ const index = indices.find((index2) => state.captures[index2 - 1] !== void 0);
130040
+ match.groups[name] = index === void 0 ? void 0 : match.captures[index - 1];
130041
+ if (match.indicesGroups !== void 0) match.indicesGroups[name] = index === void 0 ? void 0 : match.indices[index];
130042
+ }
130043
+ }
130044
+ return match;
129504
130045
  }
129505
130046
  function cloneState(state) {
129506
130047
  return { position: state.position, captures: state.captures.slice() };
@@ -129530,13 +130071,13 @@ function clearNodeCaptures(node, captures) {
129530
130071
  }
129531
130072
  return;
129532
130073
  }
129533
- if (node.type === "quantifier") {
130074
+ if (node.type === "quantifier" || node.type === "lookahead" || node.type === "lookbehind") {
129534
130075
  clearNodeCaptures(node.body, captures);
129535
130076
  }
129536
130077
  }
129537
130078
  function charge(context) {
129538
- context.steps += 1;
129539
- allocateRegexSteps(context.steps);
130079
+ context.work.steps += 1;
130080
+ allocateRegexSteps(context.work.steps);
129540
130081
  }
129541
130082
  function normalizeLastIndex(lastIndex) {
129542
130083
  if (Number.isNaN(lastIndex) || lastIndex <= 0) {
@@ -129544,9 +130085,20 @@ function normalizeLastIndex(lastIndex) {
129544
130085
  }
129545
130086
  return Math.min(Math.floor(lastIndex), Number.MAX_SAFE_INTEGER);
129546
130087
  }
129547
- function charactersEqual(left, right, ignoreCase) {
130088
+ function charactersEqual(left, right, ignoreCase, unicode = false) {
130089
+ if (unicode && ignoreCase && left !== void 0)
130090
+ return new RegExp(`^\\u{${right.codePointAt(0).toString(16)}}$`, "iu").test(left);
129548
130091
  return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
129549
130092
  }
130093
+ function advanceStringIndex(input, index, unicode) {
130094
+ return index + (unicode && (input.codePointAt(index) ?? 0) > 65535 ? 2 : 1);
130095
+ }
130096
+ function readCharacter(input, position, direction, unicode) {
130097
+ let index = direction === 1 ? position : position - 1;
130098
+ if (index < 0 || index >= input.length) return void 0;
130099
+ 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--;
130100
+ return unicode ? String.fromCodePoint(input.codePointAt(index)) : input[index];
130101
+ }
129550
130102
  function foldCharacter(character2, ignoreCase) {
129551
130103
  if (!ignoreCase) {
129552
130104
  return character2;
@@ -130124,7 +130676,7 @@ function callReplaceLikeMethod(value, methodName, args, budget, callClosure, use
130124
130676
  );
130125
130677
  }
130126
130678
  async function replaceRegex(value, regex, replacement, budget, callClosure, context) {
130127
- if (hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
130679
+ if (getSandboxRegexPattern(regex).groups !== void 0 || hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
130128
130680
  return regexReplace(value, regex, replacement, budget, callClosure, context);
130129
130681
  if (regex.flags.includes("g")) regex.lastIndex = 0;
130130
130682
  const cursor2 = regex.lastIndex;
@@ -130174,7 +130726,7 @@ async function regexReplace(input, regex, replacementInput, budget, callClosure,
130174
130726
  input = void 0;
130175
130727
  replacement = isSandboxClosure(replacementInput) ? replacementInput : await sandboxString(replacementInput, budget, context);
130176
130728
  replacementInput = void 0;
130177
- if (isSandboxRegex(regex) && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
130729
+ if (isSandboxRegex(regex) && getSandboxRegexPattern(regex).groups === void 0 && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
130178
130730
  release2();
130179
130731
  return await replaceRegex(value, regex, replacement, budget, callClosure, context);
130180
130732
  }
@@ -130389,7 +130941,7 @@ function splitNormalized(value, separator, limit, budget, parent) {
130389
130941
  while (result2.length < limit) {
130390
130942
  const match = executeRegex(splitter, value, Number(splitter.lastIndex));
130391
130943
  if (match === null) break;
130392
- if (match.text.length === 0) splitter.lastIndex = match.index + 1;
130944
+ if (match.text.length === 0) splitter.lastIndex = advanceStringIndex(value, match.index, splitter.flags.includes("u") || splitter.flags.includes("v"));
130393
130945
  endedWithZeroWidthMatch = match.text.length === 0 && match.index === value.length;
130394
130946
  if (match.text.length === 0 && (match.index === copiedThrough || match.index === value.length))
130395
130947
  continue;
@@ -130548,7 +131100,7 @@ function callMatchLikeMethod(value, methodName, args, compilation, lastIndex) {
130548
131100
  return match?.index ?? -1;
130549
131101
  }
130550
131102
  if (methodName === "match" && !regex.flags.includes("g"))
130551
- return toMatchArray(executeRegex(regex, value, lastIndex ?? Number(regex.lastIndex)), value);
131103
+ return toMatchArray(executeRegex(regex, value, lastIndex ?? Number(regex.lastIndex)), value, compilation.owner?.budget);
130552
131104
  if (methodName === "match") regex.lastIndex = 0;
130553
131105
  const matcher = methodName === "matchAll" ? createSandboxRegex(regex.source, regex.flags, normalizeLastIndex(lastIndex ?? Number(regex.lastIndex)), compilation) : regex;
130554
131106
  if (methodName === "matchAll")
@@ -130564,7 +131116,7 @@ function collectRegexMatches(regex, value, all, budget, lastIndex = 0) {
130564
131116
  budget?.allocateArrayLength(matches.length + 1);
130565
131117
  matches.push(match);
130566
131118
  lastIndex = match.index + match.text.length;
130567
- if (all && match.text.length === 0) regex.lastIndex = ++lastIndex;
131119
+ if (all && match.text.length === 0) regex.lastIndex = lastIndex = advanceStringIndex(value, lastIndex, regex.flags.includes("u") || regex.flags.includes("v"));
130568
131120
  } while (all);
130569
131121
  return matches;
130570
131122
  }
@@ -136968,7 +137520,7 @@ async function callRegexMethod(target, methodName, args, budget, context) {
136968
137520
  cursor2 = target.lastIndex;
136969
137521
  const lastIndex = await sandboxNumber(cursor2, budget, context);
136970
137522
  const match = executeRegex(target, input, lastIndex);
136971
- return toMatchArray(match, input);
137523
+ return toMatchArray(match, input, budget);
136972
137524
  } finally {
136973
137525
  budget.setRetainedValues(retained, void 0);
136974
137526
  }
@@ -137019,17 +137571,26 @@ async function regexToString(target, budget, context) {
137019
137571
  function executeRegex(target, input, lastIndex) {
137020
137572
  const pattern = getSandboxRegexPattern(target);
137021
137573
  const match = matchRegex(pattern, input, lastIndex);
137022
- if (pattern.flags.global) {
137574
+ if (pattern.flags.global || pattern.flags.sticky) {
137023
137575
  target.lastIndex = match === null ? 0 : match.index + match.text.length;
137024
137576
  }
137025
137577
  return match;
137026
137578
  }
137027
- function toMatchArray(match, input) {
137579
+ function toMatchArray(match, input, budget) {
137028
137580
  if (match === null) {
137029
137581
  return null;
137030
137582
  }
137583
+ budget?.allocateArrayLength(match.captures.length + 1);
137031
137584
  const result = [match.text, ...match.captures];
137032
- Object.assign(result, { index: match.index, input, groups: void 0 });
137585
+ if (match.groups !== void 0) setSandboxPrototype(match.groups, null, budget);
137586
+ if (match.indicesGroups !== void 0) setSandboxPrototype(match.indicesGroups, null, budget);
137587
+ Object.assign(result, { index: match.index, input, groups: match.groups });
137588
+ if (match.indices !== void 0) {
137589
+ budget?.allocateArrayLength(match.indices.length);
137590
+ budget?.allocateArrayLength(2);
137591
+ Object.assign(match.indices, { groups: match.indicesGroups });
137592
+ Object.assign(result, { indices: match.indices });
137593
+ }
137033
137594
  return result;
137034
137595
  }
137035
137596
  var regexMethodNames, regexFlagProperties;
@@ -137064,9 +137625,10 @@ function nextRegExpIterator(iterator, budget) {
137064
137625
  budget?.visitNode();
137065
137626
  if (state.exhausted) return { value: void 0, done: true };
137066
137627
  const matcher = state.matcher;
137628
+ if (!isSandboxRegex(matcher)) throw new TypeError("Custom RegExp iterator execution requires a sandbox context.");
137067
137629
  const input = state.input;
137068
137630
  const match = executeRegex(matcher, input, Number(matcher.lastIndex));
137069
- if (match === null || !matcher.flags.includes("g")) {
137631
+ if (match === null || !(state.global ?? matcher.flags.includes("g"))) {
137070
137632
  state.exhausted = true;
137071
137633
  state.matcher = void 0;
137072
137634
  state.input = void 0;
@@ -137074,12 +137636,52 @@ function nextRegExpIterator(iterator, budget) {
137074
137636
  if (match === null) return { value: void 0, done: true };
137075
137637
  if (!state.exhausted && match.text.length === 0) {
137076
137638
  const index = Number(matcher.lastIndex);
137077
- const unicode = matcher.flags.includes("u") || matcher.flags.includes("v");
137639
+ const unicode = state.unicode ?? (matcher.flags.includes("u") || matcher.flags.includes("v"));
137078
137640
  const codePoint = input.codePointAt(index);
137079
137641
  matcher.lastIndex = index + (unicode && codePoint !== void 0 && codePoint > 65535 ? 2 : 1);
137080
137642
  }
137081
- budget?.allocateArrayLength(match.captures.length + 1);
137082
- return { value: toMatchArray(match, input), done: false };
137643
+ return { value: toMatchArray(match, input, budget), done: false };
137644
+ }
137645
+ async function nextObservableRegExpIterator(iterator, budget, context) {
137646
+ const state = regexpIteratorState(iterator);
137647
+ if (state.exhausted) return { value: void 0, done: true };
137648
+ const matcher = state.matcher;
137649
+ if (isSandboxRegex(matcher) && !hasRegexPropertyOverride(matcher, ["exec"], budget) && (matcher.lastIndex === null || typeof matcher.lastIndex !== "object"))
137650
+ return nextRegExpIterator(iterator, budget);
137651
+ const input = state.input;
137652
+ let result;
137653
+ let field;
137654
+ const release2 = retainValues(budget, () => [iterator, matcher, input, result, field]);
137655
+ const read = (value, key3) => {
137656
+ if (context.getProperty !== void 0) return context.getProperty(value, key3);
137657
+ const descriptor = getSandboxPropertyDescriptor(value, key3, budget);
137658
+ return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
137659
+ };
137660
+ try {
137661
+ budget.visitNode();
137662
+ result = await regexExec(matcher, input, budget, context);
137663
+ const global2 = state.global ?? (isSandboxRegex(matcher) && matcher.flags.includes("g"));
137664
+ if (result === null || !global2) {
137665
+ state.exhausted = true;
137666
+ state.matcher = void 0;
137667
+ state.input = void 0;
137668
+ return result === null ? { value: void 0, done: true } : { value: result, done: false };
137669
+ }
137670
+ field = await read(result, "0");
137671
+ const text5 = await sandboxString(field, budget, context);
137672
+ field = void 0;
137673
+ if (text5.length === 0) {
137674
+ field = await read(matcher, "lastIndex");
137675
+ const index = normalizeLastIndex(await sandboxNumber(field, budget, context));
137676
+ field = void 0;
137677
+ const unicode = state.unicode ?? (isSandboxRegex(matcher) && (matcher.flags.includes("u") || matcher.flags.includes("v")));
137678
+ const point = input.codePointAt(index);
137679
+ await setSandboxProperty(matcher, "lastIndex", index + (unicode && point !== void 0 && point > 65535 ? 2 : 1), budget, true, context);
137680
+ }
137681
+ return { value: result, done: false };
137682
+ } finally {
137683
+ release2();
137684
+ }
137083
137685
  }
137084
137686
  function getRegExpIteratorMember(property, budget) {
137085
137687
  if (property === Symbol.toStringTag) return "RegExp String Iterator";
@@ -137096,7 +137698,7 @@ function getRegExpIteratorMember(property, budget) {
137096
137698
  const receiver = context?.thisValue;
137097
137699
  if (!isSandboxRegExpIterator(receiver))
137098
137700
  throw new TypeError("RegExp string iterator next requires a matching receiver.");
137099
- return nextRegExpIterator(receiver, budget);
137701
+ return context === void 0 ? nextRegExpIterator(receiver, budget) : nextObservableRegExpIterator(receiver, budget, context);
137100
137702
  }
137101
137703
  });
137102
137704
  }
@@ -137106,6 +137708,12 @@ var init_regexp_iterator2 = __esm({
137106
137708
  init_regexp_iterator();
137107
137709
  init_values();
137108
137710
  init_regex();
137711
+ init_object_model();
137712
+ init_accessors();
137713
+ init_interpreter();
137714
+ init_string_coercion();
137715
+ init_engine2();
137716
+ init_resources();
137109
137717
  }
137110
137718
  });
137111
137719
 
@@ -137292,8 +137900,11 @@ function getSandboxIterator(value, budget, context) {
137292
137900
  }
137293
137901
  if (isSandboxCollectionIterator(value))
137294
137902
  return { next: () => nextCollectionIterator(value, budget), snapshotIndex: () => 0 };
137295
- if (isSandboxRegExpIterator(value))
137903
+ if (isSandboxRegExpIterator(value)) {
137904
+ if (context !== void 0 && budget !== void 0)
137905
+ return { asynchronous: true, next: () => nextObservableRegExpIterator(value, budget, context), snapshotIndex: () => 0 };
137296
137906
  return { next: () => nextRegExpIterator(value, budget), snapshotIndex: () => 0 };
137907
+ }
137297
137908
  if (isGuestHostObject(value)) return getHostObjectIterator(value);
137298
137909
  if (isFloat32Array(value)) {
137299
137910
  return syncIterator(Float32Array.prototype.values.call(value));
@@ -141550,7 +142161,7 @@ function copyToSandbox(value, state, path193 = "<root>", cloneSandboxCollections
141550
142161
  const copy = restoreSandboxRegExpIterator({ matcher: void 0, input: void 0, exhausted: true });
141551
142162
  state.seen.set(value, copy);
141552
142163
  const matcher = copyToSandbox(snapshot2.matcher, state, `${path193}.<matcher>`, true, depth + 1);
141553
- if (matcher !== void 0 && !isSandboxRegex(matcher)) throw new TypeError("Invalid RegExp iterator matcher.");
142164
+ if (matcher !== void 0 && (snapshot2.global === void 0 ? !isSandboxRegex(matcher) : matcher === null || typeof matcher !== "object")) throw new TypeError("Invalid RegExp iterator matcher.");
141554
142165
  restoreSandboxRegExpIterator({ ...snapshot2, matcher }, copy);
141555
142166
  for (const entry of getEnumerableObjectEntries(value, path193)) {
141556
142167
  defineOwnDataProperty(copy, entry.key, copyToSandbox(entry.value, state, joinPath2(path193, entry.key), true, depth + 1));
@@ -141738,6 +142349,7 @@ function copyToSandbox(value, state, path193 = "<root>", cloneSandboxCollections
141738
142349
  const copy = createPlainObject(
141739
142350
  !cloneSandboxCollections || Object.getPrototypeOf(value) === null
141740
142351
  );
142352
+ if (!state.structuredClone && hasNullObjectPrototype(value)) setSandboxPrototype(copy, null);
141741
142353
  state.seen.set(value, copy);
141742
142354
  const errorType = sandboxErrorTypes.get(value);
141743
142355
  if (errorType !== void 0) sandboxErrorTypes.set(copy, errorType);
@@ -141949,7 +142561,7 @@ function copyFromSandbox(value, state, path193 = "<root>", options, depth = 0) {
141949
142561
  if (existing !== void 0) {
141950
142562
  return existing;
141951
142563
  }
141952
- const copy = createPlainObject(Object.getPrototypeOf(value) === null);
142564
+ const copy = createPlainObject(hasNullObjectPrototype(value) || Object.getPrototypeOf(value) === null);
141953
142565
  state.seen.set(value, copy);
141954
142566
  for (const entry of getEnumerableObjectEntries(value, path193)) {
141955
142567
  defineOwnDataProperty(
@@ -142372,11 +142984,14 @@ function serializeHeapReference(value, path193, state) {
142372
142984
  if (isSandboxRegExpIterator(value)) {
142373
142985
  const snapshot2 = regexpIteratorState(value);
142374
142986
  const matcher = snapshot2.matcher;
142987
+ const serializedMatcher = snapshot2.global === void 0 && isSandboxRegex(matcher) ? { kind: "regex", source: matcher.source, flags: matcher.flags, lastIndex: Number(matcher.lastIndex) } : serializeDumpValue(matcher, `${path193}.<matcher>`, state);
142988
+ if (serializedMatcher === SKIP_VALUE) throw new TypeError("Unsupported RegExp iterator matcher in public dump.");
142375
142989
  const entries = /* @__PURE__ */ Object.create(null);
142376
142990
  state.heap[String(id)] = {
142377
142991
  kind: "regexp-iterator",
142378
142992
  exhausted: snapshot2.exhausted,
142379
- matcher: matcher === void 0 ? { kind: "undefined" } : { kind: "regex", source: matcher.source, flags: matcher.flags, lastIndex: Number(matcher.lastIndex) },
142993
+ matcher: serializedMatcher,
142994
+ ...snapshot2.global === void 0 ? {} : { global: snapshot2.global, unicode: snapshot2.unicode },
142380
142995
  input: snapshot2.input ?? { kind: "undefined" },
142381
142996
  entries,
142382
142997
  symbolEntries: serializeSymbolProperties(value, (entry) => {
@@ -142449,6 +143064,7 @@ function serializeHeapReference(value, path193, state) {
142449
143064
  });
142450
143065
  state.heap[String(id)] = {
142451
143066
  kind: "object",
143067
+ ...hasNullObjectPrototype(value) ? { sandboxNullPrototype: true } : {},
142452
143068
  entries: serializeObjectEntries(value, path193, state),
142453
143069
  ...symbolEntries.length === 0 ? {} : { symbolEntries },
142454
143070
  ...errorType === void 0 ? {} : { errorType }
@@ -142482,7 +143098,7 @@ function indexHeapContainers(snapshot2) {
142482
143098
  const heapIds = /* @__PURE__ */ new Map();
142483
143099
  let nextId = 1;
142484
143100
  for (const [value, stat35] of stats2.entries()) {
142485
- if (stat35.count > 1 || stat35.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)) {
143101
+ if (stat35.count > 1 || stat35.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)) {
142486
143102
  heapIds.set(value, nextId);
142487
143103
  nextId += 1;
142488
143104
  }
@@ -142664,6 +143280,8 @@ function validateDumpHeap(root, state) {
142664
143280
  continue;
142665
143281
  }
142666
143282
  if (entry.kind === "object") {
143283
+ if (Object.hasOwn(entry, "sandboxNullPrototype") && entry.sandboxNullPrototype !== true)
143284
+ fail2("invalidValue", `${path193}.sandboxNullPrototype`, "invalid object prototype");
142667
143285
  requireRecord3(entry.entries, `${path193}.entries`);
142668
143286
  continue;
142669
143287
  }
@@ -142784,7 +143402,11 @@ function validateTaggedValue(record2, path193, state) {
142784
143402
  return;
142785
143403
  case "array":
142786
143404
  case "arguments":
143405
+ return;
142787
143406
  case "object":
143407
+ if (Object.hasOwn(record2, "sandboxNullPrototype") && record2.sandboxNullPrototype !== true)
143408
+ fail2("invalidValue", `${path193}.sandboxNullPrototype`, "invalid object prototype");
143409
+ return;
142788
143410
  case "map":
142789
143411
  case "set":
142790
143412
  case "collection-iterator":
@@ -142854,6 +143476,8 @@ function validateHeapValue(value, path193, state, heap) {
142854
143476
  }
142855
143477
  if (record2.kind === "set") requireArray(record2.values, `${path193}.values`, state);
142856
143478
  if (record2.kind === "regexp-iterator") {
143479
+ if ((record2.global !== void 0 || record2.unicode !== void 0) && (typeof record2.global !== "boolean" || typeof record2.unicode !== "boolean"))
143480
+ fail2("invalidValue", path193, "invalid RegExp iterator modes");
142857
143481
  if (typeof record2.exhausted !== "boolean") fail2("invalidValue", `${path193}.exhausted`, "invalid iterator exhaustion");
142858
143482
  if (!Object.hasOwn(record2, "matcher") || !Object.hasOwn(record2, "input")) fail2("invalidValue", path193, "missing RegExp iterator state");
142859
143483
  requireRecord3(record2.entries, `${path193}.entries`);
@@ -155079,6 +155703,104 @@ var init_math = __esm({
155079
155703
  }
155080
155704
  });
155081
155705
 
155706
+ // packages/safe-js/src/interp/methods/regex-split.ts
155707
+ async function regexSplit(target, input, limit, constructor, budget, context) {
155708
+ if (target === null || typeof target !== "object") throw new TypeError("RegExp split requires an object receiver.");
155709
+ let string;
155710
+ let species;
155711
+ let field;
155712
+ let flags;
155713
+ let matcher;
155714
+ let match;
155715
+ const result = [];
155716
+ const release2 = retainValues(budget, () => [target, input, limit, string, species, field, flags, matcher, match, result]);
155717
+ const read = (value, key3) => {
155718
+ if (context?.getProperty !== void 0) return context.getProperty(value, key3);
155719
+ const descriptor = getSandboxPropertyDescriptor(value, key3, budget);
155720
+ return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
155721
+ };
155722
+ const append = (value) => {
155723
+ budget.allocateArrayLength(result.length + 1);
155724
+ result.push(value);
155725
+ };
155726
+ try {
155727
+ string = await sandboxString(input, budget, context);
155728
+ input = void 0;
155729
+ field = await read(target, "constructor");
155730
+ species = constructor;
155731
+ if (field !== void 0) {
155732
+ if (field === null || typeof field !== "object") throw new TypeError("Invalid RegExp species constructor.");
155733
+ species = await read(field, Symbol.species);
155734
+ if (species === null || species === void 0) species = constructor;
155735
+ }
155736
+ field = void 0;
155737
+ if (!isSandboxClosure(species) || species.construct === void 0) throw new TypeError("RegExp species must be a constructor.");
155738
+ field = await read(target, "flags");
155739
+ flags = await sandboxString(field, budget, context);
155740
+ field = void 0;
155741
+ const unicode = flags.includes("u") || flags.includes("v");
155742
+ if (!flags.includes("y")) flags = budget.allocateString(flags + "y");
155743
+ matcher = await invokeBuiltinClosure(species, [target, flags], budget, context, void 0, true);
155744
+ const maximum = limit === void 0 ? 2 ** 32 - 1 : await sandboxNumber(limit, budget, context) >>> 0;
155745
+ limit = void 0;
155746
+ if (maximum === 0) return result;
155747
+ if (string.length === 0) {
155748
+ match = await regexExec(matcher, string, budget, context);
155749
+ if (match === null) append(string);
155750
+ return result;
155751
+ }
155752
+ let end = 0;
155753
+ let index = 0;
155754
+ while (index < string.length) {
155755
+ budget.visitNode();
155756
+ match = void 0;
155757
+ await setSandboxProperty(matcher, "lastIndex", index, budget, true, context);
155758
+ match = await regexExec(matcher, string, budget, context);
155759
+ if (match !== null) {
155760
+ field = await read(matcher, "lastIndex");
155761
+ const next = Math.min(normalizeLastIndex(await sandboxNumber(field, budget, context)), string.length);
155762
+ field = void 0;
155763
+ if (next !== end) {
155764
+ append(budget.allocateString(string.slice(end, index)));
155765
+ if (result.length === maximum) return result;
155766
+ end = next;
155767
+ field = await read(match, "length");
155768
+ const length = normalizeLastIndex(await sandboxNumber(field, budget, context));
155769
+ field = void 0;
155770
+ for (let capture = 1; capture < length; capture++) {
155771
+ budget.visitNode();
155772
+ field = await read(match, String(capture));
155773
+ append(field);
155774
+ field = void 0;
155775
+ if (result.length === maximum) return result;
155776
+ }
155777
+ index = end;
155778
+ continue;
155779
+ }
155780
+ }
155781
+ index += unicode && (string.codePointAt(index) ?? 0) > 65535 ? 2 : 1;
155782
+ }
155783
+ append(budget.allocateString(string.slice(end)));
155784
+ return result;
155785
+ } finally {
155786
+ release2();
155787
+ }
155788
+ }
155789
+ var init_regex_split = __esm({
155790
+ "packages/safe-js/src/interp/methods/regex-split.ts"() {
155791
+ "use strict";
155792
+ init_values();
155793
+ init_object_model();
155794
+ init_accessors();
155795
+ init_builtin_call();
155796
+ init_interpreter();
155797
+ init_string_coercion();
155798
+ init_engine2();
155799
+ init_resources();
155800
+ init_regex();
155801
+ }
155802
+ });
155803
+
155082
155804
  // packages/safe-js/src/interp/globals/regex.ts
155083
155805
  function createRegexGlobals(options) {
155084
155806
  const invoke2 = (construct) => async (args, context) => {
@@ -155143,7 +155865,55 @@ function createRegexGlobals(options) {
155143
155865
  }
155144
155866
  };
155145
155867
  const constructor = createSandboxClosure({ guest: true, sandbox: true, name: "RegExp", length: 2, call: invoke2(false), construct: invoke2(true) });
155868
+ Object.defineProperty(materializeFunctionProperties(constructor), "escape", {
155869
+ value: createSandboxClosure({
155870
+ guest: true,
155871
+ sandbox: true,
155872
+ name: "escape",
155873
+ length: 1,
155874
+ call: (args) => {
155875
+ const input = args[0];
155876
+ if (typeof input !== "string") throw new TypeError("RegExp.escape requires a string.");
155877
+ const allocation = {};
155878
+ let escaped = "";
155879
+ try {
155880
+ for (const character2 of input) {
155881
+ options.budget.visitNode();
155882
+ const point = character2.codePointAt(0);
155883
+ let part = character2;
155884
+ if (escaped.length === 0 && (point >= 48 && point <= 57 || point >= 65 && point <= 90 || point >= 97 && point <= 122)) {
155885
+ part = `\\x${point.toString(16)}`;
155886
+ } else if ("^$\\.*+?()[]{}|/".includes(character2)) {
155887
+ part = "\\" + character2;
155888
+ } else {
155889
+ const control2 = "\f\n\r \v".indexOf(character2);
155890
+ if (control2 !== -1) part = "\\" + "fnrtv"[control2];
155891
+ else if (",-=<>#&!%:;@~'`\"".includes(character2) || character2.trim() === "" || point >= 55296 && point <= 57343) {
155892
+ part = point <= 255 ? `\\x${point.toString(16).padStart(2, "0")}` : `\\u${point.toString(16).padStart(4, "0")}`;
155893
+ }
155894
+ }
155895
+ options.budget.setRetainedDataUsage(allocation, escaped.length + part.length);
155896
+ escaped = options.budget.allocateString(escaped + part);
155897
+ }
155898
+ return escaped;
155899
+ } finally {
155900
+ options.budget.setRetainedDataUsage(allocation, 0);
155901
+ }
155902
+ }
155903
+ }),
155904
+ writable: true,
155905
+ configurable: true
155906
+ });
155146
155907
  const prototype = /* @__PURE__ */ Object.create(null);
155908
+ Object.defineProperty(materializeFunctionProperties(constructor), Symbol.species, {
155909
+ get: accessorAdapter(createSandboxClosure({
155910
+ sandbox: true,
155911
+ name: "get [Symbol.species]",
155912
+ length: 0,
155913
+ call: (_args, context) => context?.thisValue
155914
+ }), "get"),
155915
+ configurable: true
155916
+ });
155147
155917
  Object.defineProperty(materializeFunctionProperties(constructor), "prototype", { value: prototype, writable: false });
155148
155918
  Object.defineProperty(prototype, "constructor", { value: constructor, writable: true, configurable: true });
155149
155919
  Object.defineProperty(prototype, Symbol.search, {
@@ -155186,6 +155956,73 @@ function createRegexGlobals(options) {
155186
155956
  writable: true,
155187
155957
  configurable: true
155188
155958
  });
155959
+ Object.defineProperty(prototype, Symbol.matchAll, {
155960
+ value: createSandboxClosure({
155961
+ guest: true,
155962
+ sandbox: true,
155963
+ name: "[Symbol.matchAll]",
155964
+ length: 1,
155965
+ call: async (args, context) => {
155966
+ const target = context?.thisValue;
155967
+ if (target === null || typeof target !== "object") throw new TypeError("RegExp matchAll requires an object receiver.");
155968
+ let input = args[0];
155969
+ let string;
155970
+ let species;
155971
+ let field;
155972
+ let flags;
155973
+ let matcher;
155974
+ const release2 = retainValues(options.budget, () => [target, input, string, species, field, flags, matcher]);
155975
+ const read = (value, key3) => {
155976
+ if (context?.getProperty !== void 0) return context.getProperty(value, key3);
155977
+ const descriptor = getSandboxPropertyDescriptor(value, key3, options.budget);
155978
+ return descriptor === void 0 ? void 0 : readPropertyDescriptor(descriptor, value, context);
155979
+ };
155980
+ try {
155981
+ string = await sandboxString(input, options.budget, context);
155982
+ input = void 0;
155983
+ field = await read(target, "constructor");
155984
+ species = constructor;
155985
+ if (field !== void 0) {
155986
+ if (field === null || typeof field !== "object") throw new TypeError("Invalid RegExp species constructor.");
155987
+ species = await read(field, Symbol.species);
155988
+ if (species === null || species === void 0) species = constructor;
155989
+ }
155990
+ field = void 0;
155991
+ if (!isSandboxClosure(species) || species.construct === void 0) throw new TypeError("RegExp species must be a constructor.");
155992
+ field = await read(target, "flags");
155993
+ flags = await sandboxString(field, options.budget, context);
155994
+ field = void 0;
155995
+ matcher = await invokeBuiltinClosure(species, [target, flags], options.budget, context, void 0, true);
155996
+ field = await read(target, "lastIndex");
155997
+ const cursor2 = normalizeLastIndex(await sandboxNumber(field, options.budget, context));
155998
+ field = void 0;
155999
+ await setSandboxProperty(matcher, "lastIndex", cursor2, options.budget, true, context);
156000
+ return restoreSandboxRegExpIterator({
156001
+ matcher,
156002
+ input: string,
156003
+ exhausted: false,
156004
+ global: flags.includes("g"),
156005
+ unicode: flags.includes("u") || flags.includes("v")
156006
+ });
156007
+ } finally {
156008
+ release2();
156009
+ }
156010
+ }
156011
+ }),
156012
+ writable: true,
156013
+ configurable: true
156014
+ });
156015
+ Object.defineProperty(prototype, Symbol.split, {
156016
+ value: createSandboxClosure({
156017
+ guest: true,
156018
+ sandbox: true,
156019
+ name: "[Symbol.split]",
156020
+ length: 2,
156021
+ call: (args, context) => regexSplit(context?.thisValue, args[0], args[1], constructor, options.budget, context)
156022
+ }),
156023
+ writable: true,
156024
+ configurable: true
156025
+ });
155189
156026
  for (const name of ["exec", "test", "toString"]) {
155190
156027
  Object.defineProperty(prototype, name, {
155191
156028
  value: createSandboxClosure({
@@ -155231,6 +156068,11 @@ var init_regex2 = __esm({
155231
156068
  init_regex();
155232
156069
  init_string();
155233
156070
  init_builtin_call();
156071
+ init_regexp_iterator();
156072
+ init_engine2();
156073
+ init_resources();
156074
+ init_interpreter();
156075
+ init_regex_split();
155234
156076
  }
155235
156077
  });
155236
156078