@poe-platform/safe-bash 0.1.49 → 0.1.51

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.
@@ -4822,47 +4822,62 @@ function evaluateArithmetic(program, variables) {
4822
4822
  throw new Error(`Unsupported arithmetic operator ${operator}`);
4823
4823
  }
4824
4824
  };
4825
- const evaluate = (node) => {
4826
- if (++steps > 1e4) throw new Error("Arithmetic operation limit exceeded");
4827
- let value2;
4828
- if (node.kind === "literal") return node.value;
4829
- if (node.kind === "name") {
4830
- if (visiting.has(node.name) || visiting.size >= 64) throw new Error("Arithmetic variable recursion");
4831
- visiting.add(node.name);
4832
- try {
4833
- return evaluate(parseArithmetic(variables[node.name] ?? "0"));
4834
- } finally {
4835
- visiting.delete(node.name);
4836
- }
4837
- }
4838
- if (node.kind === "conditional") return evaluate(evaluate(node.condition) ? node.yes : node.no);
4839
- if (node.kind === "unary") {
4840
- const operand = evaluate(node.operand);
4841
- if (node.operator === "+") value2 = operand;
4842
- else if (node.operator === "-") value2 = -operand;
4843
- else if (node.operator === "!") value2 = BigInt(!operand);
4844
- else if (node.operator === "~") value2 = ~operand;
4845
- else {
4846
- value2 = BigInt.asIntN(64, operand + (node.operator === "++" ? 1n : -1n));
4847
- variables[node.operand.name] = String(value2);
4848
- if (node.postfix) value2 = operand;
4849
- }
4850
- } else {
4851
- if (node.operator === "=") value2 = evaluate(node.right);
4852
- else {
4853
- const left = evaluate(node.left);
4854
- if (node.operator === "&&") return left ? BigInt(evaluate(node.right) !== 0n) : 0n;
4855
- if (node.operator === "||") return left ? 1n : BigInt(evaluate(node.right) !== 0n);
4856
- if (node.operator === ",") return evaluate(node.right);
4857
- value2 = binary(precedence[node.operator] === 2 ? node.operator.slice(0, -1) : node.operator, left, evaluate(node.right), node.right.start ?? 0);
4858
- }
4859
- if (precedence[node.operator] === 2) variables[node.left.name] = String(BigInt.asIntN(64, value2));
4860
- }
4861
- return BigInt.asIntN(64, value2);
4862
- };
4863
4825
  try {
4864
4826
  if (program.error) throw program.error;
4865
- return evaluate(program.tree);
4827
+ const pending = [{ kind: "evaluate", node: program.tree }];
4828
+ let value2 = 0n;
4829
+ while (pending.length) {
4830
+ const frame = pending.pop();
4831
+ if (frame.kind === "evaluate") {
4832
+ if (++steps > 1e4) throw new Error("Arithmetic operation limit exceeded");
4833
+ const node = frame.node;
4834
+ if (node.kind === "literal") value2 = node.value;
4835
+ else if (node.kind === "name") {
4836
+ if (visiting.has(node.name) || visiting.size >= 64) throw new Error("Arithmetic variable recursion");
4837
+ visiting.add(node.name);
4838
+ pending.push({ kind: "variable", name: node.name }, { kind: "evaluate", node: parseArithmetic(variables[node.name] ?? "0") });
4839
+ } else if (node.kind === "conditional") {
4840
+ pending.push({ kind: "conditional", node }, { kind: "evaluate", node: node.condition });
4841
+ } else if (node.kind === "unary") {
4842
+ pending.push({ kind: "unary", node }, { kind: "evaluate", node: node.operand });
4843
+ } else if (node.operator === "=") {
4844
+ pending.push({ kind: "right", node }, { kind: "evaluate", node: node.right });
4845
+ } else {
4846
+ pending.push({ kind: "left", node }, { kind: "evaluate", node: node.left });
4847
+ }
4848
+ } else if (frame.kind === "variable") visiting.delete(frame.name);
4849
+ else if (frame.kind === "conditional") {
4850
+ pending.push({ kind: "evaluate", node: value2 ? frame.node.yes : frame.node.no });
4851
+ } else if (frame.kind === "unary") {
4852
+ const { node } = frame;
4853
+ const operand = value2;
4854
+ if (node.operator === "+") value2 = operand;
4855
+ else if (node.operator === "-") value2 = -operand;
4856
+ else if (node.operator === "!") value2 = BigInt(!operand);
4857
+ else if (node.operator === "~") value2 = ~operand;
4858
+ else {
4859
+ value2 = BigInt.asIntN(64, operand + (node.operator === "++" ? 1n : -1n));
4860
+ variables[node.operand.name] = String(value2);
4861
+ if (node.postfix) value2 = operand;
4862
+ }
4863
+ value2 = BigInt.asIntN(64, value2);
4864
+ } else if (frame.kind === "left") {
4865
+ const { node } = frame;
4866
+ if (node.operator === "&&" || node.operator === "||") {
4867
+ if (node.operator === "&&" ? value2 === 0n : value2 !== 0n) value2 = BigInt(value2 !== 0n);
4868
+ else pending.push({ kind: "logical" }, { kind: "evaluate", node: node.right });
4869
+ } else {
4870
+ if (node.operator !== ",") pending.push({ kind: "right", node, left: value2 });
4871
+ pending.push({ kind: "evaluate", node: node.right });
4872
+ }
4873
+ } else if (frame.kind === "right") {
4874
+ const { node } = frame;
4875
+ if (node.operator !== "=") value2 = binary(precedence[node.operator] === 2 ? node.operator.slice(0, -1) : node.operator, frame.left, value2, node.right.start ?? 0);
4876
+ if (precedence[node.operator] === 2) variables[node.left.name] = String(BigInt.asIntN(64, value2));
4877
+ value2 = BigInt.asIntN(64, value2);
4878
+ } else value2 = BigInt(value2 !== 0n);
4879
+ }
4880
+ return value2;
4866
4881
  } catch (error) {
4867
4882
  if (error instanceof ArithmeticFailure) throw new Error(`${program.source.trimStart()}: ${error.message} (error token is "${program.source.slice(error.offset)}")`);
4868
4883
  if (error instanceof ShellSyntaxError) {
@@ -13801,21 +13816,31 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
13801
13816
  this.writeVariable(state, "REPLY", line.value);
13802
13817
  } else {
13803
13818
  const separators = exact ? "" : state.variables.IFS ?? " \n";
13804
- const characters = Array.from(line.value);
13805
- const separator = (index) => index < characters.length && !line.escaped.has(index) && separators.includes(characters[index]);
13806
- const whitespace = (index) => separator(index) && /[ \t\n]/u.test(characters[index]);
13807
- let end = characters.length;
13808
- while (end > 0 && whitespace(end - 1)) end--;
13819
+ let end = 0;
13820
+ let offset = 0;
13821
+ let point = 0;
13822
+ for (const character of line.value) {
13823
+ offset += character.length;
13824
+ if (line.escaped.has(point) || !separators.includes(character) || !" \n".includes(character)) end = offset;
13825
+ point++;
13826
+ }
13809
13827
  let position = 0;
13810
- while (position < end && whitespace(position)) position++;
13828
+ point = 0;
13829
+ const separator = () => position < end && !line.escaped.has(point) && separators.includes(String.fromCodePoint(line.value.codePointAt(position)));
13830
+ const whitespace = () => separator() && " \n".includes(line.value[position]);
13831
+ const advance = () => {
13832
+ position += line.value.codePointAt(position) > 65535 ? 2 : 1;
13833
+ point++;
13834
+ };
13835
+ while (position < end && whitespace()) advance();
13811
13836
  const fields = [];
13812
- while (position < end) {
13837
+ while (position < end && fields.length < names.length) {
13813
13838
  const start = position;
13814
- while (position < end && !separator(position)) position++;
13839
+ while (position < end && !separator()) advance();
13815
13840
  fields.push({ start, end: position });
13816
- while (position < end && whitespace(position)) position++;
13817
- if (position < end && separator(position)) position++;
13818
- while (position < end && whitespace(position)) position++;
13841
+ while (position < end && whitespace()) advance();
13842
+ if (position < end && separator()) advance();
13843
+ while (position < end && whitespace()) advance();
13819
13844
  }
13820
13845
  for (let index = 0; index < names.length; index++) {
13821
13846
  if (state.readonlyVariables?.has(names[index])) {
@@ -13823,7 +13848,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
13823
13848
  return index === names.length - 1 ? 1 : 2;
13824
13849
  }
13825
13850
  const field = fields[index];
13826
- await this.assignVariable(state, names[index], field ? characters.slice(field.start, index === names.length - 1 && fields.length > names.length ? end : field.end).join("") : "");
13851
+ await this.assignVariable(state, names[index], field ? line.value.slice(field.start, index === names.length - 1 && position < end ? end : field.end) : "");
13827
13852
  }
13828
13853
  }
13829
13854
  return line.terminated ? 0 : 1;
@@ -14575,6 +14600,21 @@ var InputCursor = class {
14575
14600
  signal.throwIfAborted();
14576
14601
  }
14577
14602
  };
14603
+ var ReadText = class {
14604
+ #chunks = [];
14605
+ #pending = [];
14606
+ append(value2) {
14607
+ if (!value2) return;
14608
+ this.#pending.push(value2);
14609
+ if (this.#pending.length === 1024) {
14610
+ this.#chunks.push(this.#pending.join(""));
14611
+ this.#pending.length = 0;
14612
+ }
14613
+ }
14614
+ finish() {
14615
+ return this.#chunks.join("") + this.#pending.join("");
14616
+ }
14617
+ };
14578
14618
  var ShellInput = class _ShellInput {
14579
14619
  constructor(source, budget, signal = budget.signal) {
14580
14620
  this.budget = budget;
@@ -14631,7 +14671,8 @@ var ShellInput = class _ShellInput {
14631
14671
  return this.#cursor.consume(this.signal, () => options2 ? this.readBounded(raw, options2) : this.readLine(raw));
14632
14672
  }
14633
14673
  async readBounded(raw, options2) {
14634
- const characters = [];
14674
+ const text = new ReadText();
14675
+ let characters = 0;
14635
14676
  const escaped = /* @__PURE__ */ new Set();
14636
14677
  const decoder3 = new TextDecoder("utf-8", { fatal: true });
14637
14678
  const delimiter = options2.delimiter ?? 10;
@@ -14676,18 +14717,21 @@ var ShellInput = class _ShellInput {
14676
14717
  escapedCharacter = true;
14677
14718
  }
14678
14719
  const decoded = decoder3.decode(Uint8Array.of(byte), { stream: true });
14720
+ let decodedCharacters = 0;
14679
14721
  for (const character of decoded) {
14680
14722
  if (escapedCharacter) {
14681
14723
  escapedCharacter = false;
14682
- escaped.add(characters.length);
14724
+ escaped.add(characters);
14683
14725
  }
14684
- characters.push(character);
14726
+ text.append(character);
14727
+ characters++;
14728
+ decodedCharacters++;
14685
14729
  }
14686
- units += options2.byteCount ? 1 : Array.from(decoded).length;
14730
+ units += options2.byteCount ? 1 : decodedCharacters;
14687
14731
  if (units === options2.count) terminated = true;
14688
14732
  }
14689
14733
  decoder3.decode();
14690
- return { value: characters.join(""), escaped, terminated };
14734
+ return { value: text.finish(), escaped, terminated };
14691
14735
  } catch (error) {
14692
14736
  if (error instanceof TypeError && error.message.includes("encoded data")) throw new Error("read: unsupported non-UTF-8 text boundary");
14693
14737
  throw error;
@@ -14739,17 +14783,21 @@ var ShellInput = class _ShellInput {
14739
14783
  }
14740
14784
  const value2 = new TextDecoder().decode(bytes).replace(/\0/gu, "");
14741
14785
  const escaped = /* @__PURE__ */ new Set();
14742
- if (raw) return { value: value2, escaped, terminated };
14743
- const characters = Array.from(value2);
14744
- const unescaped = [];
14745
- for (let index = 0; index < characters.length; index++) {
14746
- if (characters[index] === "\\") {
14747
- if (++index === characters.length) break;
14748
- escaped.add(unescaped.length);
14749
- }
14750
- unescaped.push(characters[index]);
14751
- }
14752
- return { value: unescaped.join(""), escaped, terminated };
14786
+ if (raw || !value2.includes("\\")) return { value: value2, escaped, terminated };
14787
+ const text = new ReadText();
14788
+ let characters = 0;
14789
+ for (let index = 0; index < value2.length; ) {
14790
+ const slash = value2.indexOf("\\", index);
14791
+ const span = value2.slice(index, slash < 0 ? value2.length : slash);
14792
+ text.append(span);
14793
+ for (let pointOffset = 0; pointOffset < span.length; pointOffset += span.codePointAt(pointOffset) > 65535 ? 2 : 1) characters++;
14794
+ if (slash < 0 || slash + 1 === value2.length) break;
14795
+ const character = String.fromCodePoint(value2.codePointAt(slash + 1));
14796
+ escaped.add(characters++);
14797
+ text.append(character);
14798
+ index = slash + 1 + character.length;
14799
+ }
14800
+ return { value: text.finish(), escaped, terminated };
14753
14801
  }
14754
14802
  close() {
14755
14803
  if (!this.#closing) {