@poe-platform/safe-js 0.1.197 → 0.1.198

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.
@@ -27,7 +27,7 @@ import {
27
27
  validateMigrationSemantics,
28
28
  validateSnapshotData,
29
29
  validateSnapshotMigration
30
- } from "./chunk-7KLRGTR4.js";
30
+ } from "./chunk-T43UKNMF.js";
31
31
 
32
32
  // packages/safe-js/src/migrate.ts
33
33
  import { createHash } from "node:crypto";
@@ -8249,4 +8249,4 @@ export {
8249
8249
  parseMcpConfig,
8250
8250
  makeMcpModule
8251
8251
  };
8252
- //# sourceMappingURL=chunk-GMRA5QVS.js.map
8252
+ //# sourceMappingURL=chunk-4WIZV3GZ.js.map
@@ -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,6 +745,8 @@ 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":
742
752
  case "backreference":
@@ -756,7 +766,7 @@ function measureNode(node) {
756
766
  return usage;
757
767
  }
758
768
  case "group":
759
- return 5 + measureNode(node.body);
769
+ return 5 + measureNode(node.body) + (node.name === void 0 ? 0 : 1 + node.name.length);
760
770
  case "lookahead":
761
771
  case "lookbehind":
762
772
  return 4 + measureNode(node.body);
@@ -2049,6 +2059,8 @@ function createIdentifier(token, name) {
2049
2059
  }
2050
2060
 
2051
2061
  // packages/safe-js/src/interp/regex/parse.ts
2062
+ var groupNameStart = /^[$_\p{ID_Start}]$/u;
2063
+ var groupNamePart = /^[$\u200c\u200d\p{ID_Continue}]$/u;
2052
2064
  function parseRegex(source, flags = "", compilation, valueUnits = 0) {
2053
2065
  const guard = new RegexCompileGuard(compilation);
2054
2066
  try {
@@ -2060,6 +2072,7 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
2060
2072
  const body = parser.parse();
2061
2073
  guard.allocate(5 + source.length);
2062
2074
  const pattern = { source, flags: parsedFlags, captureCount: parser.captureCount, body };
2075
+ if (Object.keys(parser.namedGroups).length > 0) pattern.groups = parser.namedGroups;
2063
2076
  guard.retain(pattern, valueUnits);
2064
2077
  return pattern;
2065
2078
  } finally {
@@ -2076,6 +2089,8 @@ var RegexParser = class {
2076
2089
  captureCount = 0;
2077
2090
  cursor = 0;
2078
2091
  totalCaptureCount;
2092
+ hasNamedCaptures = false;
2093
+ namedGroups = /* @__PURE__ */ Object.create(null);
2079
2094
  get position() {
2080
2095
  return this.cursor;
2081
2096
  }
@@ -2091,6 +2106,7 @@ var RegexParser = class {
2091
2106
  }
2092
2107
  this.fail(`Unexpected character '${this.peek()}'`);
2093
2108
  }
2109
+ if (Object.keys(this.namedGroups).length > 0) this.validateNamedGroups(body);
2094
2110
  return body;
2095
2111
  }
2096
2112
  parseAlternation() {
@@ -2167,6 +2183,7 @@ var RegexParser = class {
2167
2183
  }
2168
2184
  parseGroup(start) {
2169
2185
  let capturing = true;
2186
+ let name;
2170
2187
  let assertionNegated;
2171
2188
  let lookbehind = false;
2172
2189
  if (this.peek() === "?") {
@@ -2186,13 +2203,20 @@ var RegexParser = class {
2186
2203
  lookbehind = true;
2187
2204
  this.position += 3;
2188
2205
  } else if (extension.startsWith("?<")) {
2189
- this.fail("Named groups are not supported", start);
2206
+ this.position += 2;
2207
+ name = this.parseGroupName(start);
2190
2208
  } else {
2191
2209
  this.fail("Unsupported group construct", start);
2192
2210
  }
2193
2211
  }
2194
2212
  if (capturing) this.guard.allocate(1);
2195
2213
  const index = capturing ? ++this.captureCount : void 0;
2214
+ if (name !== void 0) {
2215
+ this.guard.allocate(name.length + 2);
2216
+ const indices = this.namedGroups[name] ??= [];
2217
+ this.guard.array(indices.length + 1);
2218
+ indices.push(index);
2219
+ }
2196
2220
  this.guard.enterGroup();
2197
2221
  let body;
2198
2222
  try {
@@ -2209,7 +2233,7 @@ var RegexParser = class {
2209
2233
  return { type: lookbehind ? "lookbehind" : "lookahead", negated: assertionNegated, body };
2210
2234
  }
2211
2235
  this.guard.allocate(5);
2212
- return { type: "group", capturing, index, body };
2236
+ return { type: "group", capturing, index, body, ...name === void 0 ? {} : { name } };
2213
2237
  }
2214
2238
  parseCharacterClass(start) {
2215
2239
  const negated = this.peek() === "^";
@@ -2269,6 +2293,15 @@ var RegexParser = class {
2269
2293
  this.fail("Trailing escape", start);
2270
2294
  }
2271
2295
  const escaped = this.take();
2296
+ if (escaped === "k") {
2297
+ this.totalCaptureCount ??= this.countAllCaptures();
2298
+ if (this.hasNamedCaptures) {
2299
+ if (inCharacterClass || this.take() !== "<") this.fail("Invalid named backreference", start);
2300
+ const name = this.parseGroupName(start);
2301
+ this.guard.allocate(3 + name.length);
2302
+ return { type: "namedBackreference", name };
2303
+ }
2304
+ }
2272
2305
  if (isDecimalDigit2(escaped)) {
2273
2306
  if (!inCharacterClass && escaped !== "0") {
2274
2307
  let end = this.position;
@@ -2358,10 +2391,62 @@ var RegexParser = class {
2358
2391
  else if (character === "\\") escaped = true;
2359
2392
  else if (character === "[") characterClass = true;
2360
2393
  else if (character === "]") characterClass = false;
2361
- else if (!characterClass && character === "(" && this.source[index + 1] !== "?") count++;
2394
+ else if (!characterClass && character === "(") {
2395
+ const named = this.source[index + 1] === "?" && this.source[index + 2] === "<" && this.source[index + 3] !== "=" && this.source[index + 3] !== "!";
2396
+ if (named) this.hasNamedCaptures = true;
2397
+ if (named || this.source[index + 1] !== "?") count++;
2398
+ }
2362
2399
  }
2363
2400
  return count;
2364
2401
  }
2402
+ parseGroupName(start) {
2403
+ let name = "";
2404
+ while (!this.atEnd() && this.peek() !== ">") {
2405
+ let character = this.take();
2406
+ if (character === "\\") {
2407
+ if (this.take() !== "u") this.fail("Invalid group name escape", start);
2408
+ if (this.peek() === "{") {
2409
+ this.position++;
2410
+ const begin = this.position;
2411
+ while (!this.atEnd() && this.peek() !== "}") this.position++;
2412
+ this.guard.allocate(this.position - begin);
2413
+ const digits = this.source.slice(begin, this.position);
2414
+ const point = Number.parseInt(digits, 16);
2415
+ if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
2416
+ this.fail("Invalid group name escape", start);
2417
+ character = String.fromCodePoint(point);
2418
+ } else character = this.parseHexEscape(4, "Unicode", start);
2419
+ }
2420
+ this.guard.allocate(character.length);
2421
+ name += character;
2422
+ }
2423
+ if (this.take() !== ">" || name.length === 0) this.fail("Invalid group name", start);
2424
+ let first = true;
2425
+ for (const character of name) {
2426
+ this.guard.work(1);
2427
+ if (!(first ? groupNameStart : groupNamePart).test(character)) this.fail("Invalid group name", start);
2428
+ first = false;
2429
+ }
2430
+ return name;
2431
+ }
2432
+ validateNamedGroups(node) {
2433
+ this.guard.work(1);
2434
+ this.guard.allocate(1);
2435
+ const names = /* @__PURE__ */ new Set();
2436
+ if (node.type === "namedBackreference" && !Object.hasOwn(this.namedGroups, node.name))
2437
+ this.fail("Unknown named backreference");
2438
+ if (node.type === "group" && node.name !== void 0) names.add(node.name);
2439
+ 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] : [];
2440
+ for (const child of children) {
2441
+ for (const name of this.validateNamedGroups(child)) {
2442
+ this.guard.work(1);
2443
+ if (names.has(name) && node.type !== "alternation") this.fail("Duplicate capture group name");
2444
+ this.guard.allocate(1);
2445
+ names.add(name);
2446
+ }
2447
+ }
2448
+ return names;
2449
+ }
2365
2450
  parseQuantifier() {
2366
2451
  const character = this.peek();
2367
2452
  if (character === "*") {
@@ -9373,7 +9458,7 @@ function matchRegexFrom(pattern, input, startIndex) {
9373
9458
  return null;
9374
9459
  }
9375
9460
  for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
9376
- const context = { input, flags: pattern.flags, direction: 1, work: { steps: 0 } };
9461
+ const context = { input, flags: pattern.flags, groups: pattern.groups, direction: 1, work: { steps: 0 } };
9377
9462
  charge(context);
9378
9463
  const initialState = {
9379
9464
  position: attempt,
@@ -9381,7 +9466,7 @@ function matchRegexFrom(pattern, input, startIndex) {
9381
9466
  };
9382
9467
  const result = matchNode(pattern.body, initialState, context).next();
9383
9468
  if (!result.done) {
9384
- return toRegexMatch(input, attempt, result.value, pattern.flags.hasIndices);
9469
+ return toRegexMatch(input, attempt, result.value, pattern.flags.hasIndices, pattern.groups);
9385
9470
  }
9386
9471
  if (pattern.flags.sticky) break;
9387
9472
  }
@@ -9399,8 +9484,19 @@ function* matchNode(node, state, context) {
9399
9484
  yield { ...state, position: state.position + context.direction };
9400
9485
  }
9401
9486
  return;
9402
- case "backreference": {
9403
- const capture = state.captures[node.index - 1];
9487
+ case "backreference":
9488
+ case "namedBackreference": {
9489
+ let capture;
9490
+ if (node.type === "backreference") capture = state.captures[node.index - 1];
9491
+ else {
9492
+ for (const index of context.groups?.[node.name] ?? []) {
9493
+ charge(context);
9494
+ if (state.captures[index - 1] !== void 0) {
9495
+ capture = state.captures[index - 1];
9496
+ break;
9497
+ }
9498
+ }
9499
+ }
9404
9500
  if (capture === void 0) {
9405
9501
  yield state;
9406
9502
  return;
@@ -9545,7 +9641,7 @@ function matchesCharacterClassItem(character, item, ignoreCase) {
9545
9641
  const matched = item.kind === "digit" ? isDigit(character) : item.kind === "word" ? isWordCharacter(character) : isSpaceCharacter(character);
9546
9642
  return item.negated ? !matched : matched;
9547
9643
  }
9548
- function toRegexMatch(input, start, state, hasIndices) {
9644
+ function toRegexMatch(input, start, state, hasIndices, groups) {
9549
9645
  const match = {
9550
9646
  index: start,
9551
9647
  text: input.slice(start, state.position),
@@ -9556,6 +9652,15 @@ function toRegexMatch(input, start, state, hasIndices) {
9556
9652
  if (hasIndices) {
9557
9653
  match.indices = [[start, state.position], ...state.captures.map((capture) => capture === void 0 ? void 0 : [capture.start, capture.end])];
9558
9654
  }
9655
+ if (groups !== void 0) {
9656
+ match.groups = /* @__PURE__ */ Object.create(null);
9657
+ if (hasIndices) match.indicesGroups = /* @__PURE__ */ Object.create(null);
9658
+ for (const [name, indices] of Object.entries(groups)) {
9659
+ const index = indices.find((index2) => state.captures[index2 - 1] !== void 0);
9660
+ match.groups[name] = index === void 0 ? void 0 : match.captures[index - 1];
9661
+ if (match.indicesGroups !== void 0) match.indicesGroups[name] = index === void 0 ? void 0 : match.indices[index];
9662
+ }
9663
+ }
9559
9664
  return match;
9560
9665
  }
9561
9666
  function cloneState(state) {
@@ -10178,7 +10283,7 @@ function callReplaceLikeMethod(value, methodName, args, budget, callClosure, use
10178
10283
  );
10179
10284
  }
10180
10285
  async function replaceRegex(value, regex, replacement, budget, callClosure, context) {
10181
- if (hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
10286
+ if (getSandboxRegexPattern(regex).groups !== void 0 || hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget))
10182
10287
  return regexReplace(value, regex, replacement, budget, callClosure, context);
10183
10288
  if (regex.flags.includes("g")) regex.lastIndex = 0;
10184
10289
  const cursor = regex.lastIndex;
@@ -10228,7 +10333,7 @@ async function regexReplace(input, regex, replacementInput, budget, callClosure,
10228
10333
  input = void 0;
10229
10334
  replacement = isSandboxClosure(replacementInput) ? replacementInput : await sandboxString(replacementInput, budget, context);
10230
10335
  replacementInput = void 0;
10231
- if (isSandboxRegex(regex) && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
10336
+ if (isSandboxRegex(regex) && getSandboxRegexPattern(regex).groups === void 0 && !hasRegexPropertyOverride(regex, ["exec", "flags", ...Object.keys(regexFlagProperties)], budget)) {
10232
10337
  release();
10233
10338
  return await replaceRegex(value, regex, replacement, budget, callClosure, context);
10234
10339
  }
@@ -16829,11 +16934,13 @@ function toMatchArray(match, input, budget) {
16829
16934
  }
16830
16935
  budget?.allocateArrayLength(match.captures.length + 1);
16831
16936
  const result = [match.text, ...match.captures];
16832
- Object.assign(result, { index: match.index, input, groups: void 0 });
16937
+ if (match.groups !== void 0) setSandboxPrototype(match.groups, null, budget);
16938
+ if (match.indicesGroups !== void 0) setSandboxPrototype(match.indicesGroups, null, budget);
16939
+ Object.assign(result, { index: match.index, input, groups: match.groups });
16833
16940
  if (match.indices !== void 0) {
16834
16941
  budget?.allocateArrayLength(match.indices.length);
16835
16942
  budget?.allocateArrayLength(2);
16836
- Object.assign(match.indices, { groups: void 0 });
16943
+ Object.assign(match.indices, { groups: match.indicesGroups });
16837
16944
  Object.assign(result, { indices: match.indices });
16838
16945
  }
16839
16946
  return result;
@@ -37182,4 +37289,4 @@ export {
37182
37289
  FileSnapshotBackend,
37183
37290
  run
37184
37291
  };
37185
- //# sourceMappingURL=chunk-7KLRGTR4.js.map
37292
+ //# sourceMappingURL=chunk-T43UKNMF.js.map