@poe-platform/safe-js 0.1.198 → 0.1.199

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.
@@ -754,7 +754,7 @@ function measureNode(node) {
754
754
  case "characterClass": {
755
755
  let usage = 5 + node.items.length;
756
756
  for (const item of node.items) {
757
- usage += item.type === "character" ? 3 + item.value.length : item.type === "range" ? 4 + item.from.length + item.to.length : 4;
757
+ 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 : 4;
758
758
  }
759
759
  return usage;
760
760
  }
@@ -2068,7 +2068,7 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
2068
2068
  guard.checkLength(flags.length, true);
2069
2069
  guard.allocate(5 + valueUnits);
2070
2070
  const parsedFlags = parseFlags(flags, guard);
2071
- const parser = new RegexParser(source, guard);
2071
+ const parser = new RegexParser(source, guard, parsedFlags.unicode);
2072
2072
  const body = parser.parse();
2073
2073
  guard.allocate(5 + source.length);
2074
2074
  const pattern = { source, flags: parsedFlags, captureCount: parser.captureCount, body };
@@ -2080,12 +2080,14 @@ function parseRegex(source, flags = "", compilation, valueUnits = 0) {
2080
2080
  }
2081
2081
  }
2082
2082
  var RegexParser = class {
2083
- constructor(source, guard) {
2083
+ constructor(source, guard, unicode) {
2084
2084
  this.source = source;
2085
2085
  this.guard = guard;
2086
+ this.unicode = unicode;
2086
2087
  }
2087
2088
  source;
2088
2089
  guard;
2090
+ unicode;
2089
2091
  captureCount = 0;
2090
2092
  cursor = 0;
2091
2093
  totalCaptureCount;
@@ -2106,7 +2108,7 @@ var RegexParser = class {
2106
2108
  }
2107
2109
  this.fail(`Unexpected character '${this.peek()}'`);
2108
2110
  }
2109
- if (Object.keys(this.namedGroups).length > 0) this.validateNamedGroups(body);
2111
+ if (this.unicode || Object.keys(this.namedGroups).length > 0) this.validateNamedGroups(body);
2110
2112
  return body;
2111
2113
  }
2112
2114
  parseAlternation() {
@@ -2148,7 +2150,7 @@ var RegexParser = class {
2148
2150
  if (quantifier === void 0) {
2149
2151
  return body;
2150
2152
  }
2151
- if (body.type === "anchor" || body.type === "wordBoundary" || body.type === "lookbehind") {
2153
+ if (body.type === "anchor" || body.type === "wordBoundary" || body.type === "lookbehind" || this.unicode && body.type === "lookahead") {
2152
2154
  this.fail("Invalid quantifier target", quantifierStart);
2153
2155
  }
2154
2156
  const greedy = this.peek() !== "?";
@@ -2159,7 +2161,7 @@ var RegexParser = class {
2159
2161
  return { type: "quantifier", body, ...quantifier, greedy };
2160
2162
  }
2161
2163
  parseAtom() {
2162
- const character = this.take();
2164
+ const character = this.takeCharacter();
2163
2165
  switch (character) {
2164
2166
  case ".":
2165
2167
  this.guard.allocate(2);
@@ -2177,6 +2179,7 @@ var RegexParser = class {
2177
2179
  case "\\":
2178
2180
  return this.parseEscape(false, this.position - 1);
2179
2181
  default:
2182
+ if (this.unicode && (character === "]" || character === "}")) this.fail("Invalid Unicode pattern character");
2180
2183
  this.guard.allocate(3 + character.length);
2181
2184
  return { type: "literal", value: character };
2182
2185
  }
@@ -2257,7 +2260,7 @@ var RegexParser = class {
2257
2260
  if (left.type !== "character" || right.type !== "character") {
2258
2261
  this.fail("Character class ranges require literal endpoints", rangePosition);
2259
2262
  }
2260
- if (left.value.charCodeAt(0) > right.value.charCodeAt(0)) {
2263
+ if (left.value.codePointAt(0) > right.value.codePointAt(0)) {
2261
2264
  this.fail("Character class range is out of order", rangePosition);
2262
2265
  }
2263
2266
  this.guard.allocate(4 + left.value.length + right.value.length);
@@ -2286,7 +2289,7 @@ var RegexParser = class {
2286
2289
  this.fail("Unsupported character class escape", escapeStart);
2287
2290
  }
2288
2291
  this.guard.allocate(4);
2289
- return { type: "character", value: this.take() };
2292
+ return { type: "character", value: this.takeCharacter() };
2290
2293
  }
2291
2294
  parseEscape(inCharacterClass, start) {
2292
2295
  if (this.atEnd()) {
@@ -2295,7 +2298,7 @@ var RegexParser = class {
2295
2298
  const escaped = this.take();
2296
2299
  if (escaped === "k") {
2297
2300
  this.totalCaptureCount ??= this.countAllCaptures();
2298
- if (this.hasNamedCaptures) {
2301
+ if (this.unicode || this.hasNamedCaptures) {
2299
2302
  if (inCharacterClass || this.take() !== "<") this.fail("Invalid named backreference", start);
2300
2303
  const name = this.parseGroupName(start);
2301
2304
  this.guard.allocate(3 + name.length);
@@ -2317,6 +2320,8 @@ var RegexParser = class {
2317
2320
  return { type: "backreference", index };
2318
2321
  }
2319
2322
  }
2323
+ if (this.unicode && (escaped !== "0" || isDecimalDigit2(this.peek())))
2324
+ this.fail("Invalid decimal escape", start);
2320
2325
  this.guard.allocate(4);
2321
2326
  if (escaped === "8" || escaped === "9") return { type: "literal", value: escaped };
2322
2327
  let code = Number(escaped);
@@ -2327,7 +2332,24 @@ var RegexParser = class {
2327
2332
  return { type: "literal", value: String.fromCharCode(code) };
2328
2333
  }
2329
2334
  if (escaped === "p" || escaped === "P") {
2330
- this.fail("Unicode property escapes are not supported", start);
2335
+ if (!this.unicode) this.fail("Unicode property escapes are not supported", start);
2336
+ if (this.take() !== "{") this.fail("Invalid Unicode property escape", start);
2337
+ const begin = this.position;
2338
+ while (!this.atEnd() && this.peek() !== "}") {
2339
+ const character = this.take();
2340
+ if (!isDecimalDigit2(character) && !(character >= "a" && character <= "z") && !(character >= "A" && character <= "Z") && character !== "_" && character !== "=")
2341
+ this.fail("Invalid Unicode property escape", start);
2342
+ }
2343
+ this.guard.allocate(this.position - begin + 9);
2344
+ const value = this.source.slice(begin, this.position);
2345
+ if (this.take() !== "}") this.fail("Unterminated Unicode property escape", start);
2346
+ try {
2347
+ new RegExp(`\\p{${value}}`, "u");
2348
+ } catch {
2349
+ this.fail("Unknown Unicode property", start);
2350
+ }
2351
+ this.guard.array(1);
2352
+ return { type: "characterClass", negated: false, items: [{ type: "property", value, negated: escaped === "P" }] };
2331
2353
  }
2332
2354
  if (escaped === "x") {
2333
2355
  this.guard.allocate(4);
@@ -2335,7 +2357,29 @@ var RegexParser = class {
2335
2357
  }
2336
2358
  if (escaped === "u") {
2337
2359
  this.guard.allocate(4);
2338
- return { type: "literal", value: this.parseHexEscape(4, "Unicode", start) };
2360
+ if (this.unicode && this.peek() === "{") {
2361
+ this.position++;
2362
+ const begin = this.position;
2363
+ while (!this.atEnd() && this.peek() !== "}") this.position++;
2364
+ this.guard.allocate(this.position - begin);
2365
+ const digits = this.source.slice(begin, this.position);
2366
+ const point = Number.parseInt(digits, 16);
2367
+ if (this.take() !== "}" || digits.length === 0 || !allHexDigits(digits) || point > 1114111)
2368
+ this.fail("Invalid Unicode escape", start);
2369
+ return { type: "literal", value: String.fromCodePoint(point) };
2370
+ }
2371
+ let value = this.parseHexEscape(4, "Unicode", start);
2372
+ if (this.unicode && value.charCodeAt(0) >= 55296 && value.charCodeAt(0) <= 56319 && this.source.startsWith("\\u", this.position)) {
2373
+ const digits = this.source.slice(this.position + 2, this.position + 6);
2374
+ const point = Number.parseInt(digits, 16);
2375
+ this.guard.work(digits.length);
2376
+ this.guard.allocate(digits.length);
2377
+ if (digits.length === 4 && allHexDigits(digits) && point >= 56320 && point <= 57343) {
2378
+ value += String.fromCharCode(point);
2379
+ this.position += 6;
2380
+ }
2381
+ }
2382
+ return { type: "literal", value };
2339
2383
  }
2340
2384
  this.guard.allocate(25);
2341
2385
  const kinds = {
@@ -2366,6 +2410,15 @@ var RegexParser = class {
2366
2410
  v: "\v",
2367
2411
  "0": "\0"
2368
2412
  };
2413
+ if (escaped === "c" && this.unicode) {
2414
+ const letter = this.take();
2415
+ if (!(letter >= "a" && letter <= "z") && !(letter >= "A" && letter <= "Z"))
2416
+ this.fail("Invalid control escape", start);
2417
+ this.guard.allocate(4);
2418
+ return { type: "literal", value: String.fromCharCode(letter.charCodeAt(0) % 32) };
2419
+ }
2420
+ if (this.unicode && controls[escaped] === void 0 && !"^$\\.*+?()[]{}|/".includes(escaped) && !(inCharacterClass && escaped === "-"))
2421
+ this.fail("Invalid identity escape", start);
2369
2422
  this.guard.allocate(4);
2370
2423
  return { type: "literal", value: controls[escaped] ?? escaped };
2371
2424
  }
@@ -2518,6 +2571,12 @@ var RegexParser = class {
2518
2571
  this.position += 1;
2519
2572
  return character;
2520
2573
  }
2574
+ takeCharacter() {
2575
+ if (!this.unicode || this.atEnd()) return this.take();
2576
+ const character = String.fromCodePoint(this.source.codePointAt(this.position));
2577
+ this.position += character.length;
2578
+ return character;
2579
+ }
2521
2580
  atEnd() {
2522
2581
  return this.position >= this.source.length;
2523
2582
  }
@@ -2531,6 +2590,7 @@ function parseFlags(flags, guard) {
2531
2590
  hasIndices: false,
2532
2591
  global: false,
2533
2592
  sticky: false,
2593
+ unicode: false,
2534
2594
  ignoreCase: false,
2535
2595
  multiline: false,
2536
2596
  dotAll: false
@@ -2541,7 +2601,8 @@ function parseFlags(flags, guard) {
2541
2601
  i: "ignoreCase",
2542
2602
  m: "multiline",
2543
2603
  s: "dotAll",
2544
- y: "sticky"
2604
+ y: "sticky",
2605
+ u: "unicode"
2545
2606
  };
2546
2607
  for (let position = 0; position < flags.length; position += 1) {
2547
2608
  guard.work(1);
@@ -9457,7 +9518,8 @@ function matchRegexFrom(pattern, input, startIndex) {
9457
9518
  if (startIndex > input.length) {
9458
9519
  return null;
9459
9520
  }
9460
- for (let attempt = startIndex; attempt <= input.length; attempt += 1) {
9521
+ if (pattern.flags.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--;
9522
+ for (let attempt = startIndex; attempt <= input.length; attempt = advanceStringIndex(input, attempt, pattern.flags.unicode)) {
9461
9523
  const context = { input, flags: pattern.flags, groups: pattern.groups, direction: 1, work: { steps: 0 } };
9462
9524
  charge(context);
9463
9525
  const initialState = {
@@ -9474,14 +9536,14 @@ function matchRegexFrom(pattern, input, startIndex) {
9474
9536
  }
9475
9537
  function* matchNode(node, state, context) {
9476
9538
  charge(context);
9477
- const characterIndex = context.direction === 1 ? state.position : state.position - 1;
9539
+ const character = readCharacter(context.input, state.position, context.direction, context.flags.unicode);
9478
9540
  switch (node.type) {
9479
9541
  case "empty":
9480
9542
  yield state;
9481
9543
  return;
9482
9544
  case "literal":
9483
- if (charactersEqual(context.input[characterIndex], node.value, context.flags.ignoreCase)) {
9484
- yield { ...state, position: state.position + context.direction };
9545
+ if (charactersEqual(character, node.value, context.flags.ignoreCase, context.flags.unicode)) {
9546
+ yield { ...state, position: state.position + context.direction * character.length };
9485
9547
  }
9486
9548
  return;
9487
9549
  case "backreference":
@@ -9501,19 +9563,23 @@ function* matchNode(node, state, context) {
9501
9563
  yield state;
9502
9564
  return;
9503
9565
  }
9504
- const length = capture.end - capture.start;
9505
- const start = context.direction === 1 ? state.position : state.position - length;
9506
- if (start < 0 || start + length > context.input.length) return;
9507
- for (let offset = 0; offset < length; offset++) {
9566
+ let position = state.position;
9567
+ let reference = context.direction === 1 ? capture.start : capture.end;
9568
+ const end = context.direction === 1 ? capture.end : capture.start;
9569
+ while (reference !== end) {
9508
9570
  charge(context);
9509
- if (!charactersEqual(context.input[start + offset], context.input[capture.start + offset], context.flags.ignoreCase)) return;
9571
+ const expected = readCharacter(context.input, reference, context.direction, context.flags.unicode);
9572
+ const actual = readCharacter(context.input, position, context.direction, context.flags.unicode);
9573
+ if (!charactersEqual(actual, expected, context.flags.ignoreCase, context.flags.unicode)) return;
9574
+ reference += context.direction * expected.length;
9575
+ position += context.direction * actual.length;
9510
9576
  }
9511
- yield { ...state, position: state.position + context.direction * length };
9577
+ yield { ...state, position };
9512
9578
  return;
9513
9579
  }
9514
9580
  case "dot":
9515
- if (characterIndex >= 0 && characterIndex < context.input.length && (context.flags.dotAll || !isLineTerminator(context.input[characterIndex]))) {
9516
- yield { ...state, position: state.position + context.direction };
9581
+ if (character !== void 0 && (context.flags.dotAll || !isLineTerminator(character))) {
9582
+ yield { ...state, position: state.position + context.direction * character.length };
9517
9583
  }
9518
9584
  return;
9519
9585
  case "anchor":
@@ -9522,17 +9588,16 @@ function* matchNode(node, state, context) {
9522
9588
  }
9523
9589
  return;
9524
9590
  case "wordBoundary": {
9525
- const previousWord = state.position > 0 && isWordCharacter(context.input[state.position - 1]);
9526
- const nextWord = state.position < context.input.length && isWordCharacter(context.input[state.position]);
9591
+ const previousWord = state.position > 0 && matchesCharacterClassItem(context.input[state.position - 1], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, context.flags.unicode);
9592
+ const nextWord = state.position < context.input.length && matchesCharacterClassItem(context.input[state.position], { type: "kind", kind: "word", negated: false }, context.flags.ignoreCase, context.flags.unicode);
9527
9593
  if (previousWord !== nextWord !== node.negated) {
9528
9594
  yield state;
9529
9595
  }
9530
9596
  return;
9531
9597
  }
9532
9598
  case "characterClass": {
9533
- const character = context.input[characterIndex];
9534
- if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context.flags.ignoreCase)) {
9535
- yield { ...state, position: state.position + context.direction };
9599
+ if (character !== void 0 && matchesCharacterClass(character, node.items, node.negated, context)) {
9600
+ yield { ...state, position: state.position + context.direction * character.length };
9536
9601
  }
9537
9602
  return;
9538
9603
  }
@@ -9615,11 +9680,27 @@ function matchesAnchor(kind, position, context) {
9615
9680
  }
9616
9681
  return position === context.input.length || context.flags.multiline && position < context.input.length && isLineTerminator(context.input[position]);
9617
9682
  }
9618
- function matchesCharacterClass(character, items, negated, ignoreCase) {
9619
- const matched = items.some((item) => matchesCharacterClassItem(character, item, ignoreCase));
9683
+ function matchesCharacterClass(character, items, negated, context) {
9684
+ const matched = items.some((item) => {
9685
+ if (context.flags.unicode) charge(context);
9686
+ return matchesCharacterClassItem(character, item, context.flags.ignoreCase, context.flags.unicode);
9687
+ });
9620
9688
  return negated ? !matched : matched;
9621
9689
  }
9622
- function matchesCharacterClassItem(character, item, ignoreCase) {
9690
+ function matchesCharacterClassItem(character, item, ignoreCase, unicode) {
9691
+ if (unicode) {
9692
+ const hex = (value) => `\\u{${value.codePointAt(0).toString(16)}}`;
9693
+ let atom;
9694
+ if (item.type === "character") atom = hex(item.value);
9695
+ else if (item.type === "range") atom = `[${hex(item.from)}-${hex(item.to)}]`;
9696
+ else if (item.type === "property") atom = `\\${item.negated ? "P" : "p"}{${item.value}}`;
9697
+ else {
9698
+ const kind = item.kind === "digit" ? "d" : item.kind === "word" ? "w" : "s";
9699
+ atom = `\\${item.negated ? kind.toUpperCase() : kind}`;
9700
+ }
9701
+ return new RegExp(`^(?:${atom})$`, ignoreCase ? "iu" : "u").test(character);
9702
+ }
9703
+ if (item.type === "property") return false;
9623
9704
  if (item.type === "character") {
9624
9705
  return charactersEqual(character, item.value, ignoreCase);
9625
9706
  }
@@ -9705,9 +9786,20 @@ function normalizeLastIndex(lastIndex) {
9705
9786
  }
9706
9787
  return Math.min(Math.floor(lastIndex), Number.MAX_SAFE_INTEGER);
9707
9788
  }
9708
- function charactersEqual(left, right, ignoreCase) {
9789
+ function charactersEqual(left, right, ignoreCase, unicode = false) {
9790
+ if (unicode && ignoreCase && left !== void 0)
9791
+ return new RegExp(`^\\u{${right.codePointAt(0).toString(16)}}$`, "iu").test(left);
9709
9792
  return left !== void 0 && foldCharacter(left, ignoreCase) === foldCharacter(right, ignoreCase);
9710
9793
  }
9794
+ function advanceStringIndex(input, index, unicode) {
9795
+ return index + (unicode && (input.codePointAt(index) ?? 0) > 65535 ? 2 : 1);
9796
+ }
9797
+ function readCharacter(input, position, direction, unicode) {
9798
+ let index = direction === 1 ? position : position - 1;
9799
+ if (index < 0 || index >= input.length) return void 0;
9800
+ 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--;
9801
+ return unicode ? String.fromCodePoint(input.codePointAt(index)) : input[index];
9802
+ }
9711
9803
  function foldCharacter(character, ignoreCase) {
9712
9804
  if (!ignoreCase) {
9713
9805
  return character;
@@ -10548,7 +10640,7 @@ function splitNormalized(value, separator, limit, budget, parent) {
10548
10640
  while (result2.length < limit) {
10549
10641
  const match = executeRegex(splitter, value, Number(splitter.lastIndex));
10550
10642
  if (match === null) break;
10551
- if (match.text.length === 0) splitter.lastIndex = match.index + 1;
10643
+ if (match.text.length === 0) splitter.lastIndex = advanceStringIndex(value, match.index, splitter.flags.includes("u"));
10552
10644
  endedWithZeroWidthMatch = match.text.length === 0 && match.index === value.length;
10553
10645
  if (match.text.length === 0 && (match.index === copiedThrough || match.index === value.length))
10554
10646
  continue;
@@ -10723,7 +10815,7 @@ function collectRegexMatches(regex, value, all, budget, lastIndex = 0) {
10723
10815
  budget?.allocateArrayLength(matches.length + 1);
10724
10816
  matches.push(match);
10725
10817
  lastIndex = match.index + match.text.length;
10726
- if (all && match.text.length === 0) regex.lastIndex = ++lastIndex;
10818
+ if (all && match.text.length === 0) regex.lastIndex = lastIndex = advanceStringIndex(value, lastIndex, regex.flags.includes("u"));
10727
10819
  } while (all);
10728
10820
  return matches;
10729
10821
  }
@@ -37289,4 +37381,4 @@ export {
37289
37381
  FileSnapshotBackend,
37290
37382
  run
37291
37383
  };
37292
- //# sourceMappingURL=chunk-T43UKNMF.js.map
37384
+ //# sourceMappingURL=chunk-X5VIB5JV.js.map