@poe-platform/safe-bash 0.1.744 → 0.1.745

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.
@@ -70595,7 +70595,7 @@ var Runtime = class _Runtime {
70595
70595
  throw new NounsetDiagnosticFailure(reason);
70596
70596
  }
70597
70597
  }
70598
- extractSimpleErePattern(pattern) {
70598
+ extractSimpleErePattern(pattern, state) {
70599
70599
  const cached = pattern._cachedSimpleEre;
70600
70600
  if (cached !== void 0) return cached ?? void 0;
70601
70601
  if (pattern.parts.length === 0) {
@@ -70604,8 +70604,18 @@ var Runtime = class _Runtime {
70604
70604
  }
70605
70605
  if (pattern.parts.length === 1) {
70606
70606
  const p02 = pattern.parts[0];
70607
+ if (state !== void 0 && p02.kind === "variable" && !p02.quoted && !p02.operator && !p02.substring && !p02.length && !p02.indirect && !p02.prefixNames && !p02.specialParameter && !p02.transform && getArraySelector(p02) === void 0 && isShellIdentifier(p02.name) && !stateMonitor(state)?.store?.get(p02.name)) {
70608
+ const raw = state.variables[p02.name];
70609
+ const val = this._syncArithRawWriteOnly && this._syncArithTouched?.has(p02.name) ? raw : raw === void 0 ? void 0 : stateMonitor(state)?.values.get(p02.name, raw) ?? raw;
70610
+ if (typeof val !== "string" || val.length === 0 || val.includes("\\") || val.includes("~")) return void 0;
70611
+ const varCache = pattern._cachedVarEre;
70612
+ if (varCache && varCache.text === val) return varCache;
70613
+ const nextVarCache = { text: val, literal: false, isVar: p02.name };
70614
+ pattern._cachedVarEre = nextVarCache;
70615
+ return nextVarCache;
70616
+ }
70607
70617
  if (p02.kind !== "text" || p02.byteValue || p02.value.includes("\\") || p02.value.includes("~")) {
70608
- pattern._cachedSimpleEre = null;
70618
+ if (p02.kind !== "variable") pattern._cachedSimpleEre = null;
70609
70619
  return void 0;
70610
70620
  }
70611
70621
  const res2 = { text: p02.value, literal: !!p02.quoted };
@@ -70626,7 +70636,7 @@ var Runtime = class _Runtime {
70626
70636
  return res;
70627
70637
  }
70628
70638
  getFastAnchoredEreRegex(pattern, state) {
70629
- const pat = this.extractSimpleErePattern(pattern);
70639
+ const pat = this.extractSimpleErePattern(pattern, state);
70630
70640
  if (!pat || pat.literal || state.nocasematch || this.budget.limits.maxExpansionBytes !== Infinity || this.budget.limits.maxExpansionFields !== Infinity) {
70631
70641
  return void 0;
70632
70642
  }
@@ -70646,7 +70656,7 @@ var Runtime = class _Runtime {
70646
70656
  }
70647
70657
  }
70648
70658
  }
70649
- if (caretOk && /^[\^a-zA-Z0-9_.\-/:@()\[\]+?*,;=| $]+$/.test(pat.text) && !pat.text.includes("[:") && !pat.text.includes("[.") && !pat.text.includes("[=") && !pat.text.includes("()") && !pat.text.includes("[]") && !pat.text.includes("][") && !/\([^)]*[*+?][^)]*\)[*+?]/.test(pat.text)) {
70659
+ if (caretOk && !pat.text.includes("|") && !/[*+?][*+?]/.test(pat.text) && /^[\^a-zA-Z0-9_.\-/:@()\[\]+?*,;=| $]+$/.test(pat.text) && !pat.text.includes("[:") && !pat.text.includes("[.") && !pat.text.includes("[=") && !pat.text.includes("()") && !pat.text.includes("[]") && !pat.text.includes("][") && !/\([^)]*[*+?][^)]*\)[*+?]/.test(pat.text)) {
70650
70660
  try {
70651
70661
  patWithCache._fastAnchoredRe = new RegExp(pat.text, "s");
70652
70662
  } catch {
@@ -70659,7 +70669,7 @@ var Runtime = class _Runtime {
70659
70669
  return patWithCache._fastAnchoredRe ?? void 0;
70660
70670
  }
70661
70671
  trySyncEre(subject, pattern, state, ignoreYield = false) {
70662
- const pat = this.extractSimpleErePattern(pattern);
70672
+ const pat = this.extractSimpleErePattern(pattern, state);
70663
70673
  if (!pat) return void 0;
70664
70674
  const monitor = stateMonitor(state);
70665
70675
  if (!monitor || monitor.hasOverlay("BASH_REMATCH") || state.readonlyVariables?.has("BASH_REMATCH") || state.exported.has("BASH_REMATCH") || !ignoreYield && (0, yield_exports.hasYieldCheckpoint)(this.signal)) {
@@ -72333,7 +72343,7 @@ var Runtime = class _Runtime {
72333
72343
  const entry = assignment.entries[i];
72334
72344
  if (!entry.index || entry.append) return false;
72335
72345
  const kSrc = entry.index.source ?? entry.index.decimal;
72336
- if (kSrc.length === 0 || kSrc.length > 4096 || /[$\x60\\"']/.test(kSrc)) return false;
72346
+ if (kSrc.length === 0 || kSrc.length > 4096 || kSrc.startsWith("~") || /[$\x60\\"']/.test(kSrc)) return false;
72337
72347
  let val = "";
72338
72348
  if (entry.value.parts.length > 0) {
72339
72349
  try {
@@ -72403,6 +72413,23 @@ var Runtime = class _Runtime {
72403
72413
  }
72404
72414
  continue;
72405
72415
  }
72416
+ if (entry.value.parts.length === 1 && !entry.value.parts[0].quoted && (entry.value.parts[0].kind === "variable" || entry.value.parts[0].kind === "substitution") && (rawState.variables.IFS === void 0 || rawState.variables.IFS === " \n") && !rawState.noglob && this.budget.limits.maxExpansionFields === Infinity && this.budget.limits.maxExpansionBytes === Infinity) {
72417
+ let unsplit;
72418
+ try {
72419
+ unsplit = this.fastValueWord(entry.value, rawState, io, false, false, false, false, void 0, diagnosticLine);
72420
+ } catch {
72421
+ return false;
72422
+ }
72423
+ if (typeof unsplit !== "string" || hasGlobOrEscape(unsplit, !!rawState.extglob)) return false;
72424
+ const cw = entry.value;
72425
+ const splitWords = cw._cachedSplitSrc === unsplit && cw._cachedSplitWords !== void 0 ? cw._cachedSplitWords : (cw._cachedSplitSrc = unsplit, cw._cachedSplitWords = unsplit.split(/[ \t\n]+/).filter((w) => w.length > 0));
72426
+ if (splitWords.length > 1500) return false;
72427
+ for (let swIdx = 0; swIdx < splitWords.length; swIdx++) {
72428
+ const sw = splitWords[swIdx];
72429
+ items.push({ explicitIdx: void 0, val: sw, bLen: shellValueByteLength(sw) });
72430
+ }
72431
+ continue;
72432
+ }
72406
72433
  if (entry.value.parts.length === 0 || !entry.value.parts.every((p) => p.quoted || p.kind === "text" && p.value.length > 0 && !p.value.includes(" ") && !p.value.includes(" ") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true))) {
72407
72434
  return false;
72408
72435
  }
@@ -72435,16 +72462,14 @@ var Runtime = class _Runtime {
72435
72462
  }
72436
72463
  try {
72437
72464
  if (!assignment.append && target.values.size > 0) {
72438
- if (!(target.values.size === keepIndices.size && target.maximum === resolved.length - 1)) {
72439
- for (const k of target.values.keys()) {
72440
- if (!keepIndices.has(k)) target.remove(k);
72441
- }
72442
- let newMax = -1;
72443
- for (const k of target.values.keys()) {
72444
- if (k > newMax) newMax = k;
72445
- }
72446
- target.maximum = newMax;
72465
+ for (const k of target.values.keys()) {
72466
+ if (!keepIndices.has(k)) target.remove(k);
72467
+ }
72468
+ let newMax = -1;
72469
+ for (const k of target.values.keys()) {
72470
+ if (k > newMax) newMax = k;
72447
72471
  }
72472
+ target.maximum = newMax;
72448
72473
  }
72449
72474
  for (let i = 0; i < resolved.length; i++) {
72450
72475
  const { idx, val, bLen } = resolved[i];
@@ -74938,7 +74963,7 @@ var Runtime = class _Runtime {
74938
74963
  if (e.append) return false;
74939
74964
  if (isAssoc) {
74940
74965
  const kSrc = e.index ? e.index.source ?? e.index.decimal : "";
74941
- return kSrc.length > 0 && !/[$\x60\\"']/.test(kSrc) && isNoBraceSyncAssignWord(e.value);
74966
+ return kSrc.length > 0 && !kSrc.startsWith("~") && !/[$\x60\\"']/.test(kSrc) && isNoBraceSyncAssignWord(e.value);
74942
74967
  }
74943
74968
  if (e.index !== void 0) {
74944
74969
  const kSrc = (e.index.source ?? e.index.decimal).trim();
@@ -75087,7 +75112,7 @@ var Runtime = class _Runtime {
75087
75112
  if (e.append) return false;
75088
75113
  if (wantAssoc) {
75089
75114
  const kSrc = e.index ? e.index.source ?? e.index.decimal : "";
75090
- return kSrc.length > 0 && !/[$\x60\\"']/.test(kSrc) && isNoBraceSyncAssignWord(e.value);
75115
+ return kSrc.length > 0 && !kSrc.startsWith("~") && !/[$\x60\\"']/.test(kSrc) && isNoBraceSyncAssignWord(e.value);
75091
75116
  }
75092
75117
  if (e.index !== void 0) {
75093
75118
  const kSrc = (e.index.source ?? e.index.decimal).trim();
@@ -75332,7 +75357,7 @@ var Runtime = class _Runtime {
75332
75357
  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);
75333
75358
  if (e.kind === "binary") {
75334
75359
  if (e.operator === "=~") {
75335
- if (!this.isPureSyncValueWord(e.left, rawState) || !this.extractSimpleErePattern(e.right) || rawState.readonlyVariables?.has("BASH_REMATCH") || rawState.exported.has("BASH_REMATCH") || hasUnpreparedLocal(rawState, "BASH_REMATCH")) return false;
75360
+ if (!this.isPureSyncValueWord(e.left, rawState) || !this.extractSimpleErePattern(e.right, rawState) || rawState.readonlyVariables?.has("BASH_REMATCH") || rawState.exported.has("BASH_REMATCH") || hasUnpreparedLocal(rawState, "BASH_REMATCH")) return false;
75336
75361
  const mon = stateMonitor(rawState);
75337
75362
  if (!mon || (this.budget.limits.maxExpansionBytes !== Infinity || this.budget.limits.maxExpansionFields !== Infinity) || mon.hasOverlay("BASH_REMATCH")) return false;
75338
75363
  const st = mon.store ?? requireArrays(rawState);
@@ -75609,7 +75634,7 @@ var Runtime = class _Runtime {
75609
75634
  if (expr.kind === "unary") return (expr.operator === "-n" || expr.operator === "-z" || expr.operator === "-v" || syncConditionalFileUnaryOps.has(expr.operator)) && okWord(expr.operand);
75610
75635
  if (expr.kind === "binary") {
75611
75636
  if (!okWord(expr.left) || !okWord(expr.right)) return false;
75612
- if (expr.operator === "=~") return depth === 0 && this.extractSimpleErePattern(expr.right) !== void 0;
75637
+ if (expr.operator === "=~") return depth === 0 && this.extractSimpleErePattern(expr.right, rawState) !== void 0;
75613
75638
  if (expr.operator === "==" || expr.operator === "=" || expr.operator === "!=") {
75614
75639
  if (expr.right.parts.length > 0 && expr.right.parts.every((p) => p.quoted)) return true;
75615
75640
  if (expr.right.parts.length > 0 && expr.right.parts.every(
@@ -75706,7 +75731,7 @@ var Runtime = class _Runtime {
75706
75731
  if (expr.kind === "binary") {
75707
75732
  if (expr.operator === "=~") {
75708
75733
  if (depth !== 0) return void 0;
75709
- if (!this.extractSimpleErePattern(expr.right)) return void 0;
75734
+ if (!this.extractSimpleErePattern(expr.right, rawState)) return void 0;
75710
75735
  let subject;
75711
75736
  try {
75712
75737
  subject = this.fastValueWord(expr.left, rawState, io, false, false, false, true, void 0, diagnosticLine);
@@ -76820,7 +76845,7 @@ var Runtime = class _Runtime {
76820
76845
  } catch {
76821
76846
  scanArgs = void 0;
76822
76847
  }
76823
- if (typeof optstring === "string" && scanArgs !== void 0) {
76848
+ if (typeof optstring === "string" && (!optstring.startsWith("-") || optstring === "-") && scanArgs !== void 0) {
76824
76849
  rawState.getopts ??= cloneGetoptsBinding(rawState);
76825
76850
  const res = scanGetoptsSync(rawState.getopts.cursor, optstring, scanArgs);
76826
76851
  if (res !== void 0) {
@@ -77667,10 +77692,11 @@ var Runtime = class _Runtime {
77667
77692
  const ops = [];
77668
77693
  for (let ui = uStart; ui < command7.words.length; ui++) {
77669
77694
  const wu = command7.words[ui];
77695
+ const canSkipGlobUnset = Boolean(wu.parts[0]?.quoted || rawState.noglob || !rawState.nullglob && this._isMemoryBackingFs && tryGetMemoryDirectoryEntryNamesSync5(this.backingFs, rawState.cwd)?.size === 0);
77670
77696
  let tExpanded;
77671
77697
  try {
77672
- const fv = this.fastValueWord(wu, rawState, io, true, false, false, true, void 0, diagnosticLine);
77673
- if (typeof fv === "string") tExpanded = fv;
77698
+ const fv = this.fastValueWord(wu, rawState, io, !canSkipGlobUnset, false, false, true, void 0, diagnosticLine);
77699
+ if (typeof fv === "string" && (!canSkipGlobUnset || !fv.includes(" ") && !fv.includes(" ") && !fv.includes("\n"))) tExpanded = fv;
77674
77700
  } catch {
77675
77701
  }
77676
77702
  if (tExpanded === void 0) {
@@ -78701,7 +78727,18 @@ var Runtime = class _Runtime {
78701
78727
  }
78702
78728
  if (part.kind === "variable") {
78703
78729
  if (this._syncLoopFnCheckDepth > 0 && (part.substring || getArraySelector(part)?.kind === "element")) return false;
78704
- if (part.prefixNames !== void 0 || part.transform !== void 0) return false;
78730
+ if (part.prefixNames !== void 0) {
78731
+ if (part.indirect || part.specialParameter || part.length || part.substring || part.transform !== void 0 || part.operator !== void 0 || getArraySelector(part) !== void 0 || this.budget.limits.maxExpansionFields !== Infinity || this.budget.limits.maxExpansionBytes !== Infinity || !isShellIdentifier(part.name)) {
78732
+ return false;
78733
+ }
78734
+ continue;
78735
+ }
78736
+ if (part.transform !== void 0) {
78737
+ if (part.transform !== "U" && part.transform !== "L" && part.transform !== "u" && (part.transform !== "Q" || byteLocale(rawState.variables)) || part.indirect || part.specialParameter || part.length || part.substring || part.operator !== void 0 || getArraySelector(part) !== void 0 || this.budget.limits.maxExpansionBytes !== Infinity || !isShellIdentifier(part.name) || stateMonitor(rawState)?.store?.get(part.name) || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || part.name === "DIRSTACK" || rawState.nounset && rawState.variables[part.name] === void 0) {
78738
+ return false;
78739
+ }
78740
+ continue;
78741
+ }
78705
78742
  if (!part.indirect && !part.prefixNames && !part.length && !part.substring && !part.transform && part.operator === void 0 && getArraySelector(part) === void 0 && (part.name === "?" || part.name === "#" || part.name.length === 1 && part.name >= "1" && part.name <= "9")) {
78706
78743
  if (rawState.nounset && part.name >= "1" && part.name <= "9" && rawState.positional[part.name.charCodeAt(0) - 49] === void 0) return false;
78707
78744
  continue;
@@ -78815,11 +78852,9 @@ var Runtime = class _Runtime {
78815
78852
  let cmd = p.commands[0];
78816
78853
  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";
78817
78854
  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);
78818
- if (p.commands.length === 1 && (cmd.kind === "for" || cmd.kind === "arithmetic-for") && cmd.redirects.length === 0) {
78819
- if (cmd.body.lists.length === 1 && !cmd.body.lists[0].terminator && cmd.body.lists[0].pipelines.every((pl) => pl.commands.length === 1 && pl.commands[0].kind === "simple" && pl.commands[0].redirects.length === 0 && (pl.commands[0].words[0]?.plain === "echo" ? this.isSyncEchoCallOk(pl.commands[0], rawState) : pl.commands[0].words[0]?.plain === "printf" && pl.commands[0].words[1]?.plain !== "-v" && this.isSyncPrintfCallOk(pl.commands[0], 1, rawState, cmd.kind === "for" ? cmd.name : void 0)))) {
78820
- continue;
78821
- }
78822
- return false;
78855
+ if (cmd.kind === "for" || cmd.kind === "arithmetic-for" || cmd.kind === "while") return false;
78856
+ if (p.commands.length === 1 && (cmd.kind === "if" || cmd.kind === "case") && this.isPureSyncSubIfOrCase(cmd, rawState)) {
78857
+ continue;
78823
78858
  }
78824
78859
  if (cmd.kind !== "simple" || cmd.redirects.length > 0 && !hasSingleStdinRedir && !hasSingleHereStringRedir || cmd.words.length === 0) return false;
78825
78860
  let w0Plain = cmd.words[0].plain;
@@ -78844,11 +78879,11 @@ var Runtime = class _Runtime {
78844
78879
  }
78845
78880
  return false;
78846
78881
  }
78847
- const isFileCommand = w0Plain === "cat" || w0Plain === "head" || w0Plain === "tail" || w0Plain === "jq" || w0Plain === "awk" || w0Plain === "grep" || w0Plain === "sed" || w0Plain === "cut" || w0Plain === "wc" || w0Plain === "sort" || w0Plain === "tr" || hasSingleHereStringRedir && (w0Plain === "base64" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl");
78848
- if (!w0Plain || w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "dirname" && w0Plain !== "basename" && w0Plain !== "seq" && !isFileCommand || rawState.functions.has(w0Plain) || rawState.extensions?.builtins.has(w0Plain)) return false;
78882
+ 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");
78883
+ const def = w0Plain ? this.commands.get(w0Plain) ?? (w0Plain === "rev" || w0Plain === "tac" ? this.getExternalCommand(w0Plain) : void 0) : void 0;
78884
+ 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;
78849
78885
  if ((hasSingleStdinRedir || hasSingleHereStringRedir) && !isFileCommand) return false;
78850
- const def = this.commands.get(w0Plain);
78851
- if (!def || (w0Plain === "printf" ? def.execute !== printfCommand.execute : w0Plain === "echo" ? !defaultEchoExecutors.has(def.execute) : w0Plain === "seq" ? !builtInDirectContextExecutors.has(def.execute) && (customRegisteredCommands.has(def.execute) || customRegisteredRegistries.has(this.commands)) : !builtInDirectContextExecutors.has(def.execute))) return false;
78886
+ if (w0Plain === "printf" ? def.execute !== printfCommand.execute : w0Plain === "echo" ? !defaultEchoExecutors.has(def.execute) : w0Plain === "seq" || w0Plain === "rev" || w0Plain === "tac" ? !builtInDirectContextExecutors.has(def.execute) && (customRegisteredCommands.has(def.execute) || customRegisteredRegistries.has(this.commands)) : !builtInDirectContextExecutors.has(def.execute)) return false;
78852
78887
  if (!cmd.words.slice(1).every((w) => this.isPureSyncValueWord(w, rawState))) return false;
78853
78888
  if (isFileCommand) {
78854
78889
  if (w0Plain === "tr" && !hasSingleStdinRedir && !hasSingleHereStringRedir) return false;
@@ -78859,17 +78894,46 @@ var Runtime = class _Runtime {
78859
78894
  const vCheck = this.tryReadMemoryFileViewSync(resolvePath(rawState.cwd, fPlain), false);
78860
78895
  if (!vCheck || vCheck.byteLength > 16384 || vCheck.includes(0)) return false;
78861
78896
  }
78862
- const opCount = hasSingleStdinRedir || hasSingleHereStringRedir ? cmd.words.length - 1 : cmd.words.length - 2;
78897
+ const opWords = hasSingleStdinRedir || hasSingleHereStringRedir ? cmd.words.slice(1) : cmd.words.slice(1, -1);
78898
+ const opCount = opWords.length;
78899
+ const op0 = opWords[0]?.plain;
78900
+ const op1 = opWords[1]?.plain;
78863
78901
  if (w0Plain === "cat" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl") {
78864
78902
  if (opCount !== 0) return false;
78865
78903
  } else {
78866
78904
  if (p.commands.length !== 1 && !hasSingleHereStringRedir) return false;
78867
- if ((w0Plain === "head" || w0Plain === "tail") && opCount > 2) return false;
78868
- if ((w0Plain === "jq" || w0Plain === "awk" || w0Plain === "grep" || w0Plain === "sed") && (opCount < 1 || opCount > 3)) return false;
78869
- if (w0Plain === "cut" && (opCount < 1 || opCount > 4)) return false;
78870
- if (w0Plain === "wc" && opCount !== 1) return false;
78871
- if ((w0Plain === "sort" || w0Plain === "base64") && (opCount > 1 || w0Plain === "sort" && byteLocale(rawState.variables))) return false;
78872
- if (w0Plain === "tr" && opCount !== 2) return false;
78905
+ if (w0Plain === "head" || w0Plain === "tail") {
78906
+ const validHT = opCount === 0 || opCount === 1 && op0 !== void 0 && /^-(?:n|c)?[0-9]{1,5}$/.test(op0) || opCount === 2 && (op0 === "-n" || op0 === "-c") && op1 !== void 0 && /^[0-9]{1,5}$/.test(op1);
78907
+ if (!validHT) return false;
78908
+ }
78909
+ const plainOps = [];
78910
+ for (let oi = 0; oi < opCount; oi++) {
78911
+ const ow = opWords[oi];
78912
+ const pw = ow.plain ?? (ow.parts.length > 0 && ow.parts.every((pt) => pt.kind === "text") ? ow.parts.map((pt) => pt.value).join("") : void 0);
78913
+ if (pw === void 0) break;
78914
+ plainOps.push(pw);
78915
+ }
78916
+ if (w0Plain === "cut") {
78917
+ if (plainOps.length !== opCount || this.evalSyncCut([], plainOps, byteLocale(rawState.variables)) === void 0) return false;
78918
+ } else if (w0Plain === "sed") {
78919
+ if (plainOps.length !== opCount || this.evalSyncSed([], plainOps) === void 0) return false;
78920
+ } else if (w0Plain === "grep") {
78921
+ if (plainOps.length !== opCount || this.evalSyncGrep([], plainOps, Boolean(rawState.errexit)) === void 0) return false;
78922
+ } else if (w0Plain === "awk") {
78923
+ if (plainOps.length !== opCount || this.evalSyncAwk([], plainOps) === void 0) return false;
78924
+ } else if (w0Plain === "jq") {
78925
+ if (plainOps.length !== opCount || this.evalSyncJq("null", plainOps) === void 0) return false;
78926
+ } else if (w0Plain === "wc") {
78927
+ if (opCount !== 1 || op0 !== "-l" && op0 !== "-c" && op0 !== "-w") return false;
78928
+ } else if (w0Plain === "sort") {
78929
+ if (byteLocale(rawState.variables) || opCount > 1 || opCount === 1 && op0 !== "-r" && op0 !== "-u" && op0 !== "-n" && op0 !== "-rn" && op0 !== "-nr" && op0 !== "-ru" && op0 !== "-ur") return false;
78930
+ } else if (w0Plain === "uniq") {
78931
+ if (opCount > 1 || opCount === 1 && op0 !== "-d" && op0 !== "-u" && op0 !== "-c") return false;
78932
+ } else if (w0Plain === "base64") {
78933
+ if (opCount > 1 || opCount === 1 && op0 !== "-d" && op0 !== "--decode") return false;
78934
+ } else if (w0Plain === "tr") {
78935
+ if (plainOps.length !== opCount || this.evalSyncTr("", plainOps) === void 0) return false;
78936
+ }
78873
78937
  }
78874
78938
  }
78875
78939
  if (w0Plain === "printf") {
@@ -78899,6 +78963,7 @@ var Runtime = class _Runtime {
78899
78963
  }
78900
78964
  if (p.commands.length >= 2) {
78901
78965
  if (w0Plain !== "printf" && w0Plain !== "echo" && w0Plain !== "seq" && w0Plain !== "cat" && !hasSingleHereStringRedir || syncPurePipelineSlotInUse || !this.budget.canSyncPurePipe || rawState.errexit || rawState.nounset) return false;
78966
+ if (w0Plain === "printf" && !this.isSyncPrintfCallOk(cmd, 1, rawState)) return false;
78902
78967
  for (let sIdx = 1; sIdx < p.commands.length; sIdx++) {
78903
78968
  const sCmd = p.commands[sIdx];
78904
78969
  if (sCmd.kind !== "simple" || sCmd.redirects.length !== 0 || sCmd.words.length === 0) return false;
@@ -78951,8 +79016,7 @@ var Runtime = class _Runtime {
78951
79016
  if (!grepOk) return false;
78952
79017
  }
78953
79018
  if (sName === "jq") {
78954
- const jqFilter = sPlainArgs.length === 1 ? sPlainArgs[0] : sPlainArgs.length === 2 && (sPlainArgs[0] === "-r" || sPlainArgs[0] === "--raw-output") ? sPlainArgs[1] : void 0;
78955
- if (!jqFilter || !/^\.[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*$/.test(jqFilter)) return false;
79019
+ return false;
78956
79020
  }
78957
79021
  if (sName === "base64") {
78958
79022
  if (sPlainArgs.length > 1 || sPlainArgs.length === 1 && sPlainArgs[0] !== "-d" && sPlainArgs[0] !== "--decode") return false;
@@ -79017,6 +79081,49 @@ var Runtime = class _Runtime {
79017
79081
  }
79018
79082
  return void 0;
79019
79083
  }
79084
+ execSyncUnsetStep(step, rawState, io, monitor, touched) {
79085
+ const uVars = step.unsetVars;
79086
+ const store = monitor.store;
79087
+ let lastExpanded = "";
79088
+ for (let ui = 0; ui < uVars.length; ui++) {
79089
+ const uvn = uVars[ui];
79090
+ if (uvn.charCodeAt(0) === 64) {
79091
+ const wIdx = Number(uvn.slice(1));
79092
+ const wu = step.cmd.words[wIdx];
79093
+ const tExpanded = this.fastValueWord(wu, rawState, io, false, false, false, false, 0, step.line);
79094
+ lastExpanded = tExpanded;
79095
+ const bracket = tExpanded.indexOf("[");
79096
+ if (bracket > 0 && tExpanded.endsWith("]") && store) {
79097
+ const arrName = tExpanded.slice(0, bracket);
79098
+ const subStr = tExpanded.slice(bracket + 1, -1);
79099
+ const binding = store.get(arrName);
79100
+ if (binding) {
79101
+ if (binding.associative) {
79102
+ const id = fastStringHexIdentity(subStr);
79103
+ const existingKey = binding.keys.get(id);
79104
+ if (existingKey !== void 0) {
79105
+ binding.remove(existingKey.index);
79106
+ store.changed(monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets), arrName);
79107
+ }
79108
+ } else {
79109
+ const idxNum = /^(?:0|[1-9][0-9]{0,8})$/.test(subStr) ? Number(subStr) : resolveSimpleArithOperand(subStr, rawState, monitor, store, this._syncArithRawWriteOnly ? this._syncArithTouched : void 0);
79110
+ const resolvedIdx = idxNum !== void 0 ? idxNum >= 0 ? idxNum : binding.maximum + 1 + idxNum : void 0;
79111
+ if (resolvedIdx !== void 0 && resolvedIdx >= 0 && binding.values.has(resolvedIdx)) {
79112
+ binding.remove(resolvedIdx);
79113
+ store.changed(monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets), arrName);
79114
+ }
79115
+ }
79116
+ }
79117
+ }
79118
+ } else {
79119
+ delete rawState.variables[uvn];
79120
+ monitor.proxy.exported.delete(uvn);
79121
+ touched.add(uvn);
79122
+ lastExpanded = uvn;
79123
+ }
79124
+ }
79125
+ return lastExpanded;
79126
+ }
79020
79127
  extractSyncUnsetVars(cmd, rawState) {
79021
79128
  if (this._syncLoopFnCheckDepth > 0 || cmd.redirects.length !== 0 || cmd.words.length < 2 || cmd.words.length > 16 || cmd.words[0].plain !== "unset") return void 0;
79022
79129
  if (hasShellFunction(rawState, "unset") || rawState.extensions?.builtins.has("unset") || hasActiveVariableAttributes(rawState)) return void 0;
@@ -79031,6 +79138,16 @@ var Runtime = class _Runtime {
79031
79138
  const vn = cmd.words[i].plain;
79032
79139
  if (vn && startIdx === 1 && hasShellFunction(rawState, vn)) return void 0;
79033
79140
  if (!vn || vn.startsWith("-") || !isShellIdentifier(vn) || controlNames.has(vn) || vn === "OPTIND" || rawState.readonlyVariables?.has(vn) || rawState.variableAttributes?.get(vn) || store?.get(vn) || stateMonitor(rawState)?.hasOverlay(vn) || rawState.locals.some((f) => f.has(vn))) {
79141
+ const wu = cmd.words[i];
79142
+ const p02 = wu.parts[0];
79143
+ const pLast = wu.parts[wu.parts.length - 1];
79144
+ const m = p02?.kind === "text" ? /^([a-zA-Z_][a-zA-Z0-9_]*)\[/.exec(p02.value) : void 0;
79145
+ const arrName = m?.[1];
79146
+ const b = arrName ? store?.get(arrName) : void 0;
79147
+ if (arrName && b && b.references === 1 && !store.watches.has(arrName) && !rawState.readonlyVariables?.has(arrName) && !hasUnpreparedLocal(rawState, arrName) && !stateMonitor(rawState)?.hasOverlay(arrName) && pLast?.kind === "text" && pLast.value.endsWith("]") && this.isPureSyncValueWord(wu, rawState) && (p02.quoted || rawState.noglob || !rawState.nullglob && this._isMemoryBackingFs && tryGetMemoryDirectoryEntryNamesSync5(this.backingFs, rawState.cwd)?.size === 0)) {
79148
+ vars.push(`@${i}`);
79149
+ continue;
79150
+ }
79034
79151
  return void 0;
79035
79152
  }
79036
79153
  vars.push(vn);
@@ -79052,13 +79169,10 @@ var Runtime = class _Runtime {
79052
79169
  if (w0Plain !== "local" && w0Plain !== "declare" && w0Plain !== "typeset" && w0Plain !== "export") return void 0;
79053
79170
  if (hasShellFunction(rawState, w0Plain) || rawState.extensions?.builtins.has(w0Plain) || hasActiveVariableAttributes(rawState)) return void 0;
79054
79171
  if (w0Plain === "local" && rawState.locals.length === 0) return void 0;
79055
- let startIdx = 1;
79056
- let attr;
79172
+ const startIdx = 1;
79057
79173
  const w1Plain = cmd.words[1]?.plain;
79058
79174
  if (w0Plain !== "export" && (w1Plain === "-u" || w1Plain === "-l" || w1Plain === "-i")) {
79059
- if (cmd.words.length < 3) return void 0;
79060
- attr = w1Plain.slice(1);
79061
- startIdx = 2;
79175
+ return void 0;
79062
79176
  }
79063
79177
  const store = stateMonitor(rawState)?.store;
79064
79178
  const items = [];
@@ -79076,7 +79190,7 @@ var Runtime = class _Runtime {
79076
79190
  return void 0;
79077
79191
  }
79078
79192
  }
79079
- return { kind: w0Plain === "export" ? "export" : w0Plain === "local" ? "local" : "declare", attr, items };
79193
+ return { kind: w0Plain === "export" ? "export" : w0Plain === "local" ? "local" : "declare", items };
79080
79194
  }
79081
79195
  isQuotedAtWord(w) {
79082
79196
  const p02 = w.parts.length === 1 ? w.parts[0] : w.parts.length === 2 && w.parts[0].kind === "text" && w.parts[0].value === "" ? w.parts[1] : void 0;
@@ -79086,20 +79200,10 @@ var Runtime = class _Runtime {
79086
79200
  if (words === void 0) return true;
79087
79201
  if (words.length === 0 || words.length > 64) return false;
79088
79202
  if (words.length === 1 && this.isQuotedAtWord(words[0])) return true;
79089
- const store = stateMonitor(rawState)?.store;
79090
79203
  if (words.length === 1) {
79091
79204
  const w0 = words[0];
79092
79205
  if (rawState.braceexpand !== false && tryFastExpandBraceRange(w0, this.budget, void 0) !== void 0) return true;
79093
79206
  if (io !== void 0 && this.tryExpandSyncArrayMembersWord(w0, rawState, io, line) !== void 0) return true;
79094
- 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;
79095
- if (p02 && (rawState.variables.IFS === void 0 || rawState.variables.IFS === " \n") && !rawState.noglob) {
79096
- if (p02.kind === "variable" && !p02.quoted && !p02.indirect && !p02.prefixNames && !p02.length && !p02.substring && !p02.transform && p02.operator === void 0 && getArraySelector(p02) === void 0 && isShellIdentifier(p02.name) && !store?.get(p02.name) && !stateMonitor(rawState)?.hasOverlay(p02.name)) {
79097
- return true;
79098
- }
79099
- if (p02.kind === "substitution" && !p02.quoted && this.isPureSyncValueWord(w0, rawState)) {
79100
- return true;
79101
- }
79102
- }
79103
79207
  }
79104
79208
  const stdIfs = (rawState.variables.IFS ?? " \n") === " \n";
79105
79209
  for (let i = 0; i < words.length; i++) {
@@ -79129,9 +79233,8 @@ var Runtime = class _Runtime {
79129
79233
  if (arrMembers !== void 0) return arrMembers;
79130
79234
  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;
79131
79235
  if (p02 && !p02.quoted && (rawState.variables.IFS === void 0 || rawState.variables.IFS === " \n") && !rawState.noglob) {
79132
- if (p02.kind === "variable" && !p02.indirect && !p02.prefixNames && !p02.length && !p02.substring && !p02.transform && p02.operator === void 0 && getArraySelector(p02) === void 0) {
79133
- const curRaw = rawState.variables[p02.name];
79134
- const rawVal = curRaw === void 0 ? "" : touched.has(p02.name) ? curRaw : monitor.values.get(p02.name, curRaw) ?? curRaw;
79236
+ if (p02.kind === "variable" && !p02.indirect && !p02.prefixNames && !p02.length && !p02.transform && getArraySelector(p02) === void 0) {
79237
+ const rawVal = p02.operator === void 0 && !p02.substring ? rawState.variables[p02.name] === void 0 ? "" : touched.has(p02.name) ? rawState.variables[p02.name] : monitor.values.get(p02.name, rawState.variables[p02.name]) ?? rawState.variables[p02.name] : this.fastValueWord(w0, rawState, io, false, false, false, false, 0, line);
79135
79238
  if (typeof rawVal === "string") {
79136
79239
  const cw = w0;
79137
79240
  if (cw._cachedSplitSrc === rawVal && cw._cachedSplitWords !== void 0) return cw._cachedSplitWords;
@@ -79222,6 +79325,8 @@ var Runtime = class _Runtime {
79222
79325
  let rawMode = false;
79223
79326
  let arrayTarget;
79224
79327
  let delimChar;
79328
+ let maxChars;
79329
+ let exactChars;
79225
79330
  if (isMapfile) {
79226
79331
  rawMode = true;
79227
79332
  arrayTarget = cmd.words[2]?.plain ?? "MAPFILE";
@@ -79246,6 +79351,19 @@ var Runtime = class _Runtime {
79246
79351
  if (dPlain === void 0 || dPlain.length !== 1 || dPlain.charCodeAt(0) === 0 || dPlain.charCodeAt(0) >= 128) return void 0;
79247
79352
  delimChar = dPlain;
79248
79353
  argIdx += 2;
79354
+ } else if (p === "-n" || p === "-rn" || p === "-nr" || p === "-N" || p === "-rN" || p === "-Nr") {
79355
+ if (p.includes("r")) rawMode = true;
79356
+ exactChars = p.includes("N");
79357
+ const nPlain = cmd.words[argIdx + 1]?.plain;
79358
+ if (!nPlain || !/^[1-9][0-9]{0,5}$/.test(nPlain) || byteLocale(rawState.variables)) return void 0;
79359
+ maxChars = Number(nPlain);
79360
+ argIdx += 2;
79361
+ } else if ((p.startsWith("-n") || p.startsWith("-rn") || p.startsWith("-N") || p.startsWith("-rN")) && /^[1-9][0-9]{0,5}$/.test(p.slice(p.startsWith("-r") ? 3 : 2))) {
79362
+ if (byteLocale(rawState.variables)) return void 0;
79363
+ if (p.startsWith("-r")) rawMode = true;
79364
+ exactChars = p.includes("N");
79365
+ maxChars = Number(p.slice(p.startsWith("-r") ? 3 : 2));
79366
+ argIdx++;
79249
79367
  } else if (p === "-ra" || p === "-ar" || p === "-a") {
79250
79368
  if (p.includes("r")) rawMode = true;
79251
79369
  if (argIdx + 1 >= cmd.words.length || !cmd.words[argIdx + 1].plain) return void 0;
@@ -79259,7 +79377,7 @@ var Runtime = class _Runtime {
79259
79377
  return void 0;
79260
79378
  }
79261
79379
  }
79262
- if (!rawMode || delimChar !== void 0 && arrayTarget !== void 0) return void 0;
79380
+ if (!rawMode || (delimChar !== void 0 || maxChars !== void 0) && arrayTarget !== void 0) return void 0;
79263
79381
  }
79264
79382
  const monitor = stateMonitor(rawState);
79265
79383
  const store = monitor?.store;
@@ -79268,31 +79386,8 @@ var Runtime = class _Runtime {
79268
79386
  return void 0;
79269
79387
  }
79270
79388
  const arrStore = store ?? requireArrays(rawState);
79271
- let existingArr = arrStore.get(arrayTarget);
79272
- if (existingArr && (existingArr.associative || existingArr.references !== 1 || arrStore.watches.has(arrayTarget))) return void 0;
79273
- if (!existingArr && !arrStore.watches.has(arrayTarget)) {
79274
- const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
79275
- const recBinding = arrStore.takeRecycled(arrayTarget, false, recTickets);
79276
- if (recBinding) {
79277
- if (monitor) monitor.epoch = recTickets.epoch;
79278
- existingArr = recBinding;
79279
- } else {
79280
- try {
79281
- const created = IndexedBinding.create(arrStore.owner, false);
79282
- const prepared = arrStore.prepareExistingName(arrayTarget, shellValueByteLength(arrayTarget), arrStore.owner, this.signal);
79283
- if (prepared) {
79284
- const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
79285
- arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
79286
- if (monitor) monitor.epoch = initTickets.epoch;
79287
- existingArr = created;
79288
- } else {
79289
- void created.release();
79290
- }
79291
- } catch {
79292
- }
79293
- }
79294
- }
79295
- if (!existingArr) return void 0;
79389
+ const existingArr = arrStore.get(arrayTarget);
79390
+ if (!existingArr || existingArr.associative || existingArr.references !== 1 || arrStore.watches.has(arrayTarget)) return void 0;
79296
79391
  return { ifsWord, varNames: [], arrayTarget, ...isMapfile ? { isMapfile: true } : {}, isBareReply: false, inputWord: r0.target };
79297
79392
  }
79298
79393
  const varNames = [];
@@ -79308,7 +79403,48 @@ var Runtime = class _Runtime {
79308
79403
  if (rawState.readonlyVariables?.has("REPLY") || rawState.variableAttributes?.get("REPLY") || store?.get("REPLY") || monitor?.hasOverlay("REPLY")) return void 0;
79309
79404
  varNames.push("REPLY");
79310
79405
  }
79311
- return { ifsWord, varNames, isBareReply, inputWord: r0.target, ...delimChar !== void 0 ? { delimChar } : {} };
79406
+ return { ifsWord, varNames, isBareReply, inputWord: r0.target, ...delimChar !== void 0 ? { delimChar } : {}, ...maxChars !== void 0 ? { maxChars } : {}, ...exactChars !== void 0 ? { exactChars } : {} };
79407
+ }
79408
+ isPureSyncSubIfOrCase(cmd, rawState) {
79409
+ if (cmd.redirects.length !== 0) return false;
79410
+ const isSimpleEchoOrPrintf = (s) => {
79411
+ if (s.lists.length !== 1 || s.lists[0].terminator || s.lists[0].pipelines.length !== 1) return false;
79412
+ const pl = s.lists[0].pipelines[0];
79413
+ if (pl.negate || pl.commands.length !== 1) return false;
79414
+ const sc = pl.commands[0];
79415
+ if (sc.kind !== "simple" || sc.redirects.length !== 0 || sc.words.length === 0) return false;
79416
+ const w0 = sc.words[0]?.plain;
79417
+ if (w0 === "echo") return this.isSyncEchoCallOk(sc, rawState);
79418
+ if (w0 === "printf" && sc.words[1]?.plain !== "-v") return this.isSyncPrintfCallOk(sc, 1, rawState);
79419
+ return false;
79420
+ };
79421
+ if (cmd.kind === "if") {
79422
+ for (const br of cmd.branches) {
79423
+ if (br.condition.lists.length !== 1 || br.condition.lists[0].terminator || br.condition.lists[0].pipelines.length !== 1) return false;
79424
+ const bp = br.condition.lists[0].pipelines[0];
79425
+ if (bp.negate || bp.commands.length !== 1) return false;
79426
+ const bc = bp.commands[0];
79427
+ if (bc.kind === "arithmetic") {
79428
+ 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;
79429
+ } else if (bc.kind === "conditional") {
79430
+ if (bc.redirects.length !== 0 || rawState.nocasematch || byteLocale(rawState.variables) || !this.canSyncConditional(bc.expression, 0, rawState)) return false;
79431
+ if (bc.expression.kind === "binary" && bc.expression.operator === "=~") return false;
79432
+ } else if (!this.extractPosixBracketCondExpr(bc, rawState, true, br.body)) {
79433
+ return false;
79434
+ }
79435
+ if (!isSimpleEchoOrPrintf(br.body)) return false;
79436
+ }
79437
+ if (cmd.otherwise && !isSimpleEchoOrPrintf(cmd.otherwise)) return false;
79438
+ return true;
79439
+ }
79440
+ if (rawState.nocasematch || rawState.extglob || !this.isPureSyncValueWord(cmd.subject, rawState)) return false;
79441
+ const work = { remaining: 4096, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
79442
+ for (const cl of cmd.clauses) {
79443
+ if (cl.terminator !== ";;" && cl.terminator !== "esac") return false;
79444
+ if (!cl.patterns.every((pw) => pw.plain !== void 0 && tryMatchesPatternSync(pw.plain, "", work, false, false) !== void 0)) return false;
79445
+ if (!isSimpleEchoOrPrintf(cl.body)) return false;
79446
+ }
79447
+ return true;
79312
79448
  }
79313
79449
  canSyncLoopBody(script2, rawState, io, nested = false, printfInductionName) {
79314
79450
  if (script2.lists.length === 0) return false;
@@ -79326,7 +79462,11 @@ var Runtime = class _Runtime {
79326
79462
  if (e.kind === "nonempty") return this.isPureSyncValueWord(e.operand, rawState);
79327
79463
  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);
79328
79464
  if (e.kind === "binary") {
79329
- if (e.operator === "=~") 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");
79465
+ if (e.operator === "=~") {
79466
+ const patInfo = this.extractSimpleErePattern(e.right, rawState);
79467
+ if (patInfo?.isVar) return false;
79468
+ 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");
79469
+ }
79330
79470
  return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
79331
79471
  }
79332
79472
  if (e.kind === "not") return checkLeaf(e.operand);
@@ -79502,7 +79642,8 @@ var Runtime = class _Runtime {
79502
79642
  }
79503
79643
  return false;
79504
79644
  }
79505
- if (this.extractSyncUnsetVars(cmd, rawState) !== void 0 || this.extractSyncLocalDeclStep(cmd, rawState) !== void 0 || this.extractSyncShiftCount(cmd, rawState) !== void 0) {
79645
+ const declaration = this.extractSyncLocalDeclStep(cmd, rawState);
79646
+ if (this.extractSyncUnsetVars(cmd, rawState) !== void 0 || declaration !== void 0 || this.extractSyncShiftCount(cmd, rawState) !== void 0) {
79506
79647
  continue;
79507
79648
  }
79508
79649
  if (cmd.redirects.length === 0 && cmd.words.length >= 1 && cmd.words.length <= 16 && this.extractSyncLoopFnSpec(cmd, rawState, io) !== void 0) {
@@ -79519,41 +79660,35 @@ var Runtime = class _Runtime {
79519
79660
  if (arrAssign) {
79520
79661
  if (this._syncLoopFnCheckDepth > 0) return false;
79521
79662
  if (hasUnpreparedLocals(rawState)) return false;
79522
- let curArr = store?.get(arrAssign.name);
79523
- if (!curArr && (arrAssign.kind === "compound" || arrAssign.kind === "element") && this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity && isShellIdentifier(arrAssign.name) && rawState.variables[arrAssign.name] === void 0 && !rawState.readonlyVariables?.has(arrAssign.name) && !rawState.exported.has(arrAssign.name) && !rawState.variableAttributes?.get(arrAssign.name) && !controlNames.has(arrAssign.name) && !stateMonitor(rawState)?.hasOverlay(arrAssign.name)) {
79524
- const monitor = stateMonitor(rawState);
79525
- const arrStore = monitor?.store ?? (monitor ? requireArrays(rawState) : void 0);
79526
- if (arrStore && !arrStore.watches.has(arrAssign.name)) {
79527
- const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
79528
- const recBinding = arrStore.takeRecycled(arrAssign.name, false, recTickets);
79529
- if (recBinding) {
79530
- if (monitor) monitor.epoch = recTickets.epoch;
79531
- curArr = recBinding;
79532
- } else {
79533
- try {
79534
- const created = IndexedBinding.create(arrStore.owner, false);
79535
- const prepared = arrStore.prepareExistingName(arrAssign.name, shellValueByteLength(arrAssign.name), arrStore.owner, this.signal);
79536
- if (prepared) {
79537
- const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
79538
- arrStore.publish(arrAssign.name, created, initTickets, prepared, false, arrStore.owner);
79539
- if (monitor) monitor.epoch = initTickets.epoch;
79540
- curArr = created;
79541
- } else {
79542
- void created.release();
79543
- }
79544
- } catch {
79545
- }
79546
- }
79547
- }
79548
- }
79663
+ if (arrAssign.kind === "element") return false;
79664
+ const curArr = store?.get(arrAssign.name);
79549
79665
  const activeArrStore = store ?? stateMonitor(rawState)?.store;
79550
79666
  if (!curArr || curArr.references !== 1 || activeArrStore?.watches.has(arrAssign.name) || rawState.readonlyVariables?.has(arrAssign.name) || rawState.exported.has(arrAssign.name) || controlNames.has(arrAssign.name)) {
79551
79667
  return false;
79552
79668
  }
79553
- if (arrAssign.kind === "compound" && !curArr.associative && arrAssign.entries.length <= 16 && arrAssign.entries.every((e) => !e.index && !e.append)) {
79669
+ if (arrAssign.kind === "compound" && arrAssign.entries.length <= 16 && arrAssign.entries.every((e) => !e.append)) {
79554
79670
  let allEntriesOk = true;
79555
79671
  for (let ei = 0; ei < arrAssign.entries.length; ei++) {
79556
- const ev = arrAssign.entries[ei].value;
79672
+ const entry = arrAssign.entries[ei];
79673
+ const ev = entry.value;
79674
+ if (curArr.associative) {
79675
+ const kSrc = entry.index ? entry.index.source ?? entry.index.decimal : "";
79676
+ if (kSrc.length === 0 || kSrc.length > 4096 || kSrc.startsWith("~") || /[$\x60\\"']/.test(kSrc) || !this.isPureSyncValueWord(ev, rawState)) {
79677
+ allEntriesOk = false;
79678
+ break;
79679
+ }
79680
+ continue;
79681
+ }
79682
+ if (entry.index !== void 0) {
79683
+ const kSrc = (entry.index.source ?? entry.index.decimal).trim();
79684
+ const original = compoundEntryWords.get(entry);
79685
+ const hasBraceInOriginal = rawState.braceexpand !== false && Boolean(original?.parts.some((p2) => p2.kind === "text" && !p2.quoted && p2.value.includes("{")));
79686
+ if (!/^(?:0|[1-9][0-9]{0,8})$/.test(kSrc) || hasBraceInOriginal || rawState.braceexpand !== false && ev.parts.some((p2) => !p2.quoted && p2.kind === "text" && p2.value.includes("{")) || !this.isPureSyncValueWord(ev, rawState)) {
79687
+ allEntriesOk = false;
79688
+ break;
79689
+ }
79690
+ continue;
79691
+ }
79557
79692
  if (!this.isPureSyncValueWord(ev, rawState) || !ev.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))) {
79558
79693
  allEntriesOk = false;
79559
79694
  break;
@@ -79562,18 +79697,6 @@ var Runtime = class _Runtime {
79562
79697
  if (allEntriesOk) continue;
79563
79698
  return false;
79564
79699
  }
79565
- if (arrAssign.kind === "element" && (!arrAssign.append || this.budget.limits.maxExpansionBytes === Infinity) && curArr.associative) {
79566
- const kSrc = arrAssign.index.source ?? arrAssign.index.decimal;
79567
- if (kSrc.trim().length > 0 && !kSrc.includes("`") && !kSrc.includes("$(") && this.isPureSyncValueWord(arrAssign.value, rawState)) continue;
79568
- return false;
79569
- }
79570
- if (arrAssign.kind === "element" && !curArr.associative) {
79571
- const subSrc = (arrAssign.index.source ?? arrAssign.index.decimal).trim();
79572
- if (subSrc.length > 0 && subSrc.length <= 64 && /^[$a-zA-Z0-9_ +*-]+$/.test(subSrc) && !subSrc.includes("/") && !subSrc.includes("%") && !subSrc.includes("=") && !subSrc.includes("++") && !subSrc.includes("--") && this.isPureSyncValueWord(arrAssign.value, rawState)) {
79573
- continue;
79574
- }
79575
- return false;
79576
- }
79577
79700
  return false;
79578
79701
  }
79579
79702
  const assignment = this.assignment(w0);
@@ -80015,6 +80138,7 @@ var Runtime = class _Runtime {
80015
80138
  return 0;
80016
80139
  }
80017
80140
  trySyncLoop(command7, pipeline, rawState, monitor, store, existing, elem0, canMutatePipeStatus, io, diagnosticLine, syncReadInputText) {
80141
+ if (!syncSinks.get(io.stderr)) return void 0;
80018
80142
  if (store && !existing) {
80019
80143
  if (this.budget.limits.maxExpansionFields !== Infinity || this.budget.limits.maxExpansionBytes !== Infinity || monitor.internalOwner().ledger.checkpoint(this.signal, 0) || publishPipelineStatus(rawState, singleStatusZero, this.signal, io[invocationScope])) {
80020
80144
  return void 0;
@@ -80038,7 +80162,9 @@ var Runtime = class _Runtime {
80038
80162
  const initializer = command7.kind === "arithmetic-for" ? command7.expressions[0]?.tree : void 0;
80039
80163
  const condition = command7.kind === "arithmetic-for" ? command7.expressions[1]?.tree : void 0;
80040
80164
  const increment = command7.kind === "arithmetic-for" ? command7.expressions[2]?.tree : void 0;
80041
- 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 : void 0;
80165
+ const whileCondCmd = command7.kind === "while" && command7.condition.lists.length === 1 && command7.condition.lists[0].pipelines.length === 1 ? command7.condition.lists[0].pipelines[0].commands[0] : void 0;
80166
+ const whilePrintfInd = whileCondCmd?.kind === "arithmetic" && !whileCondCmd.expression.error && whileCondCmd.expression.tree?.kind === "binary" && (whileCondCmd.expression.tree.left.kind === "name" ? whileCondCmd.expression.tree.left.name : whileCondCmd.expression.tree.left.kind === "unary" && whileCondCmd.expression.tree.left.operand.kind === "name" ? whileCondCmd.expression.tree.left.operand.name : void 0);
80167
+ 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 : whilePrintfInd && this.canSyncPrintfInductionBody(command7.body, rawState) ? whilePrintfInd : void 0;
80042
80168
  if (guestArrays(rawState) && (guestArrays(rawState).watches.size > 0 || this.budget.limits.maxExpansionBytes < 65536) || !this.canSyncLoopBody(command7.body, rawState, io, false, printfInductionName)) {
80043
80169
  command7._skipTrySyncLoop = true;
80044
80170
  return void 0;
@@ -80052,16 +80178,26 @@ var Runtime = class _Runtime {
80052
80178
  elem0 = existing?.values.get(0);
80053
80179
  if (!existing || !elem0) return void 0;
80054
80180
  }
80055
- for (const v of Object.values(rawState.variables)) {
80181
+ for (const v of [...Object.values(rawState.variables), ...rawState.positional]) {
80056
80182
  if (typeof v === "string") {
80057
80183
  for (let k = 0; k < v.length; k++) {
80058
80184
  if (v.charCodeAt(k) >= 128) return void 0;
80059
80185
  }
80060
80186
  }
80061
80187
  }
80188
+ if (store) {
80189
+ for (const { binding } of store.bindings.values()) {
80190
+ for (const slot of binding.values.values()) {
80191
+ const value2 = slot.text.value;
80192
+ for (let k = 0; k < value2.length; k++) {
80193
+ if (value2.charCodeAt(k) >= 128) return void 0;
80194
+ }
80195
+ }
80196
+ }
80197
+ }
80062
80198
  const { steps: bodyAssignments, redirectCount } = this.buildSyncLoopBody(command7, rawState, io);
80063
80199
  if (bodyAssignments.length > 30) return void 0;
80064
- const touched = sharedSyncLoopTouched;
80200
+ const touched = this._syncArithRawWriteOnly ? /* @__PURE__ */ new Set() : sharedSyncLoopTouched;
80065
80201
  touched.clear();
80066
80202
  let lastCmd;
80067
80203
  let lastArg = "";
@@ -80130,7 +80266,7 @@ var Runtime = class _Runtime {
80130
80266
  }
80131
80267
  };
80132
80268
  const stepMutatesInduction = (st) => {
80133
- if (st.name === inductionName2 || st.readHereString?.varNames.includes(inductionName2) || st.readHereString?.arrayTarget === inductionName2 || st.unsetVars?.includes(inductionName2) || st.localDecl?.attr === "i" || st.localDecl?.items.some((it) => it.name === inductionName2)) return true;
80269
+ if (st.name === inductionName2 || st.readHereString?.varNames.includes(inductionName2) || st.readHereString?.arrayTarget === inductionName2 || st.unsetVars?.includes(inductionName2) || st.localDecl?.items.some((it) => it.name === inductionName2)) return true;
80134
80270
  if (st.arithStmt?.hasMutation && arithTreeMutatesVar(st.arithStmt.tree, inductionName2)) return true;
80135
80271
  if (st.printfVArgs?.some((w) => w.parts.some((p) => p.kind === "arithmetic" && p.expression.hasMutation && arithTreeMutatesVar(p.expression.tree, inductionName2)))) return true;
80136
80272
  if (st.arithStmt?.error && new RegExp("\\b" + inductionName2 + "\\b").test(st.arithStmt.source)) return true;
@@ -80167,9 +80303,11 @@ var Runtime = class _Runtime {
80167
80303
  intSteps2[b] = intStep;
80168
80304
  continue;
80169
80305
  }
80170
- if (step.value) {
80171
- for (let i = 0; i < step.value.parts.length; i++) {
80172
- const part = step.value.parts[i];
80306
+ const wordsToScan = step.arrayAssign?.kind === "compound" ? step.arrayAssign.entries.map((e) => e.value) : step.value ? [step.value] : [];
80307
+ for (let wIdx = 0; wIdx < wordsToScan.length; wIdx++) {
80308
+ const wVal = wordsToScan[wIdx];
80309
+ for (let i = 0; i < wVal.parts.length; i++) {
80310
+ const part = wVal.parts[i];
80173
80311
  if (part.kind === "text" || part.kind === "variable") continue;
80174
80312
  if (part.kind === "arithmetic") {
80175
80313
  if (part.expression.error) {
@@ -80309,7 +80447,7 @@ var Runtime = class _Runtime {
80309
80447
  try {
80310
80448
  let lastInductionVal;
80311
80449
  const intBudgetSnapshot = this.budget.parsing.snapshot();
80312
- let canUseIntRegisters = iterations > 0 && allIntStepsReady && (!hasSubIntStep || this.middleware.length === 0 && rawState.depth < this.budget.maxSubstitutionDepthSmi) && !this.budget.hasCpuLimit && this.budget.maxExpansionFieldsSmi >= 1 && this.budget.maxExpansionBytesSmi >= 32 && !store?.get(inductionName) && inductionName !== "LINENO" && inductionName !== "_" && inductionName !== "FUNCNAME";
80450
+ let canUseIntRegisters = !prevRawWrite2 && iterations > 0 && allIntStepsReady && (!hasSubIntStep || this.middleware.length === 0 && rawState.depth < this.budget.maxSubstitutionDepthSmi) && !this.budget.hasCpuLimit && this.budget.maxExpansionFieldsSmi >= 1 && this.budget.maxExpansionBytesSmi >= 32 && !store?.get(inductionName) && inductionName !== "LINENO" && inductionName !== "_" && inductionName !== "FUNCNAME";
80313
80451
  if (canUseIntRegisters && arithNamesList.length > 0) {
80314
80452
  for (let a = 0; a < arithNamesList.length; a++) {
80315
80453
  const refName = arithNamesList[a];
@@ -80547,6 +80685,8 @@ var Runtime = class _Runtime {
80547
80685
  if (e.kind === "unary") return (e.operator === "-n" || e.operator === "-z" || e.operator === "-v") && this.isPureSyncValueWord(e.operand, rawState);
80548
80686
  if (e.kind === "binary") {
80549
80687
  if (e.operator === "=~") {
80688
+ const patInfo = this.extractSimpleErePattern(e.right, rawState);
80689
+ if (patInfo?.isVar) return false;
80550
80690
  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");
80551
80691
  }
80552
80692
  return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
@@ -80904,9 +81044,9 @@ var Runtime = class _Runtime {
80904
81044
  if (!asciiOk) break;
80905
81045
  }
80906
81046
  if (asciiOk) fastLoopWords = arrMembers;
80907
- } else if (p02.kind === "variable" && !p02.quoted && !p02.indirect && !p02.prefixNames && !p02.length && !p02.substring && !p02.transform && p02.operator === void 0 && getArraySelector(p02) === void 0 && (rawState.variables.IFS === void 0 || rawState.variables.IFS === " \n") && !rawState.noglob && !store?.get(p02.name) && !monitor.hasOverlay(p02.name)) {
80908
- const rawVal = rawState.variables[p02.name] ?? "";
80909
- if (rawVal.length <= 32768 && !/[*?[\]\\]/.test(rawVal)) {
81047
+ } else if (p02.kind === "variable" && !p02.quoted && !p02.indirect && !p02.prefixNames && !p02.length && !p02.transform && getArraySelector(p02) === void 0 && (rawState.variables.IFS === void 0 || rawState.variables.IFS === " \n") && !rawState.noglob && !store?.get(p02.name) && !monitor.hasOverlay(p02.name) && (p02.operator === void 0 && !p02.substring || this.isPureSyncValueWord(command7.words[0], rawState))) {
81048
+ const rawVal = p02.operator === void 0 && !p02.substring ? rawState.variables[p02.name] ?? "" : this.fastValueWord(command7.words[0], rawState, io, false, false, false, false, 0, diagnosticLine);
81049
+ if (typeof rawVal === "string" && rawVal.length <= 32768 && !/[*?[\]\\]/.test(rawVal)) {
80910
81050
  let asciiOk = true;
80911
81051
  for (let j = 0; j < rawVal.length; j++) {
80912
81052
  if (rawVal.charCodeAt(j) >= 128) {
@@ -81264,10 +81404,15 @@ ${s1}
81264
81404
  }
81265
81405
  canSyncPrintfInductionBody(script2, rawState) {
81266
81406
  for (const list of script2.lists) for (const pipeline of list.pipelines) for (const command7 of pipeline.commands) {
81407
+ if (command7.kind === "arithmetic") {
81408
+ if (command7.redirects.length === 0 && !command7.expression.error && !command7.expression.hasSubscript && isSafeSmiProgram(command7.expression) && command7.expression.tree?.kind === "unary" && (command7.expression.tree.operator === "++" || command7.expression.tree.operator === "--") && command7.expression.tree.operand.kind === "name") continue;
81409
+ return false;
81410
+ }
81267
81411
  if (command7.kind !== "simple" || hasShellFunction(rawState, command7.words[0]?.plain ?? "") || command7.words.some((word) => getArrayAssignment(word) !== void 0)) return false;
81268
81412
  for (const word of [...command7.words, ...command7.redirects.map((redirect) => redirect.target)]) for (const part of word.parts) {
81269
81413
  if (part.kind === "text") continue;
81270
81414
  if (part.kind === "variable" && !part.indirect && !part.length && !part.substring && !part.transform && !part.prefixNames && part.operator === void 0 && getArraySelector(part) === void 0) continue;
81415
+ if (part.kind === "arithmetic" && !part.expression.error && !part.expression.hasMutation && !part.expression.hasSubscript && isSafeSmiProgram(part.expression) && /^[a-zA-Z0-9_ +*-]+$/.test(part.expression.source)) continue;
81271
81416
  if (part.kind === "substitution" && this.canSyncPrintfInductionBody(part.script, rawState)) continue;
81272
81417
  return false;
81273
81418
  }
@@ -81289,6 +81434,10 @@ ${s1}
81289
81434
  args.push("0");
81290
81435
  continue;
81291
81436
  }
81437
+ if (i > fmtWordIdx && inductionName !== void 0 && valueParts.length === 1 && part?.kind === "arithmetic" && part.quoted && !part.expression.error && !part.expression.hasMutation && !part.expression.hasSubscript && isSafeSmiProgram(part.expression) && /^[a-zA-Z0-9_ +*-]+$/.test(part.expression.source) && this.canSyncArithmeticWithoutFault(part.expression.tree, rawState, cmd.line ?? 1)) {
81438
+ args.push("0");
81439
+ continue;
81440
+ }
81292
81441
  let arg = "";
81293
81442
  for (const part2 of w.parts) {
81294
81443
  if (part2.kind !== "text" || !part2.quoted && (part2.value.length === 0 || part2.value.includes(" ") || part2.value.includes(" ") || part2.value.includes("\n") || part2.value.includes("{") || hasGlobOrEscape(part2.value, true))) return false;
@@ -81303,6 +81452,33 @@ ${s1}
81303
81452
  if (!p02 || p02.kind !== "text" || p02.value.length === 0 || p02.value.startsWith("-")) return false;
81304
81453
  return w.parts.every((p) => p.kind === "text" || p.kind === "variable" && !p.indirect && !p.prefixNames && !p.length && !p.substring && p.operator === void 0 && getArraySelector(p) === void 0);
81305
81454
  }
81455
+ execSyncReadHereStringStep(rs, step, rawState, io, monitor, touched) {
81456
+ const rawInput = this.fastValueWord(rs.inputWord, rawState, io, false, false, false, false, 0, step.line);
81457
+ const delim = rs.delimChar ?? "\n";
81458
+ let lineStr;
81459
+ let status2 = 0;
81460
+ if (rs.maxChars !== void 0) {
81461
+ const fullInput = rawInput + "\n";
81462
+ if (rs.exactChars) {
81463
+ lineStr = fullInput.length > rs.maxChars ? fullInput.slice(0, rs.maxChars) : fullInput;
81464
+ status2 = fullInput.length >= rs.maxChars ? 0 : 1;
81465
+ } else {
81466
+ const nlIdx = fullInput.indexOf(delim);
81467
+ const untilDelim = nlIdx === -1 ? fullInput : fullInput.slice(0, nlIdx);
81468
+ lineStr = untilDelim.length > rs.maxChars ? untilDelim.slice(0, rs.maxChars) : untilDelim;
81469
+ status2 = nlIdx !== -1 || fullInput.length >= rs.maxChars ? 0 : 1;
81470
+ }
81471
+ } else {
81472
+ const fullInput = delim === "\n" ? rawInput : rawInput + "\n";
81473
+ const nlIdx = rs.isMapfile ? -1 : fullInput.indexOf(delim);
81474
+ lineStr = nlIdx === -1 ? fullInput : fullInput.slice(0, nlIdx);
81475
+ status2 = !rs.isMapfile && delim !== "\n" && nlIdx === -1 ? 1 : 0;
81476
+ }
81477
+ const ifsStr = rs.exactChars ? "" : rs.ifsWord !== void 0 ? this.fastValueWord(rs.ifsWord, rawState, io, false, false, false, false, 0, step.line) : rawState.variables.IFS ?? " \n";
81478
+ this.splitSyncReadLine(lineStr, ifsStr, rs.varNames, rs.isBareReply, rawState, touched, rs.arrayTarget, monitor, rs.isMapfile);
81479
+ rawState.status = status2;
81480
+ return step.cmd.words[step.cmd.words.length - 1].plain;
81481
+ }
81306
81482
  splitSyncReadLine(lineStr, ifsStr, varNames, isBareReply, rawState, touched, arrayTarget, monitor, isMapfile = false) {
81307
81483
  if (arrayTarget !== void 0 && monitor !== void 0) {
81308
81484
  const arrStore = monitor.store ?? requireArrays(rawState);
@@ -81414,15 +81590,8 @@ ${s1}
81414
81590
  touched.add(item.name);
81415
81591
  }
81416
81592
  if (item.value !== void 0) {
81417
- let val = this.fastValueWord(item.value, rawState, io, false, false, false, rawState.braceexpand !== false, 0, line);
81418
- if (decl.attr === "u") val = val.toUpperCase();
81419
- else if (decl.attr === "l") val = val.toLowerCase();
81420
- else if (decl.attr === "i") {
81421
- const curRaw = item.append ? rawState.variables[item.name] : void 0;
81422
- const curStr = curRaw === void 0 ? "" : touched.has(item.name) ? curRaw : monitor.values.get(item.name, curRaw) ?? curRaw;
81423
- val = applySyncScalarAttributes("i", val, typeof curStr === "string" ? curStr : "", item.append, rawState, monitor, arrayStore(rawState), touched) ?? "0";
81424
- }
81425
- if (item.append && decl.attr !== "i") {
81593
+ const val = this.fastValueWord(item.value, rawState, io, false, false, false, rawState.braceexpand !== false, 0, line);
81594
+ if (item.append) {
81426
81595
  const curRaw = rawState.variables[item.name];
81427
81596
  const curStr = curRaw === void 0 ? "" : touched.has(item.name) ? curRaw : monitor.values.get(item.name, curRaw) ?? curRaw;
81428
81597
  rawState.variables[item.name] = (typeof curStr === "string" ? curStr : "") + val;
@@ -81434,9 +81603,6 @@ ${s1}
81434
81603
  } else {
81435
81604
  lastArg = item.name;
81436
81605
  }
81437
- if (decl.attr !== void 0) {
81438
- (this._syncPendingVarAttrs ??= /* @__PURE__ */ new Map()).set(item.name, decl.attr);
81439
- }
81440
81606
  if (decl.kind === "export") {
81441
81607
  rawState.exported.add(item.name);
81442
81608
  }
@@ -81444,20 +81610,12 @@ ${s1}
81444
81610
  return lastArg;
81445
81611
  }
81446
81612
  _syncTouchedPositionals = false;
81447
- _syncPendingVarAttrs = void 0;
81448
81613
  flushSyncPositionals(rawState) {
81449
81614
  if (this._syncTouchedPositionals) {
81450
81615
  this._syncTouchedPositionals = false;
81451
81616
  this._fastSubPositional = void 0;
81452
81617
  this.replacePositionals(rawState, rawState.positional);
81453
81618
  }
81454
- if (this._syncPendingVarAttrs && this._syncPendingVarAttrs.size > 0) {
81455
- rawState.variableAttributes ??= /* @__PURE__ */ new Map();
81456
- for (const [k, v] of this._syncPendingVarAttrs) {
81457
- rawState.variableAttributes.set(k, v);
81458
- }
81459
- this._syncPendingVarAttrs.clear();
81460
- }
81461
81619
  }
81462
81620
  execSyncShiftStep(shiftCount, cmd, rawState) {
81463
81621
  const activePos = this._fastSubPositional ?? rawState.positional;
@@ -81563,13 +81721,7 @@ ${s1}
81563
81721
  break;
81564
81722
  }
81565
81723
  if (step.unsetVars !== void 0) {
81566
- for (let ui = 0; ui < step.unsetVars.length; ui++) {
81567
- const uvn = step.unsetVars[ui];
81568
- delete rawState.variables[uvn];
81569
- monitor.proxy.exported.delete(uvn);
81570
- touched.add(uvn);
81571
- }
81572
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
81724
+ lastArg = this.execSyncUnsetStep(step, rawState, io, monitor, touched);
81573
81725
  rawState.status = 0;
81574
81726
  continue;
81575
81727
  }
@@ -81585,16 +81737,7 @@ ${s1}
81585
81737
  continue;
81586
81738
  }
81587
81739
  if (step.readHereString !== void 0) {
81588
- const rs = step.readHereString;
81589
- const rawInput = this.fastValueWord(rs.inputWord, rawState, io, false, false, false, false, 0, step.line);
81590
- const delim = rs.delimChar ?? "\n";
81591
- const fullInput = delim === "\n" ? rawInput : rawInput + "\n";
81592
- const nlIdx = rs.isMapfile ? -1 : fullInput.indexOf(delim);
81593
- const lineStr = nlIdx === -1 ? fullInput : fullInput.slice(0, nlIdx);
81594
- const ifsStr = rs.ifsWord !== void 0 ? this.fastValueWord(rs.ifsWord, rawState, io, false, false, false, false, 0, step.line) : rawState.variables.IFS ?? " \n";
81595
- this.splitSyncReadLine(lineStr, ifsStr, rs.varNames, rs.isBareReply, rawState, touched, rs.arrayTarget, monitor, rs.isMapfile);
81596
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
81597
- rawState.status = !rs.isMapfile && delim !== "\n" && nlIdx === -1 ? 1 : 0;
81740
+ lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
81598
81741
  continue;
81599
81742
  }
81600
81743
  if (deferredMask & 1 << b) {
@@ -81643,7 +81786,9 @@ ${s1}
81643
81786
  this.writeSyncStdoutText(formatted3, io);
81644
81787
  lastArg = pLastArg;
81645
81788
  } else if (step.arrayAssign !== void 0) {
81646
- this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, void 0, void 0, true);
81789
+ if (!this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, void 0, void 0, true)) {
81790
+ throw new Error("Synchronous loop array assignment was not executable");
81791
+ }
81647
81792
  lastArg = "";
81648
81793
  } else if (step.caseClauses !== void 0) {
81649
81794
  this.flushSyncStdoutBatch(io);
@@ -81799,43 +81944,53 @@ ${s1}
81799
81944
  }
81800
81945
  }
81801
81946
  evalSyncLoopArithStmt(expr, rawState, io, touched, line) {
81802
- if (!expr.error) return this.syncShellArithmeticNonZero(expr, rawState, line);
81803
- const cachedExpr = expr;
81804
- const expWord = cachedExpr._cachedArithWord ?? parseArithmeticExpansion(expr.source, this.budget.parsing, false, 0, void 0, rawState.extensions?.syntax);
81805
- cachedExpr._cachedArithWord = expWord;
81806
- const fastSrc = this.fastValueWord(expWord, rawState, io, false, false, true, false, 0, line);
81807
- const scalarMutMatch = fastSrc.length <= 64 ? SIMPLE_SCALAR_MUT_RE.exec(fastSrc) : null;
81808
- if (scalarMutMatch) {
81809
- const varName = resolveSyncNameref(rawState, scalarMutMatch[1]);
81810
- const binOp = scalarMutMatch[2];
81811
- const rhs1 = Number(scalarMutMatch[3]);
81812
- const rhsOp = scalarMutMatch[4];
81813
- const rhs2 = scalarMutMatch[5] !== void 0 ? Number(scalarMutMatch[5]) : 0;
81814
- const rhsNum = rhsOp === "+" ? rhs1 + rhs2 : rhsOp === "-" ? rhs1 - rhs2 : rhsOp === "*" ? rhs1 * rhs2 : rhs1;
81815
- const curVal = rawState.variables[varName] ?? "0";
81816
- if (curVal === "" || /^-?(?:0|[1-9][0-9]{0,12})$/.test(curVal)) {
81817
- const curNum = curVal === "" ? 0 : Number(curVal);
81818
- const nextNum = binOp === "=" ? rhsNum : binOp === "+=" ? curNum + rhsNum : curNum - rhsNum;
81819
- if (Number.isSafeInteger(nextNum)) {
81820
- this.budget.parsing.admit(4);
81821
- rawState.variables[varName] = intToStr(nextNum);
81822
- touched.add(varName);
81823
- return nextNum !== 0;
81947
+ try {
81948
+ if (!expr.error) return this.syncShellArithmeticNonZero(expr, rawState, line);
81949
+ const cachedExpr = expr;
81950
+ const expWord = cachedExpr._cachedArithWord ?? parseArithmeticExpansion(expr.source, this.budget.parsing, false, 0, void 0, rawState.extensions?.syntax);
81951
+ cachedExpr._cachedArithWord = expWord;
81952
+ const fastSrc = this.fastValueWord(expWord, rawState, io, false, false, true, false, 0, line);
81953
+ const scalarMutMatch = fastSrc.length <= 64 ? SIMPLE_SCALAR_MUT_RE.exec(fastSrc) : null;
81954
+ if (scalarMutMatch) {
81955
+ const varName = resolveSyncNameref(rawState, scalarMutMatch[1]);
81956
+ const binOp = scalarMutMatch[2];
81957
+ const rhs1 = Number(scalarMutMatch[3]);
81958
+ const rhsOp = scalarMutMatch[4];
81959
+ const rhs2 = scalarMutMatch[5] !== void 0 ? Number(scalarMutMatch[5]) : 0;
81960
+ const rhsNum = rhsOp === "+" ? rhs1 + rhs2 : rhsOp === "-" ? rhs1 - rhs2 : rhsOp === "*" ? rhs1 * rhs2 : rhs1;
81961
+ const curVal = rawState.variables[varName] ?? "0";
81962
+ if (curVal === "" || /^-?(?:0|[1-9][0-9]{0,12})$/.test(curVal)) {
81963
+ const curNum = curVal === "" ? 0 : Number(curVal);
81964
+ const nextNum = binOp === "=" ? rhsNum : binOp === "+=" ? curNum + rhsNum : curNum - rhsNum;
81965
+ if (Number.isSafeInteger(nextNum)) {
81966
+ this.budget.parsing.admit(4);
81967
+ rawState.variables[varName] = intToStr(nextNum);
81968
+ touched.add(varName);
81969
+ return nextNum !== 0;
81970
+ }
81824
81971
  }
81825
81972
  }
81826
- }
81827
- const binCmpMatch = fastSrc.length <= 64 ? /^\s*(-?(?:0|[1-9][0-9]{0,12}))\s*(==|!=|<|<=|>|>=)\s*(-?(?:0|[1-9][0-9]{0,12}))\s*$/.exec(fastSrc) : null;
81828
- if (binCmpMatch) {
81829
- const lhs = Number(binCmpMatch[1]);
81830
- const op = binCmpMatch[2];
81831
- const rhs = Number(binCmpMatch[3]);
81832
- if (Number.isSafeInteger(lhs) && Number.isSafeInteger(rhs)) {
81833
- this.budget.parsing.admit(4);
81834
- return op === ">" ? lhs > rhs : op === ">=" ? lhs >= rhs : op === "<" ? lhs < rhs : op === "<=" ? lhs <= rhs : op === "==" ? lhs === rhs : lhs !== rhs;
81973
+ const binCmpMatch = fastSrc.length <= 64 ? /^\s*(-?(?:0|[1-9][0-9]{0,12}))\s*(==|!=|<|<=|>|>=)\s*(-?(?:0|[1-9][0-9]{0,12}))\s*$/.exec(fastSrc) : null;
81974
+ if (binCmpMatch) {
81975
+ const lhs = Number(binCmpMatch[1]);
81976
+ const op = binCmpMatch[2];
81977
+ const rhs = Number(binCmpMatch[3]);
81978
+ if (Number.isSafeInteger(lhs) && Number.isSafeInteger(rhs)) {
81979
+ this.budget.parsing.admit(4);
81980
+ return op === ">" ? lhs > rhs : op === ">=" ? lhs >= rhs : op === "<" ? lhs < rhs : op === "<=" ? lhs <= rhs : op === "==" ? lhs === rhs : lhs !== rhs;
81981
+ }
81835
81982
  }
81983
+ const dynProg = prepareArithmetic(fastSrc, this.budget.parsing);
81984
+ return this.syncShellArithmeticNonZero(dynProg, rawState, line);
81985
+ } catch (error) {
81986
+ if (!(error instanceof diagnostics_exports.PublicDiagnostic)) throw error;
81987
+ const write3 = syncSinks.get(io.stderr);
81988
+ if (!write3) throw error;
81989
+ write3(fastSharedTextEncoder.encode(`${io.scriptName ?? "shell"}: line ${line}: ((: ${error.message}
81990
+ `));
81991
+ rawState.status = 1;
81992
+ return void 0;
81836
81993
  }
81837
- const dynProg = prepareArithmetic(fastSrc, this.budget.parsing);
81838
- return this.syncShellArithmeticNonZero(dynProg, rawState, line);
81839
81994
  }
81840
81995
  extractSyncLoopFnSpec(cmd, rawState, io) {
81841
81996
  if (this._syncLoopFnCheckDepth > 0 || rawState.locals && rawState.locals.length > 0) return void 0;
@@ -82069,13 +82224,7 @@ ${s1}
82069
82224
  break;
82070
82225
  }
82071
82226
  if (step.unsetVars !== void 0) {
82072
- for (let ui = 0; ui < step.unsetVars.length; ui++) {
82073
- const uvn = step.unsetVars[ui];
82074
- delete rawState.variables[uvn];
82075
- monitor.proxy.exported.delete(uvn);
82076
- touched.add(uvn);
82077
- }
82078
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
82227
+ lastArg = this.execSyncUnsetStep(step, rawState, io, monitor, touched);
82079
82228
  rawState.status = 0;
82080
82229
  onUpdate({ lastCmd, lastArg });
82081
82230
  continue;
@@ -82094,16 +82243,7 @@ ${s1}
82094
82243
  continue;
82095
82244
  }
82096
82245
  if (step.readHereString !== void 0) {
82097
- const rs = step.readHereString;
82098
- const rawInput = this.fastValueWord(rs.inputWord, rawState, io, false, false, false, false, 0, step.line);
82099
- const delim = rs.delimChar ?? "\n";
82100
- const fullInput = delim === "\n" ? rawInput : rawInput + "\n";
82101
- const nlIdx = rs.isMapfile ? -1 : fullInput.indexOf(delim);
82102
- const lineStr = nlIdx === -1 ? fullInput : fullInput.slice(0, nlIdx);
82103
- const ifsStr = rs.ifsWord !== void 0 ? this.fastValueWord(rs.ifsWord, rawState, io, false, false, false, false, 0, step.line) : rawState.variables.IFS ?? " \n";
82104
- this.splitSyncReadLine(lineStr, ifsStr, rs.varNames, rs.isBareReply, rawState, touched, rs.arrayTarget, monitor, rs.isMapfile);
82105
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
82106
- rawState.status = !rs.isMapfile && delim !== "\n" && nlIdx === -1 ? 1 : 0;
82246
+ lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
82107
82247
  onUpdate({ lastCmd, lastArg });
82108
82248
  continue;
82109
82249
  }
@@ -82182,7 +82322,9 @@ ${s1}
82182
82322
  this.budget.bytes += encoded2.byteLength;
82183
82323
  lastArg = pLastArg;
82184
82324
  } else if (step.arrayAssign !== void 0) {
82185
- this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, void 0, void 0, true);
82325
+ if (!this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, void 0, void 0, true)) {
82326
+ throw new Error("Synchronous loop array assignment was not executable");
82327
+ }
82186
82328
  lastArg = "";
82187
82329
  } else if (step.printfVArgs !== void 0 && step.name !== void 0) {
82188
82330
  const { formatted: formatted3, lastArg: pLastArg } = this.evalSyncPrintfStep(step.printfVArgs, rawState, io, step.line, step.cmd.words[0]?.plain === "echo");
@@ -82256,13 +82398,7 @@ ${s1}
82256
82398
  break;
82257
82399
  }
82258
82400
  if (step.unsetVars !== void 0) {
82259
- for (let ui = 0; ui < step.unsetVars.length; ui++) {
82260
- const uvn = step.unsetVars[ui];
82261
- delete rawState.variables[uvn];
82262
- monitor.proxy.exported.delete(uvn);
82263
- touched.add(uvn);
82264
- }
82265
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
82401
+ lastArg = this.execSyncUnsetStep(step, rawState, io, monitor, touched);
82266
82402
  rawState.status = 0;
82267
82403
  continue;
82268
82404
  }
@@ -82278,16 +82414,7 @@ ${s1}
82278
82414
  continue;
82279
82415
  }
82280
82416
  if (step.readHereString !== void 0) {
82281
- const rs = step.readHereString;
82282
- const rawInput = this.fastValueWord(rs.inputWord, rawState, io, false, false, false, false, 0, step.line);
82283
- const delim = rs.delimChar ?? "\n";
82284
- const fullInput = delim === "\n" ? rawInput : rawInput + "\n";
82285
- const nlIdx = rs.isMapfile ? -1 : fullInput.indexOf(delim);
82286
- const lineStr = nlIdx === -1 ? fullInput : fullInput.slice(0, nlIdx);
82287
- const ifsStr = rs.ifsWord !== void 0 ? this.fastValueWord(rs.ifsWord, rawState, io, false, false, false, false, 0, step.line) : rawState.variables.IFS ?? " \n";
82288
- this.splitSyncReadLine(lineStr, ifsStr, rs.varNames, rs.isBareReply, rawState, touched, rs.arrayTarget, monitor, rs.isMapfile);
82289
- lastArg = step.cmd.words[step.cmd.words.length - 1].plain;
82290
- rawState.status = !rs.isMapfile && delim !== "\n" && nlIdx === -1 ? 1 : 0;
82417
+ lastArg = this.execSyncReadHereStringStep(step.readHereString, step, rawState, io, monitor, touched);
82291
82418
  continue;
82292
82419
  }
82293
82420
  if (step.coalesceNext) {
@@ -82356,7 +82483,9 @@ ${s1}
82356
82483
  rawState.status = cStatus;
82357
82484
  continue;
82358
82485
  } else if (step.arrayAssign !== void 0) {
82359
- this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, void 0, void 0, true);
82486
+ if (!this.tryFastArrayAssignmentSync(step.arrayAssign, rawState, io, step.line, void 0, void 0, true)) {
82487
+ throw new Error("Synchronous loop array assignment was not executable");
82488
+ }
82360
82489
  lastArg = "";
82361
82490
  } else if (step.arithStmt !== void 0) {
82362
82491
  const nonZero = this.evalSyncLoopArithStmt(step.arithStmt, rawState, io, touched, step.line);
@@ -83475,7 +83604,7 @@ ${s1}
83475
83604
  extglob: true,
83476
83605
  work: { remaining: this.budget.limits.maxExpansionBytes, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes"), allocation },
83477
83606
  expand: async (word, pattern = false) => {
83478
- const fast = !pattern ? this.fastValueWord(word, state, io, false, false, false, false) : void 0;
83607
+ const fast = !pattern ? this.fastValueWord(word, state, { ...io, nameExpansionContext: "conditional" }, false, false, false, false) : void 0;
83479
83608
  if (typeof fast === "string") return fast;
83480
83609
  return (await this.word(word, state, { ...io, nameExpansionContext: "conditional" }, false, pattern, false, pattern)).join("");
83481
83610
  },
@@ -88069,7 +88198,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
88069
88198
  invalid = true;
88070
88199
  break;
88071
88200
  }
88072
- if (flag === "N") exact = true;
88201
+ if (flag === "n" || flag === "N") exact = flag === "N";
88073
88202
  const value2 = option.slice(index + 1) || names.shift();
88074
88203
  if (value2 === void 0) invalid = true;
88075
88204
  else if (flag === "p") {
@@ -89274,16 +89403,21 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
89274
89403
  if (typeof val2 !== "string") return void 0;
89275
89404
  let transformed;
89276
89405
  if (part.transform === "Q") {
89277
- for (let k = 0; k < val2.length; k++) {
89278
- const c = val2.charCodeAt(k);
89279
- if (c < 32 || c >= 127) return void 0;
89280
- }
89281
- transformed = "'" + (val2.includes("'") ? val2.split("'").join("'\\''") : val2) + "'";
89406
+ if (byteLocale(rawState.variables)) return void 0;
89407
+ transformed = this.formatSyncTransformQ(val2);
89282
89408
  } else {
89283
- for (let k = 0; k < val2.length; k++) {
89284
- if (val2.charCodeAt(k) >= 128) return void 0;
89409
+ if (part.transform === "U") {
89410
+ transformed = val2.toUpperCase();
89411
+ } else if (part.transform === "L") {
89412
+ transformed = val2.toLowerCase();
89413
+ } else if (val2.length === 0) {
89414
+ transformed = "";
89415
+ } else if (val2.charCodeAt(0) < 128) {
89416
+ transformed = val2[0].toUpperCase() + val2.slice(1);
89417
+ } else {
89418
+ const first = [...val2][0];
89419
+ transformed = first.toUpperCase() + val2.slice(first.length);
89285
89420
  }
89286
- transformed = part.transform === "U" ? val2.toUpperCase() : part.transform === "L" ? val2.toLowerCase() : val2.length === 0 ? "" : val2[0].toUpperCase() + val2.slice(1);
89287
89421
  }
89288
89422
  if (split3 && !part.quoted) {
89289
89423
  if (transformed.length === 0 || transformed.includes(" ") || transformed.includes(" ") || transformed.includes("\n") || !rawState.noglob && hasGlobOrEscape(transformed, !!rawState.extglob)) return void 0;
@@ -89291,7 +89425,21 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
89291
89425
  out += transformed;
89292
89426
  continue;
89293
89427
  }
89294
- if (part.prefixNames !== void 0) return void 0;
89428
+ if (part.prefixNames !== void 0) {
89429
+ if (split3 && !(part.quoted && part.prefixNames === "*") || part.indirect || part.specialParameter || part.length || part.substring || part.transform !== void 0 || part.operator !== void 0 || getArraySelector(part) !== void 0 || this.budget.limits.maxExpansionFields !== Infinity || this.budget.limits.maxExpansionBytes !== Infinity || !isShellIdentifier(part.name)) {
89430
+ return void 0;
89431
+ }
89432
+ const pNames = this.collectSyncPrefixNames(part.name, rawState);
89433
+ if (pNames === void 0) return void 0;
89434
+ const ifs = rawState.variables.IFS ?? " ";
89435
+ const sep = io.nameExpansionContext === "document" || io.nameExpansionContext === "conditional" && part.prefixNames === "@" ? " " : ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
89436
+ const joined = pNames.join(sep);
89437
+ if (split3 && !part.quoted) {
89438
+ if (joined.length === 0 || joined.includes(" ") || joined.includes(" ") || joined.includes("\n")) return void 0;
89439
+ }
89440
+ out += joined;
89441
+ continue;
89442
+ }
89295
89443
  if (part.indirect || part.specialParameter) return void 0;
89296
89444
  if (part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || part.name === "DIRSTACK") return void 0;
89297
89445
  if (!isShellIdentifier(part.name)) return void 0;
@@ -89871,6 +90019,513 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
89871
90019
  if (out.length * 3 > maxBytesSmi && shellValueByteLength(out) > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
89872
90020
  return out;
89873
90021
  }
90022
+ expandSyncTrCharArray(spec) {
90023
+ if (spec.length === 0) return void 0;
90024
+ const posixClasses = {
90025
+ "[:lower:]": "abcdefghijklmnopqrstuvwxyz",
90026
+ "[:upper:]": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
90027
+ "[:digit:]": "0123456789",
90028
+ "[:alpha:]": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
90029
+ "[:alnum:]": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
90030
+ "[:space:]": " \n\v\f\r ",
90031
+ "[:blank:]": " ",
90032
+ "[:xdigit:]": "0123456789ABCDEFabcdef",
90033
+ "[:punct:]": "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
90034
+ };
90035
+ const out = [];
90036
+ for (let i = 0; i < spec.length; i++) {
90037
+ if (spec[i] === "[" && spec[i + 1] === ":") {
90038
+ const close = spec.indexOf(":]", i + 2);
90039
+ if (close === -1) return void 0;
90040
+ const cls = spec.slice(i, close + 2);
90041
+ const exp = posixClasses[cls];
90042
+ if (!exp) return void 0;
90043
+ for (let k = 0; k < exp.length; k++) out.push(exp[k]);
90044
+ i = close + 1;
90045
+ continue;
90046
+ }
90047
+ if (spec[i] === "[") return void 0;
90048
+ if (spec[i] === "\\") {
90049
+ if (i + 1 >= spec.length) return void 0;
90050
+ const next = spec[++i];
90051
+ if (next === "n") out.push("\n");
90052
+ else if (next === "t") out.push(" ");
90053
+ else if (next === "r") out.push("\r");
90054
+ else if (next === "\\") out.push("\\");
90055
+ else return void 0;
90056
+ continue;
90057
+ }
90058
+ if (i + 2 < spec.length && spec[i + 1] === "-" && spec[i + 2] !== "\\") {
90059
+ const start = spec.charCodeAt(i);
90060
+ const end = spec.charCodeAt(i + 2);
90061
+ if (start <= end && end - start <= 256) {
90062
+ for (let c = start; c <= end; c++) out.push(String.fromCharCode(c));
90063
+ i += 2;
90064
+ continue;
90065
+ }
90066
+ return void 0;
90067
+ }
90068
+ out.push(spec[i]);
90069
+ }
90070
+ return out;
90071
+ }
90072
+ evalSyncTr(input3, opArgs) {
90073
+ if (opArgs.length === 2 && !opArgs[0].startsWith("-") && !opArgs[1].startsWith("-")) {
90074
+ return this.translateSyncTr(input3, opArgs[0], opArgs[1]);
90075
+ }
90076
+ if (opArgs.length === 2 && opArgs[0] === "-d" && !opArgs[1].startsWith("-")) {
90077
+ const arr = this.expandSyncTrCharArray(opArgs[1]);
90078
+ if (!arr) return void 0;
90079
+ const delSet = new Set(arr);
90080
+ let out = "";
90081
+ for (let i = 0; i < input3.length; i++) {
90082
+ const ch = input3[i];
90083
+ if (!delSet.has(ch)) out += ch;
90084
+ }
90085
+ return out;
90086
+ }
90087
+ if (opArgs.length === 2 && opArgs[0] === "-s" && !opArgs[1].startsWith("-")) {
90088
+ const arr = this.expandSyncTrCharArray(opArgs[1]);
90089
+ if (!arr) return void 0;
90090
+ const sqSet = new Set(arr);
90091
+ let out = "";
90092
+ let prev = "";
90093
+ for (let i = 0; i < input3.length; i++) {
90094
+ const ch = input3[i];
90095
+ if (sqSet.has(ch) && ch === prev) continue;
90096
+ out += ch;
90097
+ prev = ch;
90098
+ }
90099
+ return out;
90100
+ }
90101
+ if (opArgs.length === 3 && (opArgs[0] === "-s" || opArgs[0] === "-ds" || opArgs[0] === "-sd") && !opArgs[1].startsWith("-") && !opArgs[2].startsWith("-")) {
90102
+ const stage1 = opArgs[0] === "-s" ? this.translateSyncTr(input3, opArgs[1], opArgs[2]) : this.evalSyncTr(input3, ["-d", opArgs[1]]);
90103
+ if (stage1 === void 0) return void 0;
90104
+ return this.evalSyncTr(stage1, ["-s", opArgs[2]]);
90105
+ }
90106
+ return void 0;
90107
+ }
90108
+ evalSyncJq(input3, opArgs) {
90109
+ let rawOut = false;
90110
+ let filter;
90111
+ if (opArgs.length === 1 && !opArgs[0].startsWith("-")) {
90112
+ filter = opArgs[0];
90113
+ } else if (opArgs.length === 2 && (opArgs[0] === "-r" || opArgs[0] === "--raw-output" || opArgs[0] === "-c" || opArgs[0] === "--compact-output" || opArgs[0] === "-rc" || opArgs[0] === "-cr")) {
90114
+ rawOut = opArgs[0].includes("r");
90115
+ filter = opArgs[1];
90116
+ }
90117
+ if (!filter) return void 0;
90118
+ const stages = filter.split("|").map((s) => s.trim());
90119
+ const compiledStages = [];
90120
+ for (const st of stages) {
90121
+ if (st === ".") {
90122
+ compiledStages.push([]);
90123
+ continue;
90124
+ }
90125
+ if (st === "length") {
90126
+ compiledStages.push([{ kind: "length" }]);
90127
+ continue;
90128
+ }
90129
+ if (st === "keys") {
90130
+ compiledStages.push([{ kind: "keys" }]);
90131
+ continue;
90132
+ }
90133
+ if (st === "keys[]") {
90134
+ compiledStages.push([{ kind: "keys" }, { kind: "iter" }]);
90135
+ continue;
90136
+ }
90137
+ if (!st.startsWith(".")) return void 0;
90138
+ let rest = st.slice(1);
90139
+ const ops = [];
90140
+ while (rest.length > 0) {
90141
+ if (rest.startsWith(".")) rest = rest.slice(1);
90142
+ const propM = /^([a-zA-Z_][a-zA-Z0-9_]*)/.exec(rest);
90143
+ if (propM) {
90144
+ ops.push({ kind: "prop", key: propM[1] });
90145
+ rest = rest.slice(propM[1].length);
90146
+ continue;
90147
+ }
90148
+ if (rest.startsWith("[]")) {
90149
+ ops.push({ kind: "iter" });
90150
+ rest = rest.slice(2);
90151
+ continue;
90152
+ }
90153
+ const idxM = /^\[(-?[0-9]+)\]/.exec(rest);
90154
+ if (idxM) {
90155
+ ops.push({ kind: "index", idx: Number(idxM[1]) });
90156
+ rest = rest.slice(idxM[0].length);
90157
+ continue;
90158
+ }
90159
+ return void 0;
90160
+ }
90161
+ compiledStages.push(ops);
90162
+ }
90163
+ let parsed;
90164
+ try {
90165
+ parsed = JSON.parse(input3);
90166
+ } catch {
90167
+ return void 0;
90168
+ }
90169
+ let current = [parsed];
90170
+ for (const ops of compiledStages) {
90171
+ for (const op of ops) {
90172
+ const next = [];
90173
+ for (const item of current) {
90174
+ if (op.kind === "prop") {
90175
+ if (item === null || item === void 0) next.push(null);
90176
+ else if (typeof item === "object" && !Array.isArray(item)) next.push(item[op.key] ?? null);
90177
+ else return void 0;
90178
+ } else if (op.kind === "index") {
90179
+ if (item === null || item === void 0) next.push(null);
90180
+ else if (Array.isArray(item)) {
90181
+ const i = op.idx < 0 ? item.length + op.idx : op.idx;
90182
+ next.push(i >= 0 && i < item.length ? item[i] : null);
90183
+ } else return void 0;
90184
+ } else if (op.kind === "iter") {
90185
+ if (Array.isArray(item)) {
90186
+ for (const el of item) next.push(el);
90187
+ } else if (item && typeof item === "object") {
90188
+ for (const k of Object.keys(item)) next.push(item[k]);
90189
+ } else return void 0;
90190
+ } else if (op.kind === "length") {
90191
+ if (item === null || item === void 0) next.push(0);
90192
+ else if (typeof item === "string" || Array.isArray(item)) next.push(item.length);
90193
+ else if (typeof item === "object") next.push(Object.keys(item).length);
90194
+ else return void 0;
90195
+ } else if (op.kind === "keys") {
90196
+ if (Array.isArray(item)) next.push(item.map((_, idx) => idx));
90197
+ else if (item && typeof item === "object") next.push(Object.keys(item).sort());
90198
+ else return void 0;
90199
+ }
90200
+ }
90201
+ current = next;
90202
+ }
90203
+ }
90204
+ return current.map((val) => rawOut && typeof val === "string" ? val : JSON.stringify(val ?? null));
90205
+ }
90206
+ parseSyncCutSpec(spec) {
90207
+ if (!/^(?:[1-9][0-9]{0,4}|[1-9][0-9]{0,4}-[1-9][0-9]{0,4}|[1-9][0-9]{0,4}-|-[1-9][0-9]{0,4})(?:,(?:[1-9][0-9]{0,4}|[1-9][0-9]{0,4}-[1-9][0-9]{0,4}|[1-9][0-9]{0,4}-|-[1-9][0-9]{0,4}))*$/.test(spec)) {
90208
+ return void 0;
90209
+ }
90210
+ const ranges2 = [];
90211
+ for (const part of spec.split(",")) {
90212
+ const dash = part.indexOf("-");
90213
+ if (dash === -1) {
90214
+ const n = Number(part);
90215
+ ranges2.push([n, n]);
90216
+ } else if (dash === 0) {
90217
+ const end = Number(part.slice(1));
90218
+ ranges2.push([1, end]);
90219
+ } else if (dash === part.length - 1) {
90220
+ const start = Number(part.slice(0, -1));
90221
+ ranges2.push([start, Infinity]);
90222
+ } else {
90223
+ const start = Number(part.slice(0, dash));
90224
+ const end = Number(part.slice(dash + 1));
90225
+ if (start > end) return void 0;
90226
+ ranges2.push([start, end]);
90227
+ }
90228
+ }
90229
+ return (len) => {
90230
+ const out = [];
90231
+ for (let i = 1; i <= len; i++) {
90232
+ for (let r = 0; r < ranges2.length; r++) {
90233
+ const [s, e] = ranges2[r];
90234
+ if (i >= s && i <= e) {
90235
+ out.push(i - 1);
90236
+ break;
90237
+ }
90238
+ }
90239
+ }
90240
+ return out;
90241
+ };
90242
+ }
90243
+ evalSyncCut(rawLines, opArgs, byteLocaleMode) {
90244
+ const norm = [];
90245
+ let suppressNoDelim = false;
90246
+ for (let ci = 0; ci < opArgs.length; ci++) {
90247
+ const ca = opArgs[ci];
90248
+ if (ca === "-s" || ca === "--only-delimited") {
90249
+ suppressNoDelim = true;
90250
+ } else if (ca.startsWith("-sd") || ca.startsWith("-ds")) {
90251
+ suppressNoDelim = true;
90252
+ const rest = ca.slice(3);
90253
+ if (rest.length > 0) norm.push("-d" + rest);
90254
+ else if (ci + 1 < opArgs.length) norm.push("-d" + opArgs[++ci]);
90255
+ else return void 0;
90256
+ } else if ((ca === "-d" || ca === "-f" || ca === "-c") && ci + 1 < opArgs.length) {
90257
+ norm.push(ca + opArgs[++ci]);
90258
+ } else {
90259
+ norm.push(ca);
90260
+ }
90261
+ }
90262
+ if (!suppressNoDelim && norm.length === 1 && norm[0].startsWith("-c")) {
90263
+ if (byteLocaleMode) return void 0;
90264
+ const picker2 = this.parseSyncCutSpec(norm[0].slice(2));
90265
+ if (!picker2) return void 0;
90266
+ return rawLines.map((l) => {
90267
+ const chars = Array.from(l);
90268
+ const idxs = picker2(chars.length);
90269
+ return idxs.map((i) => chars[i]).join("");
90270
+ });
90271
+ }
90272
+ let delim = " ";
90273
+ let fArg;
90274
+ if (norm.length === 1 && norm[0].startsWith("-f")) {
90275
+ fArg = norm[0];
90276
+ } else if (norm.length === 2) {
90277
+ const dCandidate = norm[0].startsWith("-d") ? norm[0] : norm[1].startsWith("-d") ? norm[1] : void 0;
90278
+ const fCandidate = norm[0].startsWith("-f") ? norm[0] : norm[1].startsWith("-f") ? norm[1] : void 0;
90279
+ if (dCandidate && dCandidate.length === 3 && fCandidate) {
90280
+ delim = dCandidate[2];
90281
+ fArg = fCandidate;
90282
+ }
90283
+ }
90284
+ if (!fArg || !fArg.startsWith("-f")) return void 0;
90285
+ const picker = this.parseSyncCutSpec(fArg.slice(2));
90286
+ if (!picker) return void 0;
90287
+ const out = [];
90288
+ for (let li = 0; li < rawLines.length; li++) {
90289
+ const l = rawLines[li];
90290
+ if (!l.includes(delim)) {
90291
+ if (!suppressNoDelim) out.push(l);
90292
+ continue;
90293
+ }
90294
+ const parts = l.split(delim);
90295
+ const idxs = picker(parts.length);
90296
+ out.push(idxs.map((i) => parts[i]).join(delim));
90297
+ }
90298
+ return out;
90299
+ }
90300
+ evalSyncSed(rawLines, opArgs) {
90301
+ let quiet = false;
90302
+ let expr;
90303
+ if (opArgs.length === 1 && !opArgs[0].startsWith("-")) {
90304
+ expr = opArgs[0];
90305
+ } else if (opArgs.length === 2 && opArgs[0] === "-e") {
90306
+ expr = opArgs[1];
90307
+ } else if (opArgs.length === 2 && opArgs[0] === "-n") {
90308
+ quiet = true;
90309
+ expr = opArgs[1];
90310
+ } else if (opArgs.length === 3 && (opArgs[0] === "-n" && opArgs[1] === "-e" || opArgs[0] === "-e" && opArgs[1] === "-n")) {
90311
+ quiet = true;
90312
+ expr = opArgs[2];
90313
+ }
90314
+ if (!expr) return void 0;
90315
+ const addrCmdM = /^(?:([1-9][0-9]{0,4}|\$)(?:,([1-9][0-9]{0,4}|\$))?|\/(\^?[a-zA-Z0-9_ :;,.-]+\$?)\/)([dp])$/.exec(expr);
90316
+ if (addrCmdM) {
90317
+ const cmdChar = addrCmdM[4];
90318
+ if (quiet && cmdChar !== "p" || !quiet && cmdChar !== "d") return void 0;
90319
+ const startSpec = addrCmdM[1];
90320
+ const endSpec = addrCmdM[2];
90321
+ const patSpec = addrCmdM[3];
90322
+ const matchLine = (l, idx1, total) => {
90323
+ if (patSpec !== void 0) {
90324
+ const aStart = patSpec.startsWith("^");
90325
+ const c1 = aStart ? patSpec.slice(1) : patSpec;
90326
+ const aEnd = c1.endsWith("$");
90327
+ const core2 = aEnd ? c1.slice(0, -1) : c1;
90328
+ if (aStart && aEnd) return l === core2;
90329
+ if (aStart) return l.startsWith(core2);
90330
+ if (aEnd) return l.endsWith(core2);
90331
+ return l.includes(core2);
90332
+ }
90333
+ const sNum = startSpec === "$" ? total : Number(startSpec);
90334
+ if (endSpec === void 0) return idx1 === sNum;
90335
+ const eNum = endSpec === "$" ? total : Number(endSpec);
90336
+ return idx1 >= sNum && idx1 <= eNum;
90337
+ };
90338
+ const out = [];
90339
+ for (let i = 0; i < rawLines.length; i++) {
90340
+ const hit = matchLine(rawLines[i], i + 1, rawLines.length);
90341
+ if (cmdChar === "p" && hit) out.push(rawLines[i]);
90342
+ else if (cmdChar === "d" && !hit) out.push(rawLines[i]);
90343
+ }
90344
+ return out;
90345
+ }
90346
+ if (quiet) return void 0;
90347
+ if (!expr.startsWith("s") || expr.length < 4) return void 0;
90348
+ const delim = expr[1];
90349
+ if (!"/#|:@,;%!".includes(delim)) return void 0;
90350
+ const parts = expr.slice(2).split(delim);
90351
+ if (parts.length !== 3) return void 0;
90352
+ const [pat, rep, flags3] = parts;
90353
+ if (flags3 !== "" && flags3 !== "g" || /[&\\\n]/.test(rep)) return void 0;
90354
+ const anchorStart = pat.startsWith("^");
90355
+ const core1 = anchorStart ? pat.slice(1) : pat;
90356
+ const anchorEnd = core1.endsWith("$");
90357
+ const core = anchorEnd ? core1.slice(0, -1) : core1;
90358
+ if (core.length === 0 || !/^[a-zA-Z0-9_ :;,/-]+$/.test(core)) return void 0;
90359
+ const isGlobal = flags3 === "g";
90360
+ return rawLines.map((l) => {
90361
+ if (anchorStart && anchorEnd) return l === core ? rep : l;
90362
+ if (anchorStart) return l.startsWith(core) ? rep + l.slice(core.length) : l;
90363
+ if (anchorEnd) return l.endsWith(core) ? l.slice(0, l.length - core.length) + rep : l;
90364
+ return isGlobal ? l.split(core).join(rep) : l.replace(core, () => rep);
90365
+ });
90366
+ }
90367
+ evalSyncGrep(rawLines, opArgs, errexit) {
90368
+ if (errexit || opArgs.length !== 1 && opArgs.length !== 2) return void 0;
90369
+ const mode = opArgs.length === 2 ? opArgs[0] : "";
90370
+ const pat = opArgs[opArgs.length - 1];
90371
+ if (pat.startsWith("-")) return void 0;
90372
+ if (opArgs.length === 2 && mode !== "-v" && mode !== "-i" && mode !== "-c" && mode !== "-F" && mode !== "-E" && mode !== "-Ei" && mode !== "-iE" && mode !== "-Ev" && mode !== "-vE") {
90373
+ return void 0;
90374
+ }
90375
+ const isCaseInsensitive = mode.includes("i");
90376
+ const isInvert = mode.includes("v");
90377
+ const isCount = mode === "-c";
90378
+ const isExtended = mode.includes("E");
90379
+ const isFixed = mode.includes("F");
90380
+ const branches = isExtended ? pat.split("|") : [pat];
90381
+ const compiledBranches = [];
90382
+ for (const br of branches) {
90383
+ if (br.length === 0) return void 0;
90384
+ const anchorStart = !isFixed && br.startsWith("^");
90385
+ const c1 = anchorStart ? br.slice(1) : br;
90386
+ const anchorEnd = !isFixed && c1.endsWith("$");
90387
+ const core = anchorEnd ? c1.slice(0, -1) : c1;
90388
+ if (core.length === 0 || !/^[a-zA-Z0-9_ :;,/-]+$/.test(core)) return void 0;
90389
+ compiledBranches.push({ anchorStart, anchorEnd, needle: isCaseInsensitive ? core.toLowerCase() : core });
90390
+ }
90391
+ const matched = [];
90392
+ for (let li = 0; li < rawLines.length; li++) {
90393
+ const l = rawLines[li];
90394
+ const hay = isCaseInsensitive ? l.toLowerCase() : l;
90395
+ let hit = false;
90396
+ for (let bi = 0; bi < compiledBranches.length; bi++) {
90397
+ const b = compiledBranches[bi];
90398
+ const ok = b.anchorStart && b.anchorEnd ? hay === b.needle : b.anchorStart ? hay.startsWith(b.needle) : b.anchorEnd ? hay.endsWith(b.needle) : hay.includes(b.needle);
90399
+ if (ok) {
90400
+ hit = true;
90401
+ break;
90402
+ }
90403
+ }
90404
+ if (isInvert ? !hit : hit) matched.push(l);
90405
+ }
90406
+ return {
90407
+ lines: isCount ? [String(matched.length)] : matched,
90408
+ status: matched.length > 0 ? 0 : 1
90409
+ };
90410
+ }
90411
+ evalSyncAwk(rawLines, opArgs) {
90412
+ if (opArgs.length < 1 || opArgs.length > 3) return void 0;
90413
+ const norm = opArgs.length === 3 && opArgs[0] === "-F" ? ["-F" + opArgs[1], opArgs[2]] : opArgs;
90414
+ let awkSep;
90415
+ let awkProg;
90416
+ if (norm.length === 1) awkProg = norm[0];
90417
+ else if (norm.length === 2 && norm[0].length === 3 && norm[0].startsWith("-F") && norm[0][2] !== "\\") {
90418
+ awkSep = norm[0].slice(2);
90419
+ awkProg = norm[1];
90420
+ }
90421
+ if (!awkProg) return void 0;
90422
+ const awkM = /^\s*\{\s*print(?:\s+((?:\$(?:[0-9]+|NF)|"[^"$\\]*")(?:\s*,?\s*(?:\$(?:[0-9]+|NF)|"[^"$\\]*"))*))?\s*;?\s*\}\s*$/.exec(awkProg);
90423
+ if (!awkM) return void 0;
90424
+ const exprBody = awkM[1]?.trim();
90425
+ const parts = [];
90426
+ if (!exprBody) {
90427
+ parts.push({ kind: "field", token: "0" });
90428
+ } else {
90429
+ const tokenRe = /\$([0-9]+|NF)|"([^"$\\]*)"|(,)/g;
90430
+ let m;
90431
+ while ((m = tokenRe.exec(exprBody)) !== null) {
90432
+ if (m[1] !== void 0) parts.push({ kind: "field", token: m[1] });
90433
+ else if (m[2] !== void 0) parts.push({ kind: "lit", text: m[2] });
90434
+ else if (m[3] !== void 0) parts.push({ kind: "lit", text: " " });
90435
+ }
90436
+ }
90437
+ return rawLines.map((l) => {
90438
+ if (parts.length === 1 && parts[0].kind === "field" && parts[0].token === "0") return l;
90439
+ const fields3 = awkSep !== void 0 ? awkSep === " " ? l.trim().split(/\s+/).filter(Boolean) : l.length === 0 ? [] : l.split(awkSep) : l.trim().split(/\s+/).filter(Boolean);
90440
+ let out = "";
90441
+ for (let pi = 0; pi < parts.length; pi++) {
90442
+ const p = parts[pi];
90443
+ if (p.kind === "lit") out += p.text;
90444
+ else if (p.token === "0") out += l;
90445
+ else {
90446
+ const idx = p.token === "NF" ? fields3.length : Number(p.token);
90447
+ out += idx === 0 ? l : idx >= 1 && idx <= fields3.length ? fields3[idx - 1] : "";
90448
+ }
90449
+ }
90450
+ return out;
90451
+ });
90452
+ }
90453
+ formatSyncTransformQ(val) {
90454
+ let ansi = false;
90455
+ for (let i = 0; i < val.length; i++) {
90456
+ const c = val.charCodeAt(i);
90457
+ if (c < 32 || c === 127) {
90458
+ ansi = true;
90459
+ break;
90460
+ }
90461
+ if (c >= 128) {
90462
+ const cp = val.codePointAt(i);
90463
+ if (/[\p{Cc}\p{Cf}\p{Cn}]/u.test(String.fromCodePoint(cp))) {
90464
+ ansi = true;
90465
+ break;
90466
+ }
90467
+ if (cp > 65535) i++;
90468
+ }
90469
+ }
90470
+ if (!ansi) {
90471
+ return "'" + (val.includes("'") ? val.split("'").join("'\\''") : val) + "'";
90472
+ }
90473
+ const escMap = { 7: "\\a", 8: "\\b", 9: "\\t", 10: "\\n", 11: "\\v", 12: "\\f", 13: "\\r", 27: "\\E" };
90474
+ let out = "$'";
90475
+ for (const ch of val) {
90476
+ const cp = ch.codePointAt(0);
90477
+ if (escMap[cp] !== void 0) out += escMap[cp];
90478
+ else if (cp === 39) out += "\\'";
90479
+ else if (cp === 92) out += "\\\\";
90480
+ else if (cp >= 32 && cp < 127 || cp >= 128 && !/[\p{Cc}\p{Cf}\p{Cn}]/u.test(ch)) out += ch;
90481
+ else {
90482
+ const bytes2 = fastSharedTextEncoder.encode(ch);
90483
+ for (let bi = 0; bi < bytes2.length; bi++) out += "\\" + bytes2[bi].toString(8).padStart(3, "0");
90484
+ }
90485
+ }
90486
+ return out + "'";
90487
+ }
90488
+ sortSyncLines(rawLines, flag) {
90489
+ const rev = flag !== void 0 && flag.includes("r");
90490
+ const num = flag !== void 0 && flag.includes("n");
90491
+ const uniq = flag !== void 0 && flag.includes("u");
90492
+ const parseNum = (s) => {
90493
+ const m = /^[ \t]*([+-]?(?:\d+(?:\.\d*)?|\.\d+))/.exec(s);
90494
+ return m ? Number(m[1]) : 0;
90495
+ };
90496
+ const sorted = [...rawLines].sort((a, b) => {
90497
+ if (num) {
90498
+ const na = parseNum(a);
90499
+ const nb = parseNum(b);
90500
+ if (na !== nb) return rev ? nb - na : na - nb;
90501
+ }
90502
+ return a < b ? rev ? 1 : -1 : a > b ? rev ? -1 : 1 : 0;
90503
+ });
90504
+ if (!uniq) return sorted;
90505
+ const dedup = [];
90506
+ for (let i = 0; i < sorted.length; i++) {
90507
+ if (i === 0 || sorted[i] !== sorted[i - 1]) dedup.push(sorted[i]);
90508
+ }
90509
+ return dedup;
90510
+ }
90511
+ translateSyncTr(input3, set1Spec, set2Spec) {
90512
+ if (set1Spec === "a-z" && set2Spec === "A-Z") return input3.toUpperCase();
90513
+ if (set1Spec === "A-Z" && set2Spec === "a-z") return input3.toLowerCase();
90514
+ const s1 = this.expandSyncTrCharArray(set1Spec);
90515
+ const s2 = this.expandSyncTrCharArray(set2Spec);
90516
+ if (!s1 || !s2 || s1.length === 0 || s2.length === 0) return void 0;
90517
+ if (s1.length === 1 && s2.length === 1) return input3.split(s1[0]).join(s2[0]);
90518
+ const map = /* @__PURE__ */ new Map();
90519
+ for (let i = 0; i < s1.length; i++) {
90520
+ map.set(s1[i], s2[Math.min(i, s2.length - 1)]);
90521
+ }
90522
+ let out = "";
90523
+ for (let i = 0; i < input3.length; i++) {
90524
+ const ch = input3[i];
90525
+ out += map.get(ch) ?? ch;
90526
+ }
90527
+ return out;
90528
+ }
89874
90529
  expandSyncTrCharSet(spec) {
89875
90530
  const out = /* @__PURE__ */ new Set();
89876
90531
  for (let i = 0; i < spec.length; i++) {
@@ -90011,61 +90666,35 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90011
90666
  sArgs.push(v);
90012
90667
  }
90013
90668
  if (sName === "cut") {
90014
- const normCut = [];
90015
- for (let ci = 0; ci < sArgs.length; ci++) {
90016
- const ca = sArgs[ci];
90017
- if ((ca === "-d" || ca === "-f") && ci + 1 < sArgs.length) {
90018
- normCut.push(ca + sArgs[++ci]);
90019
- } else {
90020
- normCut.push(ca);
90021
- }
90022
- }
90023
- sArgs.length = 0;
90024
- for (let ci = 0; ci < normCut.length; ci++) sArgs.push(normCut[ci]);
90025
- const validCut2 = sArgs.length === 2 && (sArgs[0].length === 3 && sArgs[0].startsWith("-d") && sArgs[1].length >= 3 && sArgs[1].startsWith("-f") || sArgs[0] === "-c" && /^[1-9][0-9]*-[1-9][0-9]*$/.test(sArgs[1]));
90026
- const validCut1 = sArgs.length === 1 && sArgs[0].length >= 3 && sArgs[0].startsWith("-f");
90027
- if (!validCut2 && !validCut1) return void 0;
90028
- if (sArgs[0] === "-c") {
90029
- if (byteLocale(rawState.variables)) return void 0;
90030
- const [start, end2] = sArgs[1].split("-").map(Number);
90031
- if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end2) || start > end2) return void 0;
90032
- }
90669
+ if (this.evalSyncCut([], sArgs, byteLocale(rawState.variables)) === void 0) return void 0;
90033
90670
  } else if (sName === "tr") {
90034
- const validTr2 = sArgs.length === 2 && (!sArgs[0].startsWith("-") && !sArgs[1].startsWith("-") || (sArgs[0] === "-d" || sArgs[0] === "-s") && !sArgs[1].startsWith("-"));
90035
- const validTr3 = sArgs.length === 3 && (sArgs[0] === "-ds" || sArgs[0] === "-sd" || sArgs[0] === "-s") && !sArgs[1].startsWith("-") && !sArgs[2].startsWith("-");
90036
- if (!validTr2 && !validTr3) return void 0;
90671
+ if (this.evalSyncTr("", sArgs) === void 0) return void 0;
90037
90672
  } else if (sName === "uniq") {
90038
90673
  if (sArgs.length > 1 || sArgs.length === 1 && sArgs[0] !== "-c" && sArgs[0] !== "-d" && sArgs[0] !== "-u" && sArgs[0] !== "-i") return void 0;
90039
90674
  } else if (sName === "sort") {
90040
- if (sArgs.length > 1 || sArgs.length === 1 && sArgs[0] !== "-r") return void 0;
90675
+ if (sArgs.length > 1 || sArgs.length === 1 && sArgs[0] !== "-r" && sArgs[0] !== "-u" && sArgs[0] !== "-n" && sArgs[0] !== "-rn" && sArgs[0] !== "-nr" && sArgs[0] !== "-ru" && sArgs[0] !== "-ur") return void 0;
90041
90676
  } else if (sName === "head" || sName === "tail") {
90042
- if (sArgs.length === 1 && /^-(?:n)?[0-9]+$/.test(sArgs[0])) {
90043
- const numStr = sArgs[0].startsWith("-n") ? sArgs[0].slice(2) : sArgs[0].slice(1);
90677
+ if (sArgs.length === 0) {
90678
+ sArgs.push("-n", "10");
90679
+ } else if (sArgs.length === 1 && /^-(?:n|c)?[0-9]+$/.test(sArgs[0])) {
90680
+ const flag = sArgs[0].startsWith("-c") ? "-c" : "-n";
90681
+ const numStr = sArgs[0].startsWith("-n") || sArgs[0].startsWith("-c") ? sArgs[0].slice(2) : sArgs[0].slice(1);
90044
90682
  sArgs.length = 0;
90045
- sArgs.push("-n", numStr);
90683
+ sArgs.push(flag, numStr);
90046
90684
  }
90047
- if (sArgs.length !== 2 || sArgs[0] !== "-n" || !/^[0-9]+$/.test(sArgs[1])) return void 0;
90685
+ if (sArgs.length !== 2 || sArgs[0] !== "-n" && sArgs[0] !== "-c" || !/^[0-9]+$/.test(sArgs[1])) return void 0;
90048
90686
  } else if (sName === "wc") {
90049
90687
  if (sArgs.length !== 1 || sArgs[0] !== "-l" && sArgs[0] !== "-c" && sArgs[0] !== "-w") return void 0;
90050
90688
  } else if (sName === "sed") {
90051
- const validSed1 = sArgs.length === 1 && sArgs[0].startsWith("s");
90052
- const validSed2 = sArgs.length === 2 && sArgs[0] === "-e" && sArgs[1].startsWith("s");
90053
- if (!validSed1 && !validSed2) return void 0;
90689
+ if (this.evalSyncSed([], sArgs) === void 0) return void 0;
90054
90690
  } else if (sName === "rev") {
90055
90691
  if (sArgs.length !== 0) return void 0;
90056
90692
  } else if (sName === "awk") {
90057
- if (sArgs.length === 3 && sArgs[0] === "-F") {
90058
- sArgs.splice(0, 2, "-F" + sArgs[1]);
90059
- }
90060
- const awkSepOk = sArgs.length === 1 || sArgs.length === 2 && sArgs[0].length === 3 && sArgs[0].startsWith("-F") && sArgs[0][2] !== "\\";
90061
- const awkProg = sArgs[sArgs.length - 1] ?? "";
90062
- if (!awkSepOk || !/^\s*\{\s*print(?:\s+(\$(?:[0-9]+|NF)(?:\s*,\s*\$(?:[0-9]+|NF))*))?\s*;?\s*\}\s*$/.test(awkProg)) return void 0;
90693
+ if (this.evalSyncAwk([], sArgs) === void 0) return void 0;
90063
90694
  } else if (sName === "grep") {
90064
- const grepOk = sArgs.length === 1 && !sArgs[0].startsWith("-") && /^[a-zA-Z0-9_ :;,/-]+$/.test(sArgs[0]) || sArgs.length === 2 && (sArgs[0] === "-v" || sArgs[0] === "-i" || sArgs[0] === "-c" || sArgs[0] === "-F") && /^[a-zA-Z0-9_ :;,/-]+$/.test(sArgs[1]);
90065
- if (!grepOk) return void 0;
90695
+ if (this.evalSyncGrep([], sArgs, Boolean(rawState.errexit)) === void 0) return void 0;
90066
90696
  } else if (sName === "jq") {
90067
- const jqFilter = sArgs.length === 1 ? sArgs[0] : sArgs.length === 2 && (sArgs[0] === "-r" || sArgs[0] === "--raw-output") ? sArgs[1] : void 0;
90068
- if (!jqFilter || !/^\.[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*$/.test(jqFilter)) return void 0;
90697
+ if (this.evalSyncJq("null", sArgs) === void 0) return void 0;
90069
90698
  } else if (sName === "base64") {
90070
90699
  if (sArgs.length > 1 || sArgs.length === 1 && sArgs[0] !== "-d" && sArgs[0] !== "--decode") return void 0;
90071
90700
  } else if (sName === "tac" || sName === "nl") {
@@ -90139,33 +90768,36 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90139
90768
  const extDef = stageDefs[sIdx];
90140
90769
  const stageArgs = stageArgsList[sIdx];
90141
90770
  const nextBuf = (index & 1) === 0 ? sharedSyncPipeBuf0 : sharedSyncPipeBuf1;
90142
- const isInlineCutField = firstName === "cut" && (stageArgs.length === 1 && /^-[f][1-9][0-9]*(?:,[1-9][0-9]*)*$/.test(stageArgs[0]) || stageArgs.length === 2 && stageArgs[0].length === 3 && stageArgs[0].startsWith("-d") && /^-[f][1-9][0-9]*(?:,[1-9][0-9]*)*$/.test(stageArgs[1]));
90143
- const isInlineTr = firstName === "tr" && stageArgs.length === 2 && (stageArgs[0] === "a-z" && stageArgs[1] === "A-Z" || stageArgs[0] === "A-Z" && stageArgs[1] === "a-z" || stageArgs[0] === "-d" && /^[a-zA-Z0-9_ :;,./-]+$/.test(stageArgs[1]) || stageArgs[0] === "-s" && stageArgs[1].length === 1);
90771
+ const isInlineCutField = firstName === "cut";
90772
+ const isInlineTr = firstName === "tr";
90144
90773
  const isInlineAwk = firstName === "awk";
90145
90774
  const isInlineGrep = firstName === "grep";
90146
90775
  const isInlineJq = firstName === "jq";
90147
90776
  const isInlineBase64 = firstName === "base64";
90148
90777
  const isInlineTac = firstName === "tac";
90149
90778
  const isInlineNl = firstName === "nl";
90150
- const isInlineSort = firstName === "sort" && !byteLocale(rawState.variables) && (stageArgs.length === 0 || stageArgs.length === 1 && stageArgs[0] === "-r");
90151
- const isInlineUniq = firstName === "uniq" && (stageArgs.length === 0 || stageArgs.length === 1 && (stageArgs[0] === "-d" || stageArgs[0] === "-u"));
90152
- const inlineSedMatch = firstName === "sed" ? /^s\/([a-zA-Z0-9_ :;,-]+)\/([a-zA-Z0-9_ :;,./-]*)\/(g?)$/.exec(
90153
- stageArgs.length === 1 ? stageArgs[0] : stageArgs.length === 2 && stageArgs[0] === "-e" ? stageArgs[1] : ""
90154
- ) : null;
90155
- if (firstName === "rev" || firstName === "head" || firstName === "tail" || firstName === "wc" || firstName === "cut" && stageArgs.length === 2 && stageArgs[0] === "-c" || isInlineCutField || isInlineTr || isInlineSort || isInlineUniq || inlineSedMatch !== null || isInlineAwk || isInlineGrep || isInlineJq || isInlineBase64 || isInlineTac || isInlineNl) {
90779
+ const isInlineSort = firstName === "sort" && !byteLocale(rawState.variables) && (stageArgs.length === 0 || stageArgs.length === 1 && (stageArgs[0] === "-r" || stageArgs[0] === "-u" || stageArgs[0] === "-n" || stageArgs[0] === "-rn" || stageArgs[0] === "-nr" || stageArgs[0] === "-ru" || stageArgs[0] === "-ur"));
90780
+ const isInlineUniq = firstName === "uniq" && (stageArgs.length === 0 || stageArgs.length === 1 && (stageArgs[0] === "-d" || stageArgs[0] === "-u" || stageArgs[0] === "-c"));
90781
+ const inlineSedMatch = firstName === "sed";
90782
+ if (firstName === "rev" || firstName === "head" || firstName === "tail" || firstName === "wc" || firstName === "cut" && stageArgs.length === 2 && stageArgs[0] === "-c" || isInlineCutField || isInlineTr || isInlineSort || isInlineUniq || inlineSedMatch || isInlineAwk || isInlineGrep || isInlineJq || isInlineBase64 || isInlineTac || isInlineNl) {
90156
90783
  const inStr = prevLen === 0 ? "" : sharedSyncPipeDecoder.decode(prevBuf.subarray(0, prevLen));
90157
90784
  const rawLines = inStr.length === 0 ? [] : inStr.endsWith("\n") ? inStr.slice(0, -1).split("\n") : inStr.split("\n");
90158
90785
  let outLines = [];
90159
90786
  if (firstName === "rev") {
90160
90787
  outLines = rawLines.map((l) => Array.from(l).reverse().join(""));
90161
- } else if (firstName === "head") {
90162
- outLines = rawLines.slice(0, Number(stageArgs[1]));
90163
- } else if (firstName === "tail") {
90164
- const nTail = Number(stageArgs[1]);
90165
- outLines = nTail === 0 ? [] : rawLines.slice(-nTail);
90166
- } else if (firstName === "cut" && stageArgs[0] === "-c") {
90167
- const [cStart, cEnd] = stageArgs[1].split("-").map(Number);
90168
- outLines = rawLines.map((l) => Array.from(l).slice(cStart - 1, cEnd).join(""));
90788
+ } else if (firstName === "head" || firstName === "tail") {
90789
+ const count2 = Number(stageArgs[1]);
90790
+ if (stageArgs[0] === "-c") {
90791
+ const sub = firstName === "head" ? prevBuf.subarray(0, Math.min(prevLen, count2)) : count2 === 0 ? prevBuf.subarray(0, 0) : prevBuf.subarray(Math.max(0, prevLen - count2), prevLen);
90792
+ const nextTotalBytes2 = this.budget.bytes + sub.byteLength;
90793
+ if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && sub.byteLength > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
90794
+ this.budget.bytes = nextTotalBytes2;
90795
+ nextBuf.set(sub, 0);
90796
+ prevBuf = nextBuf;
90797
+ prevLen = sub.byteLength;
90798
+ continue;
90799
+ }
90800
+ outLines = firstName === "head" ? rawLines.slice(0, count2) : count2 === 0 ? [] : rawLines.slice(-count2);
90169
90801
  } else if (firstName === "wc") {
90170
90802
  if (stageArgs[0] === "-l") {
90171
90803
  let nl = 0;
@@ -90178,52 +90810,13 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90178
90810
  outLines = [String(prevLen)];
90179
90811
  }
90180
90812
  } else if (isInlineCutField) {
90181
- const delim = stageArgs.length === 2 ? stageArgs[0][2] : " ";
90182
- const fSpec = (stageArgs.length === 2 ? stageArgs[1] : stageArgs[0]).slice(2);
90183
- const fIndices = Array.from(new Set(fSpec.split(",").map(Number))).sort((a, b) => a - b);
90184
- outLines = rawLines.map((l) => {
90185
- if (!l.includes(delim)) return l;
90186
- const parts = l.split(delim);
90187
- const picked = [];
90188
- for (let fi = 0; fi < fIndices.length; fi++) {
90189
- const idx = fIndices[fi] - 1;
90190
- if (idx >= 0 && idx < parts.length) picked.push(parts[idx]);
90191
- }
90192
- return picked.join(delim);
90193
- });
90813
+ const cutRes = this.evalSyncCut(rawLines, stageArgs, byteLocale(rawState.variables));
90814
+ if (cutRes === void 0) return void 0;
90815
+ outLines = cutRes;
90194
90816
  } else if (isInlineTr) {
90195
- let transformed = inStr;
90196
- if (stageArgs[0] === "a-z" && stageArgs[1] === "A-Z") {
90197
- transformed = inStr.replace(/[a-z]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) - 32));
90198
- } else if (stageArgs[0] === "A-Z" && stageArgs[1] === "a-z") {
90199
- transformed = inStr.replace(/[A-Z]/g, (ch) => String.fromCharCode(ch.charCodeAt(0) + 32));
90200
- } else if (stageArgs[0] === "-s") {
90201
- const sq = stageArgs[1];
90202
- let out = "";
90203
- let prevSq = false;
90204
- for (let ci = 0; ci < inStr.length; ci++) {
90205
- const ch = inStr[ci];
90206
- if (ch === sq) {
90207
- if (!prevSq) {
90208
- out += ch;
90209
- prevSq = true;
90210
- }
90211
- } else {
90212
- out += ch;
90213
- prevSq = false;
90214
- }
90215
- }
90216
- transformed = out;
90217
- } else if (stageArgs[0] === "-d") {
90218
- const delSet = this.expandSyncTrCharSet(stageArgs[1]);
90219
- let out = "";
90220
- for (let ci = 0; ci < inStr.length; ci++) {
90221
- const ch = inStr[ci];
90222
- if (!delSet.has(ch)) out += ch;
90223
- }
90224
- transformed = out;
90225
- }
90226
- const outByteLen2 = transformed.length * 3 > 127 ? shellValueByteLength(transformed) : transformed.length;
90817
+ const transformed = this.evalSyncTr(inStr, stageArgs);
90818
+ if (transformed === void 0) return void 0;
90819
+ const outByteLen2 = shellValueByteLength(transformed);
90227
90820
  if (outByteLen2 > nextBuf.byteLength) return void 0;
90228
90821
  const nextTotalBytes2 = this.budget.bytes + outByteLen2;
90229
90822
  if (nextTotalBytes2 > this.budget.maxOutputBytesSmi && outByteLen2 > this.budget.limits.maxOutputBytes - this.budget.bytes) this.budget.fail("maxOutputBytes");
@@ -90233,8 +90826,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90233
90826
  prevLen = written2;
90234
90827
  continue;
90235
90828
  } else if (isInlineSort) {
90236
- const revSort = stageArgs[0] === "-r";
90237
- outLines = [...rawLines].sort((a, b) => a < b ? revSort ? 1 : -1 : a > b ? revSort ? -1 : 1 : 0);
90829
+ outLines = this.sortSyncLines(rawLines, stageArgs[0]);
90238
90830
  } else if (isInlineUniq) {
90239
90831
  const mode = stageArgs[0];
90240
90832
  outLines = [];
@@ -90244,60 +90836,24 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90244
90836
  while (uEnd < rawLines.length && rawLines[uEnd] === rawLines[uIdx]) uEnd++;
90245
90837
  const count2 = uEnd - uIdx;
90246
90838
  if (mode === "-d" ? count2 > 1 : mode === "-u" ? count2 === 1 : true) {
90247
- outLines.push(rawLines[uIdx]);
90839
+ outLines.push(mode === "-c" ? `${String(count2).padStart(7, " ")} ${rawLines[uIdx]}` : rawLines[uIdx]);
90248
90840
  }
90249
90841
  uIdx = uEnd;
90250
90842
  }
90251
- } else if (inlineSedMatch !== null) {
90252
- const pat = inlineSedMatch[1];
90253
- const rep = inlineSedMatch[2];
90254
- const isGlobal = inlineSedMatch[3] === "g";
90255
- outLines = rawLines.map((l) => isGlobal ? l.split(pat).join(rep) : l.replace(pat, () => rep));
90843
+ } else if (inlineSedMatch) {
90844
+ const sedRes = this.evalSyncSed(rawLines, stageArgs);
90845
+ if (sedRes === void 0) return void 0;
90846
+ outLines = sedRes;
90256
90847
  } else if (isInlineAwk) {
90257
- const awkSep = stageArgs.length === 2 ? stageArgs[0].slice(2) : void 0;
90258
- const awkProg = stageArgs[stageArgs.length - 1];
90259
- const awkM = /^\s*\{\s*print(?:\s+(\$(?:[0-9]+|NF)(?:\s*,\s*\$(?:[0-9]+|NF))*))?\s*;?\s*\}\s*$/.exec(awkProg);
90260
- if (!awkM) return void 0;
90261
- const toks = awkM[1] ? awkM[1].split(",").map((t) => t.trim().slice(1)) : ["0"];
90262
- outLines = [];
90263
- for (let li = 0; li < rawLines.length; li++) {
90264
- const l = rawLines[li];
90265
- if (toks.length === 1 && toks[0] === "0") {
90266
- outLines.push(l);
90267
- continue;
90268
- }
90269
- let fields3;
90270
- if (awkSep === void 0 || awkSep === " ") {
90271
- const tr = l.replace(/^[ \t]+|[ \t]+$/g, "");
90272
- fields3 = tr.length === 0 ? [] : tr.split(/[ \t]+/);
90273
- } else {
90274
- fields3 = l.length === 0 ? [] : l.split(awkSep);
90275
- }
90276
- const vals = [];
90277
- for (let ti = 0; ti < toks.length; ti++) {
90278
- const tk = toks[ti];
90279
- if (tk === "0") vals.push(l);
90280
- else if (tk === "NF") vals.push(fields3.length > 0 ? fields3[fields3.length - 1] : l);
90281
- else {
90282
- const idx = Number(tk);
90283
- vals.push(idx >= 1 && idx <= fields3.length ? fields3[idx - 1] : "");
90284
- }
90285
- }
90286
- outLines.push(vals.join(" "));
90287
- }
90848
+ const awkRes = this.evalSyncAwk(rawLines, stageArgs);
90849
+ if (awkRes === void 0) return void 0;
90850
+ outLines = awkRes;
90288
90851
  } else if (isInlineGrep) {
90289
- const gMode = stageArgs.length === 2 ? stageArgs[0] : "";
90290
- const gPat = stageArgs[stageArgs.length - 1];
90291
- const gPatLower = gMode === "-i" ? gPat.toLowerCase() : gPat;
90292
- const matched = [];
90293
- for (let li = 0; li < rawLines.length; li++) {
90294
- const l = rawLines[li];
90295
- const hit = gMode === "-i" ? l.toLowerCase().includes(gPatLower) : l.includes(gPat);
90296
- if (gMode === "-v" ? !hit : hit) matched.push(l);
90297
- }
90298
- stageStatus = matched.length === 0 ? 1 : 0;
90852
+ const grepRes = this.evalSyncGrep(rawLines, stageArgs, Boolean(rawState.errexit));
90853
+ if (grepRes === void 0) return void 0;
90854
+ stageStatus = grepRes.status;
90299
90855
  if (stageStatus !== 0) failureStatus = stageStatus;
90300
- outLines = gMode === "-c" ? [String(matched.length)] : matched;
90856
+ outLines = grepRes.lines;
90301
90857
  } else if (isInlineTac) {
90302
90858
  if (inStr.length > 0 && !inStr.endsWith("\n")) return void 0;
90303
90859
  outLines = [...rawLines].reverse();
@@ -90328,40 +90884,9 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90328
90884
  continue;
90329
90885
  }
90330
90886
  } else if (isInlineJq) {
90331
- const rawOut = stageArgs.length === 2;
90332
- const filter = stageArgs[stageArgs.length - 1];
90333
- const trimmedJson = inStr.trim();
90334
- if (!trimmedJson.startsWith("{") || trimmedJson.includes("\n")) return void 0;
90335
- let parsedObj;
90336
- try {
90337
- parsedObj = JSON.parse(trimmedJson);
90338
- } catch {
90339
- return void 0;
90340
- }
90341
- if (!parsedObj || typeof parsedObj !== "object" || Array.isArray(parsedObj)) return void 0;
90342
- const keys2 = filter.slice(1).split(".");
90343
- let cur = parsedObj;
90344
- for (let ki = 0; ki < keys2.length; ki++) {
90345
- if (cur === null || cur === void 0 || typeof cur !== "object") {
90346
- cur = void 0;
90347
- break;
90348
- }
90349
- if (Array.isArray(cur)) return void 0;
90350
- cur = Object.hasOwn(cur, keys2[ki]) ? cur[keys2[ki]] : void 0;
90351
- }
90352
- if (cur !== null && cur !== void 0 && typeof cur === "object") return void 0;
90353
- if (rawOut) {
90354
- if (typeof cur === "string") {
90355
- if (cur.includes("\n")) return void 0;
90356
- outLines = [cur];
90357
- } else if (typeof cur === "number" || typeof cur === "boolean") {
90358
- outLines = [String(cur)];
90359
- } else {
90360
- outLines = ["null"];
90361
- }
90362
- } else {
90363
- outLines = [JSON.stringify(cur ?? null)];
90364
- }
90887
+ const jqRes = this.evalSyncJq(inStr.trim(), stageArgs);
90888
+ if (jqRes === void 0) return void 0;
90889
+ outLines = jqRes;
90365
90890
  }
90366
90891
  const preservesTerminator = firstName === "head" || firstName === "tail" || firstName === "rev" || firstName === "sed";
90367
90892
  const terminated = !preservesTerminator || inStr.endsWith("\n") || firstName === "head" && outLines.length < rawLines.length;
@@ -90430,64 +90955,65 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90430
90955
  }
90431
90956
  if (pipeline.commands.length !== 1) return void 0;
90432
90957
  let cmd = pipeline.commands[0];
90433
- if ((cmd.kind === "arithmetic-for" || cmd.kind === "for") && cmd.redirects.length === 0 && !rawState.errexit && !rawState.nounset && !rawState.readonlyVariables?.size) {
90958
+ if ((cmd.kind === "if" || cmd.kind === "case") && this.isPureSyncSubIfOrCase(cmd, rawState)) {
90434
90959
  const monitor = stateMonitor(state);
90435
- if (monitor) {
90436
- const store = arrayStore(rawState);
90437
- const existing = store?.get("PIPESTATUS");
90438
- const elem0 = existing ? existing.values.get(0) : void 0;
90439
- const canMutatePipeStatus = !existing || !existing.associative && existing.references === 1 && existing.values.size === 1 && existing.maximum === 0 && elem0 !== void 0 && elem0.text.references === 1 && elem0.text.bytes === 1 && !store.watches.has("PIPESTATUS") && !monitor.hasOverlay("PIPESTATUS") && !rawState.readonlyVariables?.has("PIPESTATUS");
90440
- if (canMutatePipeStatus) {
90441
- const capture = new Capture();
90442
- capture.budget = this.budget;
90443
- capture.signal = this.signal;
90444
- const { descriptors: ignoredDescriptors, ...ioRest } = io;
90445
- const subIO = { ...ioRest, stdout: capture };
90446
- if (this.canSyncLoopBody(cmd.body, rawState, subIO)) {
90447
- const { steps: bodySteps } = this.buildSyncLoopBody(cmd, rawState, subIO);
90448
- if (bodySteps.length > 0 && bodySteps.every((s) => s.isStdoutEcho === true)) {
90449
- const indName = cmd.kind === "for" ? cmd.name : /^([a-zA-Z_][a-zA-Z_0-9]*)\s*=/.exec(cmd.expressions[0].source.trim())?.[1];
90450
- if (indName && !store?.get(indName)) {
90451
- const hadInd = Object.prototype.hasOwnProperty.call(rawState.variables, indName);
90452
- const prevInd = rawState.variables[indName];
90453
- const prevLastArg = rawState.lastArgument;
90454
- let loopRes;
90455
- rawState.depth++;
90456
- try {
90457
- loopRes = this.trySyncLoop(cmd, pipeline, rawState, monitor, store, existing, elem0, true, subIO, part.line);
90458
- } finally {
90459
- rawState.depth--;
90460
- if (prevLastArg !== void 0) rawState.lastArgument = prevLastArg;
90461
- else delete rawState.lastArgument;
90462
- if (hadInd && prevInd !== void 0) monitor.publishStringVariable(indName, prevInd);
90463
- else {
90464
- delete rawState.variables[indName];
90465
- monitor.values.invalidate(indName);
90466
- }
90467
- }
90468
- if (loopRes !== void 0) {
90469
- rawState.substitutionStatus = loopRes;
90470
- rawState.status = loopRes;
90471
- const bytes2 = capture.takeBytes();
90472
- let str = sharedSyncPipeDecoder.decode(bytes2);
90473
- let end = str.length;
90474
- while (end > 0 && str.charCodeAt(end - 1) === 10) end--;
90475
- if (end < str.length) str = str.slice(0, end);
90476
- return str;
90477
- }
90478
- }
90960
+ if (!monitor) return void 0;
90961
+ let selectedBody;
90962
+ if (cmd.kind === "if") {
90963
+ for (const br of cmd.branches) {
90964
+ const bc = br.condition.lists[0].pipelines[0].commands[0];
90965
+ let condOk = false;
90966
+ if (bc.kind === "arithmetic") {
90967
+ condOk = this.evalSyncLoopArithStmt(bc.expression, rawState, io, this._syncArithTouched ?? /* @__PURE__ */ new Set(), bc.line ?? part.line) === true;
90968
+ } else if (bc.kind === "conditional") {
90969
+ const st = this.tryEvalConditionalSync(bc.expression, rawState, monitor, arrayStore(rawState), io, bc.line ?? part.line);
90970
+ if (st === void 0) return void 0;
90971
+ condOk = st === 0;
90972
+ } else {
90973
+ const bExpr = this.extractPosixBracketCondExpr(bc, rawState, true, br.body);
90974
+ if (!bExpr) return void 0;
90975
+ const st = this.tryEvalConditionalSync(bExpr, rawState, monitor, arrayStore(rawState), io, bc.line ?? part.line);
90976
+ if (st === void 0) return void 0;
90977
+ condOk = st === 0;
90978
+ }
90979
+ if (condOk) {
90980
+ selectedBody = br.body;
90981
+ break;
90982
+ }
90983
+ }
90984
+ if (!selectedBody) selectedBody = cmd.otherwise;
90985
+ } else {
90986
+ const subj = this.fastValueWord(cmd.subject, rawState, io, false, false, false, false, void 0, part.line);
90987
+ if (typeof subj !== "string") return void 0;
90988
+ const work = { remaining: this.budget.limits.maxExpansionBytes, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
90989
+ for (const cl of cmd.clauses) {
90990
+ let matched = false;
90991
+ for (const pw of cl.patterns) {
90992
+ if (pw.plain !== void 0 && tryMatchesPatternSync(pw.plain, subj, work, false, false) === true) {
90993
+ matched = true;
90994
+ break;
90479
90995
  }
90480
90996
  }
90997
+ if (matched) {
90998
+ selectedBody = cl.body;
90999
+ break;
91000
+ }
90481
91001
  }
90482
91002
  }
91003
+ if (!selectedBody) {
91004
+ rawState.substitutionStatus = 0;
91005
+ rawState.status = 0;
91006
+ return "";
91007
+ }
91008
+ cmd = selectedBody.lists[0].pipelines[0].commands[0];
90483
91009
  }
90484
91010
  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 && this.isPureArgWord(cmd.redirects[0].target, rawState);
90485
91011
  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);
90486
91012
  if (cmd.kind !== "simple" || cmd.redirects.length > 0 && !hasSingleStdinRedir && !hasSingleHereStringRedir || cmd.words.length === 0) return void 0;
90487
91013
  let w0Plain = cmd.words[0].plain;
90488
91014
  if (!w0Plain || rawState.extensions?.builtins.has(w0Plain)) return void 0;
90489
- const isSingleFileTool = w0Plain === "cat" || w0Plain === "head" || w0Plain === "tail" || w0Plain === "jq" || w0Plain === "awk" || w0Plain === "grep" || w0Plain === "sed" || w0Plain === "cut" || w0Plain === "wc" || w0Plain === "sort" || w0Plain === "tr" || hasSingleHereStringRedir && (w0Plain === "base64" || w0Plain === "rev" || w0Plain === "tac" || w0Plain === "nl");
90490
- if (isSingleFileTool && !hasShellFunction(rawState, w0Plain) && this.commands.has(w0Plain)) {
91015
+ const isSingleFileTool = 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");
91016
+ if (isSingleFileTool && !hasShellFunction(rawState, w0Plain) && (this.commands.has(w0Plain) || (w0Plain === "rev" || w0Plain === "tac") && Boolean(this.getExternalCommand(w0Plain)))) {
90491
91017
  const allArgs = [];
90492
91018
  let fOk = true;
90493
91019
  for (let i = 1; i < cmd.words.length; i++) {
@@ -90527,111 +91053,37 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90527
91053
  fileRes = fileStr;
90528
91054
  } else if ((w0Plain === "head" || w0Plain === "tail") && opArgs.length <= 2) {
90529
91055
  let count2 = opArgs.length === 0 ? 10 : void 0;
91056
+ let byteCount2;
90530
91057
  if (opArgs.length === 1 && opArgs[0].startsWith("-n") && /^[0-9]{1,5}$/.test(opArgs[0].slice(2))) count2 = Number(opArgs[0].slice(2));
91058
+ else if (opArgs.length === 1 && opArgs[0].startsWith("-c") && /^[0-9]{1,5}$/.test(opArgs[0].slice(2))) byteCount2 = Number(opArgs[0].slice(2));
90531
91059
  else if (opArgs.length === 1 && /^-[0-9]{1,5}$/.test(opArgs[0])) count2 = Number(opArgs[0].slice(1));
90532
91060
  else if (opArgs.length === 2 && opArgs[0] === "-n" && /^[0-9]{1,5}$/.test(opArgs[1])) count2 = Number(opArgs[1]);
91061
+ else if (opArgs.length === 2 && opArgs[0] === "-c" && /^[0-9]{1,5}$/.test(opArgs[1])) byteCount2 = Number(opArgs[1]);
90533
91062
  if (count2 !== void 0) {
90534
91063
  const sliced = w0Plain === "head" ? rawLines.slice(0, count2) : count2 === 0 ? [] : rawLines.slice(-count2);
90535
91064
  fileRes = sliced.join("\n");
91065
+ } else if (byteCount2 !== void 0) {
91066
+ const slicedBytes = w0Plain === "head" ? view.subarray(0, Math.min(view.byteLength, byteCount2)) : byteCount2 === 0 ? view.subarray(0, 0) : view.subarray(Math.max(0, view.byteLength - byteCount2), view.byteLength);
91067
+ fileRes = sharedSyncPipeDecoder.decode(slicedBytes);
90536
91068
  }
90537
- } else if (w0Plain === "jq" && (opArgs.length === 1 || opArgs.length === 2)) {
90538
- const rawMode = opArgs.length === 2 && (opArgs[0] === "-r" || opArgs[0] === "--raw-output");
90539
- const jqFilter = opArgs.length === 1 ? opArgs[0] : rawMode ? opArgs[1] : "";
90540
- if (/^\.[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*$/.test(jqFilter)) {
90541
- try {
90542
- let cur = JSON.parse(fileStr.trim());
90543
- const keys2 = jqFilter.slice(1).split(".");
90544
- let validJq = true;
90545
- for (const k of keys2) {
90546
- if (cur !== null && typeof cur === "object" && !Array.isArray(cur)) {
90547
- cur = cur[k];
90548
- } else {
90549
- validJq = false;
90550
- break;
90551
- }
90552
- }
90553
- if (validJq && cur !== void 0 && (cur === null || typeof cur === "string" || typeof cur === "number" || typeof cur === "boolean")) {
90554
- fileRes = cur === null ? "null" : typeof cur === "string" ? rawMode ? cur : JSON.stringify(cur) : String(cur);
90555
- }
90556
- } catch {
90557
- }
90558
- }
90559
- } else if (w0Plain === "awk" && (opArgs.length >= 1 && opArgs.length <= 3)) {
90560
- const normAwk = opArgs.length === 3 && opArgs[0] === "-F" ? ["-F" + opArgs[1], opArgs[2]] : opArgs;
90561
- let awkSep;
90562
- let awkProg;
90563
- if (normAwk.length === 1) awkProg = normAwk[0];
90564
- else if (normAwk.length === 2 && normAwk[0].length === 3 && normAwk[0].startsWith("-F") && normAwk[0][2] !== "\\") {
90565
- awkSep = normAwk[0].slice(2);
90566
- awkProg = normAwk[1];
90567
- }
90568
- const awkM = awkProg ? /^\s*\{\s*print(?:\s+(\$(?:[0-9]+|NF)(?:\s*,\s*\$(?:[0-9]+|NF))*))?\s*;?\s*\}\s*$/.exec(awkProg) : null;
90569
- if (awkM) {
90570
- const toks = awkM[1] ? awkM[1].split(",").map((t) => t.trim().slice(1)) : ["0"];
90571
- const outLines = [];
90572
- for (let li = 0; li < rawLines.length; li++) {
90573
- const l = rawLines[li];
90574
- if (toks.length === 1 && toks[0] === "0") {
90575
- outLines.push(l);
90576
- } else {
90577
- const fields3 = awkSep !== void 0 ? awkSep === " " ? l.trim().split(/\s+/).filter(Boolean) : l.split(awkSep) : l.trim().split(/\s+/).filter(Boolean);
90578
- const vals = toks.map((tk) => {
90579
- if (tk === "0") return l;
90580
- const idx = tk === "NF" ? fields3.length : Number(tk);
90581
- if (idx === 0) return l;
90582
- return idx >= 1 && idx <= fields3.length ? fields3[idx - 1] : "";
90583
- });
90584
- outLines.push(vals.join(" "));
90585
- }
90586
- }
90587
- fileRes = outLines.join("\n");
90588
- }
90589
- } else if (w0Plain === "grep" && !rawState.errexit && (opArgs.length === 1 || opArgs.length === 2)) {
90590
- const mode = opArgs.length === 2 ? opArgs[0] : "";
90591
- const pat = opArgs[opArgs.length - 1];
90592
- if ((opArgs.length === 1 || mode === "-v" || mode === "-i" || mode === "-c" || mode === "-F") && /^[a-zA-Z0-9_ :;,/-]+$/.test(pat)) {
90593
- const needle = mode === "-i" ? pat.toLowerCase() : pat;
90594
- const matched = [];
90595
- for (let li = 0; li < rawLines.length; li++) {
90596
- const l = rawLines[li];
90597
- const hay = mode === "-i" ? l.toLowerCase() : l;
90598
- const ok = hay.includes(needle);
90599
- if (mode === "-v" ? !ok : ok) matched.push(l);
90600
- }
90601
- exitStatus = matched.length > 0 ? 0 : 1;
90602
- fileRes = mode === "-c" ? String(matched.length) : matched.join("\n");
90603
- }
90604
- } else if (w0Plain === "sed" && (opArgs.length === 1 || opArgs.length === 2 && opArgs[0] === "-e")) {
90605
- const sedExpr = opArgs[opArgs.length - 1];
90606
- const sedM = /^s\/([a-zA-Z0-9_ :;,-]+)\/([a-zA-Z0-9_ :;,./-]*)\/(g?)$/.exec(sedExpr);
90607
- if (sedM) {
90608
- const pat = sedM[1];
90609
- const rep = sedM[2];
90610
- const isGlobal = sedM[3] === "g";
90611
- fileRes = rawLines.map((l) => isGlobal ? l.split(pat).join(rep) : l.replace(pat, () => rep)).join("\n");
90612
- }
90613
- } else if (w0Plain === "cut" && opArgs.length >= 1 && opArgs.length <= 4) {
90614
- const normCut = [];
90615
- for (let ci = 0; ci < opArgs.length; ci++) {
90616
- const ca = opArgs[ci];
90617
- if ((ca === "-d" || ca === "-f") && ci + 1 < opArgs.length) normCut.push(ca + opArgs[++ci]);
90618
- else normCut.push(ca);
90619
- }
90620
- if (normCut.length === 2 && normCut[0] === "-c" && /^[1-9][0-9]*-[1-9][0-9]*$/.test(normCut[1])) {
90621
- const [cStart, cEnd] = normCut[1].split("-").map(Number);
90622
- fileRes = rawLines.map((l) => Array.from(l).slice(cStart - 1, cEnd).join("")).join("\n");
90623
- } else {
90624
- const delim = normCut.length === 2 && normCut[0].length === 3 && normCut[0].startsWith("-d") ? normCut[0][2] : normCut.length === 1 ? " " : void 0;
90625
- const fSpec = normCut.length === 2 ? normCut[1] : normCut[0];
90626
- if (delim !== void 0 && fSpec && fSpec.startsWith("-f") && /^[1-9][0-9]*(?:,[1-9][0-9]*)*$/.test(fSpec.slice(2))) {
90627
- const fIdxs = fSpec.slice(2).split(",").map((s) => Number(s) - 1);
90628
- fileRes = rawLines.map((l) => {
90629
- if (!l.includes(delim)) return l;
90630
- const parts = l.split(delim);
90631
- return fIdxs.map((idx) => idx < parts.length ? parts[idx] : "").join(delim);
90632
- }).join("\n");
90633
- }
91069
+ } else if (w0Plain === "jq") {
91070
+ const jqRes = this.evalSyncJq(fileStr.trim(), opArgs);
91071
+ if (jqRes !== void 0) fileRes = jqRes.join("\n");
91072
+ } else if (w0Plain === "awk") {
91073
+ const awkRes = this.evalSyncAwk(rawLines, opArgs);
91074
+ if (awkRes !== void 0) fileRes = awkRes.join("\n");
91075
+ } else if (w0Plain === "grep") {
91076
+ const grepRes = this.evalSyncGrep(rawLines, opArgs, Boolean(rawState.errexit));
91077
+ if (grepRes !== void 0) {
91078
+ exitStatus = grepRes.status;
91079
+ fileRes = grepRes.lines.join("\n");
90634
91080
  }
91081
+ } else if (w0Plain === "sed") {
91082
+ const sedRes = this.evalSyncSed(rawLines, opArgs);
91083
+ if (sedRes !== void 0) fileRes = sedRes.join("\n");
91084
+ } else if (w0Plain === "cut") {
91085
+ const cutRes = this.evalSyncCut(rawLines, opArgs, byteLocale(rawState.variables));
91086
+ if (cutRes !== void 0) fileRes = cutRes.join("\n");
90635
91087
  } else if (w0Plain === "wc" && opArgs.length === 1 && (opArgs[0] === "-l" || opArgs[0] === "-c" || opArgs[0] === "-w")) {
90636
91088
  let count2 = 0;
90637
91089
  if (opArgs[0] === "-l") {
@@ -90643,38 +91095,24 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
90643
91095
  count2 = trimmed.length === 0 ? 0 : trimmed.split(/\s+/).length;
90644
91096
  }
90645
91097
  fileRes = hasSingleStdinRedir || hasSingleHereStringRedir ? String(count2) : `${count2} ${fileArg}`;
90646
- } else if (w0Plain === "sort" && !byteLocale(rawState.variables) && (opArgs.length === 0 || opArgs.length === 1 && opArgs[0] === "-r")) {
90647
- const revSort = opArgs[0] === "-r";
90648
- fileRes = [...rawLines].sort((a, b) => a < b ? revSort ? 1 : -1 : a > b ? revSort ? -1 : 1 : 0).join("\n");
90649
- } else if (w0Plain === "tr" && (hasSingleStdinRedir || hasSingleHereStringRedir) && opArgs.length === 2) {
90650
- if (opArgs[0] === "a-z" && opArgs[1] === "A-Z") fileRes = fileStr.toUpperCase();
90651
- else if (opArgs[0] === "A-Z" && opArgs[1] === "a-z") fileRes = fileStr.toLowerCase();
90652
- else if (opArgs[0] === "-d" && /^[a-zA-Z0-9_ :;,./-]+$/.test(opArgs[1])) {
90653
- const delSet = this.expandSyncTrCharSet(opArgs[1]);
90654
- let out = "";
90655
- for (let ci = 0; ci < fileStr.length; ci++) {
90656
- const ch = fileStr[ci];
90657
- if (!delSet.has(ch)) out += ch;
90658
- }
90659
- fileRes = out;
90660
- } else if (opArgs[0] === "-s" && opArgs[1].length === 1) {
90661
- const sq = opArgs[1];
90662
- let out = "";
90663
- let prevSq = false;
90664
- for (let ci = 0; ci < fileStr.length; ci++) {
90665
- const ch = fileStr[ci];
90666
- if (ch === sq) {
90667
- if (!prevSq) {
90668
- out += ch;
90669
- prevSq = true;
90670
- }
90671
- } else {
90672
- out += ch;
90673
- prevSq = false;
90674
- }
91098
+ } else if (w0Plain === "sort" && !byteLocale(rawState.variables) && (opArgs.length === 0 || opArgs.length === 1 && (opArgs[0] === "-r" || opArgs[0] === "-u" || opArgs[0] === "-n" || opArgs[0] === "-rn" || opArgs[0] === "-nr" || opArgs[0] === "-ru" || opArgs[0] === "-ur"))) {
91099
+ fileRes = this.sortSyncLines(rawLines, opArgs[0]).join("\n");
91100
+ } else if (w0Plain === "uniq" && (opArgs.length === 0 || opArgs.length === 1 && (opArgs[0] === "-d" || opArgs[0] === "-u" || opArgs[0] === "-c"))) {
91101
+ const mode = opArgs[0];
91102
+ const outLines = [];
91103
+ let uIdx = 0;
91104
+ while (uIdx < rawLines.length) {
91105
+ let uEnd = uIdx + 1;
91106
+ while (uEnd < rawLines.length && rawLines[uEnd] === rawLines[uIdx]) uEnd++;
91107
+ const count2 = uEnd - uIdx;
91108
+ if (mode === "-d" ? count2 > 1 : mode === "-u" ? count2 === 1 : true) {
91109
+ outLines.push(mode === "-c" ? `${String(count2).padStart(7, " ")} ${rawLines[uIdx]}` : rawLines[uIdx]);
90675
91110
  }
90676
- fileRes = out;
91111
+ uIdx = uEnd;
90677
91112
  }
91113
+ fileRes = outLines.join("\n");
91114
+ } else if (w0Plain === "tr" && (hasSingleStdinRedir || hasSingleHereStringRedir)) {
91115
+ fileRes = this.evalSyncTr(fileStr, opArgs);
90678
91116
  } else if (hasSingleHereStringRedir && w0Plain === "base64" && (opArgs.length === 0 || opArgs.length === 1 && (opArgs[0] === "-d" || opArgs[0] === "--decode"))) {
90679
91117
  if (opArgs.length === 0) fileRes = this.syncBase64Encode(view);
90680
91118
  else fileRes = sharedSyncPipeDecoder.decode(this.syncBase64DecodeBytes(fileStr));