@poe-platform/safe-bash 0.1.737 → 0.1.738

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.
Files changed (24) hide show
  1. package/dist/safe-bash/chunks/{chunk-ZFV5FGGH.js → chunk-E2FTAYLG.js} +15 -16
  2. package/dist/safe-bash/chunks/{chunk-ZFV5FGGH.js.map → chunk-E2FTAYLG.js.map} +2 -2
  3. package/dist/safe-bash/chunks/{chunk-DFNSXDHP.js → chunk-JNHKE26E.js} +2 -2
  4. package/dist/safe-bash/chunks/{chunk-N3RTTKMA.js → chunk-JTKTBT3B.js} +2 -2
  5. package/dist/safe-bash/command-assets/git_rust-NOIGQE52.wasm +0 -0
  6. package/dist/safe-bash/command-chunks/{chunk-L6GGCZOK.js → chunk-5EOMWWKN.js} +16 -15
  7. package/dist/safe-bash/command-chunks/chunk-5EOMWWKN.js.map +7 -0
  8. package/dist/safe-bash/command-chunks/{chunk-YXAPLUY4.js → chunk-WFMUMKBQ.js} +2 -2
  9. package/dist/safe-bash/core.browser.js +443 -180
  10. package/dist/safe-bash/core.browser.js.map +3 -3
  11. package/dist/safe-bash/shell/runtime.d.ts +3 -0
  12. package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
  13. package/dist/safe-bash/shell/runtime.js +540 -205
  14. package/dist/safe-bash/shell/runtime.js.map +1 -1
  15. package/dist/safe-bash-command-git/index.js +1 -1
  16. package/dist/safe-bash-regex-engine/index.js +2 -2
  17. package/dist/safe-bash-regex-engine/text/regex.js +2 -2
  18. package/dist/safe-bash-regex-engine/text/replacement-buffer.js +1 -1
  19. package/package.json +2 -2
  20. package/dist/safe-bash/command-assets/git_rust-CB24IEB6.wasm +0 -0
  21. package/dist/safe-bash/command-chunks/chunk-L6GGCZOK.js.map +0 -7
  22. /package/dist/safe-bash/chunks/{chunk-DFNSXDHP.js.map → chunk-JNHKE26E.js.map} +0 -0
  23. /package/dist/safe-bash/chunks/{chunk-N3RTTKMA.js.map → chunk-JTKTBT3B.js.map} +0 -0
  24. /package/dist/safe-bash/command-chunks/{chunk-YXAPLUY4.js.map → chunk-WFMUMKBQ.js.map} +0 -0
@@ -69944,6 +69944,26 @@ function hasActiveVariableAttributes(state) {
69944
69944
  }
69945
69945
  return false;
69946
69946
  }
69947
+ function hasNonNamerefAttributes(state) {
69948
+ const attrs = state.variableAttributes;
69949
+ if (!attrs || attrs.size === 0) return false;
69950
+ for (const [k, val] of attrs.entries()) {
69951
+ if (val.length === 0) continue;
69952
+ if (val !== "n") return true;
69953
+ const ref = state.variables[k];
69954
+ if (!ref || !isShellIdentifier(ref) || ref === k || attrs.get(ref)) return true;
69955
+ }
69956
+ return false;
69957
+ }
69958
+ function resolveSyncNameref(state, name2) {
69959
+ const attrs = state.variableAttributes;
69960
+ if (!attrs || attrs.size === 0) return name2;
69961
+ if (attrs.get(name2) === "n") {
69962
+ const ref = state.variables[name2];
69963
+ if (ref && isShellIdentifier(ref) && ref !== name2 && !attrs.get(ref)) return ref;
69964
+ }
69965
+ return name2;
69966
+ }
69947
69967
  function publishVariable(state, name2, value2) {
69948
69968
  const monitor = stateMonitor(state);
69949
69969
  if (monitor) {
@@ -71152,6 +71172,7 @@ function resolveSimpleArithOperand(tok, rawState, monitor, activeArrayStore, syn
71152
71172
  }
71153
71173
  tok = c1 === 123 ? tok.slice(2, -1) : tok.slice(1);
71154
71174
  }
71175
+ tok = resolveSyncNameref(rawState, tok);
71155
71176
  if (rawState.nounset || activeArrayStore?.bindings.has(tok) || monitor?.hasOverlay(tok) || activeArrayStore?.watches.has(tok)) return void 0;
71156
71177
  const raw = rawState.variables[tok];
71157
71178
  if (raw === void 0 || raw === "") return 0;
@@ -71881,7 +71902,11 @@ var Runtime = class _Runtime {
71881
71902
  isSync: true,
71882
71903
  resolve: (variable, subscript) => {
71883
71904
  this.signal.throwIfAborted();
71884
- if (this._syncArithState.variableAttributes?.get(variable)?.includes("n")) throw new ArrayFailure("nameref in sync arithmetic");
71905
+ if (this._syncArithState.variableAttributes?.get(variable)?.includes("n")) {
71906
+ const resolved = resolveSyncNameref(this._syncArithState, variable);
71907
+ if (resolved === variable) throw new ArrayFailure("nameref in sync arithmetic");
71908
+ variable = resolved;
71909
+ }
71885
71910
  if (subscript !== void 0) {
71886
71911
  let resolvedSub = subscript;
71887
71912
  if (resolvedSub.charCodeAt(0) === 36 && /^\$[a-zA-Z_][a-zA-Z_0-9]*$/.test(resolvedSub)) {
@@ -72036,14 +72061,15 @@ var Runtime = class _Runtime {
72036
72061
  }
72037
72062
  }
72038
72063
  canSyncArithmeticOperands(tree, state, line, depth = 0) {
72039
- if (!tree || depth > 128 || hasActiveVariableAttributes(state) || state.readonlyVariables?.size) return false;
72064
+ if (!tree || depth > 128 || hasNonNamerefAttributes(state) || state.readonlyVariables?.size) return false;
72040
72065
  switch (tree.kind) {
72041
72066
  case "literal":
72042
72067
  return true;
72043
72068
  case "name": {
72044
- if (tree.name === "OPTIND" || tree.name === "PIPESTATUS") return false;
72069
+ const effName = resolveSyncNameref(state, tree.name);
72070
+ if (effName === "OPTIND" || effName === "PIPESTATUS") return false;
72045
72071
  const monitor = stateMonitor(state);
72046
- if (monitor?.hasOverlay(tree.name) || monitor?.store?.watches.has(tree.name)) return false;
72072
+ if (monitor?.hasOverlay(effName) || monitor?.store?.watches.has(effName)) return false;
72047
72073
  if (tree.subscript !== void 0) {
72048
72074
  if (state.nounset || hasUnpreparedLocal(state, tree.name)) return false;
72049
72075
  const binding = arrayStore(state)?.get(tree.name);
@@ -72317,6 +72343,7 @@ var Runtime = class _Runtime {
72317
72343
  name2 = this.referenceName(state, name2);
72318
72344
  const binding = arrayStore(state)?.get(name2);
72319
72345
  if (binding) return binding.get(binding.associative ? binding.keys.get("30")?.index ?? -1 : 0);
72346
+ if (name2 === "DIRSTACK") return state.cwd;
72320
72347
  if (name2 === "FUNCNAME" && state.variables.FUNCNAME === void 0) return state.functionNames?.[0];
72321
72348
  if (name2 === "_" && state.variables._ === void 0) return state.lastArgument ?? "";
72322
72349
  return state.variables[name2];
@@ -72351,12 +72378,12 @@ var Runtime = class _Runtime {
72351
72378
  const entries = this.presenceArrayEntries(state, resolved);
72352
72379
  if (bracket < 0) return entries ? entries[0] !== void 0 : this.variable(state, base) !== void 0;
72353
72380
  const selector = name2.slice(bracket + 1, -1);
72354
- if (selector === "@" || selector === "*") return entries ? entries.length > 0 : binding ? binding.values.size > 0 : this.variable(state, base) !== void 0;
72355
72381
  if (binding?.associative) {
72356
72382
  if (selector.length === 0 || selector.length > 4096 || [...selector].some((character) => "$`\\\"'".includes(character))) return void 0;
72357
72383
  const key = binding.keys.get(fastStringHexIdentity(selector));
72358
72384
  return key !== void 0 && binding.getValue(key.index) !== void 0;
72359
72385
  }
72386
+ if (selector === "@" || selector === "*") return entries ? entries.length > 0 : binding ? binding.values.size > 0 : this.variable(state, base) !== void 0;
72360
72387
  if (selector.length === 0 || selector.length > 9 || [...selector].some((character) => !"0123456789".includes(character)) || selector.length > 1 && selector[0] === "0") return void 0;
72361
72388
  const index = Number(selector);
72362
72389
  return entries ? entries[index] !== void 0 : binding ? binding.getValue(index) !== void 0 : index === 0 && this.variable(state, base) !== void 0;
@@ -72757,19 +72784,121 @@ var Runtime = class _Runtime {
72757
72784
  }
72758
72785
  }
72759
72786
  }
72787
+ canSyncArrayMembersWord(w, rawState) {
72788
+ if (rawState.nounset) return false;
72789
+ 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;
72790
+ if (!p02) return false;
72791
+ if (p02.kind !== "variable" || !p02.quoted || p02.indirect || p02.prefixNames || p02.length || p02.transform || p02.operator !== void 0) return false;
72792
+ const sel0 = getArraySelector(p02);
72793
+ if (!sel0 || sel0.kind !== "members" && sel0.kind !== "keys" || sel0.separator !== "@") return false;
72794
+ if (p02.substring) {
72795
+ if (sel0.kind !== "members" || p02.keys) return false;
72796
+ const b = stateMonitor(rawState)?.store?.get(resolveSyncNameref(rawState, p02.name));
72797
+ if (b && b.associative) return false;
72798
+ if (!this.isPureSyncValueWord(p02.substring.offset, rawState)) return false;
72799
+ if (p02.substring.length && !this.isPureSyncValueWord(p02.substring.length, rawState)) return false;
72800
+ }
72801
+ return true;
72802
+ }
72803
+ tryExpandSyncArrayMembersWord(w, rawState, io, diagnosticLine) {
72804
+ if (rawState.nounset) return void 0;
72805
+ 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;
72806
+ if (!p02) return void 0;
72807
+ if (p02.kind !== "variable" || !p02.quoted || p02.indirect || p02.prefixNames || p02.length || p02.transform || p02.operator !== void 0) return void 0;
72808
+ const sel0 = getArraySelector(p02);
72809
+ if (!sel0 || sel0.kind !== "members" && sel0.kind !== "keys" || sel0.separator !== "@") return void 0;
72810
+ const monitor = stateMonitor(rawState);
72811
+ const activeStore = monitor?.store ?? arrayStore(rawState);
72812
+ const resolvedName = resolveSyncNameref(rawState, p02.name);
72813
+ const b = activeStore?.get(resolvedName);
72814
+ if (p02.substring) {
72815
+ if (sel0.kind !== "members" || p02.keys || b && b.associative) return void 0;
72816
+ if (b && b.maximum >= 4096) return void 0;
72817
+ const evalSliceInt = (sw) => {
72818
+ if (sw.parts.length === 0) return 0;
72819
+ let expanded;
72820
+ try {
72821
+ expanded = this.fastValueWord(sw, rawState, io, false, false, false, false, void 0, diagnosticLine);
72822
+ } catch {
72823
+ return void 0;
72824
+ }
72825
+ if (typeof expanded !== "string") return void 0;
72826
+ const trimmed = expanded.trim();
72827
+ if (trimmed.length === 0) return 0;
72828
+ const syncTouched = this._syncArithRawWriteOnly ? this._syncArithTouched : void 0;
72829
+ const directOp = resolveSimpleArithOperand(trimmed, rawState, monitor, activeStore, syncTouched);
72830
+ if (directOp !== void 0) return directOp;
72831
+ const simpleExpr = tryEvalSimpleExpandedArith(trimmed, rawState, monitor, activeStore, syncTouched);
72832
+ if (simpleExpr !== void 0) return Number(simpleExpr);
72833
+ return void 0;
72834
+ };
72835
+ const offNum = evalSliceInt(p02.substring.offset);
72836
+ if (offNum === void 0) return void 0;
72837
+ let maxCount2 = Infinity;
72838
+ if (p02.substring.length) {
72839
+ const lenNum = evalSliceInt(p02.substring.length);
72840
+ if (lenNum === void 0 || lenNum < 0) return void 0;
72841
+ maxCount2 = lenNum;
72842
+ }
72843
+ if (!b) {
72844
+ const sv2 = rawState.variables[resolvedName];
72845
+ if (sv2 === void 0) return [];
72846
+ const mv2 = this._syncArithRawWriteOnly && this._syncArithTouched?.has(resolvedName) ? sv2 : monitor?.values.get(resolvedName, sv2) ?? sv2;
72847
+ if (typeof mv2 !== "string") return void 0;
72848
+ const startIdx2 = offNum < 0 ? 1 + offNum : offNum;
72849
+ if (startIdx2 < 0 || startIdx2 > 0 || maxCount2 === 0) return [];
72850
+ return [mv2];
72851
+ }
72852
+ if (b.values.size === 0 || maxCount2 === 0) return [];
72853
+ const startIdx = offNum < 0 ? b.maximum + 1 + offNum : offNum;
72854
+ if (startIdx < 0) return [];
72855
+ const out = [];
72856
+ for (let k = startIdx; k <= b.maximum && out.length < maxCount2; k++) {
72857
+ const slot = b.values.get(k);
72858
+ if (!slot) continue;
72859
+ const v = slot.text.shellValue;
72860
+ if (typeof v !== "string") return void 0;
72861
+ out.push(v);
72862
+ }
72863
+ return out;
72864
+ }
72865
+ const isKeys = sel0.kind === "keys" || p02.keys === true;
72866
+ if (b) {
72867
+ if (b.maximum >= 4096) return void 0;
72868
+ const out = [];
72869
+ for (let k = 0; k <= b.maximum; k++) {
72870
+ const slot = b.values.get(k);
72871
+ if (!slot) continue;
72872
+ const v = isKeys ? b.associative ? b.keys.get(b.keyByIndex.get(k))?.text.shellValue : String(k) : slot.text.shellValue;
72873
+ if (typeof v !== "string") return void 0;
72874
+ out.push(v);
72875
+ }
72876
+ return out;
72877
+ }
72878
+ const sv = rawState.variables[resolvedName];
72879
+ if (sv === void 0) return [];
72880
+ if (isKeys) return ["0"];
72881
+ const mv = this._syncArithRawWriteOnly && this._syncArithTouched?.has(resolvedName) ? sv : monitor?.values.get(resolvedName, sv) ?? sv;
72882
+ if (typeof mv !== "string") return void 0;
72883
+ return [mv];
72884
+ }
72760
72885
  tryFastArrayAssignmentSync(assignment, state, io, diagnosticLine, declaration, associative, ignoreYield = false) {
72761
72886
  if (!ignoreYield && (0, yield_exports.hasYieldCheckpoint)(this.signal)) return false;
72762
72887
  if (declaration) return false;
72763
- const name2 = assignment.name;
72764
- if (hasUnpreparedLocal(state, name2)) return false;
72765
- this._syncArithTouched?.delete(name2);
72766
72888
  const monitor = stateMonitor(state);
72767
72889
  const rawState = monitor ? monitor.raw : state;
72890
+ const name2 = resolveSyncNameref(rawState, assignment.name);
72891
+ if (hasUnpreparedLocal(state, name2)) return false;
72892
+ this._syncArithTouched?.delete(name2);
72768
72893
  if (rawState.readonlyVariables?.has(name2) || rawState.variableAttributes?.get(name2) || rawState.exported.has(name2) || controlNames.has(name2)) {
72769
72894
  return false;
72770
72895
  }
72771
72896
  const store = monitor?.store ?? (monitor && (this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity) ? requireArrays(rawState) : void 0);
72772
72897
  let current = store?.get(name2);
72898
+ if (assignment.kind === "compound" && !(associative ?? current?.associative) && state.braceexpand !== false && assignment.entries.some((entry) => {
72899
+ const original = compoundEntryWords.get(entry);
72900
+ return entry.index !== void 0 && original?.parts.some((part) => part.kind === "text" && !part.quoted && part.value.includes("{"));
72901
+ })) return false;
72773
72902
  if (!monitor || !store || store.watches.has(name2) || monitor.hasOverlay(name2) || current && (current.references !== 1 || associative !== void 0 && current.associative !== associative) || !current && rawState.variables[name2] !== void 0) {
72774
72903
  return false;
72775
72904
  }
@@ -72852,13 +72981,26 @@ var Runtime = class _Runtime {
72852
72981
  for (let i = 0; i < assignment.entries.length; i++) {
72853
72982
  const entry = assignment.entries[i];
72854
72983
  if (entry.append) return false;
72984
+ if (rawState.braceexpand !== false && entry.value.parts.some((p) => !p.quoted && p.kind === "text" && p.value.includes("{"))) return false;
72855
72985
  let explicitIdx;
72856
72986
  if (entry.index !== void 0) {
72857
72987
  const kSrc = (entry.index.source ?? entry.index.decimal).trim();
72858
72988
  if (!/^(?:0|[1-9][0-9]{0,8})$/.test(kSrc)) return false;
72859
72989
  explicitIdx = Number(kSrc);
72860
- } else 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))) {
72861
- return false;
72990
+ } else {
72991
+ const expandedArr = this.tryExpandSyncArrayMembersWord(entry.value, rawState, io, diagnosticLine);
72992
+ if (expandedArr !== void 0) {
72993
+ for (let mIdx = 0; mIdx < expandedArr.length; mIdx++) {
72994
+ const mVal = expandedArr[mIdx];
72995
+ const bLen2 = shellValueByteLength(mVal);
72996
+ if (bLen2 > this.budget.limits.maxExpansionBytes) return false;
72997
+ items.push({ explicitIdx: void 0, val: mVal, bLen: bLen2 });
72998
+ }
72999
+ continue;
73000
+ }
73001
+ 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))) {
73002
+ return false;
73003
+ }
72862
73004
  }
72863
73005
  let val = "";
72864
73006
  if (entry.value.parts.length > 0) {
@@ -73721,6 +73863,7 @@ var Runtime = class _Runtime {
73721
73863
  if (state.readonlyVariables?.has(name2)) throw new ArrayFailure("readonly binding");
73722
73864
  if (!watch.valid()) throw new ArrayFailure("binding changed during writer admission");
73723
73865
  prepared.validate();
73866
+ if (clear) prepared.binding.assigned = true;
73724
73867
  let retirement;
73725
73868
  monitor.publish(prepared.tickets, name2, () => {
73726
73869
  delete state.variables[name2];
@@ -75435,11 +75578,6 @@ var Runtime = class _Runtime {
75435
75578
  if (allValidVars) return true;
75436
75579
  }
75437
75580
  }
75438
- if ((w0Plain === "mapfile" || w0Plain === "readarray") && (command7.words.length === 2 || command7.words.length === 3) && command7.words[1]?.plain === "-t" && !hasShellFunction(rawState, w0Plain) && !rawState.extensions?.builtins.has(w0Plain)) {
75439
- const arrVp = command7.words[2]?.plain ?? "MAPFILE";
75440
- const st = stateMonitor(rawState)?.store;
75441
- if (isShellIdentifier(arrVp) && arrVp !== "OPTIND" && arrVp !== "PIPESTATUS" && !rawState.readonlyVariables?.has(arrVp) && !st?.get(arrVp)?.associative) return true;
75442
- }
75443
75581
  }
75444
75582
  return false;
75445
75583
  }
@@ -75471,7 +75609,7 @@ var Runtime = class _Runtime {
75471
75609
  return false;
75472
75610
  }
75473
75611
  if (arrayAssign.kind === "compound") {
75474
- const isAssoc = Boolean(st?.get(arrayAssign.name)?.associative);
75612
+ const isAssoc = Boolean(st?.get(resolveSyncNameref(rawState, arrayAssign.name))?.associative);
75475
75613
  return arrayAssign.entries.length <= 32 && arrayAssign.entries.every((e) => {
75476
75614
  if (e.append) return false;
75477
75615
  if (isAssoc) {
@@ -75482,6 +75620,7 @@ var Runtime = class _Runtime {
75482
75620
  const kSrc = (e.index.source ?? e.index.decimal).trim();
75483
75621
  return /^(?:0|[1-9][0-9]{0,8})$/.test(kSrc) && isNoBraceSyncAssignWord(e.value);
75484
75622
  }
75623
+ if (this.canSyncArrayMembersWord(e.value, rawState)) return true;
75485
75624
  return isNoBraceSyncWord(e.value) && e.value.parts.length > 0 && e.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));
75486
75625
  });
75487
75626
  }
@@ -75514,7 +75653,7 @@ var Runtime = class _Runtime {
75514
75653
  }
75515
75654
  }
75516
75655
  if (command7.words.length >= 2 && command7.words.length <= 16) {
75517
- if (w0Plain === "unset" && rawState.locals.length === 0 && !hasShellFunction(rawState, "unset") && !rawState.extensions?.builtins.has("unset")) {
75656
+ if (w0Plain === "unset" && depth === 0 && rawState.locals.length === 0 && !hasShellFunction(rawState, "unset") && !rawState.extensions?.builtins.has("unset")) {
75518
75657
  const uStart = command7.words[1]?.plain === "-v" ? 2 : 1;
75519
75658
  if (uStart < command7.words.length) {
75520
75659
  let allOk = true;
@@ -75531,7 +75670,7 @@ var Runtime = class _Runtime {
75531
75670
  if (allOk) return true;
75532
75671
  }
75533
75672
  }
75534
- if (w0Plain === "export" && rawState.locals.length === 0 && !hasShellFunction(rawState, "export") && !rawState.extensions?.builtins.has("export")) {
75673
+ if (w0Plain === "export" && rawState.locals.length === 0 && depth === 0 && !hasShellFunction(rawState, "export") && !rawState.extensions?.builtins.has("export")) {
75535
75674
  let allOk = true;
75536
75675
  for (let ei = 1; ei < command7.words.length; ei++) {
75537
75676
  const we = command7.words[ei];
@@ -75578,12 +75717,14 @@ var Runtime = class _Runtime {
75578
75717
  }
75579
75718
  if (command7.words.length >= 2 && command7.words.length <= 16 && w0Plain !== void 0 && (w0Plain === "local" ? rawState.locals.length > 0 || depth > 0 : w0Plain === "declare" || w0Plain === "typeset") && !hasShellFunction(rawState, w0Plain) && !rawState.extensions?.builtins.has(w0Plain)) {
75580
75719
  if (command7.words[1]?.plain === "-a" || command7.words[1]?.plain === "-A") return false;
75720
+ const isNamerefDecl = command7.words[1]?.plain === "-n" && (rawState.locals.length > 0 || depth > 0) && command7.words.length >= 3;
75721
+ const isGlobalDecl = command7.words[1]?.plain === "-g" && (w0Plain === "declare" || w0Plain === "typeset") && command7.words.length >= 3;
75581
75722
  let allValidLocal = true;
75582
- for (let idx = 1; idx < command7.words.length; idx++) {
75723
+ for (let idx = isNamerefDecl || isGlobalDecl ? 2 : 1; idx < command7.words.length; idx++) {
75583
75724
  const wArg = command7.words[idx];
75584
75725
  const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : void 0;
75585
75726
  if (assignment) {
75586
- if (assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND")) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
75727
+ if (!isNamerefDecl && rawState.variableAttributes?.get(assignment.name) || assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND")) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
75587
75728
  allValidLocal = false;
75588
75729
  break;
75589
75730
  }
@@ -75597,15 +75738,7 @@ var Runtime = class _Runtime {
75597
75738
  if ((w0Plain === ":" || w0Plain === "true" || w0Plain === "false") && command7.words.length <= 16 && !hasShellFunction(rawState, w0Plain) && !rawState.extensions?.builtins.has(w0Plain) && command7.words.slice(1).every(isNoBraceSyncWord)) {
75598
75739
  return true;
75599
75740
  }
75600
- if (command7.words.length >= 3 && command7.words.length <= 16 && w0Plain === "getopts" && !hasShellFunction(rawState, "getopts") && !rawState.extensions?.builtins.has("getopts")) {
75601
- const optVar = command7.words[2]?.plain;
75602
- if (optVar && isShellIdentifier(optVar) && optVar !== "OPTIND" && optVar !== "PIPESTATUS" && optVar !== "_" && !rawState.readonlyVariables?.has(optVar) && !rawState.readonlyVariables?.has("OPTIND") && !rawState.readonlyVariables?.has("OPTARG") && isNoBraceSyncWord(command7.words[1]) && (command7.words.length === 3 || command7.words.length === 4 && (() => {
75603
- const ne = command7.words[3].parts.filter((p) => !(p.kind === "text" && p.value === ""));
75604
- return ne.length === 1 && ne[0].kind === "variable" && ne[0].name === "@" && ne[0].quoted;
75605
- })() || command7.words.slice(3).every(isNoBraceSyncWord))) {
75606
- return true;
75607
- }
75608
- }
75741
+ if (w0Plain === "getopts") return false;
75609
75742
  if (w0Plain === "echo" && !hasShellFunction(rawState, "echo") && !rawState.extensions?.builtins.has("echo")) {
75610
75743
  const w1Plain = command7.words[1]?.plain;
75611
75744
  if (w1Plain === void 0 || !w1Plain.startsWith("-") || w1Plain === "-n" || w1Plain === "-e" || w1Plain === "-ne" || w1Plain === "-en") {
@@ -75633,7 +75766,15 @@ var Runtime = class _Runtime {
75633
75766
  }
75634
75767
  if (w0Plain !== void 0 && rawState.functions.has(w0Plain) && command7.words.slice(1).every(isNoBraceSyncWord)) {
75635
75768
  const fnBody = rawState.functions.get(w0Plain);
75636
- return fnBody.kind === "group" && fnBody.redirects.length === 0 && this.canSyncScriptCompound(fnBody.body, rawState, depth + 1);
75769
+ if (fnBody.kind !== "group" || fnBody.redirects.length !== 0) return false;
75770
+ rawState.locals.push(/* @__PURE__ */ new Map());
75771
+ rawState.functionDepth++;
75772
+ try {
75773
+ return this.canSyncScriptCompound(fnBody.body, rawState, depth + 1);
75774
+ } finally {
75775
+ rawState.functionDepth--;
75776
+ rawState.locals.pop();
75777
+ }
75637
75778
  }
75638
75779
  return false;
75639
75780
  }
@@ -75708,11 +75849,11 @@ var Runtime = class _Runtime {
75708
75849
  const sel0 = p02?.kind === "variable" ? getArraySelector(p02) : void 0;
75709
75850
  const isArrAt = Boolean(p02?.kind === "variable" && p02.quoted && !p02.indirect && !p02.prefixNames && !p02.length && !p02.substring && !p02.transform && p02.operator === void 0 && (sel0?.kind === "members" || sel0?.kind === "keys") && sel0.separator === "@");
75710
75851
  const isBraceRange = Boolean(p02?.kind === "text" && !p02.quoted && /^\{-?\d+\.\.-?\d+(?:\.\.-?\d+)?\}$/.test(p02.value));
75711
- if (!isArrAt && !isBraceRange && !(this.isPureSyncValueWord(w0, rawState) && w0.parts.every((p) => p.quoted || p.kind === "text" && !p.value.includes(" ") && !p.value.includes(" ") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)))) return false;
75852
+ if (!isArrAt && !isBraceRange && !this.canSyncArrayMembersWord(w0, rawState) && !(this.isPureSyncValueWord(w0, rawState) && w0.parts.every((p) => p.quoted || p.kind === "text" && !p.value.includes(" ") && !p.value.includes(" ") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)))) return false;
75712
75853
  } else {
75713
75854
  for (let i = 0; i < command7.words.length; i++) {
75714
75855
  const w = command7.words[i];
75715
- if (!this.isPureSyncValueWord(w, rawState) || !w.parts.every((p) => p.quoted || p.kind === "text" && !p.value.includes(" ") && !p.value.includes(" ") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true))) return false;
75856
+ if (!this.canSyncArrayMembersWord(w, rawState) && (!this.isPureSyncValueWord(w, rawState) || !w.parts.every((p) => p.quoted || p.kind === "text" && !p.value.includes(" ") && !p.value.includes(" ") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)))) return false;
75716
75857
  }
75717
75858
  }
75718
75859
  }
@@ -75790,7 +75931,9 @@ var Runtime = class _Runtime {
75790
75931
  }
75791
75932
  } else if (wp0 === "local" || wp0 === "declare" || wp0 === "typeset") {
75792
75933
  const isArrDecl = c.words[1]?.plain === "-a" || c.words[1]?.plain === "-A";
75793
- for (let k = isArrDecl ? 2 : 1; k < c.words.length; k++) {
75934
+ const isNameref = c.words[1]?.plain === "-n";
75935
+ const isGlobal = c.words[1]?.plain === "-g";
75936
+ for (let k = isArrDecl || isNameref || isGlobal ? 2 : 1; k < c.words.length; k++) {
75794
75937
  const wk = c.words[k];
75795
75938
  const aa = getArrayAssignment(wk);
75796
75939
  if (aa) {
@@ -75803,6 +75946,8 @@ var Runtime = class _Runtime {
75803
75946
  if (isArrDecl) {
75804
75947
  arrayVars.add(nm);
75805
75948
  if (wp0 === "local" || d > 0) localArrayVars.add(nm);
75949
+ } else if (isNameref) {
75950
+ localArrayVars.add(nm);
75806
75951
  } else {
75807
75952
  scalarVars.add(nm);
75808
75953
  const pv = asg?.value.plain;
@@ -75811,8 +75956,8 @@ var Runtime = class _Runtime {
75811
75956
  }
75812
75957
  }
75813
75958
  }
75814
- } else if (wp0 === "printf" && c.words[1]?.plain === "-v" && c.words[2]?.plain) {
75815
- const target = c.words[2].plain;
75959
+ } else if (wp0 === "printf" && c.words[1]?.plain === "-v" && (c.words[2]?.plain || c.words[2]?.parts[0]?.kind === "text")) {
75960
+ const target = c.words[2].plain ?? c.words[2].parts[0].value;
75816
75961
  const br = target.indexOf("[");
75817
75962
  if (br > 0) arrayVars.add(target.slice(0, br));
75818
75963
  else {
@@ -76099,7 +76244,22 @@ var Runtime = class _Runtime {
76099
76244
  }
76100
76245
  return void 0;
76101
76246
  }
76102
- finishSyncPipeStatus(rawState, monitor, store, existing, elem0, scope, finalStatus, restEpoch) {
76247
+ setSyncPipeStatusCell(existing, status2) {
76248
+ const cell2 = existing.values.get(0);
76249
+ if (cell2 && cell2.text.references === 1 && cell2.text.bytes === status2.length) {
76250
+ cell2.text.shellValue = status2;
76251
+ } else {
76252
+ existing.owner.chargeWork(status2.length);
76253
+ const token = new OwnedText(status2, status2.length, existing.owner.reserve({ payload: status2.length, metadata: 32, work: 4 }));
76254
+ try {
76255
+ existing.insert(0, token);
76256
+ } catch (error) {
76257
+ token.release();
76258
+ throw error;
76259
+ }
76260
+ }
76261
+ }
76262
+ finishSyncPipeStatus(rawState, monitor, store, existing, _elem0, scope, finalStatus, restEpoch) {
76103
76263
  if (!existing) {
76104
76264
  if (store) {
76105
76265
  if (publishPipelineStatus(rawState, finalStatus === 0 ? singleStatusZero : singleStatusOne, this.signal, scope)) return void 0;
@@ -76108,7 +76268,7 @@ var Runtime = class _Runtime {
76108
76268
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
76109
76269
  }
76110
76270
  } else {
76111
- (elem0 ?? existing.values.get(0)).text.shellValue = finalStatus === 0 ? "0" : "1";
76271
+ this.setSyncPipeStatusCell(existing, finalStatus === 0 ? "0" : "1");
76112
76272
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
76113
76273
  }
76114
76274
  rawState.status = finalStatus;
@@ -76124,7 +76284,7 @@ var Runtime = class _Runtime {
76124
76284
  if (!monitor) return void 0;
76125
76285
  const rawState = monitor.raw;
76126
76286
  const gArrays = guestArrays(rawState);
76127
- if (io.terminal || io.asyncDefaultInput || hasActiveExtensions(rawState) || hasActiveVariableAttributes(rawState) || gArrays && gArrays.watches.size > 0) return void 0;
76287
+ if (io.terminal || io.asyncDefaultInput || hasActiveExtensions(rawState) || hasNonNamerefAttributes(rawState) || gArrays && gArrays.watches.size > 0) return void 0;
76128
76288
  if ((this.budget.commands + 1 & 127) === 0) {
76129
76289
  if ((0, yield_exports.hasYieldCheckpoint)(this.signal) || this._syncReturnDepth === 0 && (this.budget.commands + 1 & 8191) === 0) return void 0;
76130
76290
  (0, yield_exports.runYieldCheckpoint)(this.signal);
@@ -76155,9 +76315,9 @@ var Runtime = class _Runtime {
76155
76315
  return void 0;
76156
76316
  }
76157
76317
  const elem0 = existing?.values.get(0);
76158
- if (existing && (!elem0 || elem0.text.bytes !== 1)) return void 0;
76318
+ if (existing && !elem0) return void 0;
76159
76319
  const canMutatePipeStatus = !existing || existing.references === 1 && elem0.text.references === 1;
76160
- const diagnosticLine = io.diagnosticCommandLines?.get(command7) ?? (command7.line ?? 1) + (io.diagnosticOffset ?? 0);
76320
+ const diagnosticLine = io.diagnosticCommandLines?.get(command7) ?? io.substitutionDiagnosticLines?.get(command7) ?? (command7.line ?? 1) + (io.diagnosticOffset ?? 0);
76161
76321
  if (command7.kind === "function") {
76162
76322
  if (pipeline.negate || !canMutatePipeStatus || command7.redirects.length > 0 || rawState.readonlyFunctions?.has(command7.name) || rawState.profile === "sh" && (specialBuiltinNames.has(command7.name) || rawState.extensions?.builtins.get(command7.name)?.special)) {
76163
76323
  return void 0;
@@ -76213,7 +76373,7 @@ var Runtime = class _Runtime {
76213
76373
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
76214
76374
  }
76215
76375
  } else {
76216
- activeExisting.values.get(0).text.shellValue = finalStatus === 0 ? "0" : "1";
76376
+ this.setSyncPipeStatusCell(activeExisting, finalStatus === 0 ? "0" : "1");
76217
76377
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
76218
76378
  }
76219
76379
  rawState.status = finalStatus;
@@ -76305,13 +76465,13 @@ var Runtime = class _Runtime {
76305
76465
  }
76306
76466
  const scalarMutMatch = fastSrc.length <= 64 ? SIMPLE_SCALAR_MUT_RE.exec(fastSrc) : null;
76307
76467
  if (scalarMutMatch) {
76308
- const varName = scalarMutMatch[1];
76468
+ const varName = resolveSyncNameref(rawState, scalarMutMatch[1]);
76309
76469
  const binOp = scalarMutMatch[2];
76310
76470
  const rhs1 = Number(scalarMutMatch[3]);
76311
76471
  const rhsOp = scalarMutMatch[4];
76312
76472
  const rhs2 = scalarMutMatch[5] !== void 0 ? Number(scalarMutMatch[5]) : 0;
76313
76473
  const rhsNum = rhsOp === "+" ? rhs1 + rhs2 : rhsOp === "-" ? rhs1 - rhs2 : rhsOp === "*" ? rhs1 * rhs2 : rhs1;
76314
- if (varName !== "OPTIND" && varName !== "PIPESTATUS" && !store?.get(varName) && !hasActiveVariableAttributes(rawState)) {
76474
+ if (varName !== "OPTIND" && varName !== "PIPESTATUS" && !store?.get(varName) && !hasNonNamerefAttributes(rawState)) {
76315
76475
  const curVal = this._syncArithRawWriteOnly && this._syncArithTouched?.has(varName) ? rawState.variables[varName] ?? "0" : monitor.values.get(varName, rawState.variables[varName] ?? "0") ?? rawState.variables[varName] ?? "0";
76316
76476
  if (typeof curVal === "string" && (curVal === "" || /^-?(?:0|[1-9][0-9]{0,12})$/.test(curVal))) {
76317
76477
  const curNum = curVal === "" ? 0 : Number(curVal);
@@ -76452,8 +76612,11 @@ var Runtime = class _Runtime {
76452
76612
  }
76453
76613
  return res;
76454
76614
  }
76455
- const fastLoopRes = this.trySyncLoop(command7, pipeline, rawState, monitor, store, existing, elem0, canMutatePipeStatus, io, diagnosticLine);
76456
- if (fastLoopRes !== void 0) return fastLoopRes;
76615
+ if (!command7._skipTrySyncLoop) {
76616
+ const fastLoopRes = this.trySyncLoop(command7, pipeline, rawState, monitor, store, existing, elem0, canMutatePipeStatus, io, diagnosticLine);
76617
+ if (fastLoopRes !== void 0) return fastLoopRes;
76618
+ command7._skipTrySyncLoop = true;
76619
+ }
76457
76620
  }
76458
76621
  if (command7.kind === "group" || command7.kind === "if" || command7.kind === "case" || command7.kind === "while" || command7.kind === "until" || command7.kind === "for" || command7.kind === "arithmetic-for") {
76459
76622
  if (command7.redirects.length !== 0 || pipeline.negate || !canMutatePipeStatus || !ignored && rawState.errexit || rawState.nounset || rawState.readonlyVariables?.size || (0, yield_exports.hasYieldCheckpoint)(this.signal) || this._syncReturnDepth === 0 && ((this.budget.commands + 32 & 8191) < 32 || !this.canSyncCommandCompound(command7, rawState, 0, rawState.loopDepth))) {
@@ -76644,10 +76807,10 @@ var Runtime = class _Runtime {
76644
76807
  items = pos.slice();
76645
76808
  } else if (command7.words.length === 1) {
76646
76809
  const w0 = command7.words[0];
76647
- const nonEmpty0 = w0.parts.filter((p) => !(p.kind === "text" && p.value === ""));
76648
- const p02 = nonEmpty0.length === 1 ? nonEmpty0[0] : void 0;
76810
+ items = this.tryExpandSyncArrayMembersWord(w0, rawState, io, diagnosticLine);
76811
+ const p02 = items ? void 0 : 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;
76649
76812
  const sel0 = p02?.kind === "variable" ? getArraySelector(p02) : void 0;
76650
- if (p02?.kind === "variable" && p02.quoted && (sel0?.kind === "members" || sel0?.kind === "keys") && sel0.separator === "@") {
76813
+ if (p02?.kind === "variable" && p02.quoted && !p02.substring && (sel0?.kind === "members" || sel0?.kind === "keys") && sel0.separator === "@") {
76651
76814
  const b = monitor.store?.get(p02.name);
76652
76815
  items = [];
76653
76816
  if (b) {
@@ -76678,6 +76841,11 @@ var Runtime = class _Runtime {
76678
76841
  if (!items && command7.words) {
76679
76842
  items = [];
76680
76843
  for (let i = 0; i < command7.words.length; i++) {
76844
+ const expandedArr = this.tryExpandSyncArrayMembersWord(command7.words[i], rawState, io, diagnosticLine);
76845
+ if (expandedArr !== void 0) {
76846
+ for (let mIdx = 0; mIdx < expandedArr.length; mIdx++) items.push(expandedArr[mIdx]);
76847
+ continue;
76848
+ }
76681
76849
  let fv;
76682
76850
  try {
76683
76851
  fv = this.fastValueWord(command7.words[i], rawState, io, false, false, false, false, void 0, diagnosticLine);
@@ -76853,7 +77021,7 @@ var Runtime = class _Runtime {
76853
77021
  monitor.lazyPipeStatus = singleStatusZero;
76854
77022
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
76855
77023
  } else {
76856
- elem0.text.shellValue = "0";
77024
+ this.setSyncPipeStatusCell(existing, "0");
76857
77025
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
76858
77026
  }
76859
77027
  const finalStatus2 = pipeline.negate ? 1 : 0;
@@ -76932,7 +77100,7 @@ var Runtime = class _Runtime {
76932
77100
  monitor.lazyPipeStatus = singleStatusZero;
76933
77101
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
76934
77102
  } else {
76935
- elem0.text.shellValue = "0";
77103
+ this.setSyncPipeStatusCell(existing, "0");
76936
77104
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
76937
77105
  }
76938
77106
  const finalStatus = pipeline.negate ? 1 : 0;
@@ -76947,7 +77115,6 @@ var Runtime = class _Runtime {
76947
77115
  if (w0Plain === "return" && (rawState.functionDepth > 0 || rawState.sourceDepth) && !hasActiveExtensions(rawState) && !hasShellFunction(rawState, "return") && !rawState.extensions?.builtins.has("return") && !pipeline.negate && canMutatePipeStatus) {
76948
77116
  const retStatus = rawState.status;
76949
77117
  const statusStr = retStatus === 0 ? "0" : retStatus === 1 ? "1" : String(retStatus);
76950
- if (existing && elem0.text.bytes !== statusStr.length) return void 0;
76951
77118
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
76952
77119
  this.budget.tick();
76953
77120
  rawState.substitutionStatus = 0;
@@ -76958,7 +77125,7 @@ var Runtime = class _Runtime {
76958
77125
  monitor.lazyPipeStatus = retStatus === 0 ? singleStatusZero : retStatus === 1 ? singleStatusOne : [retStatus];
76959
77126
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
76960
77127
  } else {
76961
- elem0.text.shellValue = statusStr;
77128
+ this.setSyncPipeStatusCell(existing, statusStr);
76962
77129
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
76963
77130
  }
76964
77131
  rawState.status = retStatus;
@@ -76985,7 +77152,7 @@ var Runtime = class _Runtime {
76985
77152
  monitor.lazyPipeStatus = singleStatusZero;
76986
77153
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
76987
77154
  } else {
76988
- elem0.text.shellValue = "0";
77155
+ this.setSyncPipeStatusCell(existing, "0");
76989
77156
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
76990
77157
  }
76991
77158
  rawState.status = 0;
@@ -77010,7 +77177,7 @@ var Runtime = class _Runtime {
77010
77177
  monitor.lazyPipeStatus = rawStatus === 0 ? singleStatusZero : singleStatusOne;
77011
77178
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77012
77179
  } else {
77013
- elem0.text.shellValue = statusChar;
77180
+ this.setSyncPipeStatusCell(existing, statusChar);
77014
77181
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77015
77182
  }
77016
77183
  rawState.status = finalStatus;
@@ -77040,7 +77207,7 @@ var Runtime = class _Runtime {
77040
77207
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77041
77208
  }
77042
77209
  } else {
77043
- activeExisting.values.get(0).text.shellValue = "0";
77210
+ this.setSyncPipeStatusCell(activeExisting, "0");
77044
77211
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77045
77212
  }
77046
77213
  const finalStatus = pipeline.negate ? 1 : 0;
@@ -77051,9 +77218,10 @@ var Runtime = class _Runtime {
77051
77218
  }
77052
77219
  const assignment = this.assignment(w0);
77053
77220
  if (assignment) {
77221
+ const targetAssignName = resolveSyncNameref(rawState, assignment.name);
77054
77222
  const hasSubPart = assignment.value.parts.some((part) => part.kind === "substitution");
77055
- const existingArrAssign = store?.get(assignment.name);
77056
- if (assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND")) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || hasSubPart && !this.isPureSyncValueWord(assignment.value, rawState) || rawState.readonlyVariables?.has(assignment.name) || existingArrAssign && (assignment.append || hasUnpreparedLocal(rawState, assignment.name) || rawState.exported.has(assignment.name))) {
77223
+ const existingArrAssign = store?.get(targetAssignName);
77224
+ if (targetAssignName === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND")) || targetAssignName === "PIPESTATUS" || targetAssignName.includes("[") || hasSubPart && !this.isPureSyncValueWord(assignment.value, rawState) || rawState.readonlyVariables?.has(targetAssignName) || existingArrAssign && (assignment.append || hasUnpreparedLocal(rawState, targetAssignName) || rawState.exported.has(targetAssignName))) {
77057
77225
  return void 0;
77058
77226
  }
77059
77227
  if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
@@ -77064,13 +77232,13 @@ var Runtime = class _Runtime {
77064
77232
  return void 0;
77065
77233
  }
77066
77234
  if (typeof fastAssigned !== "string") return void 0;
77067
- if (assignment.name === "OPTIND") {
77235
+ if (targetAssignName === "OPTIND") {
77068
77236
  const trimmedOptind = fastAssigned.trim();
77069
77237
  if (!/^[0-9]{1,6}$/.test(trimmedOptind)) return void 0;
77070
77238
  fastAssigned = String(Number(trimmedOptind));
77071
77239
  }
77072
77240
  if (existingArrAssign) {
77073
- if (!this.tryFastArraySubscriptWriteSync(rawState, assignment.name, "0", fastAssigned)) return void 0;
77241
+ if (!this.tryFastArraySubscriptWriteSync(rawState, targetAssignName, "0", fastAssigned)) return void 0;
77074
77242
  const restEpoch2 = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77075
77243
  this.budget.tick();
77076
77244
  if (!hasSubPart) rawState.substitutionStatus = 0;
@@ -77087,7 +77255,7 @@ var Runtime = class _Runtime {
77087
77255
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77088
77256
  }
77089
77257
  } else {
77090
- activeExisting.values.get(0).text.shellValue = "0";
77258
+ this.setSyncPipeStatusCell(activeExisting, "0");
77091
77259
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77092
77260
  }
77093
77261
  const finalStatus2 = pipeline.negate ? 1 : 0;
@@ -77098,8 +77266,8 @@ var Runtime = class _Runtime {
77098
77266
  }
77099
77267
  let finalAssigned = fastAssigned;
77100
77268
  if (assignment.append) {
77101
- const curRaw = rawState.variables[assignment.name];
77102
- const curStr = curRaw === void 0 ? "" : monitor.values.get(assignment.name, curRaw) ?? curRaw;
77269
+ const curRaw = rawState.variables[targetAssignName];
77270
+ const curStr = curRaw === void 0 ? "" : monitor.values.get(targetAssignName, curRaw) ?? curRaw;
77103
77271
  if (typeof curStr !== "string") return void 0;
77104
77272
  finalAssigned = curStr + finalAssigned;
77105
77273
  if (finalAssigned.length > this.budget.limits.maxExpansionBytes || finalAssigned.length * 3 > this.budget.limits.maxExpansionBytes && shellValueByteLength(finalAssigned) > this.budget.limits.maxExpansionBytes) return void 0;
@@ -77107,23 +77275,23 @@ var Runtime = class _Runtime {
77107
77275
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77108
77276
  this.budget.tick();
77109
77277
  if (!hasSubPart) rawState.substitutionStatus = 0;
77110
- if (assignment.name !== "_" && rawState.variables._ !== void 0) delete rawState.variables._;
77278
+ if (targetAssignName !== "_" && rawState.variables._ !== void 0) delete rawState.variables._;
77111
77279
  rawState.lastArgument = "";
77112
77280
  if (this._syncArithRawWriteOnly && this._syncArithTouched) {
77113
- rawState.variables[assignment.name] = finalAssigned;
77114
- this._syncArithTouched.add(assignment.name);
77115
- } else monitor.publishStringVariable(assignment.name, finalAssigned);
77116
- if (assignment.name === "OPTIND") {
77281
+ rawState.variables[targetAssignName] = finalAssigned;
77282
+ this._syncArithTouched.add(targetAssignName);
77283
+ } else monitor.publishStringVariable(targetAssignName, finalAssigned);
77284
+ if (targetAssignName === "OPTIND") {
77117
77285
  rawState.variables.OPTIND = finalAssigned;
77118
77286
  this.syncGetopts(rawState);
77119
77287
  }
77120
- if (rawState.allexport) monitor.proxy.exported.add(assignment.name);
77288
+ if (rawState.allexport) monitor.proxy.exported.add(targetAssignName);
77121
77289
  if (io.assignmentDiagnosticContext) io.assignmentDiagnosticContext.name = void 0;
77122
77290
  if (!existing) {
77123
77291
  monitor.lazyPipeStatus = singleStatusZero;
77124
77292
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77125
77293
  } else {
77126
- elem0.text.shellValue = "0";
77294
+ this.setSyncPipeStatusCell(existing, "0");
77127
77295
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77128
77296
  }
77129
77297
  const finalStatus = pipeline.negate ? 1 : 0;
@@ -77137,51 +77305,83 @@ var Runtime = class _Runtime {
77137
77305
  if (command7.words.length >= 1) {
77138
77306
  const w0Plain = command7.words[0].plain;
77139
77307
  if (this.budget.limits.maxExpansionFields === Infinity && command7.words.length >= 4 && w0Plain === "printf" && command7.words[1]?.plain === "-v" && command7.redirects.length === 0 && canMutatePipeStatus && (!pipeline.negate || ignored || !rawState.errexit) && !hasShellFunction(rawState, "printf") && !rawState.extensions?.builtins.has("printf")) {
77140
- const targetVar = command7.words[2]?.plain;
77141
77308
  const def = this.commands.get("printf");
77142
- if (targetVar && isShellIdentifier(targetVar) && targetVar !== "OPTIND" && targetVar !== "PIPESTATUS" && targetVar !== "_" && !rawState.readonlyVariables?.has(targetVar) && !store?.get(targetVar) && !monitor.hasOverlay(targetVar) && def && def.execute === printfCommand.execute && command7.words.length <= this.budget.maxExpansionFieldsSmi && this.arePureArgWords(command7.words, rawState)) {
77143
- fastSubScratchArgs.length = 0;
77144
- let allStrings = true;
77145
- try {
77146
- for (let i = 3; i < command7.words.length; i++) {
77147
- const v = this.fastValueWord(command7.words[i], rawState, io, true, false, false, true, void 0, diagnosticLine);
77148
- if (typeof v !== "string") {
77149
- allStrings = false;
77150
- break;
77151
- }
77152
- fastSubScratchArgs.push(v);
77309
+ if (def && def.execute === printfCommand.execute && command7.words.length <= this.budget.maxExpansionFieldsSmi && this.arePureArgWords(command7.words, rawState)) {
77310
+ let targetSpec = command7.words[2]?.plain;
77311
+ if (targetSpec === void 0) {
77312
+ try {
77313
+ targetSpec = this.fastValueWord(command7.words[2], rawState, io, true, false, false, true, void 0, diagnosticLine);
77314
+ } catch {
77315
+ targetSpec = void 0;
77153
77316
  }
77154
- } catch {
77155
- allStrings = false;
77156
77317
  }
77157
- const lastArg = fastSubScratchArgs.length > 0 ? fastSubScratchArgs[fastSubScratchArgs.length - 1] : targetVar;
77158
- const formatted3 = allStrings ? tryFastPrintf(fastSubScratchArgs) : void 0;
77159
- fastSubScratchArgs.length = 0;
77160
- if (formatted3 !== void 0 && formatted3.length <= this.budget.limits.maxExpansionBytes && (formatted3.length * 3 <= this.budget.limits.maxExpansionBytes || shellValueByteLength(formatted3) <= this.budget.limits.maxExpansionBytes)) {
77161
- if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
77162
- const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77163
- this.budget.tick();
77164
- rawState.substitutionStatus = 0;
77165
- if (rawState.variables._ !== void 0) delete rawState.variables._;
77166
- rawState.lastArgument = lastArg;
77167
- if (this._syncArithRawWriteOnly && this._syncArithTouched) {
77168
- rawState.variables[targetVar] = formatted3;
77169
- this._syncArithTouched.add(targetVar);
77170
- } else monitor.publishStringVariable(targetVar, formatted3);
77171
- if (rawState.allexport) monitor.proxy.exported.add(targetVar);
77172
- if (io.assignmentDiagnosticContext) io.assignmentDiagnosticContext.name = void 0;
77173
- if (!existing) {
77174
- monitor.lazyPipeStatus = singleStatusZero;
77175
- monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77176
- } else {
77177
- elem0.text.shellValue = "0";
77178
- store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77318
+ if (typeof targetSpec === "string") {
77319
+ const openBr = targetSpec.indexOf("[");
77320
+ const isSubTarget = openBr > 0 && targetSpec.endsWith("]") && targetSpec.length > openBr + 2;
77321
+ const rawTargetVar = isSubTarget ? targetSpec.slice(0, openBr) : targetSpec;
77322
+ const targetVar = isShellIdentifier(rawTargetVar) ? resolveSyncNameref(rawState, rawTargetVar) : "";
77323
+ if (targetVar && isShellIdentifier(targetVar) && targetVar !== "OPTIND" && targetVar !== "PIPESTATUS" && targetVar !== "_" && !rawState.readonlyVariables?.has(targetVar) && !monitor.hasOverlay(targetVar) && (isSubTarget || !store?.get(targetVar))) {
77324
+ fastSubScratchArgs.length = 0;
77325
+ let allStrings = true;
77326
+ try {
77327
+ for (let i = 3; i < command7.words.length; i++) {
77328
+ const v = this.fastValueWord(command7.words[i], rawState, io, true, false, false, true, void 0, diagnosticLine);
77329
+ if (typeof v !== "string") {
77330
+ allStrings = false;
77331
+ break;
77332
+ }
77333
+ fastSubScratchArgs.push(v);
77334
+ }
77335
+ } catch {
77336
+ allStrings = false;
77337
+ }
77338
+ const lastArg = fastSubScratchArgs.length > 0 ? fastSubScratchArgs[fastSubScratchArgs.length - 1] : targetSpec;
77339
+ const formatted3 = allStrings ? tryFastPrintf(fastSubScratchArgs) : void 0;
77340
+ fastSubScratchArgs.length = 0;
77341
+ if (formatted3 !== void 0 && formatted3.length <= this.budget.limits.maxExpansionBytes && (formatted3.length * 3 <= this.budget.limits.maxExpansionBytes || shellValueByteLength(formatted3) <= this.budget.limits.maxExpansionBytes)) {
77342
+ let wroteTarget = true;
77343
+ if (isSubTarget) {
77344
+ let subKey = targetSpec.slice(openBr + 1, -1);
77345
+ const existingArr = store?.get(targetVar);
77346
+ if (!existingArr?.associative && !/^(?:0|[1-9][0-9]{0,8})$/.test(subKey)) {
77347
+ const syncTouched = this._syncArithRawWriteOnly ? this._syncArithTouched : void 0;
77348
+ const directIdx = resolveSimpleArithOperand(subKey.trim(), rawState, monitor, store, syncTouched);
77349
+ if (directIdx !== void 0 && directIdx >= 0) subKey = String(directIdx);
77350
+ else {
77351
+ const exprIdx = tryEvalSimpleExpandedArith(subKey.trim(), rawState, monitor, store, syncTouched);
77352
+ if (exprIdx !== void 0 && Number(exprIdx) >= 0) subKey = exprIdx;
77353
+ else wroteTarget = false;
77354
+ }
77355
+ }
77356
+ if (wroteTarget && !this.tryFastArraySubscriptWriteSync(rawState, targetVar, subKey, formatted3)) wroteTarget = false;
77357
+ } else if (this._syncArithRawWriteOnly && this._syncArithTouched) {
77358
+ rawState.variables[targetVar] = formatted3;
77359
+ this._syncArithTouched.add(targetVar);
77360
+ } else monitor.publishStringVariable(targetVar, formatted3);
77361
+ if (wroteTarget) {
77362
+ if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
77363
+ const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77364
+ this.budget.tick();
77365
+ rawState.substitutionStatus = 0;
77366
+ if (rawState.variables._ !== void 0) delete rawState.variables._;
77367
+ rawState.lastArgument = lastArg;
77368
+ if (!isSubTarget && rawState.allexport) monitor.proxy.exported.add(targetVar);
77369
+ if (io.assignmentDiagnosticContext) io.assignmentDiagnosticContext.name = void 0;
77370
+ if (!existing) {
77371
+ monitor.lazyPipeStatus = singleStatusZero;
77372
+ monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77373
+ } else {
77374
+ this.setSyncPipeStatusCell(existing, "0");
77375
+ store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77376
+ }
77377
+ const finalStatus = pipeline.negate ? 1 : 0;
77378
+ rawState.status = finalStatus;
77379
+ monitor.epoch = restEpoch;
77380
+ if (store) store.epoch = restEpoch;
77381
+ return finalStatus;
77382
+ }
77383
+ }
77179
77384
  }
77180
- const finalStatus = pipeline.negate ? 1 : 0;
77181
- rawState.status = finalStatus;
77182
- monitor.epoch = restEpoch;
77183
- if (store) store.epoch = restEpoch;
77184
- return finalStatus;
77185
77385
  }
77186
77386
  }
77187
77387
  }
@@ -77229,7 +77429,7 @@ var Runtime = class _Runtime {
77229
77429
  scanArgs = this._fastSubPositional ?? rawState.positional;
77230
77430
  } else if (command7.words.length === 4 && (() => {
77231
77431
  const ne = command7.words[3].parts.filter((p) => !(p.kind === "text" && p.value === ""));
77232
- return ne.length === 1 && ne[0].kind === "variable" && ne[0].name === "@" && ne[0].quoted;
77432
+ return ne.length === 1 && ne[0].kind === "variable" && ne[0].name === "@" && ne[0].quoted && !ne[0].length && !ne[0].substring && !ne[0].operator && !ne[0].transform && !ne[0].indirect && !ne[0].prefixNames && getArraySelector(ne[0]) === void 0;
77233
77433
  })()) {
77234
77434
  scanArgs = this._fastSubPositional ?? rawState.positional;
77235
77435
  if (scanArgs.length > 0) lastArg = scanArgs[scanArgs.length - 1];
@@ -77251,7 +77451,7 @@ var Runtime = class _Runtime {
77251
77451
  } catch {
77252
77452
  scanArgs = void 0;
77253
77453
  }
77254
- if (typeof optstring === "string" && scanArgs !== void 0) {
77454
+ if (typeof optstring === "string" && optstring.startsWith(":") && scanArgs !== void 0) {
77255
77455
  rawState.getopts ??= cloneGetoptsBinding(rawState);
77256
77456
  const res = scanGetoptsSync(rawState.getopts.cursor, optstring, scanArgs);
77257
77457
  if (res !== void 0) {
@@ -77326,7 +77526,7 @@ var Runtime = class _Runtime {
77326
77526
  monitor.lazyPipeStatus = singleStatusZero;
77327
77527
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77328
77528
  } else {
77329
- elem0.text.shellValue = "0";
77529
+ this.setSyncPipeStatusCell(existing, "0");
77330
77530
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77331
77531
  }
77332
77532
  rawState.status = 0;
@@ -77410,7 +77610,7 @@ var Runtime = class _Runtime {
77410
77610
  monitor.lazyPipeStatus = singleStatusZero;
77411
77611
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77412
77612
  } else {
77413
- elem0.text.shellValue = "0";
77613
+ this.setSyncPipeStatusCell(existing, "0");
77414
77614
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77415
77615
  }
77416
77616
  const finalStatus = pipeline.negate ? 1 : 0;
@@ -77596,28 +77796,7 @@ var Runtime = class _Runtime {
77596
77796
  } else {
77597
77797
  const arrStore = monitor.store ?? requireArrays(rawState);
77598
77798
  existingArrayBinding = arrStore.get(arrayTarget);
77599
- if (!existingArrayBinding && rawState.variables[arrayTarget] === void 0 && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
77600
- const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
77601
- const recBinding = arrStore.takeRecycled(arrayTarget, false, true, recTickets);
77602
- if (recBinding) {
77603
- monitor.epoch = recTickets.epoch;
77604
- existingArrayBinding = recBinding;
77605
- } else try {
77606
- const created = IndexedBinding.create(arrStore.owner, false);
77607
- const nameByteLen = shellValueByteLength(arrayTarget);
77608
- const prepared = arrStore.prepareExistingName(arrayTarget, nameByteLen, arrStore.owner, this.signal);
77609
- if (prepared) {
77610
- const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
77611
- arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
77612
- monitor.epoch = initTickets.epoch;
77613
- existingArrayBinding = created;
77614
- } else {
77615
- void created.release();
77616
- }
77617
- } catch {
77618
- }
77619
- }
77620
- if (!existingArrayBinding || existingArrayBinding.associative || existingArrayBinding.references !== 1 || arrStore.watches.has(arrayTarget) || monitor.hasOverlay(arrayTarget)) {
77799
+ if ((existingArrayBinding ? existingArrayBinding.associative || existingArrayBinding.references !== 1 : rawState.variables[arrayTarget] !== void 0) || arrStore.watches.has(arrayTarget) || monitor.hasOverlay(arrayTarget)) {
77621
77800
  simpleRead = false;
77622
77801
  }
77623
77802
  }
@@ -77656,6 +77835,31 @@ var Runtime = class _Runtime {
77656
77835
  }
77657
77836
  } else lineStr = io.stdin.tryReadSimpleRawAsciiLineSync(readDelim, raw);
77658
77837
  if (lineStr !== void 0) {
77838
+ if (arrayTarget !== void 0 && !existingArrayBinding) {
77839
+ const arrStore = monitor.store ?? requireArrays(rawState);
77840
+ if (!existingArrayBinding && rawState.variables[arrayTarget] === void 0 && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
77841
+ const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
77842
+ const recBinding = arrStore.takeRecycled(arrayTarget, false, true, recTickets);
77843
+ if (recBinding) {
77844
+ monitor.epoch = recTickets.epoch;
77845
+ existingArrayBinding = recBinding;
77846
+ } else try {
77847
+ const created = IndexedBinding.create(arrStore.owner, false);
77848
+ const nameByteLen = shellValueByteLength(arrayTarget);
77849
+ const prepared = arrStore.prepareExistingName(arrayTarget, nameByteLen, arrStore.owner, this.signal);
77850
+ if (prepared) {
77851
+ const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
77852
+ arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
77853
+ monitor.epoch = initTickets.epoch;
77854
+ existingArrayBinding = created;
77855
+ } else {
77856
+ void created.release();
77857
+ }
77858
+ } catch {
77859
+ }
77860
+ }
77861
+ if (!existingArrayBinding) return void 0;
77862
+ }
77659
77863
  if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
77660
77864
  if (arrayTarget !== void 0 && existingArrayBinding) {
77661
77865
  const isSep = (c) => {
@@ -77705,6 +77909,7 @@ var Runtime = class _Runtime {
77705
77909
  readArrayScratchFields.length = 0;
77706
77910
  delete rawState.variables[arrayTarget];
77707
77911
  monitor.epoch = tickets.epoch;
77912
+ existingArrayBinding.assigned = true;
77708
77913
  activeArrStore.revise(arrayTarget, existingArrayBinding, tickets);
77709
77914
  } catch (error) {
77710
77915
  readArrayScratchFields.length = 0;
@@ -77761,7 +77966,7 @@ var Runtime = class _Runtime {
77761
77966
  monitor.lazyPipeStatus = singleStatusZero;
77762
77967
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77763
77968
  } else {
77764
- elem0.text.shellValue = "0";
77969
+ this.setSyncPipeStatusCell(existing, "0");
77765
77970
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77766
77971
  }
77767
77972
  rawState.status = 0;
@@ -77919,7 +78124,7 @@ var Runtime = class _Runtime {
77919
78124
  monitor.lazyPipeStatus = singleStatusZero;
77920
78125
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77921
78126
  } else {
77922
- elem0.text.shellValue = "0";
78127
+ this.setSyncPipeStatusCell(existing, "0");
77923
78128
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77924
78129
  }
77925
78130
  rawState.status = 0;
@@ -77984,7 +78189,7 @@ var Runtime = class _Runtime {
77984
78189
  monitor.lazyPipeStatus = singleStatusZero;
77985
78190
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
77986
78191
  } else {
77987
- elem0.text.shellValue = "0";
78192
+ this.setSyncPipeStatusCell(existing, "0");
77988
78193
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
77989
78194
  }
77990
78195
  rawState.status = 0;
@@ -78052,6 +78257,7 @@ var Runtime = class _Runtime {
78052
78257
  if (isLocalScope) {
78053
78258
  let existingLocal = currentFrame.get(an);
78054
78259
  if (!existingLocal) {
78260
+ if (this._syncArithRawWriteOnly && this._syncArithTouched?.has(an)) monitor.values.invalidate(an);
78055
78261
  existingLocal = saveVariable(state, an);
78056
78262
  syncLocalArrayVariables.add(existingLocal);
78057
78263
  currentFrame.set(an, existingLocal);
@@ -78108,13 +78314,15 @@ var Runtime = class _Runtime {
78108
78314
  }
78109
78315
  return void 0;
78110
78316
  }
78317
+ const isNamerefDecl = command7.words[1]?.plain === "-n" && rawState.locals.length > 0 && command7.words.length >= 3;
78318
+ const isGlobalDecl = command7.words[1]?.plain === "-g" && (w0Plain === "declare" || w0Plain === "typeset") && command7.words.length >= 3;
78111
78319
  const parsedLocals = [];
78112
78320
  let allValidLocal = true;
78113
- for (let idx = 1; idx < command7.words.length; idx++) {
78321
+ for (let idx = isNamerefDecl || isGlobalDecl ? 2 : 1; idx < command7.words.length; idx++) {
78114
78322
  const wArg = command7.words[idx];
78115
78323
  const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : void 0;
78116
78324
  if (assignment) {
78117
- if (assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND")) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || rawState.readonlyVariables?.has(assignment.name) || store?.get(assignment.name)) {
78325
+ if (!isNamerefDecl && rawState.variableAttributes?.get(assignment.name) || assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND")) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || rawState.readonlyVariables?.has(assignment.name) || store?.get(assignment.name)) {
78118
78326
  allValidLocal = false;
78119
78327
  break;
78120
78328
  }
@@ -78144,9 +78352,27 @@ var Runtime = class _Runtime {
78144
78352
  break;
78145
78353
  }
78146
78354
  }
78355
+ if (isNamerefDecl && allValidLocal) {
78356
+ for (let i = 0; i < parsedLocals.length; i++) {
78357
+ const it = parsedLocals[i];
78358
+ if (!it.val || it.append || !isShellIdentifier(it.val) || it.val === it.name || rawState.variableAttributes?.get(it.val)) {
78359
+ allValidLocal = false;
78360
+ break;
78361
+ }
78362
+ }
78363
+ }
78364
+ if (isGlobalDecl && allValidLocal && rawState.locals.length > 0) {
78365
+ for (let i = 0; i < parsedLocals.length; i++) {
78366
+ const it = parsedLocals[i];
78367
+ if (rawState.locals.some((f) => f.has(it.name))) {
78368
+ allValidLocal = false;
78369
+ break;
78370
+ }
78371
+ }
78372
+ }
78147
78373
  if (allValidLocal && parsedLocals.length > 0) {
78148
- if (rawState.locals.length === 0 && parsedLocals.some((item) => item.val === void 0 && !rawState.variableAttributes?.has(item.name))) return void 0;
78149
- const locals = rawState.locals.length > 0 ? rawState.locals[rawState.locals.length - 1] : void 0;
78374
+ if ((rawState.locals.length === 0 || isGlobalDecl) && parsedLocals.some((item) => item.val === void 0 && !rawState.variableAttributes?.has(item.name))) return void 0;
78375
+ const locals = !isGlobalDecl && rawState.locals.length > 0 ? rawState.locals[rawState.locals.length - 1] : void 0;
78150
78376
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
78151
78377
  this.budget.tick();
78152
78378
  rawState.substitutionStatus = 0;
@@ -78157,7 +78383,7 @@ var Runtime = class _Runtime {
78157
78383
  if (locals && isNewLocal) {
78158
78384
  if (this._syncArithRawWriteOnly && this._syncArithTouched) {
78159
78385
  const curVal = this._syncArithTouched.has(item.name) ? rawState.variables[item.name] : rawState.variables[item.name] === void 0 ? void 0 : monitor.values.get(item.name, rawState.variables[item.name]) ?? rawState.variables[item.name];
78160
- locals.set(item.name, { attributes: void 0, value: typeof curVal === "string" ? curVal : void 0, exported: false, readOnly: false, ...item.name === "OPTIND" ? { getopts: cloneGetoptsBinding(rawState) } : {} });
78386
+ locals.set(item.name, { attributes: void 0, value: typeof curVal === "string" ? curVal : void 0, exported: rawState.exported.has(item.name), readOnly: false, ...item.name === "OPTIND" ? { getopts: cloneGetoptsBinding(rawState) } : {} });
78161
78387
  } else locals.set(item.name, saveVariable(state, item.name));
78162
78388
  delete rawState.variables[item.name];
78163
78389
  if (this._syncArithRawWriteOnly && this._syncArithTouched) this._syncArithTouched.add(item.name);
@@ -78176,7 +78402,10 @@ var Runtime = class _Runtime {
78176
78402
  }
78177
78403
  if (rawState.allexport) monitor.proxy.exported.add(item.name);
78178
78404
  rawState.lastArgument = `${item.name}=${finalVal}`;
78179
- if (isNewLocal && rawState.variableAttributes?.has(item.name)) rawState.variableAttributes.delete(item.name);
78405
+ if (isNamerefDecl) {
78406
+ rawState.variableAttributes ??= /* @__PURE__ */ new Map();
78407
+ rawState.variableAttributes.set(item.name, "n");
78408
+ } else if (isNewLocal && rawState.variableAttributes?.has(item.name)) rawState.variableAttributes.delete(item.name);
78180
78409
  } else {
78181
78410
  if (item.name === "OPTIND") this.syncGetopts(rawState);
78182
78411
  if (!locals) {
@@ -78199,7 +78428,7 @@ var Runtime = class _Runtime {
78199
78428
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78200
78429
  }
78201
78430
  } else {
78202
- elem0.text.shellValue = "0";
78431
+ this.setSyncPipeStatusCell(existing, "0");
78203
78432
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78204
78433
  }
78205
78434
  rawState.status = 0;
@@ -78222,7 +78451,6 @@ var Runtime = class _Runtime {
78222
78451
  if (fastArg.length > 0 && fastArg.length <= 15 && /^-?[0-9]+$/.test(fastArg)) {
78223
78452
  const retStatus = (Number(fastArg) % 256 + 256) % 256;
78224
78453
  const statusStr = retStatus === 0 ? "0" : retStatus === 1 ? "1" : String(retStatus);
78225
- if (existing && elem0.text.bytes !== statusStr.length) return void 0;
78226
78454
  const prevStatus = rawState.status;
78227
78455
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
78228
78456
  this.budget.tick();
@@ -78234,7 +78462,7 @@ var Runtime = class _Runtime {
78234
78462
  monitor.lazyPipeStatus = retStatus === 0 ? singleStatusZero : retStatus === 1 ? singleStatusOne : [retStatus];
78235
78463
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78236
78464
  } else {
78237
- elem0.text.shellValue = statusStr;
78465
+ this.setSyncPipeStatusCell(existing, statusStr);
78238
78466
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78239
78467
  }
78240
78468
  rawState.status = retStatus;
@@ -78272,9 +78500,13 @@ var Runtime = class _Runtime {
78272
78500
  } else {
78273
78501
  const savedPos = rawState.positional;
78274
78502
  rawState.positional = fnArgs;
78503
+ rawState.locals.push(/* @__PURE__ */ new Map());
78504
+ rawState.functionDepth++;
78275
78505
  try {
78276
78506
  canSyncFn = this.canSyncScriptCompound(fnBody.body, rawState, 1);
78277
78507
  } finally {
78508
+ rawState.functionDepth--;
78509
+ rawState.locals.pop();
78278
78510
  rawState.positional = savedPos;
78279
78511
  }
78280
78512
  }
@@ -78384,8 +78616,8 @@ var Runtime = class _Runtime {
78384
78616
  monitor.lazyPipeStatus = exitStatus === 0 ? singleStatusZero : exitStatus === 1 ? singleStatusOne : [exitStatus];
78385
78617
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78386
78618
  }
78387
- } else if (activeExisting.values.get(0).text.bytes === statusStr.length) {
78388
- activeExisting.values.get(0).text.shellValue = statusStr;
78619
+ } else {
78620
+ this.setSyncPipeStatusCell(activeExisting, statusStr);
78389
78621
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78390
78622
  }
78391
78623
  rawState.status = exitStatus;
@@ -78438,7 +78670,7 @@ var Runtime = class _Runtime {
78438
78670
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78439
78671
  }
78440
78672
  } else {
78441
- activeExisting.values.get(0).text.shellValue = "0";
78673
+ this.setSyncPipeStatusCell(activeExisting, "0");
78442
78674
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78443
78675
  }
78444
78676
  rawState.status = 0;
@@ -78467,7 +78699,7 @@ var Runtime = class _Runtime {
78467
78699
  rawState.depth++;
78468
78700
  let evalStatus;
78469
78701
  try {
78470
- evalStatus = this.trySyncScript(cachedUnit.script, state, io, Boolean(ignored));
78702
+ evalStatus = this.trySyncScript(cachedUnit.script, state, { ...io, diagnosticOffset: (diagnosticLine ?? 1) - 1, functionCommandLines: void 0, assignmentDiagnosticContext: { name: "eval" } }, Boolean(ignored));
78471
78703
  } finally {
78472
78704
  rawState.depth--;
78473
78705
  }
@@ -78483,7 +78715,7 @@ var Runtime = class _Runtime {
78483
78715
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78484
78716
  }
78485
78717
  } else {
78486
- activeExisting.values.get(0).text.shellValue = "0";
78718
+ this.setSyncPipeStatusCell(activeExisting, "0");
78487
78719
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78488
78720
  }
78489
78721
  }
@@ -78554,7 +78786,7 @@ var Runtime = class _Runtime {
78554
78786
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78555
78787
  }
78556
78788
  } else {
78557
- elem0.text.shellValue = statusChar;
78789
+ this.setSyncPipeStatusCell(existing, statusChar);
78558
78790
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78559
78791
  }
78560
78792
  const finalStatus = pipeline.negate ? Number(fastPred === 0) : fastPred;
@@ -78614,7 +78846,7 @@ var Runtime = class _Runtime {
78614
78846
  } else {
78615
78847
  const idxNum = /^(?:0|[1-9][0-9]{0,8})$/.test(subExpr) ? Number(subExpr) : resolveSimpleArithOperand(subExpr, rawState, monitor, arrStore, this._syncArithRawWriteOnly ? this._syncArithTouched : void 0);
78616
78848
  if (idxNum !== void 0 && idxNum >= 0 && idxNum <= 2147483647) {
78617
- if (!curB && rawState.variables[arrName] === void 0 && !arrStore.watches.has(arrName) && !monitor.hasOverlay(arrName)) {
78849
+ if (!curB && !hasUnpreparedLocal(rawState, arrName) && rawState.variables[arrName] === void 0 && !arrStore.watches.has(arrName) && !monitor.hasOverlay(arrName)) {
78618
78850
  const created = IndexedBinding.create(arrStore.owner, false);
78619
78851
  const prepared = arrStore.prepareExistingName(arrName, shellValueByteLength(arrName), arrStore.owner, this.signal);
78620
78852
  if (prepared) {
@@ -78651,7 +78883,7 @@ var Runtime = class _Runtime {
78651
78883
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78652
78884
  }
78653
78885
  } else {
78654
- activeExisting.values.get(0).text.shellValue = "0";
78886
+ this.setSyncPipeStatusCell(activeExisting, "0");
78655
78887
  activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78656
78888
  }
78657
78889
  const finalStatus = pipeline.negate ? 1 : 0;
@@ -78724,7 +78956,7 @@ var Runtime = class _Runtime {
78724
78956
  monitor.lazyPipeStatus = singleStatusZero;
78725
78957
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
78726
78958
  } else {
78727
- elem0.text.shellValue = "0";
78959
+ this.setSyncPipeStatusCell(existing, "0");
78728
78960
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
78729
78961
  }
78730
78962
  const finalStatus = pipeline.negate ? 1 : 0;
@@ -78769,7 +79001,7 @@ var Runtime = class _Runtime {
78769
79001
  if (rawState.nounset && part.name >= "1" && part.name <= "9" && rawState.positional[part.name.charCodeAt(0) - 49] === void 0) return false;
78770
79002
  continue;
78771
79003
  }
78772
- if (part.prefixNames || part.specialParameter || part.transform || part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || !isShellIdentifier(part.name)) {
79004
+ if (part.prefixNames || part.specialParameter || part.transform || part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || part.name === "DIRSTACK" || !isShellIdentifier(part.name)) {
78773
79005
  return false;
78774
79006
  }
78775
79007
  if (part.indirect) {
@@ -79183,7 +79415,7 @@ var Runtime = class _Runtime {
79183
79415
  monitor.lazyPipeStatus = singleStatusZero;
79184
79416
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
79185
79417
  } else {
79186
- elem0.text.shellValue = "0";
79418
+ this.setSyncPipeStatusCell(existing, "0");
79187
79419
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
79188
79420
  }
79189
79421
  }
@@ -79535,7 +79767,7 @@ var Runtime = class _Runtime {
79535
79767
  monitor.lazyPipeStatus = singleStatusZero;
79536
79768
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
79537
79769
  } else {
79538
- elem0.text.shellValue = "0";
79770
+ this.setSyncPipeStatusCell(existing, "0");
79539
79771
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
79540
79772
  }
79541
79773
  }
@@ -79749,7 +79981,7 @@ var Runtime = class _Runtime {
79749
79981
  monitor.lazyPipeStatus = singleStatusZero;
79750
79982
  monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
79751
79983
  } else {
79752
- elem0.text.shellValue = "0";
79984
+ this.setSyncPipeStatusCell(existing, "0");
79753
79985
  store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
79754
79986
  }
79755
79987
  }
@@ -82038,7 +82270,7 @@ ${s1}
82038
82270
  previous.set(assignment.name, saved);
82039
82271
  const existingArray = arrayStore(state)?.get(assignment.name);
82040
82272
  const canSkipTypedScalarOverlay = !existingArray && words[0] === "read" && !state.functions.has("read") && !state.extensions?.builtins.has("read") && !words.some((w) => w.startsWith("-a") || w.startsWith("-") && !w.startsWith("--") && w.includes("a"));
82041
- if (words.length && !canSkipTypedScalarOverlay && (guestArrays(state) || assignment.name === "PIPESTATUS" && existingArray)) {
82273
+ if (words.length && !canSkipTypedScalarOverlay && (guestArrays(state) || existingArray)) {
82042
82274
  const store = requireArrays(state);
82043
82275
  await this.prepareVariable(state, assignment.name, saved, !existingArray);
82044
82276
  if (existingArray) {
@@ -82060,15 +82292,28 @@ ${s1}
82060
82292
  overlayOpen = true;
82061
82293
  }
82062
82294
  if (inlineInput || (state.profile === "sh" || !words.length) && assignments2.some((assignment) => state.readonlyVariables?.has(assignment.name))) await assign();
82063
- if (inlineInput && (functionCommand || words[0] === "read" && !state.extensions?.builtins.has("read")) && previous?.size) {
82295
+ if (inlineInput && previous?.size) {
82064
82296
  if (stateMonitor(state)?.lazyPipeStatus !== void 0) stateMonitor(state).activate(true);
82065
82297
  const redirectState = tryCloneStateSync(state) ?? await cloneState(state, this.signal);
82066
82298
  const variables = redirectState.variables;
82067
82299
  const redirectAssignments = /* @__PURE__ */ new Map();
82068
82300
  for (const [name2, saved] of previous) {
82069
82301
  redirectAssignments.set(name2, stateMonitor(state).values.get(name2, state.variables[name2]));
82302
+ if (saved.exported) redirectState.exported.add(name2);
82303
+ else redirectState.exported.delete(name2);
82070
82304
  if (saved.value === void 0) delete variables[name2];
82071
82305
  else publishVariable(redirectState, name2, saved.heldValue?.value ?? saved.value);
82306
+ const binding = typedSavedVariables.get(saved)?.binding;
82307
+ if (binding) {
82308
+ const store = requireArrays(redirectState);
82309
+ const prepared = await store.prepareName(name2, store.owner, this.signal);
82310
+ const tickets = store.tickets(name2);
82311
+ try {
82312
+ await store.publish(name2, binding.retain(), tickets, prepared);
82313
+ } finally {
82314
+ tickets.release();
82315
+ }
82316
+ }
82072
82317
  }
82073
82318
  redirectState.redirectAssignments = redirectAssignments;
82074
82319
  const savedIndex = previous.get("OPTIND");
@@ -82084,7 +82329,7 @@ ${s1}
82084
82329
  }
82085
82330
  const epoch2 = stateMonitor(state)?.epoch;
82086
82331
  try {
82087
- io = await this.redirect(command7.redirects, redirectState, io, inputs, outputs, false, true, false, command7.line ?? 1);
82332
+ io = await this.redirect(command7.redirects, redirectState, io, inputs, outputs, isolatedInlineInput, !isolatedInlineInput, false, command7.line ?? 1);
82088
82333
  if (parentStore && stateMonitor(state).epoch !== epoch2) throw new ArrayFailure("stale state snapshot");
82089
82334
  } finally {
82090
82335
  try {
@@ -82105,6 +82350,12 @@ ${s1}
82105
82350
  if (!previous.has(name2)) publishVariable(state, name2, stateMonitor(redirectState).values.get(name2, value2));
82106
82351
  }
82107
82352
  for (const [name2, saved] of previous) {
82353
+ const typed = typedSavedVariables.get(saved);
82354
+ const binding = arrayStore(redirectState)?.get(name2);
82355
+ if (typed && binding !== typed.binding) {
82356
+ typedSavedVariables.set(saved, { ...typed, binding: binding?.retain() });
82357
+ await typed.binding?.release();
82358
+ }
82108
82359
  saved.value = variables[name2];
82109
82360
  const value2 = stateMonitor(redirectState).values.get(name2, saved.value ?? "");
82110
82361
  const held = saved.value === void 0 ? void 0 : stateMonitor(state).values.scope.hold(value2);
@@ -85863,6 +86114,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
85863
86114
  seen.add(name2);
85864
86115
  names.push(name2);
85865
86116
  };
86117
+ await consider("DIRSTACK", true);
86118
+ if (state.functionNames?.length) await consider("FUNCNAME", true);
85866
86119
  for (const name2 in state.variables) if (Object.hasOwn(state.variables, name2)) await consider(name2, state.variables[name2] !== void 0);
85867
86120
  if (store) for (const [name2, entry] of store.bindings) await consider(name2, entry.binding.assigned);
85868
86121
  for (const frame of state.locals) for (const [name2, saved] of frame) {
@@ -85929,7 +86182,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
85929
86182
  setArraySelector(resolved2, { kind: "element", index: { decimal: (0, value_exports.shellValueText)(value2), word: { offset: word.offset, parts: [{ kind: "text", value: (0, value_exports.shellValueText)(value2), quoted: true, ...typeof value2 === "string" ? {} : { byteValue: value2 } }] } } });
85930
86183
  return resolved2;
85931
86184
  }
85932
- const maximum = binding?.maximum ?? (state.variables[part.name] === void 0 ? -1 : 0);
86185
+ const maximum = binding?.maximum ?? (part.name === "FUNCNAME" && state.variables.FUNCNAME === void 0 ? (state.functionNames?.length ?? 0) - 1 : state.variables[part.name] === void 0 ? -1 : 0);
85933
86186
  const index = await this.arrayIndex(binding, selector.index, state, io, store.owner, false, maximum);
85934
86187
  const resolved = { ...part };
85935
86188
  copyArraySelector(part, resolved);
@@ -85987,8 +86240,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
85987
86240
  const selector2 = getArraySelector(part);
85988
86241
  if (selector2?.kind === "members" || part.name === "@" || part.name === "*") {
85989
86242
  const members = selector2 ? await this.arrayMembers(part.name, state, io, part.keys) : this.positionalValues(state);
85990
- const ifs = state.variables.IFS ?? " ";
85991
- const separator = !split3 && (selector2?.kind === "members" ? selector2.separator === "@" || !part.quoted : part.name === "@") ? " " : ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
86243
+ const separator = !split3 && (selector2?.kind === "members" ? selector2.separator === "@" : part.name === "@") ? " " : this.ifsSeparator(state, io);
85992
86244
  const fragments2 = [];
85993
86245
  let bytes3 = 0;
85994
86246
  for (const member of members) {
@@ -86707,14 +86959,14 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86707
86959
  fastValueWord(word, state, io, split3, pattern, hereDocument, braces, assignmentStart, overrideDiagnosticLine) {
86708
86960
  const monitor = stateMonitor(state);
86709
86961
  const rawState = monitor ? monitor.raw : state;
86710
- if (pattern || word.parts.length === 0 || rawState.depth + (io.parameterDepth ?? 0) >= 32 || hasActiveVariableAttributes(rawState)) return void 0;
86962
+ if (pattern || word.parts.length === 0 || rawState.depth + (io.parameterDepth ?? 0) >= 32 || hasNonNamerefAttributes(rawState)) return void 0;
86711
86963
  if (guestArrays(state) && word.parts.some((part) => part.kind === "arithmetic" && !part.expression.error && !isSafeSmiProgram(part.expression))) return void 0;
86712
86964
  const activeArrayStore = arrayStore(state);
86713
86965
  const rawVars = rawState.variables;
86714
86966
  this.signal.throwIfAborted();
86715
86967
  let out = "";
86716
86968
  for (let i = 0; i < word.parts.length; i++) {
86717
- const part = word.parts[i];
86969
+ let part = word.parts[i];
86718
86970
  if (part.kind === "text") {
86719
86971
  if (part.byteValue || invokedValues.has(part)) return void 0;
86720
86972
  if (hereDocument && part.quoted && part.value.includes("$")) return void 0;
@@ -86725,7 +86977,14 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86725
86977
  }
86726
86978
  out += part.value;
86727
86979
  } else if (part.kind === "variable") {
86728
- if (rawState.variableAttributes?.get(part.name)?.includes("n")) return void 0;
86980
+ if (rawState.variableAttributes?.get(part.name)?.includes("n")) {
86981
+ if (part.indirect) return void 0;
86982
+ const resolvedName = resolveSyncNameref(rawState, part.name);
86983
+ if (resolvedName === part.name) return void 0;
86984
+ const origSel = getArraySelector(part);
86985
+ part = { ...part, name: resolvedName };
86986
+ if (origSel) setArraySelector(part, origSel);
86987
+ }
86729
86988
  if (split3 && !part.quoted && (rawVars.IFS !== void 0 && rawVars.IFS !== " \n")) return void 0;
86730
86989
  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")) {
86731
86990
  let val2;
@@ -86749,7 +87008,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86749
87008
  const refRaw = rawVars[part.name];
86750
87009
  const refName = refRaw === void 0 ? void 0 : this._syncArithRawWriteOnly && this._syncArithTouched?.has(part.name) ? refRaw : monitor?.values.get(part.name, refRaw) ?? refRaw;
86751
87010
  if (typeof refName !== "string" || !isShellIdentifier(refName)) return void 0;
86752
- if (activeArrayStore?.get(refName) || rawState.variableAttributes?.get(refName) || refName === "PIPESTATUS" || refName === "LINENO" || refName === "_" || refName === "FUNCNAME") {
87011
+ if (activeArrayStore?.get(refName) || rawState.variableAttributes?.get(refName) || refName === "PIPESTATUS" || refName === "LINENO" || refName === "_" || refName === "FUNCNAME" || refName === "DIRSTACK") {
86753
87012
  return void 0;
86754
87013
  }
86755
87014
  const targetRaw = rawVars[refName];
@@ -86762,7 +87021,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86762
87021
  continue;
86763
87022
  }
86764
87023
  if (part.indirect || part.prefixNames || part.specialParameter || part.transform) return void 0;
86765
- if (part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME") return void 0;
87024
+ if (part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || part.name === "DIRSTACK") return void 0;
86766
87025
  if (!isShellIdentifier(part.name)) return void 0;
86767
87026
  const selector = getArraySelector(part);
86768
87027
  const arrayBinding = activeArrayStore?.get(part.name);
@@ -86830,9 +87089,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86830
87089
  const ifsVal = monitor?.values.get("IFS", rawVars.IFS ?? " ") ?? rawVars.IFS ?? " ";
86831
87090
  if (validElemOp && typeof ifsVal === "string" && (ifsVal.length === 0 || ifsVal.charCodeAt(0) < 128)) {
86832
87091
  const sep = selector.separator === "@" && (!isKeys || ifsVal.length === 0) ? " " : ifsVal.length > 0 ? ifsVal[0] : "";
87092
+ const parameterLine = part.line ?? overrideDiagnosticLine;
86833
87093
  const evalSliceInt = (w) => {
86834
87094
  if (w.parts.length === 0) return 0;
86835
- const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, void 0, part.line ?? overrideDiagnosticLine);
87095
+ const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, void 0, parameterLine);
86836
87096
  if (typeof expanded !== "string") return void 0;
86837
87097
  const trimmed = expanded.trim();
86838
87098
  if (trimmed.length === 0) return 0;
@@ -87012,9 +87272,10 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
87012
87272
  if (part.length || part.operator !== void 0 || this.budget.limits.maxExpansionBytes !== Infinity || rawState.depth + (io.parameterDepth ?? 0) >= 60 || !part.substring.offset.parts.every((p) => p.kind === "text" || p.kind === "arithmetic" || p.kind === "variable" && !p.operator && !p.substring) || part.substring.length && !part.substring.length.parts.every((p) => p.kind === "text" || p.kind === "arithmetic" || p.kind === "variable" && !p.operator && !p.substring) || ValueScope.prototype.reserve !== defaultValueScopeReserve || String.prototype.codePointAt !== defaultStringCodePointAt || globalThis.Float64Array !== defaultFloat64Array || !part.substring.offset.parts.length && !part.substring.length) {
87013
87273
  return void 0;
87014
87274
  }
87275
+ const parameterLine = part.line ?? overrideDiagnosticLine;
87015
87276
  const evalSubInt = (w) => {
87016
87277
  if (w.parts.length === 0) return 0;
87017
- const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, void 0, part.line ?? overrideDiagnosticLine);
87278
+ const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, void 0, parameterLine);
87018
87279
  if (typeof expanded !== "string") return void 0;
87019
87280
  const trimmed = expanded.trim();
87020
87281
  if (trimmed.length === 0) return 0;
@@ -87072,7 +87333,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
87072
87333
  }
87073
87334
  if (part.operator !== void 0) {
87074
87335
  if (this.budget.limits.maxExpansionBytes !== Infinity || rawState.depth + (io.parameterDepth ?? 0) >= 60 || ValueScope.prototype.reserve !== defaultValueScopeReserve || String.prototype.codePointAt !== defaultStringCodePointAt || globalThis.Float64Array !== defaultFloat64Array) return void 0;
87075
- if (!rawState.nocasematch && (part.operator === "/" || part.operator === "//" || part.operator === "/#" || part.operator === "/%") && part.alternate && part.alternate.parts.length >= 1 && part.alternate.parts.every((p) => p.quoted === part.alternate.parts[0].quoted && (p.kind === "text" && !p.byteValue || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name))) && (!part.replacement || part.replacement.parts.length === 0 || part.replacement.parts.every((p) => p.kind === "text" && !p.byteValue || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name)))) {
87336
+ const patternQuoted = part.alternate?.parts[0]?.quoted;
87337
+ if (!rawState.nocasematch && (part.operator === "/" || part.operator === "//" || part.operator === "/#" || part.operator === "/%") && part.alternate && part.alternate.parts.length >= 1 && part.alternate.parts.every((p) => p.quoted === patternQuoted && (p.kind === "text" && !p.byteValue || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name))) && (!part.replacement || part.replacement.parts.length === 0 || part.replacement.parts.every((p) => p.kind === "text" && !p.byteValue || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name)))) {
87076
87338
  const patQuoted = part.alternate.parts[0].quoted;
87077
87339
  const pat = part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text" ? part.alternate.parts[0].value : this.fastValueWord(part.alternate, rawState, io, false, false, false, false, void 0, part.line ?? overrideDiagnosticLine);
87078
87340
  if (typeof pat !== "string" || pat.length === 0) return void 0;
@@ -87127,7 +87389,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
87127
87389
  out += replaced;
87128
87390
  continue;
87129
87391
  }
87130
- if ((part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") && part.alternate && part.alternate.parts.length >= 1 && part.alternate.parts.every((p) => p.quoted === part.alternate.parts[0].quoted && (p.kind === "text" && !p.byteValue || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name)))) {
87392
+ if ((part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") && part.alternate && part.alternate.parts.length >= 1 && part.alternate.parts.every((p) => p.quoted === patternQuoted && (p.kind === "text" && !p.byteValue || p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === void 0 && isShellIdentifier(p.name)))) {
87131
87393
  const patQuoted = part.alternate.parts[0].quoted;
87132
87394
  const pat = part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text" ? part.alternate.parts[0].value : this.fastValueWord(part.alternate, rawState, io, false, false, false, false, void 0, part.line ?? overrideDiagnosticLine);
87133
87395
  if (typeof pat !== "string") return void 0;
@@ -87329,7 +87591,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
87329
87591
  if (rawState.nounset && p.name >= "1" && p.name <= "9" && activePos[p.name.charCodeAt(0) - 49] === void 0) return false;
87330
87592
  continue;
87331
87593
  }
87332
- if (p.prefixNames || p.specialParameter || p.transform || p.name === "@" || p.name === "*" || p.name === "PIPESTATUS" || p.name === "LINENO" || p.name === "_" || p.name === "FUNCNAME" || !isShellIdentifier(p.name)) {
87594
+ if (p.prefixNames || p.specialParameter || p.transform || p.name === "@" || p.name === "*" || p.name === "PIPESTATUS" || p.name === "LINENO" || p.name === "_" || p.name === "FUNCNAME" || p.name === "DIRSTACK" || !isShellIdentifier(p.name)) {
87333
87595
  return false;
87334
87596
  }
87335
87597
  if (p.operator !== void 0 && (p.operator === "=" || p.operator === ":=" || p.operator === "?" || p.operator === ":?")) return false;
@@ -88217,7 +88479,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
88217
88479
  const binding = arrayStore(state)?.get(part.name);
88218
88480
  const index2 = binding?.associative ? await this.arrayIndex(binding, selector.index, state, partIO, requireArrays(state).owner) : numericIndex(selector.index, 4294967295);
88219
88481
  if (index2 === void 0 && !binding?.associative) throw new ArrayFailure("index outside 0..4294967295");
88220
- value2 = binding ? index2 === void 0 ? void 0 : binding.getValue(index2) : index2 === 0 ? value2 : void 0;
88482
+ value2 = binding ? index2 === void 0 ? void 0 : binding.getValue(index2) : part.name === "FUNCNAME" && state.variables.FUNCNAME === void 0 ? index2 === void 0 ? void 0 : state.functionNames?.[index2] : index2 === 0 ? value2 : void 0;
88221
88483
  }
88222
88484
  const missing = value2 === void 0 || part.operator.startsWith(":") && shellValueByteLength(value2) === 0;
88223
88485
  if (part.operator.endsWith("+") ? !missing : missing) {
@@ -88517,7 +88779,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
88517
88779
  return this.arithmeticValue(prepareArithmetic(source2 || "0", this.budget.parsing), state, io);
88518
88780
  };
88519
88781
  offset = await evaluate(substring.offset);
88520
- if (offset < 0n) offset += BigInt((binding?.maximum ?? (state.variables[name2] === void 0 ? -1 : 0)) + 1);
88782
+ const maximum = binding?.maximum ?? (name2 === "FUNCNAME" && state.variables.FUNCNAME === void 0 ? (state.functionNames?.length ?? 0) - 1 : state.variables[name2] === void 0 ? -1 : 0);
88783
+ if (offset < 0n) offset += BigInt(maximum + 1);
88521
88784
  if (substring.length) {
88522
88785
  count2 = await evaluate(substring.length);
88523
88786
  if (count2 < 0n) throw new ExpansionFailure("substring expression < 0", io.diagnosticLine);
@@ -88528,7 +88791,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
88528
88791
  if (!binding) {
88529
88792
  if (name2 === "FUNCNAME" && state.variables.FUNCNAME === void 0) {
88530
88793
  const stack = state.functionNames ?? [];
88531
- const start = offset < 0n ? Math.max(0, stack.length + Number(offset)) : Number(offset);
88794
+ const start = Number(offset);
88532
88795
  const end = count2 === void 0 ? stack.length : start + Number(count2);
88533
88796
  const sliced = stack.slice(start, end);
88534
88797
  return keys2 ? sliced.map((_v, idx) => String(start + idx)) : sliced;