re2js 2.8.4 → 2.8.6

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.
package/build/index.d.ts CHANGED
@@ -221,10 +221,10 @@ export class Matcher {
221
221
  anchorFlag: number;
222
222
  /**
223
223
  * Resets the {@code Matcher} and changes the input.
224
- * @param {MatcherInputBase} input
224
+ * @param {string|number[]|Uint8Array|MatcherInputBase} input
225
225
  * @returns {Matcher} the {@code Matcher} itself, for chained method calls
226
226
  */
227
- resetMatcherInput(input: MatcherInputBase): Matcher;
227
+ resetMatcherInput(input: string | number[] | Uint8Array | MatcherInputBase): Matcher;
228
228
  matcherInput: MatcherInputBase;
229
229
  /**
230
230
  * Returns the start of the named group of the most recent match, or -1 if the group was not
@@ -503,7 +503,7 @@ declare class RE2 {
503
503
  prefixUTF8: any;
504
504
  prefixComplete: boolean;
505
505
  prefixRune: number;
506
- pooled: AtomicReference;
506
+ machinePool: any[];
507
507
  dfa: DFA;
508
508
  onepass: {
509
509
  start: any;
@@ -523,7 +523,7 @@ declare class RE2 {
523
523
  numberOfInstructions(): any;
524
524
  get(): any;
525
525
  reset(): void;
526
- put(m: any, isNew: any): void;
526
+ put(m: any): void;
527
527
  toString(): any;
528
528
  doExecuteNFA(input: any, pos: any, anchor: any, ncap: any): any;
529
529
  match(s: any): boolean;
@@ -699,13 +699,6 @@ declare class RE2 {
699
699
  */
700
700
  findAllSubmatchIndex(s: any, n: any): any[];
701
701
  }
702
- declare class AtomicReference {
703
- constructor(initialValue: any);
704
- value: any;
705
- get(): any;
706
- set(newValue: any): void;
707
- compareAndSet(expect: any, update: any): boolean;
708
- }
709
702
  /**
710
703
  * Creates an RE2JS regex directly from a template literal.
711
704
  * @overload
@@ -873,6 +866,16 @@ export class RE2JS {
873
866
  * @returns {boolean} `true` if the exact input string fully matches the pattern, `false` otherwise.
874
867
  */
875
868
  testExact(input: string | number[] | Uint8Array): boolean;
869
+ /**
870
+ * Executes a search for a match in a specified string.
871
+ * Returns a result array, or null if no match is found.
872
+ * The returned array perfectly mirrors standard JavaScript `RegExpExecArray`,
873
+ * including `.index`, `.input`, and `.groups` properties.
874
+ *
875
+ * @param {string|number[]|Uint8Array} input the input string or byte array
876
+ * @returns {Array|null} the match array with index, input, and groups properties, or null
877
+ */
878
+ exec(input: string | number[] | Uint8Array): any[] | null;
876
879
  /**
877
880
  * Splits input around instances of the regular expression. It returns an array giving the strings
878
881
  * that occur before, between, and after instances of the regular expression.
@@ -892,9 +895,9 @@ export class RE2JS {
892
895
  * including capturing groups.
893
896
  *
894
897
  * @param {string|number[]|Uint8Array} input the input string or byte array
895
- * @returns {IterableIterator<Array>}
898
+ * @returns {IterableIterator<RegExpMatchArray>}
896
899
  */
897
- matchAll(input: string | number[] | Uint8Array): IterableIterator<any[]>;
900
+ matchAll(input: string | number[] | Uint8Array): IterableIterator<RegExpMatchArray>;
898
901
  /**
899
902
  *
900
903
  * @returns {string}
package/build/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * re2js
3
3
  * RE2JS is the JavaScript port of RE2, a regular expression engine that provides linear time matching
4
4
  *
5
- * @version v2.8.4
5
+ * @version v2.8.6
6
6
  * @author Oleksii Vasyliev
7
7
  * @homepage https://github.com/le0pard/re2js#readme
8
8
  * @repository github:le0pard/re2js
@@ -707,7 +707,7 @@ var Utils = class Utils {
707
707
  static stringToUtf8ByteArray(str) {
708
708
  if (globalThis.TextEncoder) {
709
709
  if (!cachedNativeEncoder) cachedNativeEncoder = new TextEncoder();
710
- return Utils.toArray(cachedNativeEncoder.encode(str));
710
+ return cachedNativeEncoder.encode(str);
711
711
  } else {
712
712
  let out = [], p = 0;
713
713
  for (let i = 0; i < str.length; i++) {
@@ -1245,7 +1245,7 @@ var Matcher = class Matcher {
1245
1245
  }
1246
1246
  /**
1247
1247
  * Resets the {@code Matcher} and changes the input.
1248
- * @param {MatcherInputBase} input
1248
+ * @param {string|number[]|Uint8Array|MatcherInputBase} input
1249
1249
  * @returns {Matcher} the {@code Matcher} itself, for chained method calls
1250
1250
  */
1251
1251
  resetMatcherInput(input) {
@@ -1401,7 +1401,10 @@ var Matcher = class Matcher {
1401
1401
  */
1402
1402
  genMatch(startByte, anchor) {
1403
1403
  const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1);
1404
- if (!res[0]) return false;
1404
+ if (!res[0]) {
1405
+ this.hasMatch = false;
1406
+ return false;
1407
+ }
1405
1408
  this.groups = res[1];
1406
1409
  this.hasMatch = true;
1407
1410
  this.hasGroups = this.patternGroupCount === 0;
@@ -1464,43 +1467,47 @@ var Matcher = class Matcher {
1464
1467
  let res = "";
1465
1468
  let last = 0;
1466
1469
  const m = replacement.length;
1467
- for (let i = 0; i < m - 1; i++) {
1468
- if (replacement.codePointAt(i) === Codepoint.CODES.get("\\")) {
1470
+ let i = 0;
1471
+ while (i < m) {
1472
+ const cCode = replacement.codePointAt(i);
1473
+ if (cCode === Codepoint.CODES.get("\\")) {
1469
1474
  if (last < i) res += replacement.substring(last, i);
1470
1475
  i++;
1476
+ if (i >= m) throw new RE2JSGroupException("character to be escaped is missing");
1471
1477
  last = i;
1478
+ i++;
1472
1479
  continue;
1473
1480
  }
1474
- if (replacement.codePointAt(i) === Codepoint.CODES.get("$")) {
1475
- let c = replacement.codePointAt(i + 1);
1476
- if (Codepoint.CODES.get("0") <= c && c <= Codepoint.CODES.get("9")) {
1477
- let n = c - Codepoint.CODES.get("0");
1478
- if (last < i) res += replacement.substring(last, i);
1479
- for (i += 2; i < m; i++) {
1480
- c = replacement.codePointAt(i);
1481
- if (c < Codepoint.CODES.get("0") || c > Codepoint.CODES.get("9") || n * 10 + c - Codepoint.CODES.get("0") > this.patternGroupCount) break;
1482
- n = n * 10 + c - Codepoint.CODES.get("0");
1481
+ if (cCode === Codepoint.CODES.get("$")) {
1482
+ if (last < i) res += replacement.substring(last, i);
1483
+ if (i + 1 >= m) throw new RE2JSGroupException("Illegal group reference: group index is missing");
1484
+ const nextCode = replacement.codePointAt(i + 1);
1485
+ if (Codepoint.CODES.get("0") <= nextCode && nextCode <= Codepoint.CODES.get("9")) {
1486
+ let n = nextCode - Codepoint.CODES.get("0");
1487
+ let j = i + 2;
1488
+ for (; j < m; j++) {
1489
+ const digit = replacement.codePointAt(j);
1490
+ if (digit < Codepoint.CODES.get("0") || digit > Codepoint.CODES.get("9") || n * 10 + digit - Codepoint.CODES.get("0") > this.patternGroupCount) break;
1491
+ n = n * 10 + digit - Codepoint.CODES.get("0");
1483
1492
  }
1484
1493
  if (n > this.patternGroupCount) throw new RE2JSGroupException(`n > number of groups: ${n}`);
1485
1494
  const group = this.group(n);
1486
1495
  if (group !== null) res += group;
1496
+ i = j;
1487
1497
  last = i;
1488
- i--;
1489
- continue;
1490
- } else if (c === Codepoint.CODES.get("{")) {
1491
- if (last < i) res += replacement.substring(last, i);
1492
- i++;
1493
- let j = i + 1;
1494
- while (j < replacement.length && replacement.codePointAt(j) !== Codepoint.CODES.get("}") && replacement.codePointAt(j) !== Codepoint.CODES.get(" ")) j++;
1495
- if (j === replacement.length || replacement.codePointAt(j) !== Codepoint.CODES.get("}")) throw new RE2JSGroupException("named capture group is missing trailing '}'");
1496
- const groupName = replacement.substring(i + 1, j);
1498
+ } else if (nextCode === Codepoint.CODES.get("{")) {
1499
+ let j = i + 2;
1500
+ while (j < m && replacement.codePointAt(j) !== Codepoint.CODES.get("}")) j++;
1501
+ if (j >= m) throw new RE2JSGroupException("named capture group is missing trailing '}'");
1502
+ const groupName = replacement.substring(i + 2, j);
1497
1503
  const groupVal = this.group(groupName);
1498
1504
  if (groupVal !== null) res += groupVal;
1499
- last = j + 1;
1500
- i = j;
1501
- continue;
1502
- }
1505
+ i = j + 1;
1506
+ last = i;
1507
+ } else throw new RE2JSGroupException("Illegal group reference");
1508
+ continue;
1503
1509
  }
1510
+ i++;
1504
1511
  }
1505
1512
  if (last < m) res += replacement.substring(last, m);
1506
1513
  return res;
@@ -1811,18 +1818,18 @@ var Inst = class Inst {
1811
1818
  };
1812
1819
  //#endregion
1813
1820
  //#region src/Machine.js
1814
- var Thread = class {
1815
- constructor() {
1816
- this.inst = null;
1817
- this.cap = null;
1818
- }
1819
- };
1820
1821
  var Queue = class {
1821
1822
  constructor(numInst) {
1822
1823
  this.sparse = new Int32Array(numInst);
1823
1824
  this.densePcs = new Int32Array(numInst);
1824
- this.denseThreads = new Array(numInst);
1825
+ this.denseCaps = null;
1825
1826
  this.size = 0;
1827
+ this.ncap = 0;
1828
+ }
1829
+ init(ncap) {
1830
+ this.ncap = ncap;
1831
+ const needed = this.densePcs.length * ncap;
1832
+ if (!this.denseCaps || this.denseCaps.length < needed) this.denseCaps = new Int32Array(needed);
1826
1833
  }
1827
1834
  contains(pc) {
1828
1835
  const j = this.sparse[pc];
@@ -1834,12 +1841,10 @@ var Queue = class {
1834
1841
  add(pc) {
1835
1842
  const j = this.size++;
1836
1843
  this.sparse[pc] = j;
1837
- this.denseThreads[j] = null;
1838
1844
  this.densePcs[j] = pc;
1839
1845
  return j;
1840
1846
  }
1841
1847
  clear() {
1842
- for (let i = 0; i < this.size; i++) this.denseThreads[i] = null;
1843
1848
  this.size = 0;
1844
1849
  }
1845
1850
  toString() {
@@ -1853,15 +1858,12 @@ var Queue = class {
1853
1858
  }
1854
1859
  };
1855
1860
  var Machine = class Machine {
1856
- static THREADS_CHUNK_SIZE = 128;
1857
1861
  static fromRE2(re2) {
1858
1862
  const m = new Machine();
1859
1863
  m.prog = re2.prog;
1860
1864
  m.re2 = re2;
1861
1865
  m.q0 = new Queue(m.prog.numInst());
1862
1866
  m.q1 = new Queue(m.prog.numInst());
1863
- m.pool = [];
1864
- m.poolSize = 0;
1865
1867
  m.matched = false;
1866
1868
  m.matchcap = new Int32Array(m.prog.numCap < 2 ? 2 : m.prog.numCap);
1867
1869
  m.ncap = 0;
@@ -1875,8 +1877,6 @@ var Machine = class Machine {
1875
1877
  this.re2 = null;
1876
1878
  this.q0 = null;
1877
1879
  this.q1 = null;
1878
- this.pool = [];
1879
- this.poolSize = 0;
1880
1880
  this.matched = false;
1881
1881
  this.matchcap = null;
1882
1882
  this.ncap = 0;
@@ -1884,51 +1884,19 @@ var Machine = class Machine {
1884
1884
  }
1885
1885
  init(ncap) {
1886
1886
  this.ncap = ncap;
1887
- if (ncap > this.matchcap.length) this.initNewCap(ncap);
1888
- else this.resetCap();
1887
+ if (ncap > this.matchcap.length) this.matchcap = new Int32Array(ncap).fill(-1);
1888
+ else this.matchcap.fill(-1);
1889
+ this.q0.init(ncap);
1890
+ this.q1.init(ncap);
1889
1891
  if (this.prog.numLb > 0) {
1890
1892
  if (!this.lbTable || this.lbTable.length < this.prog.numLb + 1) this.lbTable = new Int32Array(this.prog.numLb + 1);
1891
1893
  this.lbTable.fill(-1);
1892
1894
  }
1893
1895
  }
1894
- resetCap() {
1895
- for (let i = 0; i < this.poolSize; i++) this.pool[i].cap.fill(-1);
1896
- }
1897
- initNewCap(ncap) {
1898
- for (let i = 0; i < this.poolSize; i++) {
1899
- const t = this.pool[i];
1900
- t.cap = new Int32Array(ncap).fill(-1);
1901
- }
1902
- this.matchcap = new Int32Array(ncap).fill(-1);
1903
- }
1904
1896
  submatches() {
1905
1897
  if (this.ncap === 0) return Utils.emptyInts();
1906
1898
  return Utils.toArray(this.matchcap.subarray(0, this.ncap));
1907
1899
  }
1908
- alloc(inst) {
1909
- if (this.poolSize === 0) {
1910
- const capLen = this.matchcap.length;
1911
- for (let i = 0; i < Machine.THREADS_CHUNK_SIZE; i++) {
1912
- const t = new Thread();
1913
- t.cap = new Int32Array(capLen);
1914
- this.pool[this.poolSize++] = t;
1915
- }
1916
- }
1917
- this.poolSize--;
1918
- const t = this.pool[this.poolSize];
1919
- t.inst = inst;
1920
- return t;
1921
- }
1922
- freeQueue(queue, from = 0) {
1923
- for (let i = from; i < queue.size; i++) {
1924
- const t = queue.denseThreads[i];
1925
- if (t !== null) this.pool[this.poolSize++] = t;
1926
- }
1927
- queue.clear();
1928
- }
1929
- freeThread(t) {
1930
- this.pool[this.poolSize++] = t;
1931
- }
1932
1900
  match(input, pos, anchor) {
1933
1901
  const startCond = this.re2.cond;
1934
1902
  if (startCond === Utils.EMPTY_ALL) return false;
@@ -1967,13 +1935,14 @@ var Machine = class Machine {
1967
1935
  r = input.step(currentPos + width);
1968
1936
  rune1 = r >> 3;
1969
1937
  width1 = r & 7;
1938
+ flag = input.context(currentPos);
1970
1939
  }
1971
1940
  }
1972
- if (currentPos === 0 && this.prog.numLb > 0) for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, flag, null);
1941
+ if (currentPos === 0 && this.prog.numLb > 0) for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, 0, flag);
1973
1942
  if (!this.matched && (currentPos === 0 || anchor === RE2Flags.UNANCHORED)) {
1974
1943
  if (currentPos >= matchStartPos) {
1975
1944
  if (this.ncap > 0) this.matchcap[0] = currentPos;
1976
- this.add(runq, this.prog.start, currentPos, this.matchcap, flag, null);
1945
+ this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
1977
1946
  }
1978
1947
  }
1979
1948
  const nextPos = currentPos + width;
@@ -1993,7 +1962,7 @@ var Machine = class Machine {
1993
1962
  runq = nextq;
1994
1963
  nextq = tmpq;
1995
1964
  }
1996
- this.freeQueue(nextq);
1965
+ nextq.clear();
1997
1966
  return this.matched;
1998
1967
  }
1999
1968
  matchSet(input, pos, anchor) {
@@ -2021,16 +1990,16 @@ var Machine = class Machine {
2021
1990
  if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && currentPos !== 0) break;
2022
1991
  if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && currentPos !== 0) break;
2023
1992
  }
2024
- if (currentPos === 0 && this.prog.numLb > 0) for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, flag, null);
1993
+ if (currentPos === 0 && this.prog.numLb > 0) for (let i = 0; i < this.prog.lbStarts.length; i++) this.add(runq, this.prog.lbStarts[i], currentPos, this.matchcap, 0, flag);
2025
1994
  if (currentPos === 0 || anchor === RE2Flags.UNANCHORED) {
2026
- if (currentPos >= matchStartPos) this.add(runq, this.prog.start, currentPos, this.matchcap, flag, null);
1995
+ if (currentPos >= matchStartPos) this.add(runq, this.prog.start, currentPos, this.matchcap, 0, flag);
2027
1996
  }
2028
1997
  const nextPos = currentPos + width;
2029
1998
  flag = input.context(nextPos);
2030
1999
  for (let j = 0; j < runq.size; j++) {
2031
- let t = runq.denseThreads[j];
2032
- if (t === null) continue;
2033
- const i = t.inst;
2000
+ const pc = runq.densePcs[j];
2001
+ const i = this.prog.inst[pc];
2002
+ const capOffset = j * this.ncap;
2034
2003
  let add = false;
2035
2004
  switch (i.op) {
2036
2005
  case Inst.MATCH:
@@ -2047,15 +2016,11 @@ var Machine = class Machine {
2047
2016
  add = true;
2048
2017
  break;
2049
2018
  case Inst.RUNE_ANY_NOT_NL:
2050
- add = rune !== Codepoint.CODES.get("\n");
2019
+ add = rune !== 10;
2051
2020
  break;
2052
- default: throw new RE2JSInternalException("bad inst");
2053
- }
2054
- if (add) t = this.add(nextq, i.out, nextPos, t.cap, flag, t);
2055
- if (t !== null) {
2056
- this.freeThread(t);
2057
- runq.denseThreads[j] = null;
2021
+ default: continue;
2058
2022
  }
2023
+ if (add) this.add(nextq, i.out, nextPos, runq.denseCaps, capOffset, flag);
2059
2024
  }
2060
2025
  runq.clear();
2061
2026
  if (width === 0) break;
@@ -2071,28 +2036,25 @@ var Machine = class Machine {
2071
2036
  runq = nextq;
2072
2037
  nextq = tmpq;
2073
2038
  }
2074
- this.freeQueue(nextq);
2039
+ nextq.clear();
2075
2040
  return Array.from(matches).sort((a, b) => a - b);
2076
2041
  }
2077
2042
  step(runq, nextq, pos, nextPos, c, nextCond, anchor, atEnd) {
2078
2043
  const longest = this.re2.longest;
2079
2044
  for (let j = 0; j < runq.size; j++) {
2080
- let t = runq.denseThreads[j];
2081
- if (t === null) continue;
2082
- if (longest && this.matched && this.ncap > 0 && this.matchcap[0] < t.cap[0]) {
2083
- this.freeThread(t);
2084
- continue;
2085
- }
2086
- const i = t.inst;
2045
+ const pc = runq.densePcs[j];
2046
+ const capOffset = j * this.ncap;
2047
+ if (longest && this.matched && this.ncap > 0 && this.matchcap[0] < runq.denseCaps[capOffset]) continue;
2048
+ const i = this.prog.inst[pc];
2087
2049
  let add = false;
2088
2050
  switch (i.op) {
2089
2051
  case Inst.MATCH:
2090
2052
  if (anchor === RE2Flags.ANCHOR_BOTH && !atEnd) break;
2091
2053
  if (this.ncap > 0 && (!longest || !this.matched || this.matchcap[1] < pos)) {
2092
- t.cap[1] = pos;
2093
- this.matchcap.set(t.cap.subarray(0, this.ncap));
2054
+ runq.denseCaps[capOffset + 1] = pos;
2055
+ for (let k = 0; k < this.ncap; k++) this.matchcap[k] = runq.denseCaps[capOffset + k];
2094
2056
  }
2095
- if (!longest) this.freeQueue(runq, j + 1);
2057
+ if (!longest) runq.size = 0;
2096
2058
  this.matched = true;
2097
2059
  break;
2098
2060
  case Inst.RUNE:
@@ -2105,29 +2067,25 @@ var Machine = class Machine {
2105
2067
  add = true;
2106
2068
  break;
2107
2069
  case Inst.RUNE_ANY_NOT_NL:
2108
- add = c !== Codepoint.CODES.get("\n");
2070
+ add = c !== 10;
2109
2071
  break;
2110
- default: throw new RE2JSInternalException("bad inst");
2111
- }
2112
- if (add) t = this.add(nextq, i.out, nextPos, t.cap, nextCond, t);
2113
- if (t !== null) {
2114
- this.freeThread(t);
2115
- runq.denseThreads[j] = null;
2072
+ default: continue;
2116
2073
  }
2074
+ if (add) this.add(nextq, i.out, nextPos, runq.denseCaps, capOffset, nextCond);
2117
2075
  }
2118
2076
  runq.clear();
2119
2077
  }
2120
- add(q, pc, pos, cap, cond, t) {
2078
+ add(q, pc, pos, capArray, capOffset, cond) {
2121
2079
  while (true) {
2122
- if (pc === 0) return t;
2123
- if (q.contains(pc)) return t;
2080
+ if (pc === 0) return;
2081
+ if (q.contains(pc)) return;
2124
2082
  const d = q.add(pc);
2125
2083
  const inst = this.prog.inst[pc];
2126
2084
  switch (inst.op) {
2127
- case Inst.FAIL: return t;
2085
+ case Inst.FAIL: return;
2128
2086
  case Inst.ALT:
2129
2087
  case Inst.ALT_MATCH:
2130
- t = this.add(q, inst.out, pos, cap, cond, t);
2088
+ this.add(q, inst.out, pos, capArray, capOffset, cond);
2131
2089
  pc = inst.arg;
2132
2090
  continue;
2133
2091
  case Inst.EMPTY_WIDTH:
@@ -2135,16 +2093,16 @@ var Machine = class Machine {
2135
2093
  pc = inst.out;
2136
2094
  continue;
2137
2095
  }
2138
- return t;
2096
+ return;
2139
2097
  case Inst.NOP:
2140
2098
  pc = inst.out;
2141
2099
  continue;
2142
2100
  case Inst.CAPTURE: if (inst.arg < this.ncap) {
2143
- const opos = cap[inst.arg];
2144
- cap[inst.arg] = pos;
2145
- this.add(q, inst.out, pos, cap, cond, null);
2146
- cap[inst.arg] = opos;
2147
- return t;
2101
+ const opos = capArray[capOffset + inst.arg];
2102
+ capArray[capOffset + inst.arg] = pos;
2103
+ this.add(q, inst.out, pos, capArray, capOffset, cond);
2104
+ capArray[capOffset + inst.arg] = opos;
2105
+ return;
2148
2106
  } else {
2149
2107
  pc = inst.out;
2150
2108
  continue;
@@ -2163,19 +2121,18 @@ var Machine = class Machine {
2163
2121
  pc = inst.out;
2164
2122
  continue;
2165
2123
  }
2166
- return t;
2124
+ return;
2167
2125
  case Inst.MATCH:
2168
2126
  case Inst.RUNE:
2169
2127
  case Inst.RUNE1:
2170
2128
  case Inst.RUNE_ANY:
2171
2129
  case Inst.RUNE_ANY_NOT_NL:
2172
- if (t === null) t = this.alloc(inst);
2173
- else t.inst = inst;
2174
- if (this.ncap > 0 && t.cap !== cap) for (let c = 0; c < this.ncap; c++) t.cap[c] = cap[c];
2175
- q.denseThreads[d] = t;
2176
- t = null;
2177
- return t;
2178
- default: throw new Error("unhandled");
2130
+ if (this.ncap > 0) {
2131
+ const destOffset = d * this.ncap;
2132
+ for (let c = 0; c < this.ncap; c++) q.denseCaps[destOffset + c] = capArray[capOffset + c];
2133
+ }
2134
+ return;
2135
+ default: throw new RE2JSInternalException("unhandled");
2179
2136
  }
2180
2137
  }
2181
2138
  }
@@ -2772,7 +2729,9 @@ const makeOnePass = (p) => {
2772
2729
  m[pc] = true;
2773
2730
  inst.op = Inst.ALT_MATCH;
2774
2731
  }
2775
- const mergeRes = mergeRuneSets(onePassRunes[inst.out] || [], onePassRunes[inst.arg] || [], inst.out, inst.arg);
2732
+ const leftRunes = onePassRunes[inst.out] || [];
2733
+ const rightRunes = onePassRunes[inst.arg] || [];
2734
+ const mergeRes = mergeRuneSets(leftRunes, rightRunes, inst.out, inst.arg);
2776
2735
  if (!mergeRes) return false;
2777
2736
  onePassRunes[pc] = mergeRes.merged;
2778
2737
  inst.next = new Uint32Array(mergeRes.next);
@@ -5364,24 +5323,6 @@ var Parser = class Parser {
5364
5323
  };
5365
5324
  //#endregion
5366
5325
  //#region src/RE2.js
5367
- var AtomicReference = class {
5368
- constructor(initialValue) {
5369
- this.value = initialValue;
5370
- }
5371
- get() {
5372
- return this.value;
5373
- }
5374
- set(newValue) {
5375
- this.value = newValue;
5376
- }
5377
- compareAndSet(expect, update) {
5378
- if (this.value === expect) {
5379
- this.value = update;
5380
- return true;
5381
- }
5382
- return false;
5383
- }
5384
- };
5385
5326
  /**
5386
5327
  * An RE2 class instance is a compiled representation of an RE2 regular expression, independent of
5387
5328
  * the public Java-like Pattern/Matcher API.
@@ -5470,7 +5411,7 @@ var RE2 = class RE2 {
5470
5411
  this.prefixUTF8 = null;
5471
5412
  this.prefixComplete = false;
5472
5413
  this.prefixRune = 0;
5473
- this.pooled = new AtomicReference();
5414
+ this.machinePool = [];
5474
5415
  this.dfa = new DFA(this.prog);
5475
5416
  this.onepass = OnePass.compile(this.prog);
5476
5417
  this.prefilter = null;
@@ -5534,42 +5475,23 @@ var RE2 = class RE2 {
5534
5475
  return this.prog.numInst();
5535
5476
  }
5536
5477
  get() {
5537
- let head;
5538
- do
5539
- head = this.pooled.get();
5540
- while (head && !this.pooled.compareAndSet(head, head.next));
5541
- return head;
5478
+ return this.machinePool.length > 0 ? this.machinePool.pop() : null;
5542
5479
  }
5543
5480
  reset() {
5544
- this.pooled.set(null);
5545
- }
5546
- put(m, isNew) {
5547
- let head = this.pooled.get();
5548
- do {
5549
- head = this.pooled.get();
5550
- if (!isNew && head) {
5551
- m = Machine.fromMachine(m);
5552
- isNew = true;
5553
- }
5554
- if (m.next !== head) m.next = head;
5555
- } while (!this.pooled.compareAndSet(head, m));
5481
+ this.machinePool.length = 0;
5482
+ }
5483
+ put(m) {
5484
+ this.machinePool.push(m);
5556
5485
  }
5557
5486
  toString() {
5558
5487
  return this.expr;
5559
5488
  }
5560
5489
  doExecuteNFA(input, pos, anchor, ncap) {
5561
5490
  let m = this.get();
5562
- let isNew = false;
5563
- if (!m) {
5564
- m = Machine.fromRE2(this);
5565
- isNew = true;
5566
- } else if (m.next !== null) {
5567
- m = Machine.fromMachine(m);
5568
- isNew = true;
5569
- }
5491
+ if (!m) m = Machine.fromRE2(this);
5570
5492
  m.init(ncap);
5571
5493
  const cap = m.match(input, pos, anchor) ? m.submatches() : null;
5572
- this.put(m, isNew);
5494
+ this.put(m);
5573
5495
  return cap;
5574
5496
  }
5575
5497
  match(s) {
@@ -6365,6 +6287,33 @@ var RE2JS = class RE2JS {
6365
6287
  return this.re2Input.executeEngine(machineInput, 0, RE2Flags.ANCHOR_BOTH, 0) !== null;
6366
6288
  }
6367
6289
  /**
6290
+ * Executes a search for a match in a specified string.
6291
+ * Returns a result array, or null if no match is found.
6292
+ * The returned array perfectly mirrors standard JavaScript `RegExpExecArray`,
6293
+ * including `.index`, `.input`, and `.groups` properties.
6294
+ *
6295
+ * @param {string|number[]|Uint8Array} input the input string or byte array
6296
+ * @returns {Array|null} the match array with index, input, and groups properties, or null
6297
+ */
6298
+ exec(input) {
6299
+ const m = this.matcher(input);
6300
+ if (!m.find()) return null;
6301
+ const result = [m.group(0)];
6302
+ for (let i = 1; i <= m.groupCount(); i++) {
6303
+ const val = m.group(i);
6304
+ result.push(val === null ? void 0 : val);
6305
+ }
6306
+ result.index = m.start(0);
6307
+ result.input = input;
6308
+ const namedGroups = this.namedGroups();
6309
+ if (Object.keys(namedGroups).length > 0) {
6310
+ const parsedGroups = m.getNamedGroups();
6311
+ for (const key in parsedGroups) if (parsedGroups[key] === null) parsedGroups[key] = void 0;
6312
+ result.groups = parsedGroups;
6313
+ } else result.groups = void 0;
6314
+ return result;
6315
+ }
6316
+ /**
6368
6317
  * Splits input around instances of the regular expression. It returns an array giving the strings
6369
6318
  * that occur before, between, and after instances of the regular expression.
6370
6319
  *
@@ -6408,7 +6357,7 @@ var RE2JS = class RE2JS {
6408
6357
  }
6409
6358
  result.push(m.substring(last, m.inputLength()));
6410
6359
  }
6411
- if (limit !== 0 || result.length === 0) result.push(m.substring(last, m.inputLength()));
6360
+ if (limit !== 0 || result.length === 0 && !(last === m.inputLength() && last > 0)) result.push(m.substring(last, m.inputLength()));
6412
6361
  return result;
6413
6362
  }
6414
6363
  /**
@@ -6416,7 +6365,7 @@ var RE2JS = class RE2JS {
6416
6365
  * including capturing groups.
6417
6366
  *
6418
6367
  * @param {string|number[]|Uint8Array} input the input string or byte array
6419
- * @returns {IterableIterator<Array>}
6368
+ * @returns {IterableIterator<RegExpMatchArray>}
6420
6369
  */
6421
6370
  *matchAll(input) {
6422
6371
  const m = this.matcher(input);