@poe-platform/safe-bash 0.1.66 → 0.1.67

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.
@@ -4586,6 +4586,68 @@ function streamCommands() {
4586
4586
 
4587
4587
  // packages/safe-bash/src/commands/text.ts
4588
4588
  init_platform();
4589
+ var SortWork = class {
4590
+ constructor(signal) {
4591
+ this.signal = signal;
4592
+ }
4593
+ signal;
4594
+ #pending = 0;
4595
+ charge(units = 1) {
4596
+ this.signal.throwIfAborted();
4597
+ this.#pending += units;
4598
+ if (this.#pending >= 4096) return this.#checkpoint();
4599
+ }
4600
+ async #checkpoint() {
4601
+ while (this.#pending >= 4096) {
4602
+ this.#pending -= 4096;
4603
+ await yieldTurn(this.signal);
4604
+ this.signal.throwIfAborted();
4605
+ }
4606
+ }
4607
+ };
4608
+ async function sortRecords(records, compare, work) {
4609
+ if (records.length < 2) return records;
4610
+ let source = records;
4611
+ let target = new Array(records.length);
4612
+ for (let width = 1; width < records.length; width *= 2) {
4613
+ for (let begin = 0; begin < records.length; begin += width * 2) {
4614
+ const middle = Math.min(begin + width, records.length);
4615
+ const end = Math.min(begin + width * 2, records.length);
4616
+ let left = begin;
4617
+ let right = middle;
4618
+ for (let index = begin; index < end; index++) {
4619
+ const checkpoint = work.charge();
4620
+ if (checkpoint) await checkpoint;
4621
+ if (left < middle && (right === end || await compare(source[left], source[right]) <= 0)) target[index] = source[left++];
4622
+ else target[index] = source[right++];
4623
+ }
4624
+ }
4625
+ [source, target] = [target, source];
4626
+ }
4627
+ return source;
4628
+ }
4629
+ async function compareSortBytes(left, right, work) {
4630
+ const length = Math.min(left.length, right.length);
4631
+ for (let offset = 0; offset < length; offset += 1024) {
4632
+ const end = Math.min(offset + 1024, length);
4633
+ await work.charge(2 * (end - offset));
4634
+ const compared = import_buffer.Buffer.compare(left.subarray(offset, end), right.subarray(offset, end));
4635
+ if (compared) return compared;
4636
+ }
4637
+ return left.length - right.length;
4638
+ }
4639
+ async function foldSortBytes(bytes2, work) {
4640
+ const folded = new Uint8Array(bytes2.length);
4641
+ for (let offset = 0; offset < bytes2.length; offset += 1024) {
4642
+ const end = Math.min(offset + 1024, bytes2.length);
4643
+ await work.charge(end - offset);
4644
+ for (let index = offset; index < end; index++) {
4645
+ const byte = bytes2[index];
4646
+ folded[index] = byte >= 97 && byte <= 122 ? byte - 32 : byte;
4647
+ }
4648
+ }
4649
+ return folded;
4650
+ }
4589
4651
  async function admitTextOutput(context, destination) {
4590
4652
  if (destination === void 0) return;
4591
4653
  assertCommandRequirements(context, textOutputRequirements, ["output"]);
@@ -4602,27 +4664,37 @@ function compareBytes(left, right) {
4602
4664
  function fold(bytes2) {
4603
4665
  return bytes2.map((byte) => byte >= 97 && byte <= 122 ? byte - 32 : byte);
4604
4666
  }
4605
- function parseNumeric(bytes2) {
4667
+ async function parseNumeric(bytes2, work) {
4668
+ await work.charge(bytes2.length);
4606
4669
  const match = /^[ \t]*(-?)([0-9]*)(?:\.([0-9]*))?/u.exec(import_buffer.Buffer.from(bytes2).toString("latin1"));
4607
4670
  const whole = (match[2] ?? "").replace(/^0+/u, "") || "0";
4608
4671
  const fraction = (match[3] ?? "").replace(/0+$/u, "");
4609
4672
  return { whole, fraction, negative: match[1] === "-" && (whole !== "0" || fraction !== "") };
4610
4673
  }
4611
- function compareNumericValues(first, second) {
4674
+ async function compareNumericValues(first, second, work) {
4612
4675
  if (first.negative !== second.negative) return first.negative ? -1 : 1;
4613
4676
  let compared = first.whole.length - second.whole.length;
4614
- if (!compared) compared = first.whole < second.whole ? -1 : first.whole > second.whole ? 1 : 0;
4677
+ if (!compared) {
4678
+ for (let offset = 0; offset < first.whole.length && !compared; offset += 1024) {
4679
+ const end = Math.min(offset + 1024, first.whole.length);
4680
+ await work.charge(2 * (end - offset));
4681
+ const firstWhole = first.whole.slice(offset, end);
4682
+ const secondWhole = second.whole.slice(offset, end);
4683
+ compared = firstWhole < secondWhole ? -1 : firstWhole > secondWhole ? 1 : 0;
4684
+ }
4685
+ }
4615
4686
  if (!compared) {
4616
4687
  const width = Math.max(first.fraction.length, second.fraction.length);
4617
- const firstFraction = first.fraction.padEnd(width, "0");
4618
- const secondFraction = second.fraction.padEnd(width, "0");
4619
- compared = firstFraction < secondFraction ? -1 : firstFraction > secondFraction ? 1 : 0;
4688
+ for (let offset = 0; offset < width && !compared; offset += 1024) {
4689
+ const end = Math.min(offset + 1024, width);
4690
+ await work.charge(2 * (end - offset));
4691
+ const firstFraction = first.fraction.slice(offset, end).padEnd(end - offset, "0");
4692
+ const secondFraction = second.fraction.slice(offset, end).padEnd(end - offset, "0");
4693
+ compared = firstFraction < secondFraction ? -1 : firstFraction > secondFraction ? 1 : 0;
4694
+ }
4620
4695
  }
4621
4696
  return first.negative ? -compared : compared;
4622
4697
  }
4623
- function numericCompare(left, right) {
4624
- return compareNumericValues(parseNumeric(left), parseNumeric(right));
4625
- }
4626
4698
  function sortKey(specification) {
4627
4699
  const match = /^([0-9]+)(?:\.([0-9]+))?([bfnr]*)(?:,([0-9]+)(?:\.([0-9]+))?([bfnr]*))?$/u.exec(specification);
4628
4700
  if (!match) throw new UsageError(`invalid key '${specification}'`);
@@ -4634,25 +4706,33 @@ function sortKey(specification) {
4634
4706
  flags: new Set((match[3] ?? "") + (match[6] ?? ""))
4635
4707
  };
4636
4708
  }
4637
- function keyBytes(line, key, separator, blanks) {
4709
+ async function keyBytes(line, key, separator, blanks, work) {
4638
4710
  const fields = [];
4639
4711
  if (separator !== void 0) {
4640
4712
  let start2 = 0;
4641
- for (let offset = 0; offset <= line.length; offset++) if (offset === line.length || line[offset] === separator) {
4642
- fields.push({ start: start2, end: offset });
4643
- start2 = offset + 1;
4713
+ for (let offset = 0; offset <= line.length; offset++) {
4714
+ if (offset > 0 && offset % 1024 === 0) await work.charge(1024);
4715
+ if (offset === line.length || line[offset] === separator) {
4716
+ fields.push({ start: start2, end: offset });
4717
+ start2 = offset + 1;
4718
+ }
4644
4719
  }
4645
4720
  } else {
4646
4721
  let offset = 0;
4647
4722
  while (offset < line.length) {
4648
4723
  const leading = offset;
4649
- while (offset < line.length && (line[offset] === 32 || line[offset] === 9)) offset++;
4724
+ while (offset < line.length && (line[offset] === 32 || line[offset] === 9)) {
4725
+ if (++offset % 1024 === 0) await work.charge(1024);
4726
+ }
4650
4727
  const start2 = blanks ? offset : leading;
4651
4728
  if (offset === line.length) break;
4652
- while (offset < line.length && line[offset] !== 32 && line[offset] !== 9) offset++;
4729
+ while (offset < line.length && line[offset] !== 32 && line[offset] !== 9) {
4730
+ if (++offset % 1024 === 0) await work.charge(1024);
4731
+ }
4653
4732
  fields.push({ start: start2, end: offset });
4654
4733
  }
4655
4734
  }
4735
+ await work.charge(line.length % 1024);
4656
4736
  const start = (fields[key.start - 1]?.start ?? line.length) + key.startCharacter - 1;
4657
4737
  const last = key.end === void 0 ? void 0 : fields[key.end - 1];
4658
4738
  const end = key.end === void 0 ? line.length : last === void 0 ? line.length : key.endCharacter === void 0 ? last.end : Math.min(last.end, last.start + key.endCharacter);
@@ -4715,42 +4795,50 @@ function textCommands() {
4715
4795
  const keys = (parsed.values.get("k") ?? []).map(sortKey);
4716
4796
  const simple = !keys.length && !["b", "f", "n"].some((flag) => parsed.flags.has(flag));
4717
4797
  const direction = parsed.flags.has("r") ? -1 : 1;
4718
- let compareNumeric = numericCompare;
4798
+ const work = new SortWork(context.signal);
4799
+ let compareNumeric = async (left, right) => compareNumericValues(await parseNumeric(left, work), await parseNumeric(right, work), work);
4719
4800
  if (!keys.length && parsed.flags.has("n") && !["b", "f", "c"].some((flag) => parsed.flags.has(flag))) {
4720
4801
  const numericValues = /* @__PURE__ */ new Map();
4721
4802
  let retainedBytes = 0;
4722
- const numericValue = (bytes2) => {
4803
+ const numericValue = async (bytes2) => {
4723
4804
  const cached = numericValues.get(bytes2);
4724
4805
  if (cached !== void 0) return cached;
4725
4806
  context.signal.throwIfAborted();
4726
4807
  const charge2 = 6 * bytes2.length + 2;
4727
- if (numericValues.size >= 16384 || charge2 > 1048576 - retainedBytes) return parseNumeric(bytes2);
4728
- const parsedValue = parseNumeric(bytes2);
4808
+ if (numericValues.size >= 16384 || charge2 > 1048576 - retainedBytes) return parseNumeric(bytes2, work);
4809
+ const parsedValue = await parseNumeric(bytes2, work);
4729
4810
  numericValues.set(bytes2, parsedValue);
4730
4811
  retainedBytes += charge2;
4731
4812
  return parsedValue;
4732
4813
  };
4733
- compareNumeric = (left, right) => compareNumericValues(numericValue(left), numericValue(right));
4814
+ compareNumeric = async (left, right) => compareNumericValues(await numericValue(left), await numericValue(right), work);
4734
4815
  }
4735
- let keyCompare = simple ? (left, right) => compareBytes(left, right) * direction : (left, right) => {
4816
+ let keyCompare = async (left, right) => {
4817
+ const checkpoint = work.charge();
4818
+ if (checkpoint) await checkpoint;
4819
+ if (simple) return await compareSortBytes(left, right, work) * direction;
4736
4820
  for (const key of keys.length ? keys : [void 0]) {
4821
+ await work.charge();
4737
4822
  const flags = key?.flags.size ? key.flags : parsed.flags;
4738
- let first = key ? keyBytes(left, key, separator, flags.has("b")) : left;
4739
- let second = key ? keyBytes(right, key, separator, flags.has("b")) : right;
4823
+ let first = key ? await keyBytes(left, key, separator, flags.has("b"), work) : left;
4824
+ let second = key ? await keyBytes(right, key, separator, flags.has("b"), work) : right;
4740
4825
  if (!key && flags.has("b")) {
4741
- const trim = (bytes2) => {
4826
+ const trim = async (bytes2) => {
4742
4827
  let offset = 0;
4743
- while (bytes2[offset] === 9 || bytes2[offset] === 32) offset++;
4828
+ while (bytes2[offset] === 9 || bytes2[offset] === 32) {
4829
+ if (++offset % 1024 === 0) await work.charge(1024);
4830
+ }
4831
+ await work.charge(offset % 1024);
4744
4832
  return bytes2.subarray(offset);
4745
4833
  };
4746
- first = trim(first);
4747
- second = trim(second);
4834
+ first = await trim(first);
4835
+ second = await trim(second);
4748
4836
  }
4749
4837
  if (flags.has("f")) {
4750
- first = fold(first);
4751
- second = fold(second);
4838
+ first = await foldSortBytes(first, work);
4839
+ second = await foldSortBytes(second, work);
4752
4840
  }
4753
- let result = flags.has("n") ? compareNumeric(first, second) : compareBytes(first, second);
4841
+ let result = flags.has("n") ? await compareNumeric(first, second) : await compareSortBytes(first, second, work);
4754
4842
  if (flags.has("r")) result = -result;
4755
4843
  if (result) return result;
4756
4844
  }
@@ -4761,24 +4849,29 @@ function textCommands() {
4761
4849
  if (numericKey && numericKeyFlags.has("n") && !["b", "f"].some((flag) => numericKeyFlags.has(flag)) && !parsed.flags.has("c")) {
4762
4850
  const keyedNumericValues = /* @__PURE__ */ new Map();
4763
4851
  let retainedKeyBytes = 0;
4764
- const keyedNumericValue = (record4) => {
4852
+ const keyedNumericValue = async (record4) => {
4765
4853
  const cached = keyedNumericValues.get(record4);
4766
4854
  if (cached !== void 0) return cached;
4767
4855
  context.signal.throwIfAborted();
4768
- const bytes2 = keyBytes(record4, numericKey, separator, false);
4856
+ const bytes2 = await keyBytes(record4, numericKey, separator, false, work);
4769
4857
  const charge2 = 6 * bytes2.length + 2;
4770
- if (keyedNumericValues.size >= 16384 || charge2 > 1048576 - retainedKeyBytes) return parseNumeric(bytes2);
4771
- const parsedValue = parseNumeric(bytes2);
4858
+ if (keyedNumericValues.size >= 16384 || charge2 > 1048576 - retainedKeyBytes) return parseNumeric(bytes2, work);
4859
+ const parsedValue = await parseNumeric(bytes2, work);
4772
4860
  keyedNumericValues.set(record4, parsedValue);
4773
4861
  retainedKeyBytes += charge2;
4774
4862
  return parsedValue;
4775
4863
  };
4776
- keyCompare = (left, right) => {
4777
- const result = compareNumericValues(keyedNumericValue(left), keyedNumericValue(right));
4864
+ keyCompare = async (left, right) => {
4865
+ const checkpoint = work.charge();
4866
+ if (checkpoint) await checkpoint;
4867
+ const result = await compareNumericValues(await keyedNumericValue(left), await keyedNumericValue(right), work);
4778
4868
  return numericKeyFlags.has("r") ? -result : result;
4779
4869
  };
4780
4870
  }
4781
- const compare = simple ? keyCompare : (left, right) => keyCompare(left, right) || (parsed.flags.has("s") || parsed.flags.has("u") ? 0 : compareBytes(left, right) * (parsed.flags.has("r") ? -1 : 1));
4871
+ const compare = async (left, right) => {
4872
+ const result = await keyCompare(left, right);
4873
+ return result || (simple || parsed.flags.has("s") || parsed.flags.has("u") ? 0 : await compareSortBytes(left, right, work) * direction);
4874
+ };
4782
4875
  const records = [];
4783
4876
  let size = 0;
4784
4877
  const exitCode = 0;
@@ -4798,7 +4891,7 @@ function textCommands() {
4798
4891
  context.signal.throwIfAborted();
4799
4892
  size += line.bytes.length + 1;
4800
4893
  if (size > bufferLimit) throw new FsError("EFBIG", { message: "sort buffer limit exceeded" });
4801
- if (parsed.flags.has("c") && records.length && (compare(records.at(-1), line.bytes) > 0 || parsed.flags.has("u") && keyCompare(records.at(-1), line.bytes) === 0)) {
4894
+ if (parsed.flags.has("c") && records.length && (await compare(records.at(-1), line.bytes) > 0 || parsed.flags.has("u") && await keyCompare(records.at(-1), line.bytes) === 0)) {
4802
4895
  await diagnostic(context, new Error(`disorder at record ${records.length + 1}`));
4803
4896
  return { exitCode: 1 };
4804
4897
  }
@@ -4810,14 +4903,14 @@ function textCommands() {
4810
4903
  }
4811
4904
  }
4812
4905
  if (parsed.flags.has("c")) return { exitCode };
4813
- records.sort(compare);
4906
+ const ordered = await sortRecords(records, compare, work);
4814
4907
  const sorted = (async function* () {
4815
4908
  let previous;
4816
4909
  let buffer = new Uint8Array(64 * 1024);
4817
4910
  let used = 0;
4818
- for (const record4 of records) {
4911
+ for (const record4 of ordered) {
4819
4912
  context.signal.throwIfAborted();
4820
- if (parsed.flags.has("u") && previous !== void 0 && keyCompare(previous, record4) === 0) continue;
4913
+ if (parsed.flags.has("u") && previous !== void 0 && await keyCompare(previous, record4) === 0) continue;
4821
4914
  let offset = 0;
4822
4915
  while (offset < record4.length) {
4823
4916
  const length = Math.min(record4.length - offset, buffer.length - used);