@poe-platform/safe-bash 0.1.100 → 0.1.102

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.
@@ -17231,6 +17231,82 @@ function command(name2, run) {
17231
17231
  };
17232
17232
  }
17233
17233
 
17234
+ // packages/safe-bash/src/commands/text-programs/replacement-buffer.ts
17235
+ init_platform();
17236
+ var ReplacementBuffer = class {
17237
+ constructor(budget) {
17238
+ this.budget = budget;
17239
+ }
17240
+ budget;
17241
+ #segments = [];
17242
+ #size = 0;
17243
+ #allocated = 0;
17244
+ #tailUsed = 0;
17245
+ get remaining() {
17246
+ return this.budget.maxBufferBytes - this.#size;
17247
+ }
17248
+ admit(length) {
17249
+ this.budget.step(0);
17250
+ if (!Number.isSafeInteger(length) || length < 0 || length > this.remaining) throw new ProgramError("text buffer limit exceeded");
17251
+ }
17252
+ async append(source, start = 0, end = source.length) {
17253
+ this.admit(end - start);
17254
+ let offset = start;
17255
+ while (offset < end) {
17256
+ await this.budget.checkpoint();
17257
+ let tail = this.#segments.at(-1);
17258
+ const available = tail ? tail.length - this.#tailUsed : 0;
17259
+ const capacity = Math.min(1024, this.budget.maxBufferBytes - this.#allocated);
17260
+ const length = Math.min(end - offset, available || capacity);
17261
+ this.budget.step(length);
17262
+ if (!available) {
17263
+ this.budget.step();
17264
+ tail = import_buffer.Buffer.allocUnsafeSlow(capacity);
17265
+ this.#segments.push(tail);
17266
+ this.#allocated += capacity;
17267
+ this.#tailUsed = 0;
17268
+ }
17269
+ for (let index = 0; index < length; index++) tail[this.#tailUsed + index] = source.charCodeAt(offset + index);
17270
+ this.#tailUsed += length;
17271
+ this.#size += length;
17272
+ offset += length;
17273
+ }
17274
+ }
17275
+ async finish() {
17276
+ this.budget.step(0);
17277
+ if (!this.#size) return "";
17278
+ this.budget.step(this.#size);
17279
+ await this.budget.checkpoint();
17280
+ this.budget.step(0);
17281
+ if (this.#segments.length === 1) {
17282
+ const text = this.#segments[0].toString("latin1", 0, this.#size);
17283
+ this.clear();
17284
+ return text;
17285
+ }
17286
+ this.budget.step(this.#size);
17287
+ if (this.#allocated > this.budget.maxBufferBytes || this.#size > this.budget.maxBufferBytes) throw new ProgramError("text buffer limit exceeded");
17288
+ const result = import_buffer.Buffer.allocUnsafeSlow(this.#size);
17289
+ let offset = 0;
17290
+ for (const segment of this.#segments) {
17291
+ await this.budget.checkpoint();
17292
+ this.budget.step(0);
17293
+ const length = Math.min(segment.length, this.#size - offset);
17294
+ result.set(segment.subarray(0, length), offset);
17295
+ offset += length;
17296
+ }
17297
+ this.clear();
17298
+ await this.budget.checkpoint();
17299
+ this.budget.step(0);
17300
+ return result.toString("latin1");
17301
+ }
17302
+ clear() {
17303
+ this.#segments = [];
17304
+ this.#size = 0;
17305
+ this.#allocated = 0;
17306
+ this.#tailUsed = 0;
17307
+ }
17308
+ };
17309
+
17234
17310
  // packages/safe-bash/src/commands/text-programs/regex.ts
17235
17311
  var classes2 = {
17236
17312
  alpha: (character) => /^[A-Za-z]$/u.test(character),
@@ -17520,43 +17596,93 @@ var Pattern = class {
17520
17596
  return void 0;
17521
17597
  }
17522
17598
  };
17523
- function replacementText(replacement, match) {
17524
- let result = "";
17599
+ async function replacementLength(replacement, match, budget, available) {
17600
+ let length = 0;
17601
+ let tokens2 = 0;
17525
17602
  for (let index = 0; index < replacement.length; index++) {
17603
+ if (tokens2++ % 256 === 0) await budget.checkpoint();
17604
+ budget.step();
17526
17605
  const character = replacement[index];
17527
- if (character === "&") result += match.groups[0] ?? "";
17528
- else if (character === "\\" && index + 1 < replacement.length) {
17606
+ let size = 1;
17607
+ if (character === "&") {
17608
+ budget.step();
17609
+ size = match.groups[0]?.length ?? 0;
17610
+ } else if (character === "\\" && index + 1 < replacement.length) {
17611
+ budget.step();
17529
17612
  const next = replacement[++index];
17530
- result += /^[1-9]$/u.test(next) ? match.groups[Number(next)] ?? "" : next === "n" ? "\n" : next === "t" ? " " : next;
17531
- } else result += character;
17613
+ if (next >= "1" && next <= "9") {
17614
+ budget.step();
17615
+ size = match.groups[Number(next)]?.length ?? 0;
17616
+ }
17617
+ }
17618
+ if (size > available - length) throw new ProgramError("text buffer limit exceeded");
17619
+ length += size;
17532
17620
  }
17533
- return result;
17621
+ return length;
17534
17622
  }
17535
- function substitute(text, pattern, replacement, budget, global, occurrence = 1) {
17623
+ async function replacementText(replacement, match, buffer, budget) {
17624
+ let literal = 0;
17625
+ let tokens2 = 0;
17626
+ for (let index = 0; index < replacement.length; index++) {
17627
+ if (tokens2++ % 256 === 0) await budget.checkpoint();
17628
+ budget.step();
17629
+ const character = replacement[index];
17630
+ if (character !== "&" && (character !== "\\" || index + 1 === replacement.length)) continue;
17631
+ await buffer.append(replacement, literal, index);
17632
+ if (character === "&") {
17633
+ budget.step();
17634
+ await buffer.append(match.groups[0] ?? "");
17635
+ } else {
17636
+ budget.step();
17637
+ const next = replacement[++index];
17638
+ if (next >= "1" && next <= "9") {
17639
+ budget.step();
17640
+ await buffer.append(match.groups[Number(next)] ?? "");
17641
+ } else await buffer.append(next === "n" ? "\n" : next === "t" ? " " : next);
17642
+ }
17643
+ literal = index + 1;
17644
+ }
17645
+ await buffer.append(replacement, literal);
17646
+ }
17647
+ async function substitute(text, pattern, replacement, budget, global, occurrence = 1) {
17536
17648
  let search = 0;
17537
17649
  let consumed = 0;
17538
17650
  let previousEnd = -1;
17539
17651
  let encountered = 0;
17540
17652
  let count2 = 0;
17541
- let result = "";
17542
- while (search <= text.length) {
17543
- const match = pattern.find(text, budget, search);
17544
- if (!match) break;
17545
- if (match.start === match.end && match.start === previousEnd) {
17546
- search = match.end + 1;
17547
- continue;
17548
- }
17549
- encountered++;
17550
- if (encountered >= occurrence) {
17551
- result = budget.check(result + text.slice(consumed, match.start) + replacementText(replacement, match));
17552
- consumed = match.end;
17553
- count2++;
17554
- if (!global) break;
17555
- }
17556
- previousEnd = match.end > match.start ? match.end : -1;
17557
- search = match.end > match.start ? match.end : match.end + 1;
17653
+ const result = new ReplacementBuffer(budget);
17654
+ try {
17655
+ while (search <= text.length) {
17656
+ await budget.checkpoint();
17657
+ budget.step();
17658
+ const match = pattern.find(text, budget, search);
17659
+ if (!match) break;
17660
+ if (match.start === match.end && match.start === previousEnd) {
17661
+ search = match.end + 1;
17662
+ continue;
17663
+ }
17664
+ encountered++;
17665
+ if (encountered >= occurrence) {
17666
+ const prefix2 = match.start - consumed;
17667
+ result.admit(prefix2);
17668
+ const length = await replacementLength(replacement, match, budget, result.remaining - prefix2);
17669
+ result.admit(prefix2 + length);
17670
+ await result.append(text, consumed, match.start);
17671
+ await replacementText(replacement, match, result, budget);
17672
+ consumed = match.end;
17673
+ count2++;
17674
+ if (!global) break;
17675
+ }
17676
+ previousEnd = match.end > match.start ? match.end : -1;
17677
+ search = match.end > match.start ? match.end : match.end + 1;
17678
+ }
17679
+ budget.step(0);
17680
+ if (!count2) return { text: budget.check(text), count: count2 };
17681
+ await result.append(text, consumed);
17682
+ return { text: await result.finish(), count: count2 };
17683
+ } finally {
17684
+ result.clear();
17558
17685
  }
17559
- return { text: budget.check(result + text.slice(consumed)), count: count2 };
17560
17686
  }
17561
17687
 
17562
17688
  // packages/safe-bash/src/commands/text-programs/sed.ts
@@ -17935,7 +18061,7 @@ async function execute(program, context, files, quiet, budget) {
17935
18061
  [pattern, hold] = [hold, pattern];
17936
18062
  break;
17937
18063
  case "s": {
17938
- const changed = substitute(pattern, getPattern(instruction.pattern), instruction.replacement, budget, instruction.global ?? false, instruction.occurrence ?? 1);
18064
+ const changed = await substitute(pattern, getPattern(instruction.pattern), instruction.replacement, budget, instruction.global ?? false, instruction.occurrence ?? 1);
17939
18065
  pattern = changed.text;
17940
18066
  if (changed.count) {
17941
18067
  substituted = true;