@poe-platform/safe-bash 0.1.736 → 0.1.737

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.
@@ -55003,13 +55003,16 @@ function fastSafeInt(text3, budget) {
55003
55003
  function canEvalSafeSmiTree(node, depth = 0) {
55004
55004
  if (depth > 32) return false;
55005
55005
  if (node.kind === "literal") return node.value >= -94906265n && node.value <= 94906265n;
55006
- if (node.kind === "name") return node.subscript === void 0 || /^[0-9]{1,7}$/.test(node.subscript) || /^\$?[a-zA-Z_][a-zA-Z_0-9]*$/.test(node.subscript);
55006
+ if (node.kind === "name") return node.subscript === void 0 || /^[0-9]{1,7}$/.test(node.subscript) || /^\$?[a-zA-Z_][a-zA-Z_0-9]*$/.test(node.subscript) || /^\s*[a-zA-Z_][a-zA-Z_0-9]*\s*(?:[-+*]\s*(?:0|[1-9][0-9]{0,6})|[/%]\s*[1-9][0-9]{0,6})\s*$/.test(node.subscript);
55007
55007
  if (node.kind === "unary") {
55008
55008
  if (node.operator === "+" || node.operator === "-" || node.operator === "!") return canEvalSafeSmiTree(node.operand, depth + 1);
55009
55009
  if (node.operator === "++" || node.operator === "--") return node.operand.kind === "name" && canEvalSafeSmiTree(node.operand, depth + 1) && depth === 0;
55010
55010
  return false;
55011
55011
  }
55012
55012
  if (node.kind === "binary") {
55013
+ if (node.operator === "," && depth === 0) {
55014
+ return canEvalSafeSmiTree(node.left, 0) && canEvalSafeSmiTree(node.right, 0);
55015
+ }
55013
55016
  if ((node.operator === "=" || node.operator === "+=" || node.operator === "-=" || node.operator === "*=") && depth === 0) {
55014
55017
  return node.left.kind === "name" && canEvalSafeSmiTree(node.left, depth + 1) && canEvalSafeSmiTree(node.right, depth + 1);
55015
55018
  }
@@ -55048,6 +55051,11 @@ function evalSafeSmi(node, refs, budget) {
55048
55051
  return void 0;
55049
55052
  }
55050
55053
  if (node.kind === "binary") {
55054
+ if (node.operator === ",") {
55055
+ const l2 = evalSafeSmi(node.left, refs, budget);
55056
+ if (l2 === void 0) return void 0;
55057
+ return evalSafeSmi(node.right, refs, budget);
55058
+ }
55051
55059
  if (node.operator === "=") {
55052
55060
  const r2 = evalSafeSmi(node.right, refs, budget);
55053
55061
  if (r2 === void 0 || r2 < -94906265 || r2 > 94906265) return void 0;
@@ -64256,6 +64264,68 @@ async function scanGetopts(state, optstring, input3, options2) {
64256
64264
  }
64257
64265
  return finish("option", option, { kind: "unset" }, null);
64258
64266
  }
64267
+ var syncSpecScratch = new Int8Array(128);
64268
+ function scanGetoptsSync(state, optstring, args) {
64269
+ if (!record2(state) || typeof state.index !== "number" || !Number.isSafeInteger(state.index) || state.index < 0 || args.length > 1024 || optstring.length > 256) return void 0;
64270
+ for (let i = 0; i < optstring.length; i++) {
64271
+ const c = optstring.charCodeAt(i);
64272
+ if (c === 0 || c > 127) return void 0;
64273
+ }
64274
+ for (let i = 0; i < args.length; i++) {
64275
+ const a = args[i];
64276
+ if (a.length > 4096 || a.includes("\0")) return void 0;
64277
+ }
64278
+ const silent = optstring.charCodeAt(0) === 58;
64279
+ syncSpecScratch.fill(-1);
64280
+ for (let position = silent ? 1 : 0; position < optstring.length; position++) {
64281
+ const code2 = optstring.charCodeAt(position);
64282
+ if (code2 !== 58 && code2 !== 63 && syncSpecScratch[code2] === -1) syncSpecScratch[code2] = Number(optstring.charCodeAt(position + 1) === 58);
64283
+ }
64284
+ let index = state.index || 1;
64285
+ let active = state.index === 0 ? void 0 : state.active;
64286
+ if (index > args.length) {
64287
+ index = args.length + 1;
64288
+ return { state: { index }, kind: "end", status: 1, option: "?", optind: index, argument: { kind: "unset" }, diagnostic: null };
64289
+ }
64290
+ if (active && (args[active.argument] === void 0 || active.offset >= args[active.argument].length)) active = void 0;
64291
+ if (!active) {
64292
+ const token2 = args[index - 1];
64293
+ if (token2.length < 2 || token2.charCodeAt(0) !== 45) {
64294
+ return { state: { index }, kind: "end", status: 1, option: "?", optind: index, argument: { kind: "unset" }, diagnostic: null };
64295
+ }
64296
+ if (token2 === "--") {
64297
+ index++;
64298
+ return { state: { index }, kind: "end", status: 1, option: "?", optind: index, argument: { kind: "unset" }, diagnostic: null };
64299
+ }
64300
+ active = { argument: index - 1, offset: 1 };
64301
+ }
64302
+ const token = args[active.argument];
64303
+ const option = token[active.offset];
64304
+ const code = option.charCodeAt(0);
64305
+ if (code > 127) return void 0;
64306
+ const offset = active.offset + 1;
64307
+ const attached = offset < token.length;
64308
+ active = attached ? { argument: active.argument, offset } : void 0;
64309
+ if (!attached) index++;
64310
+ if (syncSpecScratch[code] === -1) {
64311
+ if (!silent) return void 0;
64312
+ return { state: active === void 0 ? { index } : { index, active }, kind: "unknown-option", status: 0, option: "?", optind: index, argument: { kind: "set", value: option }, diagnostic: null };
64313
+ }
64314
+ if (syncSpecScratch[code] === 1) {
64315
+ if (attached) {
64316
+ index++;
64317
+ return { state: { index }, kind: "option", status: 0, option, optind: index, argument: { kind: "set", value: token.slice(offset) }, diagnostic: null };
64318
+ }
64319
+ if (index <= args.length) {
64320
+ const value2 = args[index - 1];
64321
+ index++;
64322
+ return { state: active === void 0 ? { index } : { index, active }, kind: "option", status: 0, option, optind: index, argument: { kind: "set", value: value2 }, diagnostic: null };
64323
+ }
64324
+ if (!silent) return void 0;
64325
+ return { state: active === void 0 ? { index } : { index, active }, kind: "missing-argument", status: 0, option: ":", optind: index, argument: { kind: "set", value: option }, diagnostic: null };
64326
+ }
64327
+ return { state: active === void 0 ? { index } : { index, active }, kind: "option", status: 0, option, optind: index, argument: { kind: "unset" }, diagnostic: null };
64328
+ }
64259
64329
 
64260
64330
  // packages/safe-bash/src/shell/cancellation.ts
64261
64331
  init_platform();
@@ -71829,6 +71899,13 @@ var Runtime = class _Runtime {
71829
71899
  const rawSub = this._syncArithRawVars[resolvedSub];
71830
71900
  resolvedSub = rawSub === void 0 || rawSub === "" ? "0" : (0, value_exports.shellValueText)(stateMonitor(st)?.values.get(resolvedSub, rawSub) ?? rawSub);
71831
71901
  }
71902
+ } else {
71903
+ const st = this._syncArithState;
71904
+ const binding = arrayStore(st)?.get(variable);
71905
+ if (!binding || !binding.associative) {
71906
+ const subStr = tryEvalSimpleExpandedArith(resolvedSub, st, stateMonitor(st), arrayStore(st), this._syncArithRawWriteOnly ? this._syncArithTouched : void 0);
71907
+ if (subStr !== void 0 && !subStr.startsWith("-")) resolvedSub = subStr;
71908
+ }
71832
71909
  }
71833
71910
  if (resolvedSub.length === 0 || resolvedSub.length > 128 || !/^[a-zA-Z0-9_.\-/:@]+$/.test(resolvedSub)) throw new ArrayFailure("complex subscript in sync arithmetic");
71834
71911
  return `[idx]${variable}:${resolvedSub}`;
@@ -71964,9 +72041,23 @@ var Runtime = class _Runtime {
71964
72041
  case "literal":
71965
72042
  return true;
71966
72043
  case "name": {
71967
- if (tree.subscript !== void 0 || tree.name === "OPTIND" || tree.name === "PIPESTATUS" || arrayStore(state)?.get(tree.name)) return false;
72044
+ if (tree.name === "OPTIND" || tree.name === "PIPESTATUS") return false;
71968
72045
  const monitor = stateMonitor(state);
71969
72046
  if (monitor?.hasOverlay(tree.name) || monitor?.store?.watches.has(tree.name)) return false;
72047
+ if (tree.subscript !== void 0) {
72048
+ if (state.nounset || hasUnpreparedLocal(state, tree.name)) return false;
72049
+ const binding = arrayStore(state)?.get(tree.name);
72050
+ if (!binding) return false;
72051
+ if (binding.associative) {
72052
+ if (/^\$[a-zA-Z_][a-zA-Z_0-9]*$/.test(tree.subscript)) {
72053
+ const sv = tree.subscript.slice(1);
72054
+ return !arrayStore(state)?.get(sv) && !monitor?.hasOverlay(sv);
72055
+ }
72056
+ return /^[a-zA-Z0-9_.\-/:@]+$/.test(tree.subscript);
72057
+ }
72058
+ return /^(?:0|[1-9][0-9]{0,6})$/.test(tree.subscript) || /^\$?[a-zA-Z_][a-zA-Z_0-9]*$/.test(tree.subscript) || /^\s*[a-zA-Z_][a-zA-Z_0-9]*\s*(?:[-+*]\s*(?:0|[1-9][0-9]{0,6})|[/%]\s*[1-9][0-9]{0,6})\s*$/.test(tree.subscript);
72059
+ }
72060
+ if (arrayStore(state)?.get(tree.name)) return false;
71970
72061
  const value2 = state.variables[tree.name] ?? (tree.name === "LINENO" ? String(line ?? 1) : tree.name === "_" ? state.lastArgument ?? "" : tree.name === "FUNCNAME" ? state.functionNames?.[0] : void 0);
71971
72062
  const text3 = value2 === void 0 ? void 0 : this._syncArithRawWriteOnly && this._syncArithTouched?.has(tree.name) ? value2 : monitor?.values.get(tree.name, value2) ?? value2;
71972
72063
  if (text3 === void 0 || text3 === "") return true;
@@ -72231,21 +72322,45 @@ var Runtime = class _Runtime {
72231
72322
  return state.variables[name2];
72232
72323
  }
72233
72324
  async variablePresent(state, name2, io) {
72325
+ const simple = this.tryVariablePresentSync(state, name2);
72326
+ if (simple !== void 0) return simple;
72234
72327
  name2 = this.referenceName(state, name2);
72235
72328
  const bracket = name2.indexOf("[");
72236
72329
  const base = bracket < 0 ? name2 : name2.slice(0, bracket);
72237
- const validName = base.length > 0 && [...base].every((character, index2) => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".includes(character) || index2 > 0 && "0123456789".includes(character));
72238
- if (!validName || bracket >= 0 && !name2.endsWith("]")) return false;
72239
72330
  const resolved = this.referenceName(state, base);
72240
72331
  const binding = arrayStore(state)?.get(resolved);
72241
- if (bracket < 0) return this.variable(state, base) !== void 0;
72242
72332
  const selector = name2.slice(bracket + 1, -1);
72243
- if (!binding?.associative && (selector === "@" || selector === "*")) return binding ? binding.values.size > 0 : this.variable(state, base) !== void 0;
72244
- const store = arrayStore(state);
72245
- if (!store) return selector === "0" && this.variable(state, base) !== void 0;
72246
- const index = await this.arrayIndex(binding, { decimal: selector, source: selector }, state, io, store.owner);
72333
+ const entries = this.presenceArrayEntries(state, resolved);
72334
+ const store = requireArrays(state);
72335
+ const index = await this.arrayIndex(binding, { decimal: selector, source: selector }, state, io, store.owner, false, entries ? entries.length - 1 : binding?.maximum ?? (this.variable(state, base) === void 0 ? -1 : 0));
72336
+ if (entries) return index !== void 0 && entries[index] !== void 0;
72247
72337
  return index !== void 0 && (binding ? binding.getValue(index) !== void 0 : index === 0 && this.variable(state, base) !== void 0);
72248
72338
  }
72339
+ presenceArrayEntries(state, name2) {
72340
+ if (name2 === "DIRSTACK") return [state.cwd, ...state.directoryStack?.entries ?? []];
72341
+ if (name2 === "FUNCNAME" && state.variables.FUNCNAME === void 0 && !arrayStore(state)?.get(name2)) return state.functionNames ?? [];
72342
+ return void 0;
72343
+ }
72344
+ tryVariablePresentSync(state, name2) {
72345
+ name2 = this.referenceName(state, name2);
72346
+ const bracket = name2.indexOf("[");
72347
+ const base = bracket < 0 ? name2 : name2.slice(0, bracket);
72348
+ if (!isShellIdentifier(base) || bracket >= 0 && !name2.endsWith("]")) return false;
72349
+ const resolved = this.referenceName(state, base);
72350
+ const binding = arrayStore(state)?.get(resolved);
72351
+ const entries = this.presenceArrayEntries(state, resolved);
72352
+ if (bracket < 0) return entries ? entries[0] !== void 0 : this.variable(state, base) !== void 0;
72353
+ 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
+ if (binding?.associative) {
72356
+ if (selector.length === 0 || selector.length > 4096 || [...selector].some((character) => "$`\\\"'".includes(character))) return void 0;
72357
+ const key = binding.keys.get(fastStringHexIdentity(selector));
72358
+ return key !== void 0 && binding.getValue(key.index) !== void 0;
72359
+ }
72360
+ if (selector.length === 0 || selector.length > 9 || [...selector].some((character) => !"0123456789".includes(character)) || selector.length > 1 && selector[0] === "0") return void 0;
72361
+ const index = Number(selector);
72362
+ return entries ? entries[index] !== void 0 : binding ? binding.getValue(index) !== void 0 : index === 0 && this.variable(state, base) !== void 0;
72363
+ }
72249
72364
  requireParameter(value2, name2, state, io, line) {
72250
72365
  if (value2 === void 0 && state.nounset) throw new NounsetFailure(`${name2}: unbound variable`, io.diagnosticLine ?? line);
72251
72366
  }
@@ -72653,7 +72768,7 @@ var Runtime = class _Runtime {
72653
72768
  if (rawState.readonlyVariables?.has(name2) || rawState.variableAttributes?.get(name2) || rawState.exported.has(name2) || controlNames.has(name2)) {
72654
72769
  return false;
72655
72770
  }
72656
- const store = monitor?.store ?? (monitor && !this.budget._arraySession?.hasActiveLedger ? requireArrays(rawState) : void 0);
72771
+ const store = monitor?.store ?? (monitor && (this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity) ? requireArrays(rawState) : void 0);
72657
72772
  let current = store?.get(name2);
72658
72773
  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) {
72659
72774
  return false;
@@ -72698,7 +72813,7 @@ var Runtime = class _Runtime {
72698
72813
  let val = "";
72699
72814
  if (entry.value.parts.length > 0) {
72700
72815
  try {
72701
- val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, void 0, diagnosticLine);
72816
+ val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, entry.index === void 0 ? void 0 : 0, diagnosticLine);
72702
72817
  } catch {
72703
72818
  return false;
72704
72819
  }
@@ -72748,7 +72863,7 @@ var Runtime = class _Runtime {
72748
72863
  let val = "";
72749
72864
  if (entry.value.parts.length > 0) {
72750
72865
  try {
72751
- val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, void 0, diagnosticLine);
72866
+ val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, entry.index === void 0 ? void 0 : 0, diagnosticLine);
72752
72867
  } catch {
72753
72868
  return false;
72754
72869
  }
@@ -73092,7 +73207,7 @@ var Runtime = class _Runtime {
73092
73207
  if (expandedEntry) continue;
73093
73208
  }
73094
73209
  const index = entry.index ? await this.arrayIndex(targetBinding, entry.index, state, io, operation2, true) : void 0;
73095
- const fields3 = await this.valueWord(entry.value, state, io, entry.index === void 0);
73210
+ const fields3 = await this.valueWord(entry.value, state, io, entry.index === void 0, false, false, false, void 0, false, entry.index === void 0, entry.index === void 0 ? void 0 : 0);
73096
73211
  if (index !== void 0) {
73097
73212
  const value2 = await join(fields3);
73098
73213
  await insert(index, value2, entry.append);
@@ -75258,13 +75373,13 @@ var Runtime = class _Runtime {
75258
75373
  const r0 = command7.redirects[0];
75259
75374
  const rOp = r0.operator;
75260
75375
  const isDevNull = (r0.descriptor === void 0 || r0.descriptor === 1) && !r0.move && !r0.document && (rOp === ">" || rOp === ">>" || rOp === ">|") && r0.target.plain === "/dev/null";
75261
- const isReadCmd = w0Plain === "read" || command7.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS=");
75376
+ const isReadCmd = w0Plain === "read" || w0Plain === "mapfile" || w0Plain === "readarray" || command7.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS=");
75262
75377
  if (!isDevNull && w0Plain !== "echo" && w0Plain !== "printf" && !(isReadCmd && rOp === "<<<")) {
75263
75378
  pipeline._skipTrySync = true;
75264
75379
  return void 0;
75265
75380
  }
75266
75381
  } else if (wordsLen >= 2) {
75267
- if (w0Plain !== "echo" && w0Plain !== "printf" && w0Plain !== "[" && w0Plain !== "test" && w0Plain !== "mkdir" && w0Plain !== "rm" && w0Plain !== "local" && w0Plain !== "declare" && w0Plain !== "typeset" && w0Plain !== "return" && w0Plain !== "break" && w0Plain !== "continue" && w0Plain !== "shift" && w0Plain !== "read" && w0Plain !== "eval" && w0Plain !== "unset" && w0Plain !== "export" && w0Plain !== "let" && !(command7.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS=")) && !(w0Plain !== void 0 && state.functions.has(w0Plain))) {
75382
+ if (w0Plain !== ":" && w0Plain !== "true" && w0Plain !== "false" && w0Plain !== "getopts" && w0Plain !== "echo" && w0Plain !== "printf" && w0Plain !== "[" && w0Plain !== "test" && w0Plain !== "mkdir" && w0Plain !== "rm" && w0Plain !== "local" && w0Plain !== "declare" && w0Plain !== "typeset" && w0Plain !== "return" && w0Plain !== "break" && w0Plain !== "continue" && w0Plain !== "shift" && w0Plain !== "read" && w0Plain !== "eval" && w0Plain !== "unset" && w0Plain !== "export" && w0Plain !== "let" && !(command7.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS=")) && !(w0Plain !== void 0 && state.functions.has(w0Plain))) {
75268
75383
  return void 0;
75269
75384
  }
75270
75385
  } else if (w0Plain !== "echo" && w0Plain !== "printf" && w0Plain !== ":" && w0Plain !== "true" && w0Plain !== "false" && w0Plain !== "return" && w0Plain !== "break" && w0Plain !== "continue" && w0Plain !== "shift" && w0Plain !== "eval" && !(w0Plain !== void 0 && state.functions.has(w0Plain)) && !(w0.parts[0]?.kind === "text" && w0.parts[0].value.includes("=")) && !getArrayAssignment(w0)) {
@@ -75320,6 +75435,11 @@ var Runtime = class _Runtime {
75320
75435
  if (allValidVars) return true;
75321
75436
  }
75322
75437
  }
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
+ }
75323
75443
  }
75324
75444
  return false;
75325
75445
  }
@@ -75343,7 +75463,7 @@ var Runtime = class _Runtime {
75343
75463
  const fnBody = rawState.functions.get(w0Plain);
75344
75464
  return fnBody.kind === "group" && fnBody.redirects.length === 0 && this.canSyncScriptCompound(fnBody.body, rawState, depth + 1);
75345
75465
  }
75346
- const st = stateMonitor(rawState)?.store ?? (stateMonitor(rawState) && !this.budget._arraySession?.hasActiveLedger ? requireArrays(rawState) : void 0);
75466
+ const st = stateMonitor(rawState)?.store ?? (stateMonitor(rawState) && (this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity) ? requireArrays(rawState) : void 0);
75347
75467
  const arrayAssign = getArrayAssignment(w0);
75348
75468
  if (arrayAssign) {
75349
75469
  if (!st) return false;
@@ -75368,7 +75488,7 @@ var Runtime = class _Runtime {
75368
75488
  return isNoBraceSyncAssignWord(arrayAssign.value);
75369
75489
  }
75370
75490
  const assignment = this.assignment(w0);
75371
- return Boolean(assignment && assignment.name !== "OPTIND" && assignment.name !== "PIPESTATUS" && !assignment.name.includes("[") && !rawState.readonlyVariables?.has(assignment.name) && (!st?.get(assignment.name) || !assignment.append && !hasUnpreparedLocal(rawState, assignment.name) && !rawState.exported.has(assignment.name)) && isNoBraceSyncAssignWord(assignment.value));
75491
+ return Boolean(assignment && (assignment.name !== "OPTIND" || !assignment.append && !rawState.variableAttributes?.get("OPTIND")) && assignment.name !== "PIPESTATUS" && !assignment.name.includes("[") && !rawState.readonlyVariables?.has(assignment.name) && (!st?.get(assignment.name) || !assignment.append && !hasUnpreparedLocal(rawState, assignment.name) && !rawState.exported.has(assignment.name)) && isNoBraceSyncAssignWord(assignment.value));
75372
75492
  }
75373
75493
  if (w0Plain !== void 0 && command7.words.length <= 64 && rawState.functions.has(w0Plain) && this.firstInternalDiscovery(w0Plain, rawState, false) === "function" && !hasActiveExtensions(rawState)) {
75374
75494
  const fnBody = rawState.functions.get(w0Plain);
@@ -75463,17 +75583,29 @@ var Runtime = class _Runtime {
75463
75583
  const wArg = command7.words[idx];
75464
75584
  const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : void 0;
75465
75585
  if (assignment) {
75466
- if (assignment.name === "OPTIND" || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
75586
+ if (assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND")) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
75467
75587
  allValidLocal = false;
75468
75588
  break;
75469
75589
  }
75470
- } else if (!wArg.plain || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(wArg.plain) || wArg.plain === "OPTIND" || wArg.plain === "PIPESTATUS") {
75590
+ } else if (!wArg.plain || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(wArg.plain) || wArg.plain === "OPTIND" && rawState.variableAttributes?.get("OPTIND") || wArg.plain === "PIPESTATUS") {
75471
75591
  allValidLocal = false;
75472
75592
  break;
75473
75593
  }
75474
75594
  }
75475
75595
  if (allValidLocal) return true;
75476
75596
  }
75597
+ 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
+ return true;
75599
+ }
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
+ }
75477
75609
  if (w0Plain === "echo" && !hasShellFunction(rawState, "echo") && !rawState.extensions?.builtins.has("echo")) {
75478
75610
  const w1Plain = command7.words[1]?.plain;
75479
75611
  if (w1Plain === void 0 || !w1Plain.startsWith("-") || w1Plain === "-n" || w1Plain === "-e" || w1Plain === "-ne" || w1Plain === "-en") {
@@ -75522,7 +75654,31 @@ var Runtime = class _Runtime {
75522
75654
  const checkCondNoFile = (e) => {
75523
75655
  if (e.kind === "nonempty") return this.isPureSyncValueWord(e.operand, rawState);
75524
75656
  if (e.kind === "unary") return (e.operator === "-n" || e.operator === "-z" || e.operator === "-v") && this.isPureSyncValueWord(e.operand, rawState);
75525
- if (e.kind === "binary") return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
75657
+ if (e.kind === "binary") {
75658
+ if (e.operator === "=~") {
75659
+ if (!this.isPureSyncValueWord(e.left, rawState) || !this.extractSimpleErePattern(e.right) || rawState.readonlyVariables?.has("BASH_REMATCH") || rawState.exported.has("BASH_REMATCH") || hasUnpreparedLocal(rawState, "BASH_REMATCH")) return false;
75660
+ const mon = stateMonitor(rawState);
75661
+ if (!mon || (this.budget.limits.maxExpansionBytes !== Infinity || this.budget.limits.maxExpansionFields !== Infinity) || mon.hasOverlay("BASH_REMATCH")) return false;
75662
+ const st = mon.store ?? requireArrays(rawState);
75663
+ if (st.watches.has("BASH_REMATCH")) return false;
75664
+ let rem = st.get("BASH_REMATCH");
75665
+ if (!rem) {
75666
+ if (rawState.variables.BASH_REMATCH !== void 0) return false;
75667
+ const created = IndexedBinding.create(st.owner, false);
75668
+ const prepared = st.prepareExistingName("BASH_REMATCH", 12, st.owner, this.signal);
75669
+ if (!prepared) {
75670
+ void created.release();
75671
+ return false;
75672
+ }
75673
+ const initTickets = st.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
75674
+ st.publish("BASH_REMATCH", created, initTickets, prepared, false, st.owner);
75675
+ mon.epoch = initTickets.epoch;
75676
+ rem = created;
75677
+ }
75678
+ return !rem.associative && rem.references === 1;
75679
+ }
75680
+ return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
75681
+ }
75526
75682
  if (e.kind === "not") return checkCondNoFile(e.operand);
75527
75683
  if (e.kind === "and" || e.kind === "or") return checkCondNoFile(e.left) && checkCondNoFile(e.right);
75528
75684
  return false;
@@ -75663,6 +75819,17 @@ var Runtime = class _Runtime {
75663
75819
  scalarVars.add(target);
75664
75820
  nonIntScalarVars.add(target);
75665
75821
  }
75822
+ } else if (wp0 === "mapfile" || wp0 === "readarray") {
75823
+ arrayVars.add(c.words[2]?.plain ?? "MAPFILE");
75824
+ } else if (wp0 === "getopts") {
75825
+ const ov = c.words[2]?.plain;
75826
+ if (ov && isShellIdentifier(ov)) {
75827
+ scalarVars.add(ov);
75828
+ nonIntScalarVars.add(ov);
75829
+ }
75830
+ scalarVars.add("OPTIND");
75831
+ scalarVars.add("OPTARG");
75832
+ nonIntScalarVars.add("OPTARG");
75666
75833
  } else if (wp0 === "read" || c.words[1]?.plain === "read") {
75667
75834
  for (let k = 1; k < c.words.length; k++) {
75668
75835
  const vp = c.words[k]?.plain;
@@ -75800,31 +75967,8 @@ var Runtime = class _Runtime {
75800
75967
  if (expr.operator === "-n") return val.length > 0 ? 0 : 1;
75801
75968
  if (expr.operator === "-z") return val.length === 0 ? 0 : 1;
75802
75969
  if (expr.operator === "-v") {
75803
- const bracket = val.indexOf("[");
75804
- if (bracket < 0) {
75805
- if (!isShellIdentifier(val)) return 1;
75806
- const b2 = store?.get(val);
75807
- if (b2) return b2.get(b2.associative ? b2.keys.get("30")?.index ?? -1 : 0) !== void 0 ? 0 : 1;
75808
- return this.variable(rawState, val) !== void 0 ? 0 : 1;
75809
- }
75810
- if (!val.endsWith("]")) return 1;
75811
- const base = val.slice(0, bracket);
75812
- if (!isShellIdentifier(base)) return 1;
75813
- const sub = val.slice(bracket + 1, -1);
75814
- const b = store?.get(base);
75815
- if (!b?.associative && (sub === "@" || sub === "*")) {
75816
- return (b ? b.values.size > 0 : this.variable(rawState, base) !== void 0) ? 0 : 1;
75817
- }
75818
- if (b?.associative) {
75819
- if (sub.length === 0 || sub.length > 4096 || /[$\x60\\"']/.test(sub)) return void 0;
75820
- const ek = b.keys.get(fastStringHexIdentity(sub));
75821
- return ek !== void 0 && b.getValue(ek.index) !== void 0 ? 0 : 1;
75822
- }
75823
- if (/^(?:0|[1-9][0-9]{0,8})$/.test(sub)) {
75824
- const idx = Number(sub);
75825
- return (b ? b.getValue(idx) !== void 0 : idx === 0 && this.variable(rawState, base) !== void 0) ? 0 : 1;
75826
- }
75827
- return void 0;
75970
+ const present = this.tryVariablePresentSync(rawState, val);
75971
+ return present === void 0 ? void 0 : present ? 0 : 1;
75828
75972
  }
75829
75973
  if (syncConditionalFileUnaryOps.has(expr.operator)) {
75830
75974
  const fileRes = this.tryEvalFastMemoryFileUnary(expr.operator, val, rawState);
@@ -75993,7 +76137,7 @@ var Runtime = class _Runtime {
75993
76137
  let existing = store?.get("PIPESTATUS");
75994
76138
  if (store && !existing) {
75995
76139
  const initTarget = pipelineStatusTarget(rawState);
75996
- if (!this.budget._arraySession?.hasActiveLedger && (initTarget === "indexed" || initTarget === "absent") && !store.watches.has("PIPESTATUS") && !monitor.hasOverlay("PIPESTATUS") && !store.owner.ledger.checkpoint(this.signal, 0)) {
76140
+ if (this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity && (initTarget === "indexed" || initTarget === "absent") && !store.watches.has("PIPESTATUS") && !monitor.hasOverlay("PIPESTATUS") && !store.owner.ledger.checkpoint(this.signal, 0)) {
75997
76141
  try {
75998
76142
  if (!publishPipelineStatus(rawState, monitor.lazyPipeStatus ?? singleStatusZero, this.signal, scope)) {
75999
76143
  existing = store.get("PIPESTATUS");
@@ -76236,7 +76380,13 @@ var Runtime = class _Runtime {
76236
76380
  }
76237
76381
  const dynProg = prepareArithmetic(fastSrc, this.budget.parsing);
76238
76382
  if (!dynProg.error && isSafeSmiProgram(dynProg) && this.canSyncArithmeticWithoutFault(dynProg.tree, rawState, diagnosticLine)) {
76239
- const nonZero = this.syncShellArithmeticNonZero(dynProg, rawState, diagnosticLine);
76383
+ let nonZero;
76384
+ try {
76385
+ nonZero = this.syncShellArithmeticNonZero(dynProg, rawState, diagnosticLine);
76386
+ } catch (err) {
76387
+ if (err instanceof ArrayFailure) return void 0;
76388
+ throw err;
76389
+ }
76240
76390
  if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
76241
76391
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
76242
76392
  this.budget.tick();
@@ -76247,7 +76397,13 @@ var Runtime = class _Runtime {
76247
76397
  }
76248
76398
  }
76249
76399
  if (!expr.error && isSafeSmiProgram(expr) && this.canSyncArithmeticWithoutFault(expr.tree, rawState, diagnosticLine)) {
76250
- const nonZero = this.syncShellArithmeticNonZero(expr, rawState, diagnosticLine);
76400
+ let nonZero;
76401
+ try {
76402
+ nonZero = this.syncShellArithmeticNonZero(expr, rawState, diagnosticLine);
76403
+ } catch (err) {
76404
+ if (err instanceof ArrayFailure) return void 0;
76405
+ throw err;
76406
+ }
76251
76407
  if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
76252
76408
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
76253
76409
  this.budget.tick();
@@ -76352,6 +76508,12 @@ var Runtime = class _Runtime {
76352
76508
  if (command7.kind === "while" || command7.kind === "until") {
76353
76509
  this.budget.tick();
76354
76510
  let lastStatus = 0;
76511
+ const enableBatchRawWrite = !this._syncArithRawWriteOnly && !hasActiveExtensions(rawState) && !hasActiveVariableAttributes(rawState) && !rawState.readonlyVariables?.size && !rawState.allexport;
76512
+ const batchTouched = enableBatchRawWrite ? /* @__PURE__ */ new Set() : void 0;
76513
+ if (enableBatchRawWrite) {
76514
+ this._syncArithRawWriteOnly = true;
76515
+ this._syncArithTouched = batchTouched;
76516
+ }
76355
76517
  rawState.loopDepth++;
76356
76518
  this._syncReturnDepth++;
76357
76519
  try {
@@ -76398,6 +76560,15 @@ var Runtime = class _Runtime {
76398
76560
  } finally {
76399
76561
  this._syncReturnDepth--;
76400
76562
  rawState.loopDepth--;
76563
+ if (enableBatchRawWrite && batchTouched) {
76564
+ this._syncArithRawWriteOnly = false;
76565
+ this._syncArithTouched = void 0;
76566
+ for (const vName of batchTouched) {
76567
+ const vVal = rawState.variables[vName];
76568
+ if (typeof vVal === "string") monitor.publishStringVariable(vName, vVal);
76569
+ else if (vVal === void 0) delete monitor.proxy.variables[vName];
76570
+ }
76571
+ }
76401
76572
  }
76402
76573
  rawState.status = lastStatus;
76403
76574
  return lastStatus;
@@ -76408,11 +76579,17 @@ var Runtime = class _Runtime {
76408
76579
  return void 0;
76409
76580
  }
76410
76581
  this.budget.tick();
76411
- if (e0) this.syncShellArithmeticNonZero(e0, rawState, diagnosticLine);
76582
+ const enableBatchRawWrite = !this._syncArithRawWriteOnly && !hasActiveExtensions(rawState) && !hasActiveVariableAttributes(rawState) && !rawState.readonlyVariables?.size && !rawState.allexport;
76583
+ const batchTouched = enableBatchRawWrite ? /* @__PURE__ */ new Set() : void 0;
76584
+ if (enableBatchRawWrite) {
76585
+ this._syncArithRawWriteOnly = true;
76586
+ this._syncArithTouched = batchTouched;
76587
+ }
76412
76588
  let lastStatus = 0;
76413
76589
  rawState.loopDepth++;
76414
76590
  this._syncReturnDepth++;
76415
76591
  try {
76592
+ if (e0) this.syncShellArithmeticNonZero(e0, rawState, diagnosticLine);
76416
76593
  let iter = 0;
76417
76594
  while (true) {
76418
76595
  if (++iter > 4096) return void 0;
@@ -76447,6 +76624,15 @@ var Runtime = class _Runtime {
76447
76624
  } finally {
76448
76625
  this._syncReturnDepth--;
76449
76626
  rawState.loopDepth--;
76627
+ if (enableBatchRawWrite && batchTouched) {
76628
+ this._syncArithRawWriteOnly = false;
76629
+ this._syncArithTouched = void 0;
76630
+ for (const vName of batchTouched) {
76631
+ const vVal = rawState.variables[vName];
76632
+ if (typeof vVal === "string") monitor.publishStringVariable(vName, vVal);
76633
+ else if (vVal === void 0) delete monitor.proxy.variables[vName];
76634
+ }
76635
+ }
76450
76636
  }
76451
76637
  rawState.status = lastStatus;
76452
76638
  return lastStatus;
@@ -76505,6 +76691,12 @@ var Runtime = class _Runtime {
76505
76691
  if (!items || items.length > 4096) return void 0;
76506
76692
  this.budget.tick();
76507
76693
  let lastStatus = 0;
76694
+ const enableBatchRawWrite = !this._syncArithRawWriteOnly && !hasActiveExtensions(rawState) && !hasActiveVariableAttributes(rawState) && !rawState.readonlyVariables?.size && !rawState.allexport;
76695
+ const batchTouched = enableBatchRawWrite ? /* @__PURE__ */ new Set() : void 0;
76696
+ if (enableBatchRawWrite) {
76697
+ this._syncArithRawWriteOnly = true;
76698
+ this._syncArithTouched = batchTouched;
76699
+ }
76508
76700
  rawState.loopDepth++;
76509
76701
  this._syncReturnDepth++;
76510
76702
  try {
@@ -76514,7 +76706,10 @@ var Runtime = class _Runtime {
76514
76706
  (0, yield_exports.runYieldCheckpoint)(this.signal);
76515
76707
  }
76516
76708
  this.budget.loop();
76517
- monitor.publishStringVariable(command7.name, items[idx]);
76709
+ if (this._syncArithRawWriteOnly && this._syncArithTouched) {
76710
+ rawState.variables[command7.name] = items[idx];
76711
+ this._syncArithTouched.add(command7.name);
76712
+ } else monitor.publishStringVariable(command7.name, items[idx]);
76518
76713
  if (rawState.allexport) rawState.exported.add(command7.name);
76519
76714
  const bodyRes = this.trySyncScript(command7.body, state, io, ignored);
76520
76715
  if (typeof bodyRes !== "number") return void 0;
@@ -76535,6 +76730,15 @@ var Runtime = class _Runtime {
76535
76730
  } finally {
76536
76731
  this._syncReturnDepth--;
76537
76732
  rawState.loopDepth--;
76733
+ if (enableBatchRawWrite && batchTouched) {
76734
+ this._syncArithRawWriteOnly = false;
76735
+ this._syncArithTouched = void 0;
76736
+ for (const vName of batchTouched) {
76737
+ const vVal = rawState.variables[vName];
76738
+ if (typeof vVal === "string") monitor.publishStringVariable(vName, vVal);
76739
+ else if (vVal === void 0) delete monitor.proxy.variables[vName];
76740
+ }
76741
+ }
76538
76742
  }
76539
76743
  rawState.status = lastStatus;
76540
76744
  return lastStatus;
@@ -76849,7 +77053,7 @@ var Runtime = class _Runtime {
76849
77053
  if (assignment) {
76850
77054
  const hasSubPart = assignment.value.parts.some((part) => part.kind === "substitution");
76851
77055
  const existingArrAssign = store?.get(assignment.name);
76852
- if (assignment.name === "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))) {
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))) {
76853
77057
  return void 0;
76854
77058
  }
76855
77059
  if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
@@ -76860,6 +77064,11 @@ var Runtime = class _Runtime {
76860
77064
  return void 0;
76861
77065
  }
76862
77066
  if (typeof fastAssigned !== "string") return void 0;
77067
+ if (assignment.name === "OPTIND") {
77068
+ const trimmedOptind = fastAssigned.trim();
77069
+ if (!/^[0-9]{1,6}$/.test(trimmedOptind)) return void 0;
77070
+ fastAssigned = String(Number(trimmedOptind));
77071
+ }
76863
77072
  if (existingArrAssign) {
76864
77073
  if (!this.tryFastArraySubscriptWriteSync(rawState, assignment.name, "0", fastAssigned)) return void 0;
76865
77074
  const restEpoch2 = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
@@ -76904,6 +77113,10 @@ var Runtime = class _Runtime {
76904
77113
  rawState.variables[assignment.name] = finalAssigned;
76905
77114
  this._syncArithTouched.add(assignment.name);
76906
77115
  } else monitor.publishStringVariable(assignment.name, finalAssigned);
77116
+ if (assignment.name === "OPTIND") {
77117
+ rawState.variables.OPTIND = finalAssigned;
77118
+ this.syncGetopts(rawState);
77119
+ }
76907
77120
  if (rawState.allexport) monitor.proxy.exported.add(assignment.name);
76908
77121
  if (io.assignmentDiagnosticContext) io.assignmentDiagnosticContext.name = void 0;
76909
77122
  if (!existing) {
@@ -76972,6 +77185,119 @@ var Runtime = class _Runtime {
76972
77185
  }
76973
77186
  }
76974
77187
  }
77188
+ if (command7.words.length >= 2 && command7.words.length <= 16 && (w0Plain === ":" || w0Plain === "true" || w0Plain === "false") && command7.redirects.length === 0 && !hasShellFunction(rawState, w0Plain) && !rawState.extensions?.builtins.has(w0Plain)) {
77189
+ const rawStatus = w0Plain === "false" ? 1 : 0;
77190
+ const statusChar = rawStatus === 0 ? "0" : "1";
77191
+ if (!canMutatePipeStatus && elem0.text.shellValue !== statusChar) return void 0;
77192
+ const finalStatus = pipeline.negate ? Number(rawStatus === 0) : rawStatus;
77193
+ if (finalStatus !== 0 && !ignored && rawState.errexit) return void 0;
77194
+ let lastArg = w0Plain;
77195
+ let argsOk = true;
77196
+ try {
77197
+ for (let i = 1; i < command7.words.length; i++) {
77198
+ const v = this.fastValueWord(command7.words[i], rawState, io, true, false, false, true, void 0, diagnosticLine);
77199
+ if (typeof v !== "string") {
77200
+ argsOk = false;
77201
+ break;
77202
+ }
77203
+ lastArg = v;
77204
+ }
77205
+ } catch {
77206
+ argsOk = false;
77207
+ }
77208
+ if (argsOk) {
77209
+ if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
77210
+ const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77211
+ this.budget.tick();
77212
+ rawState.substitutionStatus = 0;
77213
+ if (rawState.variables._ !== void 0) delete rawState.variables._;
77214
+ rawState.lastArgument = lastArg;
77215
+ if (io.assignmentDiagnosticContext) io.assignmentDiagnosticContext.name = void 0;
77216
+ return this.finishSyncPipeStatus(rawState, monitor, monitor.store, monitor.store?.get("PIPESTATUS"), elem0, scope, finalStatus, restEpoch);
77217
+ }
77218
+ }
77219
+ if (command7.words.length >= 3 && command7.words.length <= 16 && w0Plain === "getopts" && command7.redirects.length === 0 && !hasShellFunction(rawState, "getopts") && !rawState.extensions?.builtins.has("getopts")) {
77220
+ const optVar = command7.words[2]?.plain;
77221
+ if (optVar && isShellIdentifier(optVar) && optVar !== "OPTIND" && optVar !== "PIPESTATUS" && optVar !== "_" && !rawState.readonlyVariables?.has(optVar) && !rawState.readonlyVariables?.has("OPTIND") && !rawState.readonlyVariables?.has("OPTARG") && !rawState.variableAttributes?.get(optVar) && !rawState.variableAttributes?.get("OPTIND") && !rawState.variableAttributes?.get("OPTARG") && !store?.get(optVar) && !store?.get("OPTIND") && !store?.get("OPTARG") && !monitor.hasOverlay(optVar)) {
77222
+ let optstring;
77223
+ let scanArgs;
77224
+ let lastArg = optVar;
77225
+ try {
77226
+ optstring = command7.words[1].plain ?? this.fastValueWord(command7.words[1], rawState, io, true, false, false, true, void 0, diagnosticLine);
77227
+ if (typeof optstring === "string") {
77228
+ if (command7.words.length === 3) {
77229
+ scanArgs = this._fastSubPositional ?? rawState.positional;
77230
+ } else if (command7.words.length === 4 && (() => {
77231
+ 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;
77233
+ })()) {
77234
+ scanArgs = this._fastSubPositional ?? rawState.positional;
77235
+ if (scanArgs.length > 0) lastArg = scanArgs[scanArgs.length - 1];
77236
+ } else {
77237
+ const customArgs = [];
77238
+ let customOk = true;
77239
+ for (let i = 3; i < command7.words.length; i++) {
77240
+ const v = this.fastValueWord(command7.words[i], rawState, io, true, false, false, true, void 0, diagnosticLine);
77241
+ if (typeof v !== "string") {
77242
+ customOk = false;
77243
+ break;
77244
+ }
77245
+ customArgs.push(v);
77246
+ lastArg = v;
77247
+ }
77248
+ if (customOk) scanArgs = customArgs;
77249
+ }
77250
+ }
77251
+ } catch {
77252
+ scanArgs = void 0;
77253
+ }
77254
+ if (typeof optstring === "string" && scanArgs !== void 0) {
77255
+ rawState.getopts ??= cloneGetoptsBinding(rawState);
77256
+ const res = scanGetoptsSync(rawState.getopts.cursor, optstring, scanArgs);
77257
+ if (res !== void 0) {
77258
+ const rawStatus = res.status;
77259
+ const statusChar = rawStatus === 0 ? "0" : "1";
77260
+ if (canMutatePipeStatus || elem0.text.shellValue === statusChar) {
77261
+ const finalStatus = pipeline.negate ? Number(rawStatus === 0) : rawStatus;
77262
+ if (finalStatus === 0 || ignored || !rawState.errexit) {
77263
+ if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
77264
+ const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77265
+ this.budget.tick();
77266
+ rawState.substitutionStatus = 0;
77267
+ if (rawState.variables._ !== void 0) delete rawState.variables._;
77268
+ rawState.lastArgument = lastArg;
77269
+ rawState.getopts.cursor = res.state;
77270
+ const optindStr = String(res.optind);
77271
+ if (this._syncArithRawWriteOnly && this._syncArithTouched) {
77272
+ rawState.variables.OPTIND = optindStr;
77273
+ this._syncArithTouched.add("OPTIND");
77274
+ } else monitor.publishStringVariable("OPTIND", optindStr);
77275
+ if (rawState.allexport) monitor.proxy.exported.add("OPTIND");
77276
+ if (res.argument.kind === "set") {
77277
+ if (this._syncArithRawWriteOnly && this._syncArithTouched) {
77278
+ rawState.variables.OPTARG = res.argument.value;
77279
+ this._syncArithTouched.add("OPTARG");
77280
+ } else monitor.publishStringVariable("OPTARG", res.argument.value);
77281
+ if (rawState.allexport) monitor.proxy.exported.add("OPTARG");
77282
+ } else {
77283
+ delete rawState.variables.OPTARG;
77284
+ rawState.exported.delete("OPTARG");
77285
+ if (this._syncArithRawWriteOnly && this._syncArithTouched) this._syncArithTouched.add("OPTARG");
77286
+ else monitor.values.invalidate("OPTARG");
77287
+ }
77288
+ if (this._syncArithRawWriteOnly && this._syncArithTouched) {
77289
+ rawState.variables[optVar] = res.option;
77290
+ this._syncArithTouched.add(optVar);
77291
+ } else monitor.publishStringVariable(optVar, res.option);
77292
+ if (rawState.allexport) monitor.proxy.exported.add(optVar);
77293
+ if (io.assignmentDiagnosticContext) io.assignmentDiagnosticContext.name = void 0;
77294
+ return this.finishSyncPipeStatus(rawState, monitor, monitor.store, monitor.store?.get("PIPESTATUS"), elem0, scope, finalStatus, restEpoch);
77295
+ }
77296
+ }
77297
+ }
77298
+ }
77299
+ }
77300
+ }
76975
77301
  if (command7.words.length === 2 && w0Plain === "shift" && command7.redirects.length === 0 && canMutatePipeStatus && !pipeline.negate && !hasShellFunction(rawState, "shift") && !rawState.extensions?.builtins.has("shift")) {
76976
77302
  let argVal;
76977
77303
  try {
@@ -77101,6 +77427,81 @@ var Runtime = class _Runtime {
77101
77427
  const w0 = command7.words[0];
77102
77428
  const w0Plain = w0.plain;
77103
77429
  const isHereStringRead = command7.words.length >= 2 && command7.redirects.length === 1 && command7.redirects[0].operator === "<<<" && !command7.redirects[0].move && !command7.redirects[0].document && (command7.redirects[0].descriptor === void 0 || command7.redirects[0].descriptor === 0);
77430
+ if ((w0Plain === "mapfile" || w0Plain === "readarray") && isHereStringRead && (command7.words.length === 2 || command7.words.length === 3) && command7.words[1]?.plain === "-t" && canMutatePipeStatus && !pipeline.negate && !rawState.allexport && !hasShellFunction(rawState, w0Plain) && !rawState.extensions?.builtins.has(w0Plain)) {
77431
+ const arrayTarget = command7.words[2]?.plain ?? "MAPFILE";
77432
+ if (!hasUnpreparedLocal(rawState, arrayTarget) && isShellIdentifier(arrayTarget) && !rawState.readonlyVariables?.has(arrayTarget) && !rawState.exported.has(arrayTarget) && !rawState.variableAttributes?.get(arrayTarget) && !controlNames.has(arrayTarget)) {
77433
+ let hv;
77434
+ try {
77435
+ hv = this.fastValueWord(command7.redirects[0].target, rawState, io, false, false, false, false, void 0, diagnosticLine);
77436
+ } catch {
77437
+ hv = void 0;
77438
+ }
77439
+ if (typeof hv === "string" && !hv.includes("\0") && hv.length + 1 < this.budget.limits.maxExpansionBytes && hv.length + 1 <= this.budget.limits.maxInputBytes) {
77440
+ const arrStore = monitor.store ?? requireArrays(rawState);
77441
+ let existingArrayBinding = arrStore.get(arrayTarget);
77442
+ if (!existingArrayBinding && rawState.variables[arrayTarget] === void 0 && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
77443
+ const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
77444
+ const recBinding = arrStore.takeRecycled(arrayTarget, false, true, recTickets);
77445
+ if (recBinding) {
77446
+ monitor.epoch = recTickets.epoch;
77447
+ existingArrayBinding = recBinding;
77448
+ } else {
77449
+ try {
77450
+ const created = IndexedBinding.create(arrStore.owner, false);
77451
+ const prepared = arrStore.prepareExistingName(arrayTarget, shellValueByteLength(arrayTarget), arrStore.owner, this.signal);
77452
+ if (prepared) {
77453
+ const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
77454
+ arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
77455
+ monitor.epoch = initTickets.epoch;
77456
+ existingArrayBinding = created;
77457
+ } else {
77458
+ void created.release();
77459
+ }
77460
+ } catch {
77461
+ }
77462
+ }
77463
+ }
77464
+ if (existingArrayBinding && !existingArrayBinding.associative && existingArrayBinding.references === 1 && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
77465
+ const lines3 = hv.split("\n");
77466
+ const fieldLen = lines3.length;
77467
+ if (fieldLen <= 256) {
77468
+ if (rawState.extensions && !rawState.extensions.eventDepth) publishCommandSpelling(rawState, commandSpelling(command7));
77469
+ const tickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 + fieldLen * 4 });
77470
+ if (existingArrayBinding.values.size !== fieldLen || existingArrayBinding.maximum !== fieldLen - 1) {
77471
+ for (const k of [...existingArrayBinding.values.keys()]) {
77472
+ if (k >= fieldLen) existingArrayBinding.remove(k);
77473
+ }
77474
+ existingArrayBinding.maximum = fieldLen - 1;
77475
+ }
77476
+ for (let idx = 0; idx < fieldLen; idx++) {
77477
+ const val = lines3[idx];
77478
+ const byteLen = shellValueByteLength(val);
77479
+ const slot = existingArrayBinding.values.get(idx);
77480
+ if (slot && slot.text.references === 1 && slot.text.bytes === byteLen) {
77481
+ existingArrayBinding.owner.chargeWork(byteLen);
77482
+ slot.text.shellValue = val;
77483
+ } else {
77484
+ existingArrayBinding.owner.chargeWork(byteLen);
77485
+ const token = new OwnedText(val, byteLen, existingArrayBinding.owner.reserve({ payload: byteLen, metadata: 32, work: 4 }));
77486
+ existingArrayBinding.insert(idx, token);
77487
+ }
77488
+ }
77489
+ delete rawState.variables[arrayTarget];
77490
+ monitor.values.invalidate(arrayTarget);
77491
+ monitor.epoch = tickets.epoch;
77492
+ arrStore.revise(arrayTarget, existingArrayBinding, tickets);
77493
+ const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77494
+ this.budget.tick();
77495
+ rawState.substitutionStatus = 0;
77496
+ if (rawState.variables._ !== void 0) delete rawState.variables._;
77497
+ rawState.lastArgument = command7.words[command7.words.length - 1].plain ?? arrayTarget;
77498
+ if (io.assignmentDiagnosticContext) io.assignmentDiagnosticContext.name = void 0;
77499
+ return this.finishSyncPipeStatus(rawState, monitor, monitor.store, monitor.store?.get("PIPESTATUS"), elem0, scope, 0, restEpoch);
77500
+ }
77501
+ }
77502
+ }
77503
+ }
77504
+ }
77104
77505
  if ((w0Plain === "read" || command7.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS=")) && canMutatePipeStatus && !pipeline.negate && !rawState.allexport && !hasShellFunction(rawState, "read") && !rawState.extensions?.builtins.has("read") && (command7.redirects.length === 0 ? io.stdin instanceof ShellInput : isHereStringRead)) {
77105
77506
  let ifs;
77106
77507
  let readWordIdx = 1;
@@ -77152,7 +77553,7 @@ var Runtime = class _Runtime {
77152
77553
  if (nextW.plain !== void 0) delimStr = nextW.plain;
77153
77554
  else {
77154
77555
  try {
77155
- const fv = this.fastValueWord(nextW, rawState, io, false, false, false, false, 0, diagnosticLine);
77556
+ const fv = this.fastValueWord(nextW, rawState, io, true, false, false, false, void 0, diagnosticLine);
77156
77557
  if (typeof fv === "string") delimStr = fv;
77157
77558
  } catch {
77158
77559
  delimStr = void 0;
@@ -77189,14 +77590,19 @@ var Runtime = class _Runtime {
77189
77590
  const varCount = command7.words.length - readWordIdx;
77190
77591
  let existingArrayBinding;
77191
77592
  if (arrayTarget !== void 0) {
77192
- if (hasUnpreparedLocals(rawState)) return void 0;
77593
+ if (hasUnpreparedLocal(rawState, arrayTarget)) return void 0;
77193
77594
  if (varCount !== 0 || !isShellIdentifier(arrayTarget) || rawState.readonlyVariables?.has(arrayTarget) || rawState.exported.has(arrayTarget) || rawState.variableAttributes?.get(arrayTarget) || controlNames.has(arrayTarget)) {
77194
77595
  simpleRead = false;
77195
77596
  } else {
77196
77597
  const arrStore = monitor.store ?? requireArrays(rawState);
77197
77598
  existingArrayBinding = arrStore.get(arrayTarget);
77198
77599
  if (!existingArrayBinding && rawState.variables[arrayTarget] === void 0 && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
77199
- try {
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 {
77200
77606
  const created = IndexedBinding.create(arrStore.owner, false);
77201
77607
  const nameByteLen = shellValueByteLength(arrayTarget);
77202
77608
  const prepared = arrStore.prepareExistingName(arrayTarget, nameByteLen, arrStore.owner, this.signal);
@@ -77708,7 +78114,7 @@ var Runtime = class _Runtime {
77708
78114
  const wArg = command7.words[idx];
77709
78115
  const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : void 0;
77710
78116
  if (assignment) {
77711
- if (assignment.name === "OPTIND" || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || rawState.readonlyVariables?.has(assignment.name) || store?.get(assignment.name)) {
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)) {
77712
78118
  allValidLocal = false;
77713
78119
  break;
77714
78120
  }
@@ -77722,8 +78128,16 @@ var Runtime = class _Runtime {
77722
78128
  allValidLocal = false;
77723
78129
  break;
77724
78130
  }
78131
+ if (assignment.name === "OPTIND") {
78132
+ const trimmedOptind = fastAssigned.trim();
78133
+ if (!/^[0-9]{1,6}$/.test(trimmedOptind)) {
78134
+ allValidLocal = false;
78135
+ break;
78136
+ }
78137
+ fastAssigned = String(Number(trimmedOptind));
78138
+ }
77725
78139
  parsedLocals.push({ name: assignment.name, val: fastAssigned, append: assignment.append, lastArg: `${assignment.name}=${fastAssigned}` });
77726
- } else if (wArg.plain && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(wArg.plain) && wArg.plain !== "OPTIND" && wArg.plain !== "PIPESTATUS" && !rawState.readonlyVariables?.has(wArg.plain) && !store?.get(wArg.plain)) {
78140
+ } else if (wArg.plain && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(wArg.plain) && (wArg.plain !== "OPTIND" || !rawState.variableAttributes?.get("OPTIND")) && wArg.plain !== "PIPESTATUS" && !rawState.readonlyVariables?.has(wArg.plain) && !store?.get(wArg.plain)) {
77727
78141
  parsedLocals.push({ name: wArg.plain, val: void 0, append: false, lastArg: wArg.plain });
77728
78142
  } else {
77729
78143
  allValidLocal = false;
@@ -77731,6 +78145,7 @@ var Runtime = class _Runtime {
77731
78145
  }
77732
78146
  }
77733
78147
  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;
77734
78149
  const locals = rawState.locals.length > 0 ? rawState.locals[rawState.locals.length - 1] : void 0;
77735
78150
  const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
77736
78151
  this.budget.tick();
@@ -77742,7 +78157,7 @@ var Runtime = class _Runtime {
77742
78157
  if (locals && isNewLocal) {
77743
78158
  if (this._syncArithRawWriteOnly && this._syncArithTouched) {
77744
78159
  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];
77745
- locals.set(item.name, { attributes: void 0, value: typeof curVal === "string" ? curVal : void 0, exported: false, readOnly: false });
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) } : {} });
77746
78161
  } else locals.set(item.name, saveVariable(state, item.name));
77747
78162
  delete rawState.variables[item.name];
77748
78163
  if (this._syncArithRawWriteOnly && this._syncArithTouched) this._syncArithTouched.add(item.name);
@@ -77755,16 +78170,22 @@ var Runtime = class _Runtime {
77755
78170
  rawState.variables[item.name] = finalVal;
77756
78171
  this._syncArithTouched.add(item.name);
77757
78172
  } else monitor.publishStringVariable(item.name, finalVal);
78173
+ if (item.name === "OPTIND") {
78174
+ rawState.variables.OPTIND = finalVal;
78175
+ this.syncGetopts(rawState);
78176
+ }
77758
78177
  if (rawState.allexport) monitor.proxy.exported.add(item.name);
77759
78178
  rawState.lastArgument = `${item.name}=${finalVal}`;
77760
- if (!rawState.variableAttributes?.has(item.name)) {
77761
- rawState.variableAttributes ??= /* @__PURE__ */ new Map();
77762
- rawState.variableAttributes.set(item.name, "");
77763
- }
78179
+ if (isNewLocal && rawState.variableAttributes?.has(item.name)) rawState.variableAttributes.delete(item.name);
77764
78180
  } else {
77765
- if (!rawState.variableAttributes?.has(item.name)) {
77766
- rawState.variableAttributes ??= /* @__PURE__ */ new Map();
77767
- rawState.variableAttributes.set(item.name, "");
78181
+ if (item.name === "OPTIND") this.syncGetopts(rawState);
78182
+ if (!locals) {
78183
+ if (!rawState.variableAttributes?.has(item.name)) {
78184
+ rawState.variableAttributes ??= /* @__PURE__ */ new Map();
78185
+ rawState.variableAttributes.set(item.name, "");
78186
+ }
78187
+ } else if (isNewLocal && rawState.variableAttributes?.has(item.name)) {
78188
+ rawState.variableAttributes.delete(item.name);
77768
78189
  }
77769
78190
  rawState.lastArgument = item.lastArg;
77770
78191
  }
@@ -77941,9 +78362,13 @@ var Runtime = class _Runtime {
77941
78362
  rawState.locals.pop();
77942
78363
  rawState.functionNames?.shift();
77943
78364
  for (const [k, previous] of locals) {
77944
- if (this._syncArithRawWriteOnly && this._syncArithTouched && !syncLocalArrayVariables.has(previous) && !previous.heldValue && !previous.attributes && !previous.exported && !previous.readOnly && k !== "OPTIND") {
78365
+ if (this._syncArithRawWriteOnly && this._syncArithTouched && !syncLocalArrayVariables.has(previous) && !previous.heldValue && !previous.attributes && !previous.exported && !previous.readOnly) {
77945
78366
  if (previous.value === void 0) delete rawState.variables[k];
77946
78367
  else rawState.variables[k] = (0, value_exports.shellValueText)(previous.value);
78368
+ if (k === "OPTIND" && previous.getopts) {
78369
+ rawState.getopts = { integer: previous.getopts.integer, cursor: cloneGetoptsState(previous.getopts.cursor) };
78370
+ }
78371
+ rawState.variableAttributes?.delete(k);
77947
78372
  this._syncArithTouched.add(k);
77948
78373
  } else tryRestoreVariableSync(state, k, previous);
77949
78374
  }
@@ -78397,8 +78822,9 @@ var Runtime = class _Runtime {
78397
78822
  }
78398
78823
  } else if (part.operator === "^" || part.operator === "^^" || part.operator === "," || part.operator === ",,") {
78399
78824
  if (part.alternate && part.alternate.parts.length > 0) return false;
78400
- } else if (part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+") {
78825
+ } else if (part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+" || part.operator === "=" || part.operator === ":=") {
78401
78826
  if (!part.alternate || !part.alternate.parts.every((p) => p.kind === "text" || p.kind === "arithmetic" || p.kind === "variable" && !p.operator && !p.substring)) return false;
78827
+ if ((part.operator === "=" || part.operator === ":=") && (!isShellIdentifier(part.name) || part.name === "OPTIND" || part.name === "PIPESTATUS" || part.name === "_" || rawState.readonlyVariables?.has(part.name) || rawState.variableAttributes?.get(part.name) || stateMonitor(rawState)?.store?.get(part.name))) return false;
78402
78828
  } else if (part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") {
78403
78829
  if (!part.alternate || part.alternate.parts.length === 0) return false;
78404
78830
  const q0 = part.alternate.parts[0].quoted;
@@ -78427,7 +78853,15 @@ var Runtime = class _Runtime {
78427
78853
  if (!collectPureReadOnlySmiNames(part.expression, names)) {
78428
78854
  if (rawState.nounset) return false;
78429
78855
  const em = SIMPLE_EXPANDED_ARITH_RE.exec(part.source);
78430
- if (!em || (em[2] === "/" || em[2] === "%") && !(em[3] && /^[1-9][0-9]*$/.test(em[3]))) return false;
78856
+ if (!em || (em[2] === "/" || em[2] === "%") && !(em[3] && /^[1-9][0-9]*$/.test(em[3]))) {
78857
+ if (part.source.includes("<<") || part.source.includes(">>") || part.source.includes("**") || /[/%](?!\s*[1-9][0-9]*\b)/.test(part.source)) return false;
78858
+ try {
78859
+ const expW = parseArithmeticExpansion(part.source, this.budget.parsing, false, 0, void 0, rawState.extensions?.syntax);
78860
+ if (!this.isPureSyncValueWord(expW, rawState)) return false;
78861
+ } catch {
78862
+ return false;
78863
+ }
78864
+ }
78431
78865
  }
78432
78866
  continue;
78433
78867
  }
@@ -81626,7 +82060,7 @@ ${s1}
81626
82060
  overlayOpen = true;
81627
82061
  }
81628
82062
  if (inlineInput || (state.profile === "sh" || !words.length) && assignments2.some((assignment) => state.readonlyVariables?.has(assignment.name))) await assign();
81629
- if (inlineInput && functionCommand && previous?.size) {
82063
+ if (inlineInput && (functionCommand || words[0] === "read" && !state.extensions?.builtins.has("read")) && previous?.size) {
81630
82064
  if (stateMonitor(state)?.lazyPipeStatus !== void 0) stateMonitor(state).activate(true);
81631
82065
  const redirectState = tryCloneStateSync(state) ?? await cloneState(state, this.signal);
81632
82066
  const variables = redirectState.variables;
@@ -85554,7 +85988,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
85554
85988
  if (selector2?.kind === "members" || part.name === "@" || part.name === "*") {
85555
85989
  const members = selector2 ? await this.arrayMembers(part.name, state, io, part.keys) : this.positionalValues(state);
85556
85990
  const ifs = state.variables.IFS ?? " ";
85557
- const separator = selector2?.kind === "members" && !split3 && (selector2.separator === "@" || !part.quoted) ? " " : ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
85991
+ const separator = !split3 && (selector2?.kind === "members" ? selector2.separator === "@" || !part.quoted : part.name === "@") ? " " : ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
85558
85992
  const fragments2 = [];
85559
85993
  let bytes3 = 0;
85560
85994
  for (const member of members) {
@@ -85932,7 +86366,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
85932
86366
  }
85933
86367
  if (part.length) return String(binding?.values.size ?? (part.name === "FUNCNAME" && state.variables.FUNCNAME === void 0 ? state.functionNames?.length ?? 0 : state.variables[part.name] === void 0 ? 0 : 1));
85934
86368
  const values = await this.arrayMembers(part.name, state, io, selector.kind === "keys" || part.keys === true, part.substring);
85935
- const space = (selector.kind === "keys" || part.keys === true) && state.extensions?.syntax?.arrayKeys ? Boolean(hereDocument || (selector.separator === "@" ? !part.quoted && !split3 || state.variables.IFS === "" : !part.quoted && split3 && state.variables.IFS === "")) : !split3 && (selector.separator === "@" || !part.quoted);
86369
+ const space = selector.kind === "keys" || part.keys === true ? Boolean(hereDocument || (selector.separator === "@" ? !part.quoted && !split3 || state.variables.IFS === "" : !part.quoted && split3 && state.variables.IFS === "")) : !split3 && selector.separator === "@";
85936
86370
  return this.arrayJoin(store.owner, values, space ? " " : this.ifsSeparator(state, io));
85937
86371
  }
85938
86372
  if (part.substring && (part.name === "@" || part.name === "*")) {
@@ -85941,7 +86375,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
85941
86375
  return (0, value_exports.concatShellValues)(values.flatMap((entry, index) => index ? [separator, entry] : [entry]), io[valueScope]);
85942
86376
  }
85943
86377
  const namerefName = part.indirect && state.variableAttributes?.get(part.name)?.includes("n");
85944
- let value2 = namerefName ? state.variables[part.name] === void 0 ? void 0 : this.referenceName(state, part.name) : part.specialParameter ? specialValue === void 0 ? void 0 : (0, value_exports.shellValueText)(specialValue) : part.name === "?" ? String(state.status) : part.name === "-" ? `${state.allexport ? "a" : ""}${state.errexit ? "e" : ""}${state.noglob ? "f" : ""}${state.noexec ? "n" : ""}${state.nounset ? "u" : ""}${state.braceexpand !== false ? "B" : ""}${state.noclobber ? "C" : ""}` : part.name === "#" ? String(state.positional.length) : part.name === "@" || part.name === "*" ? state.positional.join(hereString && (part.name === "@" || !part.quoted) ? " " : Array.from(state.variables.IFS ?? " ")[0] ?? "") : /^0+$/u.test(part.name) ? state.arg0 ?? "virtual-bash" : /^\d+$/u.test(part.name) ? state.positional[Number(part.name) - 1] : part.name === "LINENO" ? state.extensions ? String(io.diagnosticLine ?? part.line ?? 1) : state.variables.LINENO ?? String(io.diagnosticLine ?? part.line ?? 1) : this.variable(state, part.name);
86378
+ let value2 = namerefName ? state.variables[part.name] === void 0 ? void 0 : this.referenceName(state, part.name) : part.specialParameter ? specialValue === void 0 ? void 0 : (0, value_exports.shellValueText)(specialValue) : part.name === "?" ? String(state.status) : part.name === "-" ? `${state.allexport ? "a" : ""}${state.errexit ? "e" : ""}${state.noglob ? "f" : ""}${state.noexec ? "n" : ""}${state.nounset ? "u" : ""}${state.braceexpand !== false ? "B" : ""}${state.noclobber ? "C" : ""}` : part.name === "#" ? String(state.positional.length) : part.name === "@" || part.name === "*" ? state.positional.join(part.name === "@" && !split3 || hereString && (part.name === "@" || !part.quoted) ? " " : Array.from(state.variables.IFS ?? " ")[0] ?? "") : /^0+$/u.test(part.name) ? state.arg0 ?? "virtual-bash" : /^\d+$/u.test(part.name) ? state.positional[Number(part.name) - 1] : part.name === "LINENO" ? state.extensions ? String(io.diagnosticLine ?? part.line ?? 1) : state.variables.LINENO ?? String(io.diagnosticLine ?? part.line ?? 1) : this.variable(state, part.name);
85945
86379
  let retained = part.specialParameter ? specialValue : value2;
85946
86380
  if (value2 !== void 0 && !namerefName) {
85947
86381
  if (/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(part.name)) {
@@ -85952,7 +86386,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
85952
86386
  } else if (/^0+$/u.test(part.name)) retained = stateMonitor(state)?.positionals.get(zeroPositionKey, value2) ?? value2;
85953
86387
  else if (/^[0-9]+$/u.test(part.name)) retained = stateMonitor(state)?.positionals.get(String(Number(part.name) - 1), value2) ?? value2;
85954
86388
  else if (part.name === "@" || part.name === "*") {
85955
- const separator = hereString && (part.name === "@" || !part.quoted) ? " " : this.ifsSeparator(state, io);
86389
+ const separator = part.name === "@" && !split3 || hereString && (part.name === "@" || !part.quoted) ? " " : this.ifsSeparator(state, io);
85956
86390
  const values = this.positionalValues(state);
85957
86391
  retained = (0, value_exports.concatShellValues)(values.flatMap((entry, index) => index ? [separator, entry] : [entry]), io[valueScope]);
85958
86392
  }
@@ -86395,7 +86829,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86395
86829
  }
86396
86830
  const ifsVal = monitor?.values.get("IFS", rawVars.IFS ?? " ") ?? rawVars.IFS ?? " ";
86397
86831
  if (validElemOp && typeof ifsVal === "string" && (ifsVal.length === 0 || ifsVal.charCodeAt(0) < 128)) {
86398
- const sep = selector.separator === "@" ? " " : ifsVal.length > 0 ? ifsVal[0] : "";
86832
+ const sep = selector.separator === "@" && (!isKeys || ifsVal.length === 0) ? " " : ifsVal.length > 0 ? ifsVal[0] : "";
86399
86833
  const evalSliceInt = (w) => {
86400
86834
  if (w.parts.length === 0) return 0;
86401
86835
  const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, void 0, part.line ?? overrideDiagnosticLine);
@@ -86767,7 +87201,9 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86767
87201
  out += converted;
86768
87202
  continue;
86769
87203
  }
86770
- if ((part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+") && part.alternate && !rawState.nounset && part.alternate.parts.every((p) => p.kind === "text" || p.kind === "arithmetic" || p.kind === "variable" && !p.operator && !p.substring)) {
87204
+ if ((part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+" || part.operator === "=" || part.operator === ":=") && part.alternate && !rawState.nounset && part.alternate.parts.every((p) => p.kind === "text" || p.kind === "arithmetic" || p.kind === "variable" && !p.operator && !p.substring)) {
87205
+ const isAssignOp = part.operator === "=" || part.operator === ":=";
87206
+ if (isAssignOp && (!isShellIdentifier(part.name) || part.name === "OPTIND" || part.name === "PIPESTATUS" || part.name === "_" || rawState.readonlyVariables?.has(part.name) || rawState.variableAttributes?.get(part.name) || activeArrayStore?.get(part.name) || monitor?.hasOverlay(part.name) || i < word.parts.length - 1 && !this.isPureSyncValueWord({ offset: 0, parts: word.parts.slice(i + 1) }, rawState, false))) return void 0;
86771
87207
  const raw2 = rawVars[part.name];
86772
87208
  const cur = raw2 === void 0 ? void 0 : this._syncArithRawWriteOnly && this._syncArithTouched?.has(part.name) ? raw2 : monitor?.values.get(part.name, raw2) ?? raw2;
86773
87209
  if (cur !== void 0 && typeof cur !== "string") return void 0;
@@ -86780,10 +87216,21 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
86780
87216
  resolvedScalar = altVal;
86781
87217
  } else resolvedScalar = "";
86782
87218
  } else {
86783
- const isMissing = cur === void 0 || part.operator === ":-" && cur === "";
87219
+ const isMissing = cur === void 0 || (part.operator === ":-" || part.operator === ":=") && cur === "";
86784
87220
  if (isMissing) {
86785
87221
  const altVal = this.fastValueWord(part.alternate, rawState, io, false, false, false, false, void 0, part.line ?? overrideDiagnosticLine);
86786
87222
  if (typeof altVal !== "string") return void 0;
87223
+ if (isAssignOp) {
87224
+ if (this._syncArithRawWriteOnly && this._syncArithTouched) {
87225
+ rawState.variables[part.name] = altVal;
87226
+ this._syncArithTouched.add(part.name);
87227
+ } else if (monitor) {
87228
+ monitor.publishStringVariable(part.name, altVal);
87229
+ } else {
87230
+ rawState.variables[part.name] = altVal;
87231
+ }
87232
+ if (rawState.allexport) (monitor ? monitor.proxy.exported : rawState.exported).add(part.name);
87233
+ }
86787
87234
  resolvedScalar = altVal;
86788
87235
  } else resolvedScalar = cur;
86789
87236
  }