@poe-platform/safe-bash 0.1.749 → 0.1.751

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.
@@ -5,6 +5,7 @@ import {
5
5
  command,
6
6
  createPrCommand,
7
7
  createPrCommands,
8
+ defaultSleepScheduler,
8
9
  emit,
9
10
  formatDate,
10
11
  millisecondsInstant,
@@ -12,7 +13,7 @@ import {
12
13
  parseDate,
13
14
  prCommands,
14
15
  settings
15
- } from "./chunks/chunk-MUWJPSGN.js";
16
+ } from "./chunks/chunk-B7IBQSD4.js";
16
17
  import {
17
18
  createTsortCommand,
18
19
  createTsortCommands,
@@ -1383,7 +1384,7 @@ function basicCommands() {
1383
1384
  return { exitCode: 0 };
1384
1385
  }),
1385
1386
  define("basename", async (context2) => {
1386
- const parsed = options(context2.args, "as:z", { multiple: "a", suffix: "s", zero: "z" });
1387
+ const parsed = options(context2.args, "as:z", { multiple: "a", suffix: "s", zero: "z" }, true);
1387
1388
  const multiple = parsed.flags.has("a") || parsed.flags.has("s");
1388
1389
  requireOperands(parsed.operands, 1, multiple ? Infinity : 2);
1389
1390
  const suffix2 = value(parsed, "s") ?? (multiple ? void 0 : parsed.operands[1]);
@@ -1395,7 +1396,7 @@ function basicCommands() {
1395
1396
  return { exitCode: 0 };
1396
1397
  }, 1, 1),
1397
1398
  define("dirname", async (context2) => {
1398
- const parsed = options(context2.args, "z", { zero: "z" });
1399
+ const parsed = options(context2.args, "z", { zero: "z" }, true);
1399
1400
  requireOperands(parsed.operands);
1400
1401
  for (const operand of parsed.operands) {
1401
1402
  const parent = dirname(operand);
@@ -13388,7 +13389,11 @@ function getCompiledSyncPatternRegex(pattern) {
13388
13389
  contents2 = "^";
13389
13390
  cursor++;
13390
13391
  }
13391
- if (cursor >= pattern.length || pattern.charCodeAt(cursor) === 93) {
13392
+ if (pattern.charCodeAt(cursor) === 93) {
13393
+ contents2 += "\\]";
13394
+ cursor++;
13395
+ }
13396
+ if (cursor >= pattern.length) {
13392
13397
  syncPatternRegexCache.set(pattern, null);
13393
13398
  return null;
13394
13399
  }
@@ -47527,7 +47532,9 @@ function delay(milliseconds, signal, configuration) {
47527
47532
  if (!Number.isFinite(now) || Math.abs(now) > Number.MAX_SAFE_INTEGER || previous !== void 0 && now < previous) {
47528
47533
  throw new RangeError("sleep scheduler must supply finite monotonic milliseconds");
47529
47534
  }
47530
- if (previous !== void 0) remaining -= Math.max(step, now - previous);
47535
+ if (previous !== void 0) {
47536
+ remaining -= scheduler === defaultSleepScheduler ? now - previous : Math.max(step, now - previous);
47537
+ }
47531
47538
  previous = now;
47532
47539
  if (remaining <= 0) {
47533
47540
  finish(false);
@@ -56372,7 +56379,6 @@ async function patternAdmission(pattern, context2) {
56372
56379
  }
56373
56380
  } else if (character === "]" && bracket && index > bracketStart + 1) bracket = false;
56374
56381
  }
56375
- if (bracket) unsupported("unclosed bracket pattern");
56376
56382
  }
56377
56383
  async function unary2(operator, value2, context2) {
56378
56384
  if (operator === "-n") return value2.length > 0;
@@ -75631,7 +75637,7 @@ var Runtime = class _Runtime {
75631
75637
  }
75632
75638
  return !rem.associative && rem.references === 1;
75633
75639
  }
75634
- return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
75640
+ return this.isPureSyncValueWord(e.left, rawState) && this.isPureSyncValueWord(e.right, rawState) && (!(e.operator === "==" || e.operator === "=" || e.operator === "!=") || e.right.parts.length > 0 && e.right.parts.every((p) => p.quoted));
75635
75641
  }
75636
75642
  if (e.kind === "not") return checkCondNoFile(e.operand);
75637
75643
  if (e.kind === "and" || e.kind === "or") return checkCondNoFile(e.left) && checkCondNoFile(e.right);
@@ -75888,9 +75894,15 @@ var Runtime = class _Runtime {
75888
75894
  if (expr.kind === "unary") return (expr.operator === "-n" || expr.operator === "-z" || expr.operator === "-v" || syncConditionalFileUnaryOps.has(expr.operator)) && okWord(expr.operand);
75889
75895
  if (expr.kind === "binary") {
75890
75896
  if (!okWord(expr.left) || !okWord(expr.right)) return false;
75891
- if (expr.operator === "=~") return depth === 0 && this.extractSimpleErePattern(expr.right, rawState) !== void 0;
75897
+ if (expr.operator === "=~") return !requireTotal && depth === 0 && this.extractSimpleErePattern(expr.right, rawState) !== void 0;
75892
75898
  if (expr.operator === "==" || expr.operator === "=" || expr.operator === "!=") {
75893
75899
  if (expr.right.parts.length > 0 && expr.right.parts.every((p) => p.quoted)) return true;
75900
+ if (requireTotal) {
75901
+ if (!expr.right.parts.every((p, idx) => p.kind === "text" && !p.byteValue && (p.quoted || idx > 0 || !p.value.startsWith("~")))) return false;
75902
+ const pattern = expr.right.parts.map((p) => p.kind === "text" ? p.quoted ? p.value.replace(/[\\*?[\]()]/g, "\\$&") : p.value : "").join("");
75903
+ const work = { remaining: 4096, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
75904
+ return tryMatchesPatternSync(pattern, "", work, false, true) !== void 0;
75905
+ }
75894
75906
  if (expr.right.parts.length > 0 && expr.right.parts.every(
75895
75907
  (p, idx) => p.kind === "text" && !p.byteValue && (p.quoted || idx > 0 || !p.value.startsWith("~")) || p.kind === "variable" && !p.indirect && !p.prefixNames && !p.length && !p.substring && !p.transform && p.operator === void 0 && getArraySelector(p) === void 0
75896
75908
  )) return true;
@@ -76041,19 +76053,23 @@ var Runtime = class _Runtime {
76041
76053
  if (typeof right !== "string") return void 0;
76042
76054
  const syncTouched = this._syncArithRawWriteOnly ? this._syncArithTouched : void 0;
76043
76055
  const lTrim = left.trim() || "0";
76044
- let lNum = resolveSimpleArithOperand(lTrim, rawState, monitor, store, syncTouched);
76056
+ let lNum = lTrim.length > 13 && /^-?[0-9]{1,19}$/.test(lTrim) ? BigInt.asIntN(64, BigInt(lTrim)) : resolveSimpleArithOperand(lTrim, rawState, monitor, store, syncTouched);
76045
76057
  if (lNum === void 0) {
76046
76058
  const lExpr = tryEvalSimpleExpandedArith(lTrim, rawState, monitor, store, syncTouched);
76047
76059
  if (lExpr !== void 0) lNum = Number(lExpr);
76048
76060
  }
76049
76061
  if (lNum === void 0) return void 0;
76050
76062
  const rTrim = right.trim() || "0";
76051
- let rNum = resolveSimpleArithOperand(rTrim, rawState, monitor, store, syncTouched);
76063
+ let rNum = rTrim.length > 13 && /^-?[0-9]{1,19}$/.test(rTrim) ? BigInt.asIntN(64, BigInt(rTrim)) : resolveSimpleArithOperand(rTrim, rawState, monitor, store, syncTouched);
76052
76064
  if (rNum === void 0) {
76053
76065
  const rExpr = tryEvalSimpleExpandedArith(rTrim, rawState, monitor, store, syncTouched);
76054
76066
  if (rExpr !== void 0) rNum = Number(rExpr);
76055
76067
  }
76056
76068
  if (rNum === void 0) return void 0;
76069
+ if (typeof lNum !== typeof rNum) {
76070
+ lNum = BigInt(lNum);
76071
+ rNum = BigInt(rNum);
76072
+ }
76057
76073
  let ok;
76058
76074
  switch (expr.operator) {
76059
76075
  case "-eq":
@@ -78502,7 +78518,6 @@ var Runtime = class _Runtime {
78502
78518
  this.budget.tick();
78503
78519
  rawState.substitutionStatus = 0;
78504
78520
  if (rawState.variables._ !== void 0) delete rawState.variables._;
78505
- rawState.lastArgument = fnArgs.length > 0 ? fnArgs[fnArgs.length - 1] : w0Plain;
78506
78521
  const positional = rawState.positional;
78507
78522
  let fnArgsBytes = 0;
78508
78523
  for (let i = 0; i < fnArgs.length; i++) fnArgsBytes += fnArgs[i].length;
@@ -78552,6 +78567,7 @@ var Runtime = class _Runtime {
78552
78567
  positionalSetVersion,
78553
78568
  savedPositionals: resumeSavedPos,
78554
78569
  callerLoopDepth,
78570
+ lastArgument: fnArgs.at(-1) ?? w0Plain,
78555
78571
  listIndex: bodyRes.listIndex,
78556
78572
  pipelineIndex: bodyRes.pipelineIndex
78557
78573
  });
@@ -78606,6 +78622,7 @@ var Runtime = class _Runtime {
78606
78622
  this.setSyncPipeStatusCell(activeExisting, statusStr);
78607
78623
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78608
78624
  }
78625
+ rawState.lastArgument = fnArgs.at(-1) ?? w0Plain;
78609
78626
  rawState.status = exitStatus;
78610
78627
  if (exitStatus !== 0 && !ignored && rawState.errexit) throw new Flow2("exit", exitStatus);
78611
78628
  return exitStatus;
@@ -78681,7 +78698,6 @@ var Runtime = class _Runtime {
78681
78698
  this.budget.tick();
78682
78699
  rawState.substitutionStatus = 0;
78683
78700
  if (rawState.variables._ !== void 0) delete rawState.variables._;
78684
- rawState.lastArgument = lastCmdArg;
78685
78701
  rawState.depth++;
78686
78702
  let evalStatus;
78687
78703
  try {
@@ -78690,6 +78706,7 @@ var Runtime = class _Runtime {
78690
78706
  rawState.depth--;
78691
78707
  }
78692
78708
  if (typeof evalStatus === "number") {
78709
+ rawState.lastArgument = lastCmdArg;
78693
78710
  if (cachedUnit.script.lists.length === 0) {
78694
78711
  const activeStore = monitor.store;
78695
78712
  const activeExisting = activeStore?.get("PIPESTATUS");
@@ -78980,6 +78997,7 @@ var Runtime = class _Runtime {
78980
78997
  continue;
78981
78998
  }
78982
78999
  if (part.kind === "variable") {
79000
+ if (stateMonitor(rawState)?.store?.get(part.name)) return false;
78983
79001
  if (this._syncLoopFnCheckDepth > 0 && (part.substring || getArraySelector(part)?.kind === "element")) return false;
78984
79002
  if (part.prefixNames !== void 0) {
78985
79003
  if (part.prefixNames === "@") return false;
@@ -79070,22 +79088,22 @@ var Runtime = class _Runtime {
79070
79088
  const list = part.script.lists[0];
79071
79089
  if (list.terminator || list.pipelines.length !== 1) return false;
79072
79090
  const p = list.pipelines[0];
79073
- if (p.negate || p.commands.length < 1 || p.commands.length > 5) return false;
79091
+ if (p.negate || p.commands.length !== 1) return false;
79074
79092
  let cmd = p.commands[0];
79075
- const hasSingleStdinRedir = cmd.kind === "simple" && cmd.redirects.length === 1 && cmd.redirects[0].operator === "<" && (cmd.redirects[0].descriptor === void 0 || cmd.redirects[0].descriptor === 0) && !cmd.redirects[0].move && !cmd.redirects[0].document && cmd.redirects[0].target.plain !== void 0 && !cmd.redirects[0].target.plain.startsWith("-") && cmd.redirects[0].target.plain !== "/dev/stdin";
79076
- const hasSingleHereStringRedir = cmd.kind === "simple" && cmd.redirects.length === 1 && cmd.redirects[0].operator === "<<<" && (cmd.redirects[0].descriptor === void 0 || cmd.redirects[0].descriptor === 0) && !cmd.redirects[0].move && !cmd.redirects[0].document && this.isPureSyncValueWord(cmd.redirects[0].target, rawState);
79077
79093
  if (cmd.kind === "for" || cmd.kind === "arithmetic-for" || cmd.kind === "while") return false;
79078
79094
  if (p.commands.length === 1 && (cmd.kind === "if" || cmd.kind === "case") && this.isPureSyncSubIfOrCase(cmd, rawState)) {
79079
79095
  continue;
79080
79096
  }
79081
- if (cmd.kind !== "simple" || cmd.redirects.length > 0 && !hasSingleStdinRedir && !hasSingleHereStringRedir || cmd.words.length === 0) return false;
79097
+ if (cmd.kind !== "simple" || cmd.redirects.length > 0 || cmd.words.length === 0) return false;
79082
79098
  let w0Plain = cmd.words[0].plain;
79083
79099
  if (p.commands.length === 1 && w0Plain !== void 0 && rawState.functions.has(w0Plain) && this.firstInternalDiscovery(w0Plain, rawState, false) === "function" && !rawState.extensions?.builtins.has(w0Plain)) {
79084
79100
  const fnBody = rawState.functions.get(w0Plain);
79085
- if (fnBody.kind === "group" && fnBody.redirects.length === 0 && fnBody.body.lists.length === 1 && !fnBody.body.lists[0].terminator && fnBody.body.lists[0].pipelines.length === 1 && !fnBody.body.lists[0].pipelines[0].negate && fnBody.body.lists[0].pipelines[0].commands.length === 1 && fnBody.body.lists[0].pipelines[0].commands[0].kind === "simple" && fnBody.body.lists[0].pipelines[0].commands[0].redirects.length === 0 && cmd.words.slice(1).every((w) => this.isPureSyncValueWord(w, rawState))) {
79101
+ if (fnBody.kind === "group" && fnBody.redirects.length === 0 && fnBody.body.lists.length === 1 && !fnBody.body.lists[0].terminator && fnBody.body.lists[0].pipelines.length === 1 && !fnBody.body.lists[0].pipelines[0].negate && fnBody.body.lists[0].pipelines[0].commands.length === 1 && fnBody.body.lists[0].pipelines[0].commands[0].kind === "simple" && fnBody.body.lists[0].pipelines[0].commands[0].redirects.length === 0 && cmd.words.slice(1).every((w) => this.isPureSyncValueWord(w, rawState) && w.parts.length > 0 && w.parts.every(
79102
+ (part2) => part2.quoted || part2.kind === "text" && part2.value.length > 0 && !part2.value.includes(" ") && !part2.value.includes(" ") && !part2.value.includes("\n") && !part2.value.includes("{") && !hasGlobOrEscape(part2.value, true)
79103
+ ))) {
79086
79104
  const innerCmd = fnBody.body.lists[0].pipelines[0].commands[0];
79087
79105
  const innerW0 = innerCmd.words[0]?.plain;
79088
- if (innerW0 && !rawState.functions.has(innerW0) && !rawState.extensions?.builtins.has(innerW0)) {
79106
+ if (innerW0 && (innerW0 === "echo" || innerW0 === "printf" || innerW0 === "dirname" || innerW0 === "basename" || innerW0 === "pwd" || innerW0 === "command" || innerW0 === "type" || innerW0 === "seq") && !rawState.functions.has(innerW0) && !rawState.extensions?.builtins.has(innerW0)) {
79089
79107
  cmd = innerCmd;
79090
79108
  w0Plain = innerW0;
79091
79109
  }
@@ -79097,81 +79115,15 @@ var Runtime = class _Runtime {
79097
79115
  return false;
79098
79116
  }
79099
79117
  if (w0Plain === "command" && cmd.words[1]?.plain === "-v" || w0Plain === "type" && cmd.words[1]?.plain === "-t") {
79100
- if (p.commands.length === 1 && cmd.words.length === 3 && !rawState.functions.has(w0Plain) && !rawState.extensions?.builtins.has(w0Plain) && this.isPureSyncValueWord(cmd.words[2], rawState) && (cmd.words[2].plain !== void 0 && this.tryResolveSyncDiscovery(w0Plain === "command" ? "name" : "kind", cmd.words[2].plain, rawState) !== void 0 || this._isMemoryBackingFs && this.backingFs?.capabilities?.permissions !== true)) {
79101
- continue;
79102
- }
79103
79118
  return false;
79104
79119
  }
79105
- const isFileCommand = w0Plain === "cat" || w0Plain === "head" || w0Plain === "tail" || w0Plain === "jq" || w0Plain === "awk" || w0Plain === "grep" || w0Plain === "sed" || w0Plain === "cut" || w0Plain === "wc" || w0Plain === "sort" || w0Plain === "uniq" || w0Plain === "tr" || hasSingleHereStringRedir && (w0Plain === "base64" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl" || w0Plain === "paste" || w0Plain === "numfmt");
79106
- const def = w0Plain ? this.commands.get(w0Plain) ?? (w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl" || w0Plain === "paste" || w0Plain === "jq" ? this.getExternalCommand(w0Plain) : void 0) : void 0;
79107
- if (!w0Plain || w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "dirname" && w0Plain !== "basename" && w0Plain !== "seq" && !isFileCommand || !def || rawState.functions.has(w0Plain) || rawState.extensions?.builtins.has(w0Plain)) return false;
79108
- if ((hasSingleStdinRedir || hasSingleHereStringRedir) && !isFileCommand) return false;
79109
- if (w0Plain === "printf" ? def.execute !== printfCommand.execute : w0Plain === "echo" ? !defaultEchoExecutors.has(def.execute) : w0Plain === "seq" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl" || w0Plain === "paste" || w0Plain === "jq" ? !builtInDirectContextExecutors.has(def.execute) && customRegisteredCommands.has(def.execute) : !builtInDirectContextExecutors.has(def.execute)) return false;
79120
+ const def = w0Plain ? this.commands.get(w0Plain) : void 0;
79121
+ if (!w0Plain || w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "dirname" && w0Plain !== "basename" && w0Plain !== "seq" || !def || rawState.functions.has(w0Plain) || rawState.extensions?.builtins.has(w0Plain)) return false;
79122
+ if (w0Plain === "printf" ? def.execute !== printfCommand.execute : w0Plain === "echo" ? !defaultEchoExecutors.has(def.execute) : w0Plain === "seq" ? !builtInDirectContextExecutors.has(def.execute) && customRegisteredCommands.has(def.execute) : !builtInDirectContextExecutors.has(def.execute)) return false;
79110
79123
  if (!cmd.words.slice(1).every((w) => this.isPureSyncValueWord(w, rawState))) return false;
79111
- if (isFileCommand) {
79112
- if (w0Plain === "tr" && !hasSingleStdinRedir && !hasSingleHereStringRedir) return false;
79113
- if (w0Plain === "grep" && rawState.errexit) return false;
79114
- if (!hasSingleHereStringRedir) {
79115
- const fPlain = hasSingleStdinRedir ? cmd.redirects[0].target.plain : cmd.words[cmd.words.length - 1]?.plain;
79116
- if (!fPlain || fPlain.startsWith("-") || fPlain === "/dev/stdin") return false;
79117
- const vCheck = this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, fPlain), false);
79118
- if (!vCheck || vCheck.byteLength > 16384 || vCheck.includes(0)) return false;
79119
- }
79120
- const opWords = hasSingleStdinRedir || hasSingleHereStringRedir ? cmd.words.slice(1) : cmd.words.slice(1, -1);
79121
- const opCount = opWords.length;
79122
- const op0 = opWords[0]?.plain;
79123
- const op1 = opWords[1]?.plain;
79124
- if (w0Plain === "cat" || w0Plain === "rev" || w0Plain === "tac") {
79125
- if (opCount !== 0) return false;
79126
- } else {
79127
- if (p.commands.length !== 1 && !hasSingleHereStringRedir) return false;
79128
- if (w0Plain === "head" || w0Plain === "tail") {
79129
- const validHT = opCount === 0 || opCount === 1 && op0 !== void 0 && (/^-(?:n|c|--lines=|--bytes=)?[0-9]{1,5}$/.test(op0) || /^--(?:lines|bytes)=[0-9]{1,5}$/.test(op0) || w0Plain === "tail" && /^(?:-n|--lines=)\+[0-9]{1,5}$/.test(op0) || w0Plain === "head" && /^(?:-n|--lines=)-[0-9]{1,5}$/.test(op0)) || opCount === 2 && (op0 === "-n" && op1 !== void 0 && (/^[0-9]{1,5}$/.test(op1) || w0Plain === "tail" && /^\+[0-9]{1,5}$/.test(op1) || w0Plain === "head" && /^-[0-9]{1,5}$/.test(op1)) || op0 === "-c" && op1 !== void 0 && /^[0-9]{1,5}$/.test(op1));
79130
- if (!validHT) return false;
79131
- }
79132
- const plainOps = [];
79133
- for (let oi = 0; oi < opCount; oi++) {
79134
- const ow = opWords[oi];
79135
- const pw = ow.plain ?? (ow.parts.length > 0 && ow.parts.every((pt) => pt.kind === "text") ? ow.parts.map((pt) => pt.value).join("") : void 0);
79136
- if (pw === void 0) break;
79137
- plainOps.push(pw);
79138
- }
79139
- if (w0Plain === "cut") {
79140
- if (plainOps.length !== opCount || this.evalSyncCut(["\xE9"], plainOps, byteLocale(rawState.variables)) === void 0) return false;
79141
- } else if (w0Plain === "sed") {
79142
- if (plainOps.length !== opCount || this.evalSyncSed([], plainOps) === void 0) return false;
79143
- } else if (w0Plain === "grep") {
79144
- if (plainOps.length !== opCount || this.evalSyncGrep([], plainOps, Boolean(rawState.errexit)) === void 0) return false;
79145
- } else if (w0Plain === "awk") {
79146
- const input3 = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
79147
- if (plainOps.length !== opCount || input3 === void 0) return false;
79148
- const lines3 = input3.length === 0 ? [] : input3.split("\n");
79149
- if (input3.endsWith("\n")) lines3.pop();
79150
- if (this.evalSyncAwk(lines3, plainOps) === void 0) return false;
79151
- } else if (w0Plain === "jq") {
79152
- if (plainOps.length !== opCount) return false;
79153
- const jqIn = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
79154
- if (jqIn === void 0 || this.evalSyncJq(jqIn, plainOps) === void 0) return false;
79155
- } else if (w0Plain === "wc") {
79156
- if (opCount !== 1 || this.normalizeSyncWcFlag(op0) === void 0) return false;
79157
- } else if (w0Plain === "sort") {
79158
- if (plainOps.length !== opCount || this.evalSyncSort([], plainOps, byteLocale(rawState.variables)) === void 0) return false;
79159
- } else if (w0Plain === "uniq") {
79160
- if (plainOps.length !== opCount || this.evalSyncUniq([], plainOps) === void 0) return false;
79161
- } else if (w0Plain === "base64") {
79162
- if (opCount > 1 || opCount === 1 && op0 !== "-d" && op0 !== "--decode") return false;
79163
- } else if (w0Plain === "tr") {
79164
- if (plainOps.length !== opCount || this.evalSyncTr("", plainOps) === void 0) return false;
79165
- } else if (w0Plain === "nl") {
79166
- if (plainOps.length !== opCount || this.evalSyncNl([], plainOps) === void 0) return false;
79167
- } else if (w0Plain === "paste") {
79168
- if (plainOps.length !== opCount || this.evalSyncPaste([], plainOps) === void 0) return false;
79169
- } else if (w0Plain === "numfmt") {
79170
- const nmCheck = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
79171
- if (nmCheck === void 0 || plainOps.length !== opCount || this.evalSyncNumfmt(nmCheck.split("\n"), plainOps) === void 0) return false;
79172
- }
79173
- }
79174
- }
79124
+ if ((w0Plain === "echo" || w0Plain === "basename" || w0Plain === "dirname") && !cmd.words.slice(1).every((w) => w.parts.length > 0 && w.parts.every(
79125
+ (part2) => part2.quoted || part2.kind === "text" && part2.value.length > 0 && !part2.value.includes(" ") && !part2.value.includes(" ") && !part2.value.includes("\n") && !part2.value.includes("{") && !hasGlobOrEscape(part2.value, true)
79126
+ ))) return false;
79175
79127
  if (w0Plain === "printf") {
79176
79128
  if (!this.isSyncPrintfCallOk(cmd, 1, rawState, this._activePrintfInductionName)) return false;
79177
79129
  } else if (w0Plain === "echo") {
@@ -79197,90 +79149,13 @@ var Runtime = class _Runtime {
79197
79149
  }
79198
79150
  if ((w0Plain === "dirname" ? this.evalSyncDirname(simArgs) : this.evalSyncBasename(simArgs)) === void 0) return false;
79199
79151
  } else if (w0Plain === "seq") {
79200
- const isSeqIntWord = (w) => {
79201
- if (w.plain !== void 0) return /^-?[0-9]{1,7}$/.test(w.plain);
79202
- if (w.parts.length === 1) {
79203
- const p02 = w.parts[0];
79204
- if (p02.kind === "arithmetic") return true;
79205
- if (p02.kind === "variable" && !p02.indirect && !p02.prefixNames && !p02.substring && !p02.transform && p02.operator === void 0 && getArraySelector(p02) === void 0) {
79206
- const cur = rawState.variables[p02.name];
79207
- return cur !== void 0 && /^-?[0-9]{1,7}$/.test(cur);
79208
- }
79209
- }
79210
- return false;
79211
- };
79212
- if (cmd.words.length < 2 || cmd.words.length > 4 || !cmd.words.slice(1).every(isSeqIntWord)) return false;
79213
- }
79214
- if (p.commands.length >= 2) {
79215
- if (w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "seq" && w0Plain !== "cat" && !hasSingleHereStringRedir || syncPurePipelineSlotInUse || !this.budget.canSyncPurePipe || rawState.errexit || rawState.nounset) return false;
79216
- if (w0Plain === "printf") {
79217
- if (!this.isSyncPrintfCallOk(cmd, 1, rawState, this._activePrintfInductionName)) return false;
79218
- }
79219
- for (let sIdx = 1; sIdx < p.commands.length; sIdx++) {
79220
- const sCmd = p.commands[sIdx];
79221
- if (sCmd.kind !== "simple" || sCmd.redirects.length !== 0 || sCmd.words.length === 0) return false;
79222
- const sName = sCmd.words[0].plain;
79223
- if (!sName || sName !== "cut" && sName !== "tr" && sName !== "sort" && sName !== "head" && sName !== "tail" && sName !== "wc" && sName !== "sed" && sName !== "uniq" && sName !== "rev" && sName !== "awk" && sName !== "grep" && sName !== "jq" && sName !== "base64" && sName !== "tac" && sName !== "nl" && sName !== "paste" && sName !== "numfmt") return false;
79224
- const sDef = this.commands.get(sName) ?? (sName === "rev" || sName === "tac" || sName === "nl" || sName === "paste" || sName === "jq" ? this.getExternalCommand(sName) : void 0);
79225
- if (!sDef || customRegisteredCommands.has(sDef.execute) || sName !== "rev" && sName !== "tac" && sName !== "nl" && sName !== "paste" && sName !== "jq" && !builtInDirectContextExecutors.has(sDef.execute)) return false;
79226
- if (rawState.functions.has(sName) || rawState.extensions?.builtins.has(sName)) return false;
79227
- const sArgWords = sCmd.words.slice(1);
79228
- const sPlainArgs = [];
79229
- let allPlainStageArgs = true;
79230
- for (let k = 0; k < sArgWords.length; k++) {
79231
- const sw = sArgWords[k];
79232
- const sp = sw.plain ?? (sw.parts.length > 0 && sw.parts.every((pt) => pt.kind === "text") ? sw.parts.map((pt) => pt.value).join("") : void 0);
79233
- if (sp === void 0) {
79234
- allPlainStageArgs = false;
79235
- break;
79236
- }
79237
- sPlainArgs.push(sp);
79238
- }
79239
- if (!allPlainStageArgs) return false;
79240
- if (sName === "sort") {
79241
- if (this.evalSyncSort([], sPlainArgs, byteLocale(rawState.variables)) === void 0) return false;
79242
- } else if (sName === "uniq") {
79243
- if (this.evalSyncUniq([], sPlainArgs) === void 0) return false;
79244
- } else if (sName === "wc") {
79245
- if (sPlainArgs.length !== 1 || this.normalizeSyncWcFlag(sPlainArgs[0]) === void 0) return false;
79246
- } else if (sName === "head" || sName === "tail") {
79247
- const okHT = sPlainArgs.length === 0 || sPlainArgs.length === 1 && (/^-(?:n|c)?[0-9]{1,5}$/.test(sPlainArgs[0]) || /^--(?:lines|bytes)=[0-9]{1,5}$/.test(sPlainArgs[0]) || sName === "tail" && /^(?:-n|--lines=)\+[0-9]{1,5}$/.test(sPlainArgs[0]) || sName === "head" && /^(?:-n|--lines=)-[0-9]{1,5}$/.test(sPlainArgs[0])) || sPlainArgs.length === 2 && (sPlainArgs[0] === "-n" && (/^[0-9]{1,5}$/.test(sPlainArgs[1]) || sName === "tail" && /^\+[0-9]{1,5}$/.test(sPlainArgs[1]) || sName === "head" && /^-[0-9]{1,5}$/.test(sPlainArgs[1])) || sPlainArgs[0] === "-c" && /^[0-9]{1,5}$/.test(sPlainArgs[1]));
79248
- if (!okHT) return false;
79249
- } else if (sName === "cut") {
79250
- if (this.evalSyncCut(["\xE9"], sPlainArgs, byteLocale(rawState.variables)) === void 0) return false;
79251
- } else if (sName === "sed") {
79252
- if (this.evalSyncSed([], sPlainArgs) === void 0) return false;
79253
- } else if (sName === "awk") {
79254
- if (sIdx !== 1) return false;
79255
- const input3 = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState);
79256
- if (input3 === void 0) return false;
79257
- const lines3 = input3.length === 0 ? [] : input3.split("\n");
79258
- if (input3.endsWith("\n")) lines3.pop();
79259
- if (this.evalSyncAwk(lines3, sPlainArgs) === void 0) return false;
79260
- } else if (sName === "grep") {
79261
- if (this.evalSyncGrep([], sPlainArgs, Boolean(rawState.errexit)) === void 0) return false;
79262
- } else if (sName === "tr") {
79263
- if (this.evalSyncTr("", sPlainArgs) === void 0) return false;
79264
- } else if (sName === "jq") {
79265
- if (sIdx !== 1) return false;
79266
- const jqIn = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
79267
- if (jqIn === void 0 || this.evalSyncJq(jqIn, sPlainArgs) === void 0) return false;
79268
- } else if (sName === "base64") {
79269
- if (sPlainArgs.length !== 0) return false;
79270
- } else if (sName === "tac") {
79271
- if (sPlainArgs.length !== 0 || w0Plain !== "echo" && !hasSingleHereStringRedir) return false;
79272
- } else if (sName === "nl") {
79273
- if (w0Plain !== "echo" && !hasSingleHereStringRedir || this.evalSyncNl([], sPlainArgs) === void 0) return false;
79274
- } else if (sName === "paste") {
79275
- if (this.evalSyncPaste([], sPlainArgs) === void 0) return false;
79276
- } else if (sName === "numfmt") {
79277
- if (sIdx !== 1) return false;
79278
- const nmCheck = this.extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState)?.trim();
79279
- if (nmCheck === void 0 || this.evalSyncNumfmt(nmCheck.split("\n"), sPlainArgs) === void 0) return false;
79280
- } else if (sName === "rev") {
79281
- if (sPlainArgs.length !== 0) return false;
79282
- }
79283
- }
79152
+ if (cmd.words.length < 2 || cmd.words.length > 4) return false;
79153
+ const operands = cmd.words.slice(1).map((w) => w.plain);
79154
+ if (!operands.every((value2) => value2 !== void 0 && Number.isInteger(Number(value2)) && String(Number(value2)) === value2 && Math.abs(Number(value2)) <= 9999999)) return false;
79155
+ const first = operands.length === 1 ? 1 : Number(operands[0]);
79156
+ const increment = operands.length === 3 ? Number(operands[1]) : 1;
79157
+ const last = Number(operands[operands.length - 1]);
79158
+ if (increment === 0 || Math.abs((last - first) / increment) > 1024) return false;
79284
79159
  }
79285
79160
  continue;
79286
79161
  }
@@ -79309,10 +79184,10 @@ var Runtime = class _Runtime {
79309
79184
  if ((isNumOp || isStrOp) && safeArgWord(args[0]) && safeArgWord(args[2])) {
79310
79185
  if (isNumOp && checkIntVars) {
79311
79186
  const isGuaranteedIntWord = (w) => {
79312
- if (w.plain !== void 0) return /^-?[0-9]+$/.test(w.plain);
79187
+ if (w.plain !== void 0) return /^-?[0-9]{1,16}$/.test(w.plain);
79313
79188
  if (w.parts.length === 1) {
79314
79189
  const p02 = w.parts[0];
79315
- if (p02.kind === "arithmetic") return true;
79190
+ if (p02.kind === "arithmetic") return false;
79316
79191
  if (p02.kind === "variable" && !p02.indirect && !p02.prefixNames && !p02.substring && !p02.transform && p02.operator === void 0 && getArraySelector(p02) === void 0) {
79317
79192
  if (script2) {
79318
79193
  for (const lst of script2.lists) {
@@ -79320,13 +79195,13 @@ var Runtime = class _Runtime {
79320
79195
  const c0 = pl.commands[0];
79321
79196
  if (c0?.kind === "simple" && c0.words.length === 1) {
79322
79197
  const asg = this.assignment(c0.words[0]);
79323
- if (asg?.name === p02.name && (!asg.value.plain || !/^-?[0-9]+$/.test(asg.value.plain))) return false;
79198
+ if (asg?.name === p02.name && (!asg.value.plain || !/^-?[0-9]{1,16}$/.test(asg.value.plain))) return false;
79324
79199
  }
79325
79200
  }
79326
79201
  }
79327
79202
  }
79328
79203
  const cur = rawState.variables[p02.name];
79329
- return cur === void 0 || /^-?[0-9]+$/.test(cur);
79204
+ return cur === void 0 || /^-?[0-9]{1,16}$/.test(cur);
79330
79205
  }
79331
79206
  }
79332
79207
  return false;
@@ -79684,7 +79559,7 @@ var Runtime = class _Runtime {
79684
79559
  if (patInfo?.isVar) return false;
79685
79560
  return this.isPureSyncValueWord(e.left, rawState) && this.getFastAnchoredEreRegex(e.right, rawState) !== void 0 && !rawState.readonlyVariables?.has("BASH_REMATCH") && !rawState.exported.has("BASH_REMATCH") && !stateMonitor(rawState)?.hasOverlay("BASH_REMATCH") && !(store ?? requireArrays(rawState))?.watches.has("BASH_REMATCH");
79686
79561
  }
79687
- return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
79562
+ return this.isPureSyncValueWord(e.left, rawState) && this.isPureSyncValueWord(e.right, rawState) && (!(e.operator === "==" || e.operator === "=" || e.operator === "!=") || e.right.parts.length > 0 && e.right.parts.every((p2) => p2.quoted));
79688
79563
  }
79689
79564
  if (e.kind === "not") return checkLeaf(e.operand);
79690
79565
  if (e.kind === "and" || e.kind === "or") return checkLeaf(e.left) && checkLeaf(e.right);
@@ -79804,12 +79679,17 @@ var Runtime = class _Runtime {
79804
79679
  if (this.extractPosixBracketCondExpr(cmd, rawState, true, script2) !== void 0) continue;
79805
79680
  if (cmd.kind !== "simple") return false;
79806
79681
  if (nested && cmd.redirects.length !== 0) return false;
79682
+ if (cmd.words.length === 0) return false;
79807
79683
  if (cmd.redirects.length === 1) {
79808
79684
  const r0Check = cmd.redirects[0];
79809
79685
  const w0DevPlain = cmd.words[0].plain;
79810
79686
  if (r0Check.descriptor === 1 && !r0Check.move && !r0Check.document && (r0Check.operator === ">" || r0Check.operator === ">>") && r0Check.target.plain === "/dev/null" && this.sourceFs !== this.backingFs && this.budget.canRedirect1 && w0DevPlain !== void 0 && (w0DevPlain === "pwd" || w0DevPlain === "dirname" || w0DevPlain === "basename" || w0DevPlain === "echo") && !hasShellFunction(rawState, w0DevPlain) && !rawState.extensions?.builtins.has(w0DevPlain) && (w0DevPlain === "pwd" || this.commands.has(w0DevPlain))) {
79811
79687
  const devWordOk = (w) => this.isPureSyncValueWord(w, rawState) && w.parts.every((p2) => p2.quoted || p2.kind === "text" && p2.value.length > 0 && !p2.value.includes(" ") && !p2.value.includes(" ") && !p2.value.includes("\n") && !p2.value.includes("{") && !hasGlobOrEscape(p2.value, true));
79812
- const devShapeOk = w0DevPlain === "pwd" && cmd.words.length === 1 || (w0DevPlain === "dirname" || w0DevPlain === "echo") && cmd.words.length === 2 && !cmd.words[1].plain?.startsWith("-") && devWordOk(cmd.words[1]) || w0DevPlain === "basename" && (cmd.words.length === 2 && !cmd.words[1].plain?.startsWith("-") && devWordOk(cmd.words[1]) || cmd.words.length === 3 && !cmd.words[1].plain?.startsWith("-") && devWordOk(cmd.words[1]) && devWordOk(cmd.words[2]) || cmd.words.length === 4 && cmd.words[1].plain === "-s" && cmd.words[2].plain !== void 0 && !cmd.words[3].plain?.startsWith("-") && devWordOk(cmd.words[3]));
79688
+ const devOperandOk = (w) => {
79689
+ const first = w.parts[0];
79690
+ return first?.kind === "text" && first.value.length > 0 && !first.value.startsWith("-") && devWordOk(w);
79691
+ };
79692
+ const devShapeOk = w0DevPlain === "pwd" && cmd.words.length === 1 || (w0DevPlain === "dirname" || w0DevPlain === "echo") && cmd.words.length === 2 && devOperandOk(cmd.words[1]) || w0DevPlain === "basename" && (cmd.words.length === 2 && devOperandOk(cmd.words[1]) || cmd.words.length === 3 && devOperandOk(cmd.words[1]) && devWordOk(cmd.words[2]) || cmd.words.length === 4 && cmd.words[1].plain === "-s" && cmd.words[2].plain !== void 0 && devOperandOk(cmd.words[3]));
79813
79693
  if (devShapeOk) continue;
79814
79694
  }
79815
79695
  if (this.extractSyncReadHereStringSpec(cmd, rawState) !== void 0) continue;
@@ -80389,21 +80269,12 @@ var Runtime = class _Runtime {
80389
80269
  const forPrintfInd = command7.kind === "for" && command7.words?.length === 1 && /^\{[0-9]{1,4}\.\.[0-9]{1,4}(?:\.\.[1-9][0-9]{0,2})?\}$/.test(command7.words[0].plain ?? "") ? command7.name : void 0;
80390
80270
  const printfInductionName = initializer?.kind === "binary" && initializer.operator === "=" && initializer.left.kind === "name" && initializer.right.kind === "literal" && initializer.right.value >= 0n && initializer.right.value <= 2000n && condition?.kind === "binary" && (condition.operator === "<" || condition.operator === "<=") && condition.left.kind === "name" && condition.left.name === initializer.left.name && condition.right.kind === "literal" && condition.right.value >= 0n && condition.right.value <= 2000n && increment?.kind === "unary" && increment.operator === "++" && increment.operand.kind === "name" && increment.operand.name === initializer.left.name && this.canSyncPrintfInductionBody(command7.body, rawState, initializer.left.name) ? initializer.left.name : whilePrintfInd && this.canSyncPrintfInductionBody(command7.body, rawState, whilePrintfInd) ? whilePrintfInd : forPrintfInd && this.canSyncPrintfInductionBody(command7.body, rawState, forPrintfInd) ? forPrintfInd : void 0;
80391
80271
  const prevActivePrintfInd = this._activePrintfInductionName;
80392
- const prevActiveLoopScript = this._activeLoopBodyScript;
80393
- const prevActiveLoopCond = this._activeLoopCondScript;
80394
- const prevActiveLoopVar = this._activeLoopVarName;
80395
80272
  this._activePrintfInductionName = printfInductionName;
80396
- this._activeLoopBodyScript = command7.body;
80397
- this._activeLoopCondScript = command7.kind === "while" ? command7.condition : void 0;
80398
- this._activeLoopVarName = command7.kind === "for" ? command7.name : printfInductionName ?? (whilePrintfInd || void 0);
80399
80273
  let bodySyncOk = false;
80400
80274
  try {
80401
80275
  bodySyncOk = !(guestArrays(rawState) && (guestArrays(rawState).watches.size > 0 || this.budget.limits.maxExpansionBytes < 65536)) && this.canSyncLoopBody(command7.body, rawState, io, false, printfInductionName);
80402
80276
  } finally {
80403
80277
  this._activePrintfInductionName = prevActivePrintfInd;
80404
- this._activeLoopBodyScript = prevActiveLoopScript;
80405
- this._activeLoopCondScript = prevActiveLoopCond;
80406
- this._activeLoopVarName = prevActiveLoopVar;
80407
80278
  }
80408
80279
  if (!bodySyncOk) {
80409
80280
  command7._skipTrySyncLoop = true;
@@ -80929,7 +80800,7 @@ var Runtime = class _Runtime {
80929
80800
  if (patInfo?.isVar) return false;
80930
80801
  return depth === 0 && this.isPureSyncValueWord(e.left, rawState) && this.getFastAnchoredEreRegex(e.right, rawState) !== void 0 && !rawState.readonlyVariables?.has("BASH_REMATCH") && !rawState.exported.has("BASH_REMATCH") && !monitor.hasOverlay("BASH_REMATCH") && !(store ?? requireArrays(rawState))?.watches.has("BASH_REMATCH");
80931
80802
  }
80932
- return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
80803
+ return this.isPureSyncValueWord(e.left, rawState) && this.isPureSyncValueWord(e.right, rawState) && (!(e.operator === "==" || e.operator === "=" || e.operator === "!=") || e.right.parts.length > 0 && e.right.parts.every((p) => p.quoted));
80933
80804
  }
80934
80805
  if (e.kind === "not") return checkWhileCond(e.operand, depth + 1);
80935
80806
  if (e.kind === "and" || e.kind === "or") return checkWhileCond(e.left, depth + 1) && checkWhileCond(e.right, depth + 1);
@@ -81188,7 +81059,7 @@ var Runtime = class _Runtime {
81188
81059
  if (store) store.epoch = restEpoch2;
81189
81060
  return loopStatus2;
81190
81061
  }
81191
- if (!isShellIdentifier(command7.name) || command7.name === "OPTIND" || command7.name.includes("[") || store?.get(command7.name) || command7.words && (command7.words.length === 0 || command7.words.length > 64) || rawState.braceexpand === false) {
81062
+ if (!isShellIdentifier(command7.name) || command7.name === "OPTIND" || controlNames.has(command7.name) || command7.name === "LC_COLLATE" || command7.name.includes("[") || store?.get(command7.name) || command7.words && (command7.words.length === 0 || command7.words.length > 64) || rawState.braceexpand === false) {
81192
81063
  return void 0;
81193
81064
  }
81194
81065
  const activeValScope = io[valueScope];
@@ -81643,149 +81514,6 @@ ${s1}
81643
81514
  return pos <= 128 ? fastRedirectScratchViews[pos] : fastRedirectScratchBytes.subarray(0, pos);
81644
81515
  }
81645
81516
  _activePrintfInductionName = void 0;
81646
- _activeLoopBodyScript = void 0;
81647
- _activeLoopCondScript = void 0;
81648
- _activeLoopVarName = void 0;
81649
- isVarUnmutatedInScript(varName, script2) {
81650
- for (const list of script2.lists) {
81651
- for (const pipeline of list.pipelines) {
81652
- for (const cmd of pipeline.commands) {
81653
- if (cmd.kind === "arithmetic") {
81654
- if (cmd.expression.hasMutation && cmd.expression.source.includes(varName)) return false;
81655
- continue;
81656
- }
81657
- if (cmd.kind === "if") {
81658
- for (const br of cmd.branches) {
81659
- if (!this.isVarUnmutatedInScript(varName, br.condition) || !this.isVarUnmutatedInScript(varName, br.body)) return false;
81660
- }
81661
- if (cmd.otherwise && !this.isVarUnmutatedInScript(varName, cmd.otherwise)) return false;
81662
- continue;
81663
- }
81664
- if (cmd.kind === "case") {
81665
- for (const cl of cmd.clauses) {
81666
- if (!this.isVarUnmutatedInScript(varName, cl.body)) return false;
81667
- }
81668
- continue;
81669
- }
81670
- if (cmd.kind === "for") {
81671
- if (cmd.name === varName || !this.isVarUnmutatedInScript(varName, cmd.body)) return false;
81672
- continue;
81673
- }
81674
- if (cmd.kind === "arithmetic-for") {
81675
- if (cmd.expressions.some((e) => e && e.hasMutation && e.source.includes(varName)) || !this.isVarUnmutatedInScript(varName, cmd.body)) return false;
81676
- continue;
81677
- }
81678
- if (cmd.kind === "while") {
81679
- if (!this.isVarUnmutatedInScript(varName, cmd.condition) || !this.isVarUnmutatedInScript(varName, cmd.body)) return false;
81680
- continue;
81681
- }
81682
- if (cmd.kind === "group" || cmd.kind === "subshell") {
81683
- if (!this.isVarUnmutatedInScript(varName, cmd.body)) return false;
81684
- continue;
81685
- }
81686
- if (cmd.kind !== "simple") return false;
81687
- for (const w of cmd.words) {
81688
- const arrAss = getArrayAssignment(w);
81689
- if (arrAss && arrAss.name === varName) return false;
81690
- const p02 = w.parts[0];
81691
- if (p02?.kind === "text" && !p02.quoted && (p02.value.startsWith(varName + "=") || p02.value.startsWith(varName + "+=") || p02.value.startsWith(varName + "["))) return false;
81692
- }
81693
- const w0 = cmd.words[0]?.plain;
81694
- if (w0 === "read" || w0 === "unset" || w0 === "declare" || w0 === "typeset" || w0 === "local" || w0 === "export" || w0 === "mapfile" || w0 === "readarray") {
81695
- if (w0 === "read" && varName === "REPLY") return false;
81696
- if (cmd.words.slice(1).some((w) => (w.plain ?? "").includes(varName))) return false;
81697
- }
81698
- if (w0 === "printf" && cmd.words[1]?.plain === "-v" && (cmd.words[2]?.plain ?? "").startsWith(varName)) return false;
81699
- for (const w of [...cmd.words, ...cmd.redirects.map((r) => r.target)]) {
81700
- for (const pt of w.parts) {
81701
- if (pt.kind === "arithmetic" && pt.expression.hasMutation && pt.expression.source.includes(varName)) return false;
81702
- if (pt.kind === "substitution" && !this.isVarUnmutatedInScript(varName, pt.script)) return false;
81703
- }
81704
- }
81705
- }
81706
- }
81707
- }
81708
- return true;
81709
- }
81710
- isVarUnmutatedInActiveLoop(varName) {
81711
- if (varName === this._activeLoopVarName || varName === this._activePrintfInductionName) return false;
81712
- if (this._activeLoopCondScript && !this.isVarUnmutatedInScript(varName, this._activeLoopCondScript)) return false;
81713
- if (this._activeLoopBodyScript && !this.isVarUnmutatedInScript(varName, this._activeLoopBodyScript)) return false;
81714
- return true;
81715
- }
81716
- isFileReadOnlyScript(script2, rawState) {
81717
- const visit = (value2) => {
81718
- if (value2 === null || typeof value2 !== "object") return true;
81719
- if (Array.isArray(value2)) return value2.every(visit);
81720
- const node = value2;
81721
- if (typeof node.operator === "string" && "target" in node && !["<", "<<<", "<<", "<<-"].includes(node.operator)) return false;
81722
- if (node.kind === "simple") {
81723
- const cmd = value2;
81724
- const name2 = cmd.words[0]?.plain;
81725
- if (name2 === void 0 && !cmd.words.every((word) => this.assignment(word) || getArrayAssignment(word))) return false;
81726
- if (name2 !== void 0 && (hasShellFunction(rawState, name2) || !["jq", "cat", "echo", "printf", "test", "[", ":", "true", "false"].includes(name2))) return false;
81727
- }
81728
- return Object.values(node).every(visit);
81729
- };
81730
- return visit(script2);
81731
- }
81732
- extractLoopInvariantInput(cmd, hasSingleStdinRedir, hasSingleHereStringRedir, rawState) {
81733
- const w0 = cmd.words[0]?.plain;
81734
- const resolveInvariantWord = (w) => {
81735
- if (w.plain !== void 0) return w.plain;
81736
- if (w.parts.length > 0 && w.parts.every((pt) => pt.kind === "text")) return w.parts.map((pt) => pt.value).join("");
81737
- if (w.parts.length === 1 && w.parts[0].kind === "variable") {
81738
- const vp = w.parts[0];
81739
- if (!vp.indirect && !vp.operator && !vp.substring && !vp.transform && !vp.length && !vp.prefixNames && getArraySelector(vp) === void 0 && this.isVarUnmutatedInActiveLoop(vp.name)) {
81740
- const val = rawState.variables[vp.name];
81741
- if (typeof val === "string") return val;
81742
- }
81743
- }
81744
- return void 0;
81745
- };
81746
- if (w0 === "jq" || w0 === "numfmt" || w0 === "awk") {
81747
- if (hasSingleHereStringRedir) {
81748
- const resolved = resolveInvariantWord(cmd.redirects[0].target);
81749
- return resolved !== void 0 ? resolved + "\n" : void 0;
81750
- }
81751
- if (this._fileWrites?.size || this._outputFiles?.size) return void 0;
81752
- if ([this._activeLoopBodyScript, this._activeLoopCondScript].some((script2) => script2 && !this.isFileReadOnlyScript(script2, rawState))) return void 0;
81753
- const fPlain = hasSingleStdinRedir ? cmd.redirects[0].target.plain : cmd.words[cmd.words.length - 1]?.plain;
81754
- if (!fPlain || fPlain.startsWith("-") || fPlain === "/dev/stdin") return void 0;
81755
- const vCheck = this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, fPlain), false);
81756
- if (!vCheck || vCheck.byteLength > 16384 || vCheck.includes(0)) return void 0;
81757
- return sharedSyncPipeDecoder.decode(vCheck);
81758
- }
81759
- if (w0 === "cat") {
81760
- if (hasSingleHereStringRedir) {
81761
- const resolved = resolveInvariantWord(cmd.redirects[0].target);
81762
- return resolved !== void 0 ? resolved + "\n" : void 0;
81763
- }
81764
- if (this._fileWrites?.size || this._outputFiles?.size) return void 0;
81765
- if ([this._activeLoopBodyScript, this._activeLoopCondScript].some((script2) => script2 && !this.isFileReadOnlyScript(script2, rawState))) return void 0;
81766
- const fPlain = hasSingleStdinRedir ? cmd.redirects[0].target.plain : cmd.words[1]?.plain;
81767
- if (!fPlain || fPlain.startsWith("-") || fPlain === "/dev/stdin") return void 0;
81768
- const vCheck = this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, fPlain), false);
81769
- if (!vCheck || vCheck.byteLength > 16384 || vCheck.includes(0)) return void 0;
81770
- return sharedSyncPipeDecoder.decode(vCheck);
81771
- }
81772
- if (w0 === "echo" && cmd.words.length === 2) {
81773
- const resolved = resolveInvariantWord(cmd.words[1]);
81774
- if (resolved !== void 0 && !resolved.startsWith("-")) return resolved + "\n";
81775
- return void 0;
81776
- }
81777
- if (w0 === "printf" && cmd.words.length >= 2) {
81778
- const args = [];
81779
- for (let i = 1; i < cmd.words.length; i++) {
81780
- const r = resolveInvariantWord(cmd.words[i]);
81781
- if (r === void 0) return void 0;
81782
- args.push(r);
81783
- }
81784
- const formatted3 = tryFastPrintf(args);
81785
- return formatted3;
81786
- }
81787
- return void 0;
81788
- }
81789
81517
  canSyncPrintfInductionBody(script2, rawState, inductionName) {
81790
81518
  for (const list of script2.lists) for (const pipeline of list.pipelines) for (const command7 of pipeline.commands) {
81791
81519
  if (command7.kind === "arithmetic") {
@@ -81793,15 +81521,23 @@ ${s1}
81793
81521
  return false;
81794
81522
  }
81795
81523
  if (command7.kind !== "simple" || hasShellFunction(rawState, command7.words[0]?.plain ?? "") || command7.words.some((word) => getArrayAssignment(word) !== void 0)) return false;
81796
- const w0 = command7.words[0]?.plain;
81524
+ let commandIndex = 0;
81525
+ while (commandIndex < command7.words.length && this.assignment(command7.words[commandIndex])) commandIndex++;
81526
+ const commandWord = command7.words[commandIndex];
81527
+ if (!commandWord?.parts.every((part) => part.kind === "text")) return false;
81528
+ const w0 = commandWord.parts.map((part) => part.kind === "text" ? part.value : "").join("");
81529
+ if (w0 === "read") return false;
81530
+ if (w0 === "printf") {
81531
+ const option = command7.words[commandIndex + 1];
81532
+ if (!option?.parts.every((part) => part.kind === "text")) return false;
81533
+ if (option.parts.map((part) => part.kind === "text" ? part.value : "").join("") === "-v") return false;
81534
+ }
81797
81535
  if (w0 === "let" || w0 === "declare" || w0 === "typeset" || w0 === "local" || w0 === "export" || w0 === "unset" || w0 === "mapfile" || w0 === "readarray") return false;
81798
81536
  if (inductionName !== void 0) {
81799
81537
  if (command7.words.some((w) => {
81800
81538
  const p02 = w.parts[0];
81801
81539
  return p02?.kind === "text" && !p02.quoted && (p02.value.startsWith(inductionName + "=") || p02.value.startsWith(inductionName + "+="));
81802
81540
  })) return false;
81803
- if (w0 === "read" && (inductionName === "REPLY" || command7.words.slice(1).some((w) => w.plain === inductionName || w.plain === "-a" || w.plain === "-ra" || w.plain === "-ar"))) return false;
81804
- if (w0 === "printf" && command7.words[1]?.plain === "-v" && command7.words[2]?.plain === inductionName) return false;
81805
81541
  }
81806
81542
  for (const word of [...command7.words, ...command7.redirects.map((redirect) => redirect.target)]) for (const part of word.parts) {
81807
81543
  if (part.kind === "text") continue;
@@ -82019,6 +81755,7 @@ ${s1}
82019
81755
  execSyncLocalDeclStep(decl, rawState, io, monitor, touched, line) {
82020
81756
  const locals = (decl.kind === "local" || decl.kind === "declare") && rawState.locals.length > 0 ? rawState.locals[rawState.locals.length - 1] : void 0;
82021
81757
  let lastArg = decl.kind;
81758
+ const values = decl.items.map((item) => item.value === void 0 ? void 0 : this.fastValueWord(item.value, rawState, io, false, false, false, rawState.braceexpand !== false, 0, line));
82022
81759
  for (let i = 0; i < decl.items.length; i++) {
82023
81760
  const item = decl.items[i];
82024
81761
  const isNewLocal = locals ? !locals.has(item.name) : false;
@@ -82034,7 +81771,7 @@ ${s1}
82034
81771
  touched.add(item.name);
82035
81772
  }
82036
81773
  if (item.value !== void 0) {
82037
- const val = this.fastValueWord(item.value, rawState, io, false, false, false, rawState.braceexpand !== false, 0, line);
81774
+ const val = values[i];
82038
81775
  if (item.append) {
82039
81776
  const curRaw = rawState.variables[item.name];
82040
81777
  const curStr = curRaw === void 0 ? "" : touched.has(item.name) ? curRaw : monitor.values.get(item.name, curRaw) ?? curRaw;
@@ -82043,7 +81780,7 @@ ${s1}
82043
81780
  rawState.variables[item.name] = val;
82044
81781
  }
82045
81782
  touched.add(item.name);
82046
- lastArg = `${item.name}=${rawState.variables[item.name]}`;
81783
+ lastArg = `${item.name}${item.append ? "+=" : "="}${val}`;
82047
81784
  } else {
82048
81785
  lastArg = item.name;
82049
81786
  }
@@ -82128,7 +81865,22 @@ ${s1}
82128
81865
  this._syncStdoutBatch += text3;
82129
81866
  if (this._syncStdoutBatch.length >= 8192) this.flushSyncStdoutBatch(io);
82130
81867
  }
81868
+ runSyncDiscardStep(step, rawState, io) {
81869
+ this.budget.fileSystemOperation();
81870
+ const args = step.discardWords.map((word) => this.fastValueWord(word, rawState, io, false, false, false, false, 0, step.line));
81871
+ const cmdName = step.cmd.words[0].plain;
81872
+ let output2;
81873
+ if (cmdName === "pwd") output2 = rawState.variables.PWD ?? rawState.cwd;
81874
+ else if (cmdName === "echo") output2 = args[0];
81875
+ else if (cmdName === "dirname") output2 = this.evalSyncDirname(args);
81876
+ else output2 = this.evalSyncBasename(step.discardSuffix === void 0 ? args : ["-s", step.discardSuffix, ...args]);
81877
+ const bytes2 = shellValueByteLength(output2) + 1;
81878
+ if (this.budget.bytes + bytes2 > this.budget.maxOutputBytesSmi && bytes2 > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
81879
+ this.budget.bytes += bytes2;
81880
+ return args[args.length - 1] ?? cmdName;
81881
+ }
82131
81882
  writeSyncRedirectStep(step, encoded2, append, mode, rawState, io) {
81883
+ if (this.budget.bytes + encoded2.byteLength > this.budget.maxOutputBytesSmi && encoded2.byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
82132
81884
  encoded2 = encoded2.slice();
82133
81885
  if (step.targetDirPrefix !== void 0 && step.targetNamePrefix !== void 0) {
82134
81886
  const fileName = this.evalSyncRedirectSuffix(step.targetWord, step.targetDirPrefix, step.targetNamePrefix, rawState, io);
@@ -82281,27 +82033,7 @@ ${s1}
82281
82033
  touched.add(step.name);
82282
82034
  lastArg = pLastArg;
82283
82035
  } else if (step.isDiscardDevNull && step.discardWords !== void 0) {
82284
- this.budget.fileSystemOperation();
82285
- const dw = step.discardWords;
82286
- const cmdName = step.cmd.words[0].plain;
82287
- let evalFirst = "";
82288
- let evalLast = cmdName;
82289
- for (let wi = 0; wi < dw.length; wi++) {
82290
- const v = this.fastValueWord(dw[wi], rawState, io, false, false, false, false, 0, step.line);
82291
- if (wi === 0) evalFirst = v;
82292
- evalLast = v;
82293
- }
82294
- let outChars = 0;
82295
- if (cmdName === "pwd") outChars = (rawState.variables.PWD ?? rawState.cwd).length + 1;
82296
- else if (cmdName === "echo") outChars = evalFirst.length + 1;
82297
- else if (cmdName === "dirname") outChars = dirname(evalFirst).length + 1;
82298
- else if (cmdName === "basename") {
82299
- const sfx = step.discardSuffix !== void 0 ? step.discardSuffix : dw.length === 2 ? evalLast : void 0;
82300
- const baseStr = /^\/+$/u.test(evalFirst) ? "/" : basename(evalFirst);
82301
- outChars = (sfx && baseStr !== sfx && baseStr.endsWith(sfx) ? baseStr.length - sfx.length : baseStr.length) + 1;
82302
- }
82303
- this.budget.bytes += outChars;
82304
- lastArg = step.discardSuffix !== void 0 ? evalLast : dw.length > 0 ? evalLast : cmdName;
82036
+ lastArg = this.runSyncDiscardStep(step, rawState, io);
82305
82037
  } else if (step.name !== void 0 && step.value !== void 0) {
82306
82038
  rawState.substitutionStatus = 0;
82307
82039
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -82363,6 +82095,7 @@ ${s1}
82363
82095
  return check(tree);
82364
82096
  }
82365
82097
  canSyncErrorArithmeticStmt(expr, rawState) {
82098
+ if (expr.source.includes("$")) return false;
82366
82099
  if (expr.source.includes("/") || expr.source.includes("%") || expr.source.includes("<<") || expr.source.includes(">>") || expr.source.includes("**") || expr.source.includes("[")) return false;
82367
82100
  try {
82368
82101
  const cachedExpr = expr;
@@ -82504,27 +82237,40 @@ ${s1}
82504
82237
  const prevFastSubPos = this._fastSubPositional;
82505
82238
  rawState.positional = fnArgs;
82506
82239
  this._fastSubPositional = fnArgs;
82507
- const savedLocals = new Array(fnCall.locals.length);
82240
+ const savedLocals = [];
82241
+ const seenLocals = /* @__PURE__ */ new Set();
82508
82242
  try {
82509
- for (let i = 0; i < fnCall.locals.length; i++) {
82510
- const loc = fnCall.locals[i];
82511
- if (loc.isFirstInCmd) this.budget.tick();
82512
- savedLocals[i] = { name: loc.name, val: rawState.variables[loc.name], wasTouched: touched.has(loc.name) };
82513
- if (loc.valueWord !== void 0) {
82514
- rawState.variables[loc.name] = this.fastValueWord(loc.valueWord, rawState, io, false, false, false, false, 0, step.line);
82515
- touched.add(loc.name);
82516
- } else {
82517
- delete rawState.variables[loc.name];
82243
+ for (let i = 0; i < fnCall.locals.length; ) {
82244
+ this.budget.tick();
82245
+ let end = i + 1;
82246
+ while (end < fnCall.locals.length && !fnCall.locals[end].isFirstInCmd) end++;
82247
+ const values = fnCall.locals.slice(i, end).map((loc) => loc.valueWord === void 0 ? void 0 : this.fastValueWord(loc.valueWord, rawState, io, false, false, false, false, 0, step.line));
82248
+ const start = i;
82249
+ for (; i < end; i++) {
82250
+ const loc = fnCall.locals[i];
82251
+ const alreadyLocal = seenLocals.has(loc.name);
82252
+ if (!alreadyLocal) {
82253
+ savedLocals.push({ name: loc.name, val: rawState.variables[loc.name], wasTouched: touched.has(loc.name) });
82254
+ seenLocals.add(loc.name);
82255
+ }
82256
+ const value2 = values[i - start];
82257
+ if (value2 !== void 0) {
82258
+ rawState.variables[loc.name] = value2;
82259
+ touched.add(loc.name);
82260
+ } else if (!alreadyLocal) {
82261
+ delete rawState.variables[loc.name];
82262
+ }
82518
82263
  }
82519
82264
  }
82520
82265
  if (fnCall.steps.length > 0) {
82521
82266
  this.execSyncLoopSteps(fnCall.steps, rawState, io, monitor, touched, mode, onUpdate);
82522
82267
  } else {
82523
82268
  rawState.status = 0;
82524
- onUpdate({ lastCmd: step.cmd, lastArg: fnArgs.length > 0 ? fnArgs[fnArgs.length - 1] : fnCall.name });
82525
82269
  }
82270
+ rawState.lastArgument = fnArgs.at(-1) ?? fnCall.name;
82271
+ onUpdate({ lastCmd: step.cmd, lastArg: rawState.lastArgument });
82526
82272
  } finally {
82527
- for (let i = fnCall.locals.length - 1; i >= 0; i--) {
82273
+ for (let i = savedLocals.length - 1; i >= 0; i--) {
82528
82274
  const saved = savedLocals[i];
82529
82275
  if (saved.val !== void 0) {
82530
82276
  rawState.variables[saved.name] = saved.val;
@@ -82776,27 +82522,7 @@ ${s1}
82776
82522
  touched.add(step.name);
82777
82523
  lastArg = pLastArg;
82778
82524
  } else if (step.isDiscardDevNull && step.discardWords !== void 0) {
82779
- this.budget.fileSystemOperation();
82780
- const dw = step.discardWords;
82781
- const cmdName = step.cmd.words[0].plain;
82782
- let evalFirst = "";
82783
- let evalLast = cmdName;
82784
- for (let wi = 0; wi < dw.length; wi++) {
82785
- const v = this.fastValueWord(dw[wi], rawState, io, false, false, false, false, 0, step.line);
82786
- if (wi === 0) evalFirst = v;
82787
- evalLast = v;
82788
- }
82789
- let outChars = 0;
82790
- if (cmdName === "pwd") outChars = (rawState.variables.PWD ?? rawState.cwd).length + 1;
82791
- else if (cmdName === "echo") outChars = evalFirst.length + 1;
82792
- else if (cmdName === "dirname") outChars = dirname(evalFirst).length + 1;
82793
- else if (cmdName === "basename") {
82794
- const sfx = step.discardSuffix !== void 0 ? step.discardSuffix : dw.length === 2 ? evalLast : void 0;
82795
- const baseStr = /^\/+$/u.test(evalFirst) ? "/" : basename(evalFirst);
82796
- outChars = (sfx && baseStr !== sfx && baseStr.endsWith(sfx) ? baseStr.length - sfx.length : baseStr.length) + 1;
82797
- }
82798
- this.budget.bytes += outChars;
82799
- lastArg = step.discardSuffix !== void 0 ? evalLast : dw.length > 0 ? evalLast : cmdName;
82525
+ lastArg = this.runSyncDiscardStep(step, rawState, io);
82800
82526
  } else if (step.name !== void 0 && step.value !== void 0) {
82801
82527
  rawState.substitutionStatus = 0;
82802
82528
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -82941,27 +82667,7 @@ ${s1}
82941
82667
  touched.add(step.name);
82942
82668
  lastArg = pLastArg;
82943
82669
  } else if (step.isDiscardDevNull && step.discardWords !== void 0) {
82944
- this.budget.fileSystemOperation();
82945
- const dw = step.discardWords;
82946
- const cmdName = step.cmd.words[0].plain;
82947
- let evalFirst = "";
82948
- let evalLast = cmdName;
82949
- for (let wi = 0; wi < dw.length; wi++) {
82950
- const v = this.fastValueWord(dw[wi], rawState, io, false, false, false, false, 0, step.line);
82951
- if (wi === 0) evalFirst = v;
82952
- evalLast = v;
82953
- }
82954
- let outChars = 0;
82955
- if (cmdName === "pwd") outChars = (rawState.variables.PWD ?? rawState.cwd).length + 1;
82956
- else if (cmdName === "echo") outChars = evalFirst.length + 1;
82957
- else if (cmdName === "dirname") outChars = dirname(evalFirst).length + 1;
82958
- else if (cmdName === "basename") {
82959
- const sfx = step.discardSuffix !== void 0 ? step.discardSuffix : dw.length === 2 ? evalLast : void 0;
82960
- const baseStr = /^\/+$/u.test(evalFirst) ? "/" : basename(evalFirst);
82961
- outChars = (sfx && baseStr !== sfx && baseStr.endsWith(sfx) ? baseStr.length - sfx.length : baseStr.length) + 1;
82962
- }
82963
- this.budget.bytes += outChars;
82964
- lastArg = step.discardSuffix !== void 0 ? evalLast : dw.length > 0 ? evalLast : cmdName;
82670
+ lastArg = this.runSyncDiscardStep(step, rawState, io);
82965
82671
  } else if (step.name !== void 0 && step.value !== void 0) {
82966
82672
  rawState.substitutionStatus = 0;
82967
82673
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -83770,8 +83476,6 @@ ${s1}
83770
83476
  state.substitutionStatus = 0;
83771
83477
  const rawState = stateMonitor(state)?.raw ?? state;
83772
83478
  if (rawState.variables._ !== void 0) delete rawState.variables._;
83773
- rawState.lastArgument = wordValues[wordValues.length - 1] ?? w0Plain;
83774
- state.lastArgument = rawState.lastArgument;
83775
83479
  return await this.dispatchFastFunction(w0Plain, state.functions.get(w0Plain), wordValues.slice(1), state, originalIO);
83776
83480
  }
83777
83481
  }
@@ -84882,8 +84586,10 @@ ${s1}
84882
84586
  }
84883
84587
  const rawState = stateMonitor(state)?.raw ?? state;
84884
84588
  if (!state._readOnlyStage && rawState.variables._ !== void 0) delete rawState.variables._;
84885
- rawState.lastArgument = words.length > 0 ? words[words.length - 1] : "";
84886
- state.lastArgument = rawState.lastArgument;
84589
+ if (!state.functions.has(words[0] ?? "") && !["eval", ".", "source"].includes(words[declarationIndex] ?? "")) {
84590
+ rawState.lastArgument = words.at(-1) ?? "";
84591
+ state.lastArgument = rawState.lastArgument;
84592
+ }
84887
84593
  if (!words.length) return state.substitutionStatus;
84888
84594
  const args = words.slice(1);
84889
84595
  const argValues = allStrings ? args : wordValues.slice(1);
@@ -85107,8 +84813,10 @@ ${s1}
85107
84813
  if (!snapshotScope) {
85108
84814
  const rawState = stateMonitor(state)?.raw ?? state;
85109
84815
  if (rawState.variables._ !== void 0 && !assignments2.some((assignment) => assignment.name === "_")) delete rawState.variables._;
85110
- rawState.lastArgument = words.length > 0 ? words[words.length - 1] : "";
85111
- state.lastArgument = rawState.lastArgument;
84816
+ if (!functionCommand && !["eval", ".", "source"].includes(words[declarationIndex] ?? "")) {
84817
+ rawState.lastArgument = words.at(-1) ?? "";
84818
+ state.lastArgument = rawState.lastArgument;
84819
+ }
85112
84820
  }
85113
84821
  if (!words.length) return state.substitutionStatus;
85114
84822
  const args = words.slice(1);
@@ -85399,6 +85107,7 @@ ${s1}
85399
85107
  throw checkpointFailure;
85400
85108
  }
85401
85109
  if (hasThrown) throw thrownError;
85110
+ state.lastArgument = pendingResume?.lastArgument ?? args.at(-1) ?? name2;
85402
85111
  return exitStatus;
85403
85112
  } finally {
85404
85113
  await scope.close();
@@ -85897,6 +85606,7 @@ ${s1}
85897
85606
  throw checkpointFailure;
85898
85607
  }
85899
85608
  if (outcome.kind === "throw") throw outcome.reason;
85609
+ state.lastArgument = context3.args.at(-1) ?? context3.command;
85900
85610
  return outcome.value;
85901
85611
  }
85902
85612
  if (selectedKind === "builtin" && !(state.externalInvocation && this.commands.has(context3.command))) {
@@ -85910,8 +85620,16 @@ ${s1}
85910
85620
  return { exitCode: status2 };
85911
85621
  }
85912
85622
  if (context3.command === "command" || context3.command === "builtin" || context3.command === "type") return { exitCode: await this.discoveryBuiltin(context3, state, io, assignments2, defaultPath) };
85913
- if (context3.command === "." || context3.command === "source") return { exitCode: await this.sourceBuiltin(context3, state, { ...io, ...context3 }, special) };
85914
- if (context3.command === "eval") return { exitCode: await this.evalBuiltin(context3, state, { ...io, ...context3 }, special) };
85623
+ if (context3.command === "." || context3.command === "source") {
85624
+ const exitCode = await this.sourceBuiltin(context3, state, { ...io, ...context3 }, special);
85625
+ state.lastArgument = context3.args.at(-1) ?? context3.command;
85626
+ return { exitCode };
85627
+ }
85628
+ if (context3.command === "eval") {
85629
+ const exitCode = await this.evalBuiltin(context3, state, { ...io, ...context3 }, special);
85630
+ state.lastArgument = context3.args.at(-1) ?? context3.command;
85631
+ return { exitCode };
85632
+ }
85915
85633
  const builtinWork = this.builtin({ ...context3, [declarationArrays]: io[declarationArrays] }, state, assignments2, (error, diagnostic4) => {
85916
85634
  builtinFailure = { error, diagnostic: diagnostic4 };
85917
85635
  }, bypassFunctions);
@@ -90459,6 +90177,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90459
90177
  }
90460
90178
  expandSyncTrCharArray(spec) {
90461
90179
  if (spec.length === 0) return void 0;
90180
+ for (let i = 0; i < spec.length; i++) if (spec.charCodeAt(i) >= 128) return void 0;
90462
90181
  if (spec.includes("\\") && spec.includes("-")) return void 0;
90463
90182
  const posixClasses = {
90464
90183
  "[:lower:]": "abcdefghijklmnopqrstuvwxyz",
@@ -90884,9 +90603,9 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90884
90603
  for (const el of item) {
90885
90604
  if (!el || typeof el !== "object" || Array.isArray(el)) return void 0;
90886
90605
  const rec = el;
90887
- const k = rec.key ?? rec.name ?? rec.k;
90606
+ const k = [rec.key, rec.Key, rec.name, rec.Name].find((value2) => value2 !== void 0 && value2 !== null && value2 !== false);
90888
90607
  if (typeof k !== "string") return void 0;
90889
- obj[k] = Object.hasOwn(rec, "value") ? rec.value : Object.hasOwn(rec, "v") ? rec.v : null;
90608
+ obj[k] = Object.hasOwn(rec, "value") ? rec.value : Object.hasOwn(rec, "Value") ? rec.Value : null;
90890
90609
  }
90891
90610
  return [obj];
90892
90611
  }
@@ -90915,7 +90634,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90915
90634
  if (!Array.isArray(item) || !item.every((x) => typeof x === "string" || typeof x === "number" || typeof x === "boolean" || x === null)) return void 0;
90916
90635
  return [item.map((x) => x === null ? "" : String(x)).join(arg)];
90917
90636
  }
90918
- if (fn === "split") return typeof item === "string" ? [item.split(arg)] : void 0;
90637
+ if (fn === "split") return typeof item === "string" ? [arg === "" ? Array.from(item) : item.split(arg)] : void 0;
90919
90638
  if (fn === "ltrimstr") return typeof item === "string" ? [item.startsWith(arg) ? item.slice(arg.length) : item] : void 0;
90920
90639
  if (fn === "rtrimstr") return typeof item === "string" ? [arg.length > 0 && item.endsWith(arg) ? item.slice(0, -arg.length) : item] : void 0;
90921
90640
  if (fn === "startswith") return typeof item === "string" ? [item.startsWith(arg)] : void 0;
@@ -91120,9 +90839,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91120
90839
  break;
91121
90840
  }
91122
90841
  if (!a.startsWith("-") || a === "-") {
91123
- operands.push(a);
91124
- idx++;
91125
- continue;
90842
+ operands.push(...args.slice(idx));
90843
+ break;
91126
90844
  }
91127
90845
  if (a === "-a" || a === "--multiple") {
91128
90846
  multiple = true;
@@ -91397,6 +91115,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91397
91115
  const anchorEnd = core1.endsWith("$");
91398
91116
  const core = anchorEnd ? core1.slice(0, -1) : core1;
91399
91117
  if (core.length === 0 && !anchorStart && !anchorEnd) return void 0;
91118
+ if (core.includes("[:") || core.includes("[.") || core.includes("[=") || core.includes("[]") || core.includes("[^]") || isExtended && core.includes("|")) return void 0;
91400
91119
  let reSrc;
91401
91120
  if (/^[a-zA-Z0-9_ :;,=-]*$/.test(core)) {
91402
91121
  if (/\\[1-9]/.test(rep)) return void 0;
@@ -91443,7 +91162,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91443
91162
  }
91444
91163
  if (st.kind === "=") {
91445
91164
  out.push(String(idx1));
91446
- lastInputIndex = i;
91165
+ lastInputIndex = -1;
91447
91166
  continue;
91448
91167
  }
91449
91168
  if (st.kind === "q") {
@@ -91480,7 +91199,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91480
91199
  }
91481
91200
  return replacement;
91482
91201
  });
91483
- if (matchedOnce && st.printOnMatch) out.push(l);
91202
+ if (matchedOnce && st.printOnMatch) {
91203
+ out.push(l);
91204
+ lastInputIndex = i;
91205
+ }
91484
91206
  }
91485
91207
  if (quitNow) {
91486
91208
  break;
@@ -91556,7 +91278,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91556
91278
  const isExtended = mode.includes("E");
91557
91279
  const isFixed = mode.includes("F");
91558
91280
  const isOnlyMatching = mode.includes("o");
91559
- if (isExtended && !isFixed && rawPatterns.some((pattern) => pattern.includes("[:") || pattern.includes("[.") || pattern.includes("[="))) return void 0;
91281
+ if (!isFixed && rawPatterns.some((pattern) => pattern.includes("[:") || pattern.includes("[.") || pattern.includes("[=") || pattern.includes("[]") || pattern.includes("[^]") || isExtended && pattern.includes("[") && pattern.includes("|"))) return void 0;
91560
91282
  if (isCount && (isLineNumber || isOnlyMatching || beforeCtx > 0 || afterCtx > 0)) return void 0;
91561
91283
  if (isOnlyMatching && (beforeCtx > 0 || afterCtx > 0)) return void 0;
91562
91284
  if (isOnlyMatching) {
@@ -91579,15 +91301,18 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91579
91301
  }
91580
91302
  if (!re) return void 0;
91581
91303
  const out = [];
91304
+ let matched2 = false;
91582
91305
  for (let li = 0; li < rawLines.length; li++) {
91583
91306
  const matches2 = rawLines[li].match(re);
91584
91307
  if (matches2) {
91308
+ matched2 = true;
91585
91309
  for (let mi = 0; mi < matches2.length; mi++) {
91310
+ if (matches2[mi].length === 0) continue;
91586
91311
  out.push(isLineNumber ? `${li + 1}:${matches2[mi]}` : matches2[mi]);
91587
91312
  }
91588
91313
  }
91589
91314
  }
91590
- return { lines: out, status: out.length > 0 ? 0 : 1 };
91315
+ return { lines: out, status: matched2 ? 0 : 1 };
91591
91316
  }
91592
91317
  if (isExtended && isFixed) return void 0;
91593
91318
  const branches = [];
@@ -92413,14 +92138,16 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92413
92138
  endField = km[2] !== void 0 ? Number(km[2]) : void 0;
92414
92139
  if (endField !== void 0 && endField < startField) return void 0;
92415
92140
  const kf = km[3] ?? "";
92416
- if (kf.includes("n")) keyNum = true;
92417
- if (kf.includes("h")) keyHuman = true;
92418
- if (kf.includes("M")) keyMonth = true;
92419
- if (kf.includes("d")) keyDict = true;
92420
- if (kf.includes("r")) keyRev = true;
92421
- if (kf.includes("f")) keyFold = true;
92422
- if (kf.includes("b")) keyBlanks = true;
92423
- if (kf.includes("V")) keyVer = true;
92141
+ if (kf.length > 0) {
92142
+ keyNum = kf.includes("n");
92143
+ keyHuman = kf.includes("h");
92144
+ keyMonth = kf.includes("M");
92145
+ keyDict = kf.includes("d");
92146
+ keyRev = kf.includes("r");
92147
+ keyFold = kf.includes("f");
92148
+ keyBlanks = kf.includes("b");
92149
+ keyVer = kf.includes("V");
92150
+ }
92424
92151
  }
92425
92152
  const extractKey = (l) => {
92426
92153
  let raw = keySpec === void 0 ? l : (() => {
@@ -92444,7 +92171,13 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92444
92171
  })();
92445
92172
  if (keyBlanks) raw = raw.replace(/^[ \t]+/, "");
92446
92173
  if (keyDict) raw = raw.replace(/[^a-zA-Z0-9 \t]+/g, "");
92447
- return keyFold ? raw.toUpperCase() : raw;
92174
+ if (!keyFold) return raw;
92175
+ let folded = "";
92176
+ for (let i = 0; i < raw.length; i++) {
92177
+ const code = raw.charCodeAt(i);
92178
+ folded += code >= 97 && code <= 122 ? String.fromCharCode(code - 32) : raw[i];
92179
+ }
92180
+ return folded;
92448
92181
  };
92449
92182
  const parseNum = (s) => {
92450
92183
  const m = /^[ \t]*(-?(?:\d+(?:\.\d*)?|\.\d+))/.exec(s);
@@ -92472,6 +92205,23 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92472
92205
  const idx = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"].indexOf(m[1].toUpperCase());
92473
92206
  return idx === -1 ? 0 : idx + 1;
92474
92207
  };
92208
+ const encoded2 = /* @__PURE__ */ new Map();
92209
+ const bytesOf = (line) => {
92210
+ let bytes2 = encoded2.get(line);
92211
+ if (bytes2 === void 0) {
92212
+ bytes2 = fastSharedTextEncoder.encode(line);
92213
+ encoded2.set(line, bytes2);
92214
+ }
92215
+ return bytes2;
92216
+ };
92217
+ const compareBytes2 = (left, right) => {
92218
+ const a = bytesOf(left);
92219
+ const b = bytesOf(right);
92220
+ for (let i = 0; i < Math.min(a.length, b.length); i++) {
92221
+ if (a[i] !== b[i]) return a[i] - b[i];
92222
+ }
92223
+ return a.length - b.length;
92224
+ };
92475
92225
  const sorted = [...rawLines].sort((a, b) => {
92476
92226
  const ka = extractKey(a);
92477
92227
  const kb = extractKey(b);
@@ -92490,13 +92240,12 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92490
92240
  const vc = this.compareSyncVersion(ka, kb);
92491
92241
  if (vc !== 0) return keyRev ? -vc : vc;
92492
92242
  } else if (ka !== kb) {
92493
- return ka < kb ? keyRev ? 1 : -1 : keyRev ? -1 : 1;
92243
+ const comparison2 = compareBytes2(ka, kb);
92244
+ return keyRev ? -comparison2 : comparison2;
92494
92245
  }
92495
92246
  if (uniq || stable) return 0;
92496
- const fa = fold2 ? a.toUpperCase() : a;
92497
- const fb = fold2 ? b.toUpperCase() : b;
92498
- if (fa !== fb) return fa < fb ? rev ? 1 : -1 : rev ? -1 : 1;
92499
- return a < b ? rev ? 1 : -1 : a > b ? rev ? -1 : 1 : 0;
92247
+ const comparison = compareBytes2(a, b);
92248
+ return rev ? -comparison : comparison;
92500
92249
  });
92501
92250
  if (!uniq) return sorted;
92502
92251
  const dedup = [];
@@ -92591,6 +92340,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92591
92340
  return this.evalSyncSort(rawLines, flag !== void 0 ? [flag] : [], false) ?? [...rawLines];
92592
92341
  }
92593
92342
  translateSyncTr(input3, set1Spec, set2Spec, truncateSet1 = false) {
92343
+ if (set2Spec.includes("[:") && !(set1Spec === "[:lower:]" && set2Spec === "[:upper:]") && !(set1Spec === "[:upper:]" && set2Spec === "[:lower:]")) return void 0;
92594
92344
  if ((set1Spec === "a-z" || set1Spec === "[:lower:]") && (set2Spec === "A-Z" || set2Spec === "[:upper:]")) {
92595
92345
  return input3.replace(/[a-z]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 32));
92596
92346
  }
@@ -92866,7 +92616,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92866
92616
  const firstName = stageNames[sIdx];
92867
92617
  const extDef = stageDefs[sIdx];
92868
92618
  const stageArgs = stageArgsList[sIdx];
92869
- const nextBuf = (index & 1) === 0 ? sharedSyncPipeBuf0 : sharedSyncPipeBuf1;
92619
+ let nextBuf = (index & 1) === 0 ? sharedSyncPipeBuf0 : sharedSyncPipeBuf1;
92870
92620
  const isInlineCutField = firstName === "cut";
92871
92621
  const isInlineTr = firstName === "tr";
92872
92622
  const isInlineAwk = firstName === "awk";
@@ -92894,6 +92644,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92894
92644
  const nextTotalBytes2 = this.budget.bytes + sub.byteLength;
92895
92645
  if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && sub.byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
92896
92646
  this.budget.bytes = nextTotalBytes2;
92647
+ if (sub.byteLength > nextBuf.byteLength) nextBuf = new Uint8Array(sub.byteLength);
92897
92648
  nextBuf.set(sub, 0);
92898
92649
  prevBuf = nextBuf;
92899
92650
  prevLen = sub.byteLength;
@@ -92930,10 +92681,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92930
92681
  const transformed = this.evalSyncTr(inStr, stageArgs);
92931
92682
  if (transformed === void 0) return void 0;
92932
92683
  const outByteLen2 = shellValueByteLength(transformed);
92933
- if (outByteLen2 > nextBuf.byteLength) return void 0;
92934
92684
  const nextTotalBytes2 = this.budget.bytes + outByteLen2;
92935
92685
  if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && outByteLen2 > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
92936
92686
  this.budget.bytes = nextTotalBytes2;
92687
+ if (outByteLen2 > nextBuf.byteLength) nextBuf = new Uint8Array(outByteLen2);
92937
92688
  const written2 = transformed.length === 0 ? 0 : fastSharedTextEncoder.encodeInto(transformed, nextBuf).written;
92938
92689
  prevBuf = nextBuf;
92939
92690
  prevLen = written2;
@@ -92960,8 +92711,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92960
92711
  if (stageStatus !== 0) failureStatus = stageStatus;
92961
92712
  outLines = grepRes.lines;
92962
92713
  } else if (isInlineTac) {
92963
- if (inStr.length > 0 && !inStr.endsWith("\n")) return void 0;
92964
92714
  outLines = [...rawLines].reverse();
92715
+ if (!inStr.endsWith("\n") && outLines.length > 1) {
92716
+ outLines.splice(0, 2, outLines[0] + outLines[1]);
92717
+ }
92965
92718
  } else if (isInlineNl) {
92966
92719
  const nlRes = this.evalSyncNl(rawLines, stageArgs);
92967
92720
  if (nlRes === void 0) return void 0;
@@ -92982,10 +92735,11 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92982
92735
  const cleaned = inStr.replace(/[ \t\r\n]+/g, "");
92983
92736
  if (cleaned.length % 4 !== 0 || cleaned.length > 0 && !/^[A-Za-z0-9+/]+={0,2}$/.test(cleaned)) return void 0;
92984
92737
  const decoded = this.syncBase64DecodeBytes(cleaned);
92985
- if (decoded.some((byte) => byte === 0 || byte >= 128) || decoded.byteLength > nextBuf.byteLength) return void 0;
92738
+ if (decoded.some((byte) => byte === 0 || byte >= 128)) return void 0;
92986
92739
  const nextTotalBytes2 = this.budget.bytes + decoded.byteLength;
92987
92740
  if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && decoded.byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
92988
92741
  this.budget.bytes = nextTotalBytes2;
92742
+ if (decoded.byteLength > nextBuf.byteLength) nextBuf = new Uint8Array(decoded.byteLength);
92989
92743
  nextBuf.set(decoded, 0);
92990
92744
  prevBuf = nextBuf;
92991
92745
  prevLen = decoded.byteLength;
@@ -92997,13 +92751,13 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92997
92751
  outLines = jqRes;
92998
92752
  }
92999
92753
  const preservesTerminator = firstName === "head" || firstName === "tail" || firstName === "rev" || firstName === "sed";
93000
- const terminated = sedTerminated || !preservesTerminator || inStr.endsWith("\n") || firstName === "head" && outLines.length < rawLines.length;
92754
+ const terminated = isInlineTac ? inStr.includes("\n") : sedTerminated || !preservesTerminator || inStr.endsWith("\n") || firstName === "head" && outLines.length < rawLines.length;
93001
92755
  const outStr2 = outLines.length > 0 ? outLines.join("\n") + (terminated ? "\n" : "") : "";
93002
92756
  const outByteLen = shellValueByteLength(outStr2);
93003
- if (outByteLen > nextBuf.byteLength) return void 0;
93004
92757
  const nextTotalBytes = this.budget.bytes + outByteLen;
93005
92758
  if (nextTotalBytes > this.budget.maxOutputBytesSmi && outByteLen > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
93006
92759
  this.budget.bytes = nextTotalBytes;
92760
+ if (outByteLen > nextBuf.byteLength) nextBuf = new Uint8Array(outByteLen);
93007
92761
  const written = outStr2.length === 0 ? 0 : fastSharedTextEncoder.encodeInto(outStr2, nextBuf).written;
93008
92762
  prevBuf = nextBuf;
93009
92763
  prevLen = written;