@poe-platform/safe-bash 0.1.511 → 0.1.512

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.
@@ -1482,7 +1482,7 @@ var Parser2 = class {
1482
1482
  await this.ledger.checkpoint(this.signal);
1483
1483
  members[code] = !members[code];
1484
1484
  }
1485
- return this.node(() => ({ kind: "set", members: Object.freeze(members), nullable: false, captured: false }));
1485
+ return this.node(() => ({ kind: "set", members: Object.freeze(members), nonAscii: negate, nullable: false, captured: false }));
1486
1486
  }
1487
1487
  first = false;
1488
1488
  if (this.at("[") && (this.at(".", this.offset + 1) || this.at("=", this.offset + 1))) {
@@ -1543,6 +1543,28 @@ function resolveEreProgram(program, ledger) {
1543
1543
 
1544
1544
  // packages/safe-bash/src/commands/regex-execution/ere/matcher.ts
1545
1545
  init_platform();
1546
+
1547
+ // packages/safe-bash/src/commands/regex-execution/utf8.ts
1548
+ init_platform();
1549
+ function invalidUtf8() {
1550
+ throw new PublicDiagnostic("bounded regex unsupported: literal patterns and subjects require valid non-NUL UTF-8 bytes");
1551
+ }
1552
+ async function validateUtf8(input3, ledger, signal) {
1553
+ for (let index = 0; index < input3.length; ) {
1554
+ const first = typeof input3 === "string" ? input3.charCodeAt(index) : input3[index];
1555
+ const width = first < 128 ? 1 : first >= 194 && first <= 223 ? 2 : first >= 224 && first <= 239 ? 3 : first >= 240 && first <= 244 ? 4 : 0;
1556
+ ledger.charge("work", Math.max(width, 1), signal);
1557
+ if (first === 0 || width === 0 || width > input3.length - index) invalidUtf8();
1558
+ for (let continuation = 1; continuation < width; continuation++) {
1559
+ const byte = typeof input3 === "string" ? input3.charCodeAt(index + continuation) : input3[index + continuation];
1560
+ if (byte < 128 || byte > 191 || continuation === 1 && (first === 224 && byte < 160 || first === 237 && byte > 159 || first === 240 && byte < 144 || first === 244 && byte > 143)) invalidUtf8();
1561
+ }
1562
+ index += width;
1563
+ await ledger.checkpoint(signal);
1564
+ }
1565
+ }
1566
+
1567
+ // packages/safe-bash/src/commands/regex-execution/ere/matcher.ts
1546
1568
  function spanOrder(left, right) {
1547
1569
  if (left === null) return right === null ? 0 : -1;
1548
1570
  if (right === null) return 1;
@@ -1621,15 +1643,47 @@ async function matchEre(program, subject, ledger, signal) {
1621
1643
  await admitAscii(subject, ledger, signal);
1622
1644
  return runMatcher(program, subject, ledger, signal, 0, true);
1623
1645
  }
1624
- async function createEreSpanMatcher(program, subject, ledger, signal) {
1646
+ async function prepareUtf8EreSubject(bytes3, ledger, signal) {
1625
1647
  ledger.check(signal);
1626
- resolveEreProgram(program, ledger);
1627
- ledger.admitInput("subjectBytes", subject.length, signal);
1628
- await admitAscii(subject, ledger, signal);
1629
- ledger.charge("allocationUnits", 2, signal);
1630
- return async (start) => {
1631
- if (!Number.isSafeInteger(start) || start < 0 || start > subject.length) throw new RangeError("Invalid ERE search cursor");
1632
- return runMatcher(program, subject, ledger, signal, start, false);
1648
+ ledger.admitInput("subjectBytes", bytes3.length, signal);
1649
+ ledger.charge("allocationUnits", bytes3.length * 11 + 16, signal);
1650
+ ledger.charge("work", bytes3.length, signal);
1651
+ const owned = new Uint8Array(bytes3);
1652
+ await validateUtf8(owned, ledger, signal);
1653
+ const characters = [];
1654
+ const offsets = [];
1655
+ for (let offset = 0; offset < owned.length; ) {
1656
+ const first = owned[offset];
1657
+ const width = first < 128 ? 1 : first < 224 ? 2 : first < 240 ? 3 : 4;
1658
+ ledger.charge("work", width, signal);
1659
+ await ledger.checkpoint(signal);
1660
+ offsets.push(offset);
1661
+ characters.push(String.fromCharCode(first < 128 ? first : 128));
1662
+ offset += width;
1663
+ }
1664
+ offsets.push(owned.length);
1665
+ ledger.charge("work", characters.length, signal);
1666
+ await ledger.checkpoint(signal);
1667
+ const subject = characters.join("");
1668
+ return (program) => {
1669
+ resolveEreProgram(program, ledger);
1670
+ ledger.charge("allocationUnits", 2, signal);
1671
+ return async (start) => {
1672
+ if (!Number.isSafeInteger(start) || start < 0 || start > owned.length) throw new RangeError("Invalid UTF-8 ERE search cursor");
1673
+ let lower = 0, upper = offsets.length - 1;
1674
+ while (lower < upper) {
1675
+ ledger.charge("work", 1, signal);
1676
+ await ledger.checkpoint(signal);
1677
+ const middle = Math.floor((lower + upper) / 2);
1678
+ if (offsets[middle] < start) lower = middle + 1;
1679
+ else upper = middle;
1680
+ }
1681
+ if (offsets[lower] !== start) throw new RangeError("UTF-8 ERE cursor must be a scalar boundary");
1682
+ const span = await runMatcher(program, subject, ledger, signal, lower, false);
1683
+ if (!span) return void 0;
1684
+ ledger.charge("allocationUnits", 2, signal);
1685
+ return Object.freeze({ start: offsets[span.start], end: offsets[span.end] });
1686
+ };
1633
1687
  };
1634
1688
  }
1635
1689
  async function runMatcher(program, subject, ledger, signal, from, materialize) {
@@ -1700,7 +1754,7 @@ async function runMatcher(program, subject, ledger, signal, from, materialize) {
1700
1754
  case "literal":
1701
1755
  case "set": {
1702
1756
  const code = subject.charCodeAt(state.position);
1703
- if (state.position < subject.length && (node.kind === "dot" || node.kind === "literal" && node.code === code || node.kind === "set" && node.members[code])) {
1757
+ if (state.position < subject.length && (node.kind === "dot" || node.kind === "literal" && node.code === code || node.kind === "set" && (code < 128 ? node.members[code] : node.nonAscii))) {
1704
1758
  push(state.position + 1, current.next, state.captures, state.histories);
1705
1759
  }
1706
1760
  break;
@@ -1980,20 +2034,6 @@ async function admitBre(pattern, ledger, signal) {
1980
2034
  }
1981
2035
  }
1982
2036
  }
1983
- async function validateUtf8(input3, ledger, signal) {
1984
- for (let index = 0; index < input3.length; ) {
1985
- const first = typeof input3 === "string" ? input3.charCodeAt(index) : input3[index];
1986
- const width = first < 128 ? 1 : first >= 194 && first <= 223 ? 2 : first >= 224 && first <= 239 ? 3 : first >= 240 && first <= 244 ? 4 : 0;
1987
- ledger.charge("work", Math.max(width, 1), signal);
1988
- if (first === 0 || width === 0 || width > input3.length - index) fail("unsupported", "literal patterns and subjects require valid non-NUL UTF-8 bytes");
1989
- for (let continuation = 1; continuation < width; continuation++) {
1990
- const byte = typeof input3 === "string" ? input3.charCodeAt(index + continuation) : input3[index + continuation];
1991
- if (byte < 128 || byte > 191 || continuation === 1 && (first === 224 && byte < 160 || first === 237 && byte > 159 || first === 240 && byte < 144 || first === 244 && byte > 143)) fail("unsupported", "literal patterns and subjects require valid non-NUL UTF-8 bytes");
1992
- }
1993
- index += width;
1994
- await ledger.checkpoint(signal);
1995
- }
1996
- }
1997
2037
  async function literalBytes(pattern, selected, ledger, signal) {
1998
2038
  const { kind } = selected;
1999
2039
  let length = 0;
@@ -2154,27 +2194,18 @@ async function execute(input3, signal) {
2154
2194
  const results = [];
2155
2195
  const usage2 = { count: 0 };
2156
2196
  for (const row of rows2) {
2157
- ledger.charge("allocationUnits", row.bytes.length * 2 + 2, signal);
2158
- const characters = [];
2159
- for (const byte of row.bytes) {
2160
- ledger.charge("work", 1, signal);
2161
- if (byte === 0 || byte > 127) fail("unsupported", "subjects require non-NUL ASCII; Unicode and invalid UTF-8 are unsupported");
2162
- characters.push(String.fromCharCode(byte));
2163
- await ledger.checkpoint(signal);
2164
- }
2165
- const subject = characters.join("");
2197
+ const subject = await prepareUtf8EreSubject(row.bytes, ledger, signal);
2166
2198
  if (row.all) {
2167
2199
  ledger.charge("allocationUnits", programs2.length + 1, signal);
2168
2200
  const finders = [];
2169
- for (const program of programs2) finders.push(await createEreSpanMatcher(program, subject, ledger, signal));
2201
+ for (const program of programs2) finders.push(subject(program));
2170
2202
  results.push(await enumerate(input3, row, finders, usage2, signal));
2171
2203
  continue;
2172
2204
  }
2173
2205
  let span;
2174
2206
  for (const program of programs2) {
2175
- const match = await matchEre(program, subject, ledger, signal);
2176
- if (!match.matched) continue;
2177
- const candidate = match.captures[0];
2207
+ const candidate = await subject(program)(0);
2208
+ if (!candidate) continue;
2178
2209
  if (selected.kind === "grep") {
2179
2210
  span = candidate;
2180
2211
  break;