@poe-platform/safe-bash 0.1.750 → 0.1.752

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,
@@ -10851,6 +10852,8 @@ async function executeUniqGeneral(context2, preReadSource) {
10851
10852
  const onlyRepeated = parsed.flags.has("d");
10852
10853
  const onlyUnique = parsed.flags.has("u");
10853
10854
  const identityKey = skipFields === 0 && skipCharacters === 0 && width === Infinity && !ignoreCase;
10855
+ const locale = context2.env.LC_ALL || context2.env.LC_CTYPE || context2.env.LANG;
10856
+ const byteLocale2 = locale === "C" || locale === "POSIX";
10854
10857
  const uniqDecoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
10855
10858
  const key = (bytes2) => {
10856
10859
  if (identityKey) return bytes2;
@@ -10861,8 +10864,13 @@ async function executeUniqGeneral(context2, preReadSource) {
10861
10864
  }
10862
10865
  let result;
10863
10866
  try {
10864
- const chars = Array.from(uniqDecoder.decode(bytes2.subarray(offset)));
10865
- result = encoder.encode((width === Infinity ? chars.slice(skipCharacters) : chars.slice(skipCharacters, skipCharacters + width)).join(""));
10867
+ if (byteLocale2) {
10868
+ offset += skipCharacters;
10869
+ result = bytes2.subarray(offset, width === Infinity ? void 0 : offset + width);
10870
+ } else {
10871
+ const chars = Array.from(uniqDecoder.decode(bytes2.subarray(offset)));
10872
+ result = encoder.encode((width === Infinity ? chars.slice(skipCharacters) : chars.slice(skipCharacters, skipCharacters + width)).join(""));
10873
+ }
10866
10874
  } catch (error) {
10867
10875
  if (!(error instanceof TypeError)) throw error;
10868
10876
  offset += skipCharacters;
@@ -11319,7 +11327,7 @@ function textCommands() {
11319
11327
  } else {
11320
11328
  const f1 = Number(part.slice(0, dashIdx));
11321
11329
  const f2 = Number(part.slice(dashIdx + 1));
11322
- if (f1 < 1 || f2 < f1 || f2 > 30) {
11330
+ if (!Number.isFinite(f2) || f1 < 1 || f2 < f1 || f2 > 30) {
11323
11331
  okMask = false;
11324
11332
  break;
11325
11333
  }
@@ -13388,7 +13396,11 @@ function getCompiledSyncPatternRegex(pattern) {
13388
13396
  contents2 = "^";
13389
13397
  cursor++;
13390
13398
  }
13391
- if (cursor >= pattern.length || pattern.charCodeAt(cursor) === 93) {
13399
+ if (pattern.charCodeAt(cursor) === 93) {
13400
+ contents2 += "\\]";
13401
+ cursor++;
13402
+ }
13403
+ if (cursor >= pattern.length) {
13392
13404
  syncPatternRegexCache.set(pattern, null);
13393
13405
  return null;
13394
13406
  }
@@ -47527,7 +47539,9 @@ function delay(milliseconds, signal, configuration) {
47527
47539
  if (!Number.isFinite(now) || Math.abs(now) > Number.MAX_SAFE_INTEGER || previous !== void 0 && now < previous) {
47528
47540
  throw new RangeError("sleep scheduler must supply finite monotonic milliseconds");
47529
47541
  }
47530
- if (previous !== void 0) remaining -= Math.max(step, now - previous);
47542
+ if (previous !== void 0) {
47543
+ remaining -= scheduler === defaultSleepScheduler ? now - previous : Math.max(step, now - previous);
47544
+ }
47531
47545
  previous = now;
47532
47546
  if (remaining <= 0) {
47533
47547
  finish(false);
@@ -68474,8 +68488,6 @@ var DiscardCommandFailure = class extends CommandFailure2 {
68474
68488
  };
68475
68489
  var ParameterExpansionFailure = class extends ExpansionFailure {
68476
68490
  };
68477
- var SubstringRangeFailure = class extends ExpansionFailure {
68478
- };
68479
68491
  var NounsetFailure = class extends ExpansionFailure {
68480
68492
  constructor(message3, line, status2 = 1) {
68481
68493
  super(message3, line);
@@ -75887,9 +75899,15 @@ var Runtime = class _Runtime {
75887
75899
  if (expr.kind === "unary") return (expr.operator === "-n" || expr.operator === "-z" || expr.operator === "-v" || syncConditionalFileUnaryOps.has(expr.operator)) && okWord(expr.operand);
75888
75900
  if (expr.kind === "binary") {
75889
75901
  if (!okWord(expr.left) || !okWord(expr.right)) return false;
75890
- if (expr.operator === "=~") return depth === 0 && this.extractSimpleErePattern(expr.right, rawState) !== void 0;
75902
+ if (expr.operator === "=~") return !requireTotal && depth === 0 && this.extractSimpleErePattern(expr.right, rawState) !== void 0;
75891
75903
  if (expr.operator === "==" || expr.operator === "=" || expr.operator === "!=") {
75892
75904
  if (expr.right.parts.length > 0 && expr.right.parts.every((p) => p.quoted)) return true;
75905
+ if (requireTotal) {
75906
+ if (!expr.right.parts.every((p, idx) => p.kind === "text" && !p.byteValue && (p.quoted || idx > 0 || !p.value.startsWith("~")))) return false;
75907
+ const pattern = expr.right.parts.map((p) => p.kind === "text" ? p.quoted ? p.value.replace(/[\\*?[\]()]/g, "\\$&") : p.value : "").join("");
75908
+ const work = { remaining: 4096, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
75909
+ return tryMatchesPatternSync(pattern, "", work, false, true) !== void 0;
75910
+ }
75893
75911
  if (expr.right.parts.length > 0 && expr.right.parts.every(
75894
75912
  (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
75895
75913
  )) return true;
@@ -76040,19 +76058,23 @@ var Runtime = class _Runtime {
76040
76058
  if (typeof right !== "string") return void 0;
76041
76059
  const syncTouched = this._syncArithRawWriteOnly ? this._syncArithTouched : void 0;
76042
76060
  const lTrim = left.trim() || "0";
76043
- let lNum = resolveSimpleArithOperand(lTrim, rawState, monitor, store, syncTouched);
76061
+ let lNum = lTrim.length > 13 && /^-?[0-9]{1,19}$/.test(lTrim) ? BigInt.asIntN(64, BigInt(lTrim)) : resolveSimpleArithOperand(lTrim, rawState, monitor, store, syncTouched);
76044
76062
  if (lNum === void 0) {
76045
76063
  const lExpr = tryEvalSimpleExpandedArith(lTrim, rawState, monitor, store, syncTouched);
76046
76064
  if (lExpr !== void 0) lNum = Number(lExpr);
76047
76065
  }
76048
76066
  if (lNum === void 0) return void 0;
76049
76067
  const rTrim = right.trim() || "0";
76050
- let rNum = resolveSimpleArithOperand(rTrim, rawState, monitor, store, syncTouched);
76068
+ let rNum = rTrim.length > 13 && /^-?[0-9]{1,19}$/.test(rTrim) ? BigInt.asIntN(64, BigInt(rTrim)) : resolveSimpleArithOperand(rTrim, rawState, monitor, store, syncTouched);
76051
76069
  if (rNum === void 0) {
76052
76070
  const rExpr = tryEvalSimpleExpandedArith(rTrim, rawState, monitor, store, syncTouched);
76053
76071
  if (rExpr !== void 0) rNum = Number(rExpr);
76054
76072
  }
76055
76073
  if (rNum === void 0) return void 0;
76074
+ if (typeof lNum !== typeof rNum) {
76075
+ lNum = BigInt(lNum);
76076
+ rNum = BigInt(rNum);
76077
+ }
76056
76078
  let ok;
76057
76079
  switch (expr.operator) {
76058
76080
  case "-eq":
@@ -78501,7 +78523,6 @@ var Runtime = class _Runtime {
78501
78523
  this.budget.tick();
78502
78524
  rawState.substitutionStatus = 0;
78503
78525
  if (rawState.variables._ !== void 0) delete rawState.variables._;
78504
- rawState.lastArgument = fnArgs.length > 0 ? fnArgs[fnArgs.length - 1] : w0Plain;
78505
78526
  const positional = rawState.positional;
78506
78527
  let fnArgsBytes = 0;
78507
78528
  for (let i = 0; i < fnArgs.length; i++) fnArgsBytes += fnArgs[i].length;
@@ -78682,7 +78703,6 @@ var Runtime = class _Runtime {
78682
78703
  this.budget.tick();
78683
78704
  rawState.substitutionStatus = 0;
78684
78705
  if (rawState.variables._ !== void 0) delete rawState.variables._;
78685
- rawState.lastArgument = lastCmdArg;
78686
78706
  rawState.depth++;
78687
78707
  let evalStatus;
78688
78708
  try {
@@ -78691,6 +78711,7 @@ var Runtime = class _Runtime {
78691
78711
  rawState.depth--;
78692
78712
  }
78693
78713
  if (typeof evalStatus === "number") {
78714
+ rawState.lastArgument = lastCmdArg;
78694
78715
  if (cachedUnit.script.lists.length === 0) {
78695
78716
  const activeStore = monitor.store;
78696
78717
  const activeExisting = activeStore?.get("PIPESTATUS");
@@ -78981,6 +79002,7 @@ var Runtime = class _Runtime {
78981
79002
  continue;
78982
79003
  }
78983
79004
  if (part.kind === "variable") {
79005
+ if (stateMonitor(rawState)?.store?.get(part.name)) return false;
78984
79006
  if (this._syncLoopFnCheckDepth > 0 && (part.substring || getArraySelector(part)?.kind === "element")) return false;
78985
79007
  if (part.prefixNames !== void 0) {
78986
79008
  if (part.prefixNames === "@") return false;
@@ -79008,40 +79030,16 @@ var Runtime = class _Runtime {
79008
79030
  if (getArraySelector(part) !== void 0) {
79009
79031
  return false;
79010
79032
  }
79011
- if (part.length || part.substring || part.operator !== void 0) {
79033
+ if (part.substring) return false;
79034
+ if (part.length || part.operator !== void 0) {
79012
79035
  if (this.budget.limits.maxExpansionBytes !== Infinity || rawState.depth >= 32 || rawState.nounset || rawState.nocasematch || byteLocale(rawState.variables) !== false) {
79013
79036
  return false;
79014
79037
  }
79015
79038
  if (part.length) {
79016
- if (part.operator !== void 0 || part.substring) return false;
79017
- } else if (part.substring) {
79018
- if (part.operator !== void 0 || !part.substring.offset.parts.every((p) => p.kind === "text" || p.kind === "variable" && !p.operator && !p.substring && !p.length) || part.substring.length && !part.substring.length.parts.every((p) => p.kind === "text" || p.kind === "variable" && !p.operator && !p.substring && !p.length)) {
79019
- return false;
79020
- }
79021
- } else if (part.operator === "^" || part.operator === "^^" || part.operator === "," || part.operator === ",,") {
79022
- if (part.alternate && part.alternate.parts.length > 0) return false;
79039
+ if (part.operator !== void 0) return false;
79023
79040
  } else if (part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+") {
79024
79041
  if (!part.alternate || !part.alternate.parts.every((p) => p.kind === "text" || p.kind === "arithmetic" || p.kind === "variable" && !p.operator && !p.substring && p.prefixNames !== "@")) return false;
79025
79042
  if (!this.isPureSyncValueWord(part.alternate, rawState, allowAt)) return false;
79026
- } else if (part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") {
79027
- if (!part.alternate || part.alternate.parts.length === 0) return false;
79028
- const q0 = part.alternate.parts[0].quoted;
79029
- const trimOp = part.operator;
79030
- if (!part.alternate.parts.every((p, idx) => p.quoted === q0 && (p.kind === "text" && !p.byteValue && (p.quoted || !hasGlobOrEscape(p.value, !!rawState.extglob) || idx === 0 && (trimOp === "#" || trimOp === "##") && p.value === "*" || idx === part.alternate.parts.length - 1 && (trimOp === "%" || trimOp === "%%") && p.value === "*" || part.alternate.parts.length === 1 && Boolean(tryCompileTrimGlobToRegex(p.value, trimOp, !!rawState.extglob))) || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && (getArraySelector(p) === void 0 || p.name === "BASH_REMATCH" && getArraySelector(p)?.kind === "element" && /^[0-9]{1,2}$/.test(getArraySelector(p).index.decimal)) && isShellIdentifier(p.name)))) {
79031
- return false;
79032
- }
79033
- } else if (part.operator === "/" || part.operator === "//" || part.operator === "/#" || part.operator === "/%") {
79034
- if (!part.alternate || part.alternate.parts.length === 0) return false;
79035
- const q0 = part.alternate.parts[0].quoted;
79036
- const repOp = part.operator;
79037
- if (!part.alternate.parts.every((p) => p.quoted === q0 && (p.kind === "text" && !p.byteValue && (p.quoted || !hasGlobOrEscape(p.value, !!rawState.extglob) || part.alternate.parts.length === 1 && Boolean(tryCompileFixedGlobToRegex(p.value, repOp, !!rawState.extglob))) || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name)))) {
79038
- return false;
79039
- }
79040
- if (part.replacement && part.replacement.parts.length > 0) {
79041
- if (!part.replacement.parts.every((p) => p.kind === "text" && !p.byteValue && !p.value.includes("&") && !p.value.includes("\\") && (p.quoted || !p.value.startsWith("~")) || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name))) {
79042
- return false;
79043
- }
79044
- }
79045
79043
  } else return false;
79046
79044
  }
79047
79045
  continue;
@@ -79110,11 +79108,7 @@ var Runtime = class _Runtime {
79110
79108
  if (w0Plain === "printf") {
79111
79109
  if (!this.isSyncPrintfCallOk(cmd, 1, rawState, this._activePrintfInductionName)) return false;
79112
79110
  } else if (w0Plain === "echo") {
79113
- const firstArg = cmd.words[1];
79114
- if (firstArg) {
79115
- const prefix3 = firstArg.parts.find((part2) => part2.kind !== "text" || part2.value.length > 0);
79116
- if (prefix3?.kind !== "text" || prefix3.value.startsWith("-")) return false;
79117
- }
79111
+ if (!this.isSyncSubEchoCallOk(cmd, rawState)) return false;
79118
79112
  } else if (w0Plain === "dirname" || w0Plain === "basename") {
79119
79113
  const simArgs = [];
79120
79114
  let seenDoubleDash = false;
@@ -79167,10 +79161,10 @@ var Runtime = class _Runtime {
79167
79161
  if ((isNumOp || isStrOp) && safeArgWord(args[0]) && safeArgWord(args[2])) {
79168
79162
  if (isNumOp && checkIntVars) {
79169
79163
  const isGuaranteedIntWord = (w) => {
79170
- if (w.plain !== void 0) return /^-?[0-9]+$/.test(w.plain);
79164
+ if (w.plain !== void 0) return /^-?[0-9]{1,16}$/.test(w.plain);
79171
79165
  if (w.parts.length === 1) {
79172
79166
  const p02 = w.parts[0];
79173
- if (p02.kind === "arithmetic") return true;
79167
+ if (p02.kind === "arithmetic") return false;
79174
79168
  if (p02.kind === "variable" && !p02.indirect && !p02.prefixNames && !p02.substring && !p02.transform && p02.operator === void 0 && getArraySelector(p02) === void 0) {
79175
79169
  if (script2) {
79176
79170
  for (const lst of script2.lists) {
@@ -79178,13 +79172,13 @@ var Runtime = class _Runtime {
79178
79172
  const c0 = pl.commands[0];
79179
79173
  if (c0?.kind === "simple" && c0.words.length === 1) {
79180
79174
  const asg = this.assignment(c0.words[0]);
79181
- if (asg?.name === p02.name && (!asg.value.plain || !/^-?[0-9]+$/.test(asg.value.plain))) return false;
79175
+ if (asg?.name === p02.name && (!asg.value.plain || !/^-?[0-9]{1,16}$/.test(asg.value.plain))) return false;
79182
79176
  }
79183
79177
  }
79184
79178
  }
79185
79179
  }
79186
79180
  const cur = rawState.variables[p02.name];
79187
- return cur === void 0 || /^-?[0-9]+$/.test(cur);
79181
+ return cur === void 0 || /^-?[0-9]{1,16}$/.test(cur);
79188
79182
  }
79189
79183
  }
79190
79184
  return false;
@@ -79274,6 +79268,7 @@ var Runtime = class _Runtime {
79274
79268
  canSyncNestedForWords(words, rawState, io, line) {
79275
79269
  if (words === void 0) return true;
79276
79270
  if (words.length === 0 || words.length > 64) return false;
79271
+ if (words.some((w) => w.parts.some((p) => p.kind === "variable" && (p.substring || p.operator !== void 0 || p.transform)))) return false;
79277
79272
  if (words.length === 1 && this.isQuotedAtWord(words[0])) return true;
79278
79273
  if (words.length === 1) {
79279
79274
  const w0 = words[0];
@@ -79304,8 +79299,9 @@ var Runtime = class _Runtime {
79304
79299
  }
79305
79300
  if (words.length === 1) {
79306
79301
  const w0 = words[0];
79307
- const arrMembers = this.tryExpandSyncArrayMembersWord(w0, rawState, io, line);
79308
- if (arrMembers !== void 0) return arrMembers;
79302
+ if (this.canSyncArrayMembersWord(w0, rawState)) {
79303
+ return this.tryExpandSyncArrayMembersWord(w0, rawState, io, line);
79304
+ }
79309
79305
  const p02 = w0.parts.length === 1 ? w0.parts[0] : w0.parts.length === 2 && w0.parts[0].kind === "text" && w0.parts[0].value === "" ? w0.parts[1] : void 0;
79310
79306
  if (p02 && !p02.quoted && (rawState.variables.IFS === void 0 || rawState.variables.IFS === " \n") && !rawState.noglob) {
79311
79307
  if (p02.kind === "variable" && !p02.indirect && !p02.prefixNames && !p02.length && !p02.transform && getArraySelector(p02) === void 0) {
@@ -79480,6 +79476,35 @@ var Runtime = class _Runtime {
79480
79476
  }
79481
79477
  return { ifsWord, varNames, isBareReply, inputWord: r0.target, ...delimChar !== void 0 ? { delimChar } : {}, ...maxChars !== void 0 ? { maxChars } : {}, ...exactChars !== void 0 ? { exactChars } : {} };
79482
79478
  }
79479
+ canSyncLoopConditionalOperands(expression, rawState, allowRegex = true) {
79480
+ const checkLeaf = (e) => {
79481
+ if (e.kind === "nonempty") return this.isPureSyncValueWord(e.operand, rawState);
79482
+ if (e.kind === "unary") return (e.operator === "-n" || e.operator === "-z" || e.operator === "-v" || syncConditionalFileUnaryOps.has(e.operator) && this._isMemoryBackingFs && this.canFastMemoryRedirect && this.budget.limits.maxFileSystemOperations >= 1e3 && (this._fileWrites === void 0 || this._fileWrites.size === 0) && (this._outputFiles === void 0 || this._outputFiles.size === 0)) && this.isPureSyncValueWord(e.operand, rawState);
79483
+ if (e.kind === "binary") {
79484
+ if (e.operator === "=~") {
79485
+ if (!allowRegex) return false;
79486
+ const patInfo = this.extractSimpleErePattern(e.right, rawState);
79487
+ if (patInfo?.isVar) return false;
79488
+ 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") && !(stateMonitor(rawState)?.store ?? requireArrays(rawState))?.watches.has("BASH_REMATCH");
79489
+ }
79490
+ 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));
79491
+ }
79492
+ if (e.kind === "not") return checkLeaf(e.operand);
79493
+ if (e.kind === "and" || e.kind === "or") return checkLeaf(e.left) && checkLeaf(e.right);
79494
+ return false;
79495
+ };
79496
+ return checkLeaf(expression);
79497
+ }
79498
+ isSyncSubEchoCallOk(cmd, rawState) {
79499
+ if (!this.isSyncEchoCallOk(cmd, rawState)) return false;
79500
+ if (!cmd.words.slice(1).every((w) => w.parts.length > 0 && w.parts.every(
79501
+ (part) => part.quoted || part.kind === "text" && part.value.length > 0 && !part.value.includes(" ") && !part.value.includes(" ") && !part.value.includes("\n") && !part.value.includes("{") && !hasGlobOrEscape(part.value, true)
79502
+ ))) return false;
79503
+ const firstArg = cmd.words[1];
79504
+ if (!firstArg) return true;
79505
+ const prefix3 = firstArg.parts.find((part) => part.kind !== "text" || part.value.length > 0);
79506
+ return prefix3?.kind === "text" && !prefix3.value.startsWith("-");
79507
+ }
79483
79508
  isPureSyncSubIfOrCase(cmd, rawState) {
79484
79509
  if (cmd.redirects.length !== 0) return false;
79485
79510
  const isSimpleEchoOrPrintf = (s) => {
@@ -79489,7 +79514,7 @@ var Runtime = class _Runtime {
79489
79514
  const sc = pl.commands[0];
79490
79515
  if (sc.kind !== "simple" || sc.redirects.length !== 0 || sc.words.length === 0) return false;
79491
79516
  const w0 = sc.words[0]?.plain;
79492
- if (w0 === "echo") return this.isSyncEchoCallOk(sc, rawState);
79517
+ if (w0 === "echo") return this.isSyncSubEchoCallOk(sc, rawState);
79493
79518
  if (w0 === "printf" && sc.words[1]?.plain !== "-v") return this.isSyncPrintfCallOk(sc, 1, rawState);
79494
79519
  return false;
79495
79520
  };
@@ -79503,9 +79528,10 @@ var Runtime = class _Runtime {
79503
79528
  if (bc.redirects.length !== 0 || bc.expression.error || bc.expression.hasMutation || bc.expression.hasSubscript || !isSafeSmiProgram(bc.expression) || !this.canSyncArithmeticWithoutFault(bc.expression.tree, rawState, bc.line ?? 1)) return false;
79504
79529
  } else if (bc.kind === "conditional") {
79505
79530
  if (bc.redirects.length !== 0 || rawState.nocasematch || byteLocale(rawState.variables) || !this.canSyncConditional(bc.expression, 0, rawState, true)) return false;
79506
- if (bc.expression.kind === "binary" && bc.expression.operator === "=~") return false;
79507
- } else if (!this.extractPosixBracketCondExpr(bc, rawState, true, br.body)) {
79508
- return false;
79531
+ if (!this.canSyncLoopConditionalOperands(bc.expression, rawState, false)) return false;
79532
+ } else {
79533
+ const expression = this.extractPosixBracketCondExpr(bc, rawState, true, br.body);
79534
+ if (!expression || !this.canSyncLoopConditionalOperands(expression, rawState, false)) return false;
79509
79535
  }
79510
79536
  if (!isSimpleEchoOrPrintf(br.body)) return false;
79511
79537
  }
@@ -79533,22 +79559,7 @@ var Runtime = class _Runtime {
79533
79559
  const cmd = pipeline.commands[0];
79534
79560
  const canSyncLoopCondCmd = (c) => {
79535
79561
  if (c.redirects.length !== 0 || rawState.nocasematch || byteLocale(rawState.variables) || !this.canSyncConditional(c.expression, 0, rawState, true)) return false;
79536
- const checkLeaf = (e) => {
79537
- if (e.kind === "nonempty") return this.isPureSyncValueWord(e.operand, rawState);
79538
- if (e.kind === "unary") return (e.operator === "-n" || e.operator === "-z" || e.operator === "-v" || syncConditionalFileUnaryOps.has(e.operator) && this._isMemoryBackingFs && this.canFastMemoryRedirect && this.budget.limits.maxFileSystemOperations >= 1e3 && (this._fileWrites === void 0 || this._fileWrites.size === 0) && (this._outputFiles === void 0 || this._outputFiles.size === 0)) && this.isPureSyncValueWord(e.operand, rawState);
79539
- if (e.kind === "binary") {
79540
- if (e.operator === "=~") {
79541
- const patInfo = this.extractSimpleErePattern(e.right, rawState);
79542
- if (patInfo?.isVar) return false;
79543
- 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");
79544
- }
79545
- 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));
79546
- }
79547
- if (e.kind === "not") return checkLeaf(e.operand);
79548
- if (e.kind === "and" || e.kind === "or") return checkLeaf(e.left) && checkLeaf(e.right);
79549
- return false;
79550
- };
79551
- return checkLeaf(c.expression);
79562
+ return this.canSyncLoopConditionalOperands(c.expression, rawState);
79552
79563
  };
79553
79564
  if (cmd.kind === "arithmetic") {
79554
79565
  if (cmd.redirects.length === 0) {
@@ -79668,7 +79679,11 @@ var Runtime = class _Runtime {
79668
79679
  const w0DevPlain = cmd.words[0].plain;
79669
79680
  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))) {
79670
79681
  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));
79671
- 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]));
79682
+ const devOperandOk = (w) => {
79683
+ const first = w.parts[0];
79684
+ return first?.kind === "text" && first.value.length > 0 && !first.value.startsWith("-") && devWordOk(w);
79685
+ };
79686
+ 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]));
79672
79687
  if (devShapeOk) continue;
79673
79688
  }
79674
79689
  if (this.extractSyncReadHereStringSpec(cmd, rawState) !== void 0) continue;
@@ -79776,7 +79791,7 @@ var Runtime = class _Runtime {
79776
79791
  return false;
79777
79792
  }
79778
79793
  const assignment = this.assignment(w0);
79779
- if (assignment && (assignment.name === "LC_ALL" || assignment.name === "LC_CTYPE" || assignment.name === "LC_COLLATE" || assignment.name === "LANG")) return false;
79794
+ if (assignment && (assignment.name === "IFS" || assignment.name === "LC_ALL" || assignment.name === "LC_CTYPE" || assignment.name === "LC_COLLATE" || assignment.name === "LANG")) return false;
79780
79795
  if (!assignment || assignment.append && this.budget.limits.maxExpansionBytes !== Infinity || assignment.name === "OPTIND" || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || rawState.readonlyVariables?.has(assignment.name) || rawState.variableAttributes?.get(assignment.name) || store?.get(assignment.name) || !this.isPureSyncValueWord(assignment.value, rawState)) {
79781
79796
  return false;
79782
79797
  }
@@ -80674,7 +80689,7 @@ var Runtime = class _Runtime {
80674
80689
  if (rawState.allexport) monitor.proxy.exported.add(varName);
80675
80690
  } else {
80676
80691
  monitor.values.invalidate(varName);
80677
- monitor.proxy.exported.delete(varName);
80692
+ if (!rawState.exported.has(varName)) monitor.proxy.exported.delete(varName);
80678
80693
  }
80679
80694
  }
80680
80695
  }
@@ -81013,7 +81028,7 @@ var Runtime = class _Runtime {
81013
81028
  if (rawState.allexport) monitor.proxy.exported.add(varName);
81014
81029
  } else {
81015
81030
  monitor.values.invalidate(varName);
81016
- monitor.proxy.exported.delete(varName);
81031
+ if (!rawState.exported.has(varName)) monitor.proxy.exported.delete(varName);
81017
81032
  }
81018
81033
  }
81019
81034
  }
@@ -81500,15 +81515,23 @@ ${s1}
81500
81515
  return false;
81501
81516
  }
81502
81517
  if (command7.kind !== "simple" || hasShellFunction(rawState, command7.words[0]?.plain ?? "") || command7.words.some((word) => getArrayAssignment(word) !== void 0)) return false;
81503
- const w0 = command7.words[0]?.plain;
81518
+ let commandIndex = 0;
81519
+ while (commandIndex < command7.words.length && this.assignment(command7.words[commandIndex])) commandIndex++;
81520
+ const commandWord = command7.words[commandIndex];
81521
+ if (!commandWord?.parts.every((part) => part.kind === "text")) return false;
81522
+ const w0 = commandWord.parts.map((part) => part.kind === "text" ? part.value : "").join("");
81523
+ if (w0 === "read") return false;
81524
+ if (w0 === "printf") {
81525
+ const option = command7.words[commandIndex + 1];
81526
+ if (!option?.parts.every((part) => part.kind === "text")) return false;
81527
+ if (option.parts.map((part) => part.kind === "text" ? part.value : "").join("") === "-v") return false;
81528
+ }
81504
81529
  if (w0 === "let" || w0 === "declare" || w0 === "typeset" || w0 === "local" || w0 === "export" || w0 === "unset" || w0 === "mapfile" || w0 === "readarray") return false;
81505
81530
  if (inductionName !== void 0) {
81506
81531
  if (command7.words.some((w) => {
81507
81532
  const p02 = w.parts[0];
81508
81533
  return p02?.kind === "text" && !p02.quoted && (p02.value.startsWith(inductionName + "=") || p02.value.startsWith(inductionName + "+="));
81509
81534
  })) return false;
81510
- 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;
81511
- if (w0 === "printf" && command7.words[1]?.plain === "-v" && command7.words[2]?.plain === inductionName) return false;
81512
81535
  }
81513
81536
  for (const word of [...command7.words, ...command7.redirects.map((redirect) => redirect.target)]) for (const part of word.parts) {
81514
81537
  if (part.kind === "text") continue;
@@ -81726,6 +81749,7 @@ ${s1}
81726
81749
  execSyncLocalDeclStep(decl, rawState, io, monitor, touched, line) {
81727
81750
  const locals = (decl.kind === "local" || decl.kind === "declare") && rawState.locals.length > 0 ? rawState.locals[rawState.locals.length - 1] : void 0;
81728
81751
  let lastArg = decl.kind;
81752
+ 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));
81729
81753
  for (let i = 0; i < decl.items.length; i++) {
81730
81754
  const item = decl.items[i];
81731
81755
  const isNewLocal = locals ? !locals.has(item.name) : false;
@@ -81741,7 +81765,7 @@ ${s1}
81741
81765
  touched.add(item.name);
81742
81766
  }
81743
81767
  if (item.value !== void 0) {
81744
- const val = this.fastValueWord(item.value, rawState, io, false, false, false, rawState.braceexpand !== false, 0, line);
81768
+ const val = values[i];
81745
81769
  if (item.append) {
81746
81770
  const curRaw = rawState.variables[item.name];
81747
81771
  const curStr = curRaw === void 0 ? "" : touched.has(item.name) ? curRaw : monitor.values.get(item.name, curRaw) ?? curRaw;
@@ -81750,7 +81774,7 @@ ${s1}
81750
81774
  rawState.variables[item.name] = val;
81751
81775
  }
81752
81776
  touched.add(item.name);
81753
- lastArg = `${item.name}=${rawState.variables[item.name]}`;
81777
+ lastArg = `${item.name}${item.append ? "+=" : "="}${val}`;
81754
81778
  } else {
81755
81779
  lastArg = item.name;
81756
81780
  }
@@ -81835,7 +81859,22 @@ ${s1}
81835
81859
  this._syncStdoutBatch += text3;
81836
81860
  if (this._syncStdoutBatch.length >= 8192) this.flushSyncStdoutBatch(io);
81837
81861
  }
81862
+ runSyncDiscardStep(step, rawState, io) {
81863
+ this.budget.fileSystemOperation();
81864
+ const args = step.discardWords.map((word) => this.fastValueWord(word, rawState, io, false, false, false, false, 0, step.line));
81865
+ const cmdName = step.cmd.words[0].plain;
81866
+ let output2;
81867
+ if (cmdName === "pwd") output2 = rawState.variables.PWD ?? rawState.cwd;
81868
+ else if (cmdName === "echo") output2 = args[0];
81869
+ else if (cmdName === "dirname") output2 = this.evalSyncDirname(args);
81870
+ else output2 = this.evalSyncBasename(step.discardSuffix === void 0 ? args : ["-s", step.discardSuffix, ...args]);
81871
+ const bytes2 = shellValueByteLength(output2) + 1;
81872
+ if (this.budget.bytes + bytes2 > this.budget.maxOutputBytesSmi && bytes2 > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
81873
+ this.budget.bytes += bytes2;
81874
+ return args[args.length - 1] ?? cmdName;
81875
+ }
81838
81876
  writeSyncRedirectStep(step, encoded2, append, mode, rawState, io) {
81877
+ if (this.budget.bytes + encoded2.byteLength > this.budget.maxOutputBytesSmi && encoded2.byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
81839
81878
  encoded2 = encoded2.slice();
81840
81879
  if (step.targetDirPrefix !== void 0 && step.targetNamePrefix !== void 0) {
81841
81880
  const fileName = this.evalSyncRedirectSuffix(step.targetWord, step.targetDirPrefix, step.targetNamePrefix, rawState, io);
@@ -81988,27 +82027,7 @@ ${s1}
81988
82027
  touched.add(step.name);
81989
82028
  lastArg = pLastArg;
81990
82029
  } else if (step.isDiscardDevNull && step.discardWords !== void 0) {
81991
- this.budget.fileSystemOperation();
81992
- const dw = step.discardWords;
81993
- const cmdName = step.cmd.words[0].plain;
81994
- let evalFirst = "";
81995
- let evalLast = cmdName;
81996
- for (let wi = 0; wi < dw.length; wi++) {
81997
- const v = this.fastValueWord(dw[wi], rawState, io, false, false, false, false, 0, step.line);
81998
- if (wi === 0) evalFirst = v;
81999
- evalLast = v;
82000
- }
82001
- let outChars = 0;
82002
- if (cmdName === "pwd") outChars = (rawState.variables.PWD ?? rawState.cwd).length + 1;
82003
- else if (cmdName === "echo") outChars = evalFirst.length + 1;
82004
- else if (cmdName === "dirname") outChars = dirname(evalFirst).length + 1;
82005
- else if (cmdName === "basename") {
82006
- const sfx = step.discardSuffix !== void 0 ? step.discardSuffix : dw.length === 2 ? evalLast : void 0;
82007
- const baseStr = /^\/+$/u.test(evalFirst) ? "/" : basename(evalFirst);
82008
- outChars = (sfx && baseStr !== sfx && baseStr.endsWith(sfx) ? baseStr.length - sfx.length : baseStr.length) + 1;
82009
- }
82010
- this.budget.bytes += outChars;
82011
- lastArg = step.discardSuffix !== void 0 ? evalLast : dw.length > 0 ? evalLast : cmdName;
82030
+ lastArg = this.runSyncDiscardStep(step, rawState, io);
82012
82031
  } else if (step.name !== void 0 && step.value !== void 0) {
82013
82032
  rawState.substitutionStatus = 0;
82014
82033
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -82497,27 +82516,7 @@ ${s1}
82497
82516
  touched.add(step.name);
82498
82517
  lastArg = pLastArg;
82499
82518
  } else if (step.isDiscardDevNull && step.discardWords !== void 0) {
82500
- this.budget.fileSystemOperation();
82501
- const dw = step.discardWords;
82502
- const cmdName = step.cmd.words[0].plain;
82503
- let evalFirst = "";
82504
- let evalLast = cmdName;
82505
- for (let wi = 0; wi < dw.length; wi++) {
82506
- const v = this.fastValueWord(dw[wi], rawState, io, false, false, false, false, 0, step.line);
82507
- if (wi === 0) evalFirst = v;
82508
- evalLast = v;
82509
- }
82510
- let outChars = 0;
82511
- if (cmdName === "pwd") outChars = (rawState.variables.PWD ?? rawState.cwd).length + 1;
82512
- else if (cmdName === "echo") outChars = evalFirst.length + 1;
82513
- else if (cmdName === "dirname") outChars = dirname(evalFirst).length + 1;
82514
- else if (cmdName === "basename") {
82515
- const sfx = step.discardSuffix !== void 0 ? step.discardSuffix : dw.length === 2 ? evalLast : void 0;
82516
- const baseStr = /^\/+$/u.test(evalFirst) ? "/" : basename(evalFirst);
82517
- outChars = (sfx && baseStr !== sfx && baseStr.endsWith(sfx) ? baseStr.length - sfx.length : baseStr.length) + 1;
82518
- }
82519
- this.budget.bytes += outChars;
82520
- lastArg = step.discardSuffix !== void 0 ? evalLast : dw.length > 0 ? evalLast : cmdName;
82519
+ lastArg = this.runSyncDiscardStep(step, rawState, io);
82521
82520
  } else if (step.name !== void 0 && step.value !== void 0) {
82522
82521
  rawState.substitutionStatus = 0;
82523
82522
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -82662,27 +82661,7 @@ ${s1}
82662
82661
  touched.add(step.name);
82663
82662
  lastArg = pLastArg;
82664
82663
  } else if (step.isDiscardDevNull && step.discardWords !== void 0) {
82665
- this.budget.fileSystemOperation();
82666
- const dw = step.discardWords;
82667
- const cmdName = step.cmd.words[0].plain;
82668
- let evalFirst = "";
82669
- let evalLast = cmdName;
82670
- for (let wi = 0; wi < dw.length; wi++) {
82671
- const v = this.fastValueWord(dw[wi], rawState, io, false, false, false, false, 0, step.line);
82672
- if (wi === 0) evalFirst = v;
82673
- evalLast = v;
82674
- }
82675
- let outChars = 0;
82676
- if (cmdName === "pwd") outChars = (rawState.variables.PWD ?? rawState.cwd).length + 1;
82677
- else if (cmdName === "echo") outChars = evalFirst.length + 1;
82678
- else if (cmdName === "dirname") outChars = dirname(evalFirst).length + 1;
82679
- else if (cmdName === "basename") {
82680
- const sfx = step.discardSuffix !== void 0 ? step.discardSuffix : dw.length === 2 ? evalLast : void 0;
82681
- const baseStr = /^\/+$/u.test(evalFirst) ? "/" : basename(evalFirst);
82682
- outChars = (sfx && baseStr !== sfx && baseStr.endsWith(sfx) ? baseStr.length - sfx.length : baseStr.length) + 1;
82683
- }
82684
- this.budget.bytes += outChars;
82685
- lastArg = step.discardSuffix !== void 0 ? evalLast : dw.length > 0 ? evalLast : cmdName;
82664
+ lastArg = this.runSyncDiscardStep(step, rawState, io);
82686
82665
  } else if (step.name !== void 0 && step.value !== void 0) {
82687
82666
  rawState.substitutionStatus = 0;
82688
82667
  const val = this.fastValueWord(step.value, rawState, io, false, false, false, false, 0, step.line);
@@ -83491,8 +83470,6 @@ ${s1}
83491
83470
  state.substitutionStatus = 0;
83492
83471
  const rawState = stateMonitor(state)?.raw ?? state;
83493
83472
  if (rawState.variables._ !== void 0) delete rawState.variables._;
83494
- rawState.lastArgument = wordValues[wordValues.length - 1] ?? w0Plain;
83495
- state.lastArgument = rawState.lastArgument;
83496
83473
  return await this.dispatchFastFunction(w0Plain, state.functions.get(w0Plain), wordValues.slice(1), state, originalIO);
83497
83474
  }
83498
83475
  }
@@ -84184,7 +84161,7 @@ ${s1}
84184
84161
  (0, diagnostics_exports.publicDiagnosticMessage)(failure, this.budget.onInternalError);
84185
84162
  }
84186
84163
  }
84187
- if (error instanceof ExpansionFailure && !(error instanceof SubstringRangeFailure && state.loopDepth > 0) || error instanceof BraceExpansionFailure) throw completedExit(error instanceof ParameterExpansionFailure && !state.isolated ? 127 : 1);
84164
+ if (error instanceof ExpansionFailure || error instanceof BraceExpansionFailure) throw completedExit(error instanceof ParameterExpansionFailure && !state.isolated ? 127 : 1);
84188
84165
  if (error instanceof FatalCommandFailure) throw completedExit(error.status);
84189
84166
  if (error instanceof DiscardCommandFailure) throw completedExit(error.status, "discard");
84190
84167
  const status2 = outputTracker.outputStatus ?? (error instanceof CommandFailure2 ? error.status : 1);
@@ -84603,8 +84580,10 @@ ${s1}
84603
84580
  }
84604
84581
  const rawState = stateMonitor(state)?.raw ?? state;
84605
84582
  if (!state._readOnlyStage && rawState.variables._ !== void 0) delete rawState.variables._;
84606
- rawState.lastArgument = words.length > 0 ? words[words.length - 1] : "";
84607
- state.lastArgument = rawState.lastArgument;
84583
+ if (!state.functions.has(words[0] ?? "") && !["eval", ".", "source"].includes(words[declarationIndex] ?? "")) {
84584
+ rawState.lastArgument = words.at(-1) ?? "";
84585
+ state.lastArgument = rawState.lastArgument;
84586
+ }
84608
84587
  if (!words.length) return state.substitutionStatus;
84609
84588
  const args = words.slice(1);
84610
84589
  const argValues = allStrings ? args : wordValues.slice(1);
@@ -84828,8 +84807,10 @@ ${s1}
84828
84807
  if (!snapshotScope) {
84829
84808
  const rawState = stateMonitor(state)?.raw ?? state;
84830
84809
  if (rawState.variables._ !== void 0 && !assignments2.some((assignment) => assignment.name === "_")) delete rawState.variables._;
84831
- rawState.lastArgument = words.length > 0 ? words[words.length - 1] : "";
84832
- state.lastArgument = rawState.lastArgument;
84810
+ if (!functionCommand && !["eval", ".", "source"].includes(words[declarationIndex] ?? "")) {
84811
+ rawState.lastArgument = words.at(-1) ?? "";
84812
+ state.lastArgument = rawState.lastArgument;
84813
+ }
84833
84814
  }
84834
84815
  if (!words.length) return state.substitutionStatus;
84835
84816
  const args = words.slice(1);
@@ -85633,8 +85614,16 @@ ${s1}
85633
85614
  return { exitCode: status2 };
85634
85615
  }
85635
85616
  if (context3.command === "command" || context3.command === "builtin" || context3.command === "type") return { exitCode: await this.discoveryBuiltin(context3, state, io, assignments2, defaultPath) };
85636
- if (context3.command === "." || context3.command === "source") return { exitCode: await this.sourceBuiltin(context3, state, { ...io, ...context3 }, special) };
85637
- if (context3.command === "eval") return { exitCode: await this.evalBuiltin(context3, state, { ...io, ...context3 }, special) };
85617
+ if (context3.command === "." || context3.command === "source") {
85618
+ const exitCode = await this.sourceBuiltin(context3, state, { ...io, ...context3 }, special);
85619
+ state.lastArgument = context3.args.at(-1) ?? context3.command;
85620
+ return { exitCode };
85621
+ }
85622
+ if (context3.command === "eval") {
85623
+ const exitCode = await this.evalBuiltin(context3, state, { ...io, ...context3 }, special);
85624
+ state.lastArgument = context3.args.at(-1) ?? context3.command;
85625
+ return { exitCode };
85626
+ }
85638
85627
  const builtinWork = this.builtin({ ...context3, [declarationArrays]: io[declarationArrays] }, state, assignments2, (error, diagnostic4) => {
85639
85628
  builtinFailure = { error, diagnostic: diagnostic4 };
85640
85629
  }, bypassFunctions);
@@ -89256,7 +89245,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
89256
89245
  if (expression.length) {
89257
89246
  const length = await arithmetic2(expression.length);
89258
89247
  end = length.value < 0n ? size + length.value : offset + length.value;
89259
- if (end < offset) throw new SubstringRangeFailure(`${length.source}: substring expression < 0`, line);
89248
+ if (end < offset) throw new ExpansionFailure(`${length.source}: substring expression < 0`, line);
89260
89249
  if (end > size) end = size;
89261
89250
  }
89262
89251
  this.signal.throwIfAborted();
@@ -90241,6 +90230,11 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90241
90230
  return out;
90242
90231
  }
90243
90232
  evalSyncTr(input3, opArgs) {
90233
+ for (const value2 of opArgs) {
90234
+ for (let i = 0; i < value2.length; i++) {
90235
+ if (value2.charCodeAt(i) >= 128) return void 0;
90236
+ }
90237
+ }
90244
90238
  let idx = 0;
90245
90239
  let flagC = false;
90246
90240
  let flagD = false;
@@ -91120,6 +91114,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91120
91114
  const anchorEnd = core1.endsWith("$");
91121
91115
  const core = anchorEnd ? core1.slice(0, -1) : core1;
91122
91116
  if (core.length === 0 && !anchorStart && !anchorEnd) return void 0;
91117
+ if (core.includes("[:") || core.includes("[.") || core.includes("[=") || core.includes("[]") || core.includes("[^]") || isExtended && core.includes("|")) return void 0;
91123
91118
  let reSrc;
91124
91119
  if (/^[a-zA-Z0-9_ :;,=-]*$/.test(core)) {
91125
91120
  if (/\\[1-9]/.test(rep)) return void 0;
@@ -91282,7 +91277,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91282
91277
  const isExtended = mode.includes("E");
91283
91278
  const isFixed = mode.includes("F");
91284
91279
  const isOnlyMatching = mode.includes("o");
91285
- if (isExtended && !isFixed && rawPatterns.some((pattern) => pattern.includes("[:") || pattern.includes("[.") || pattern.includes("[="))) return void 0;
91280
+ if (!isFixed && rawPatterns.some((pattern) => pattern.includes("[:") || pattern.includes("[.") || pattern.includes("[=") || pattern.includes("[]") || pattern.includes("[^]") || isExtended && pattern.includes("[") && pattern.includes("|"))) return void 0;
91286
91281
  if (isCount && (isLineNumber || isOnlyMatching || beforeCtx > 0 || afterCtx > 0)) return void 0;
91287
91282
  if (isOnlyMatching && (beforeCtx > 0 || afterCtx > 0)) return void 0;
91288
91283
  if (isOnlyMatching) {
@@ -91305,15 +91300,18 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91305
91300
  }
91306
91301
  if (!re) return void 0;
91307
91302
  const out = [];
91303
+ let matched2 = false;
91308
91304
  for (let li = 0; li < rawLines.length; li++) {
91309
91305
  const matches2 = rawLines[li].match(re);
91310
91306
  if (matches2) {
91307
+ matched2 = true;
91311
91308
  for (let mi = 0; mi < matches2.length; mi++) {
91309
+ if (matches2[mi].length === 0) continue;
91312
91310
  out.push(isLineNumber ? `${li + 1}:${matches2[mi]}` : matches2[mi]);
91313
91311
  }
91314
91312
  }
91315
91313
  }
91316
- return { lines: out, status: out.length > 0 ? 0 : 1 };
91314
+ return { lines: out, status: matched2 ? 0 : 1 };
91317
91315
  }
91318
91316
  if (isExtended && isFixed) return void 0;
91319
91317
  const branches = [];
@@ -91864,7 +91862,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
91864
91862
  const out = [];
91865
91863
  let curStyle = bodyStyle;
91866
91864
  let num = start;
91867
- const unnumberedPrefix = " ".repeat(width + sep.length);
91865
+ const unnumberedPrefix = " ".repeat(width + shellValueByteLength(sep));
91868
91866
  for (let i = 0; i < rawLines.length; i++) {
91869
91867
  const l = rawLines[i];
91870
91868
  if (l === "\\:" || l === "\\:\\:" || l === "\\:\\:\\:") {
@@ -92002,7 +92000,9 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92002
92000
  const units = "KMGTPEZY";
92003
92001
  const out = [];
92004
92002
  for (let i = 0; i < rawLines.length; i++) {
92005
- const raw = rawLines[i].trim();
92003
+ const line = rawLines[i];
92004
+ const raw = line.trim();
92005
+ if (line !== raw) return void 0;
92006
92006
  if (raw.length === 0) {
92007
92007
  out.push("");
92008
92008
  continue;
@@ -92270,7 +92270,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92270
92270
  if (arg === "-L" || arg === "--max-line-length") return "-L";
92271
92271
  return void 0;
92272
92272
  }
92273
- evalSyncUniq(rawLines, opArgs) {
92273
+ evalSyncUniq(rawLines, opArgs, isByteLocale = false) {
92274
92274
  let ignoreCase = false;
92275
92275
  let hasCount = false;
92276
92276
  let onlyRepeated = false;
@@ -92309,6 +92309,18 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92309
92309
  return void 0;
92310
92310
  }
92311
92311
  }
92312
+ if (isByteLocale && (skipChars !== 0 || checkChars !== Infinity) && rawLines.some((line) => {
92313
+ for (let i = 0; i < line.length; i++) if (line.charCodeAt(i) > 127) return true;
92314
+ return false;
92315
+ })) return void 0;
92316
+ const foldAscii = (value2) => {
92317
+ let folded = "";
92318
+ for (let i = 0; i < value2.length; i++) {
92319
+ const code = value2.charCodeAt(i);
92320
+ folded += code >= 97 && code <= 122 ? String.fromCharCode(code - 32) : value2[i];
92321
+ }
92322
+ return folded;
92323
+ };
92312
92324
  const keyOf = (l) => {
92313
92325
  let offset = 0;
92314
92326
  for (let f = 0; f < skipFields; f++) {
@@ -92317,11 +92329,11 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92317
92329
  }
92318
92330
  if (skipChars === 0 && checkChars === Infinity) {
92319
92331
  const sub2 = l.slice(offset);
92320
- return ignoreCase ? sub2.toLowerCase() : sub2;
92332
+ return ignoreCase ? foldAscii(sub2) : sub2;
92321
92333
  }
92322
92334
  const chars = Array.from(l.slice(offset));
92323
92335
  const sub = (checkChars === Infinity ? chars.slice(skipChars) : chars.slice(skipChars, skipChars + checkChars)).join("");
92324
- return ignoreCase ? sub.toLowerCase() : sub;
92336
+ return ignoreCase ? foldAscii(sub) : sub;
92325
92337
  };
92326
92338
  const outLines = [];
92327
92339
  let uIdx = 0;
@@ -92341,6 +92353,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92341
92353
  return this.evalSyncSort(rawLines, flag !== void 0 ? [flag] : [], false) ?? [...rawLines];
92342
92354
  }
92343
92355
  translateSyncTr(input3, set1Spec, set2Spec, truncateSet1 = false) {
92356
+ if (set2Spec.includes("[:") && !(set1Spec === "[:lower:]" && set2Spec === "[:upper:]") && !(set1Spec === "[:upper:]" && set2Spec === "[:lower:]")) return void 0;
92344
92357
  if ((set1Spec === "a-z" || set1Spec === "[:lower:]") && (set2Spec === "A-Z" || set2Spec === "[:upper:]")) {
92345
92358
  return input3.replace(/[a-z]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 32));
92346
92359
  }
@@ -92616,7 +92629,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92616
92629
  const firstName = stageNames[sIdx];
92617
92630
  const extDef = stageDefs[sIdx];
92618
92631
  const stageArgs = stageArgsList[sIdx];
92619
- const nextBuf = (index & 1) === 0 ? sharedSyncPipeBuf0 : sharedSyncPipeBuf1;
92632
+ let nextBuf = (index & 1) === 0 ? sharedSyncPipeBuf0 : sharedSyncPipeBuf1;
92620
92633
  const isInlineCutField = firstName === "cut";
92621
92634
  const isInlineTr = firstName === "tr";
92622
92635
  const isInlineAwk = firstName === "awk";
@@ -92644,6 +92657,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92644
92657
  const nextTotalBytes2 = this.budget.bytes + sub.byteLength;
92645
92658
  if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && sub.byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
92646
92659
  this.budget.bytes = nextTotalBytes2;
92660
+ if (sub.byteLength > nextBuf.byteLength) nextBuf = new Uint8Array(sub.byteLength);
92647
92661
  nextBuf.set(sub, 0);
92648
92662
  prevBuf = nextBuf;
92649
92663
  prevLen = sub.byteLength;
@@ -92663,8 +92677,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92663
92677
  for (let k = 0; k < inStr.length; k++) if (inStr.charCodeAt(k) === 10) nl++;
92664
92678
  outLines = [String(nl)];
92665
92679
  } else if (stageArgs[0] === "-w") {
92666
- const trimmed = inStr.trim();
92667
- outLines = [String(trimmed.length === 0 ? 0 : trimmed.split(/[ \t\n\r\f\v]+/).length)];
92680
+ if (!byteLocale(rawState.variables) && prevBuf.subarray(0, prevLen).some((byte) => byte > 127)) return void 0;
92681
+ outLines = [String(inStr.split(/[ \t\n\r\f\v]+/).filter(Boolean).length)];
92668
92682
  } else if (stageArgs[0] === "-m") {
92669
92683
  outLines = [String(byteLocale(rawState.variables) ? prevLen : Array.from(inStr).length)];
92670
92684
  } else if (stageArgs[0] === "-L") {
@@ -92680,10 +92694,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92680
92694
  const transformed = this.evalSyncTr(inStr, stageArgs);
92681
92695
  if (transformed === void 0) return void 0;
92682
92696
  const outByteLen2 = shellValueByteLength(transformed);
92683
- if (outByteLen2 > nextBuf.byteLength) return void 0;
92684
92697
  const nextTotalBytes2 = this.budget.bytes + outByteLen2;
92685
92698
  if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && outByteLen2 > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
92686
92699
  this.budget.bytes = nextTotalBytes2;
92700
+ if (outByteLen2 > nextBuf.byteLength) nextBuf = new Uint8Array(outByteLen2);
92687
92701
  const written2 = transformed.length === 0 ? 0 : fastSharedTextEncoder.encodeInto(transformed, nextBuf).written;
92688
92702
  prevBuf = nextBuf;
92689
92703
  prevLen = written2;
@@ -92691,7 +92705,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92691
92705
  } else if (isInlineSort) {
92692
92706
  outLines = this.evalSyncSort(rawLines, stageArgs, false) ?? [];
92693
92707
  } else if (isInlineUniq) {
92694
- const uniqRes = this.evalSyncUniq(rawLines, stageArgs);
92708
+ const uniqRes = this.evalSyncUniq(rawLines, stageArgs, byteLocale(rawState.variables));
92695
92709
  if (uniqRes === void 0) return void 0;
92696
92710
  outLines = uniqRes;
92697
92711
  } else if (inlineSedMatch) {
@@ -92710,8 +92724,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92710
92724
  if (stageStatus !== 0) failureStatus = stageStatus;
92711
92725
  outLines = grepRes.lines;
92712
92726
  } else if (isInlineTac) {
92713
- if (inStr.length > 0 && !inStr.endsWith("\n")) return void 0;
92714
92727
  outLines = [...rawLines].reverse();
92728
+ if (!inStr.endsWith("\n") && outLines.length > 1) {
92729
+ outLines.splice(0, 2, outLines[0] + outLines[1]);
92730
+ }
92715
92731
  } else if (isInlineNl) {
92716
92732
  const nlRes = this.evalSyncNl(rawLines, stageArgs);
92717
92733
  if (nlRes === void 0) return void 0;
@@ -92732,10 +92748,11 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92732
92748
  const cleaned = inStr.replace(/[ \t\r\n]+/g, "");
92733
92749
  if (cleaned.length % 4 !== 0 || cleaned.length > 0 && !/^[A-Za-z0-9+/]+={0,2}$/.test(cleaned)) return void 0;
92734
92750
  const decoded = this.syncBase64DecodeBytes(cleaned);
92735
- if (decoded.some((byte) => byte === 0 || byte >= 128) || decoded.byteLength > nextBuf.byteLength) return void 0;
92751
+ if (decoded.some((byte) => byte === 0 || byte >= 128)) return void 0;
92736
92752
  const nextTotalBytes2 = this.budget.bytes + decoded.byteLength;
92737
92753
  if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && decoded.byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
92738
92754
  this.budget.bytes = nextTotalBytes2;
92755
+ if (decoded.byteLength > nextBuf.byteLength) nextBuf = new Uint8Array(decoded.byteLength);
92739
92756
  nextBuf.set(decoded, 0);
92740
92757
  prevBuf = nextBuf;
92741
92758
  prevLen = decoded.byteLength;
@@ -92747,13 +92764,13 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92747
92764
  outLines = jqRes;
92748
92765
  }
92749
92766
  const preservesTerminator = firstName === "head" || firstName === "tail" || firstName === "rev" || firstName === "sed";
92750
- const terminated = sedTerminated || !preservesTerminator || inStr.endsWith("\n") || firstName === "head" && outLines.length < rawLines.length;
92767
+ const terminated = isInlineTac ? inStr.includes("\n") : sedTerminated || !preservesTerminator || inStr.endsWith("\n") || firstName === "head" && outLines.length < rawLines.length;
92751
92768
  const outStr2 = outLines.length > 0 ? outLines.join("\n") + (terminated ? "\n" : "") : "";
92752
92769
  const outByteLen = shellValueByteLength(outStr2);
92753
- if (outByteLen > nextBuf.byteLength) return void 0;
92754
92770
  const nextTotalBytes = this.budget.bytes + outByteLen;
92755
92771
  if (nextTotalBytes > this.budget.maxOutputBytesSmi && outByteLen > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
92756
92772
  this.budget.bytes = nextTotalBytes;
92773
+ if (outByteLen > nextBuf.byteLength) nextBuf = new Uint8Array(outByteLen);
92757
92774
  const written = outStr2.length === 0 ? 0 : fastSharedTextEncoder.encodeInto(outStr2, nextBuf).written;
92758
92775
  prevBuf = nextBuf;
92759
92776
  prevLen = written;
@@ -92977,14 +92994,16 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
92977
92994
  const sortRes = this.evalSyncSort(rawLines, opArgs, false);
92978
92995
  if (sortRes !== void 0) fileRes = renderLines(sortRes);
92979
92996
  } else if (w0Plain === "uniq") {
92980
- const uniqRes = this.evalSyncUniq(rawLines, opArgs);
92997
+ const uniqRes = this.evalSyncUniq(rawLines, opArgs, byteLocale(rawState.variables));
92981
92998
  if (uniqRes !== void 0) fileRes = renderLines(uniqRes);
92982
92999
  } else if (w0Plain === "tr" && (hasSingleStdinRedir || hasSingleHereStringRedir)) {
92983
93000
  fileRes = this.evalSyncTr(fileStr, opArgs);
92984
93001
  } else if (hasSingleHereStringRedir && w0Plain === "base64" && (opArgs.length === 0 || opArgs.length === 1 && (opArgs[0] === "-d" || opArgs[0] === "--decode"))) {
92985
93002
  if (opArgs.length === 0) fileRes = this.syncBase64Encode(view) + "\n";
92986
93003
  else {
92987
- const decoded = this.syncBase64DecodeBytes(fileStr);
93004
+ const cleaned = fileStr.replace(/[ \t\r\n]+/g, "");
93005
+ if (cleaned.length % 4 !== 0 || cleaned.length > 0 && !/^[A-Za-z0-9+/]+={0,2}$/.test(cleaned)) return void 0;
93006
+ const decoded = this.syncBase64DecodeBytes(cleaned);
92988
93007
  if (decoded.some((byte) => byte === 0 || byte >= 128)) return void 0;
92989
93008
  fileRes = sharedSyncPipeDecoder.decode(decoded);
92990
93009
  }