@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.
- package/dist/safe-bash/command-assets/git_rust-CB24IEB6.wasm +0 -0
- package/dist/safe-bash/core.browser.js +522 -75
- package/dist/safe-bash/core.browser.js.map +3 -3
- package/dist/safe-bash/shell/arithmetic.d.ts.map +1 -1
- package/dist/safe-bash/shell/arithmetic.js +10 -1
- package/dist/safe-bash/shell/arithmetic.js.map +1 -1
- package/dist/safe-bash/shell/getopts.d.ts +1 -0
- package/dist/safe-bash/shell/getopts.d.ts.map +1 -1
- package/dist/safe-bash/shell/getopts.js +71 -0
- package/dist/safe-bash/shell/getopts.js.map +1 -1
- package/dist/safe-bash/shell/runtime.d.ts +2 -0
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +561 -100
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/dist/safe-bash-command-git/index.js +1 -1
- package/package.json +2 -2
- package/dist/safe-bash/command-assets/git_rust-VC5UCZXR.wasm +0 -0
|
@@ -63,7 +63,7 @@ export const customRegisteredCommands = new WeakSet();
|
|
|
63
63
|
export const customRegisteredRegistries = new WeakSet();
|
|
64
64
|
import { defaultPredicateExecutors, tryFastPredicate } from "../commands/predicates.js";
|
|
65
65
|
import { builtInDirectContextExecutors, pathOf, RESOLVED_EXIT_ONE, RESOLVED_EXIT_ZERO, UsageError } from "../commands/internal.js";
|
|
66
|
-
import { cloneGetoptsState, createGetoptsInput, createGetoptsState, GetoptsError, getoptsInputAllocationSize, scanGetopts, withGetoptsIndex } from "./getopts.js";
|
|
66
|
+
import { cloneGetoptsState, createGetoptsInput, createGetoptsState, GetoptsError, getoptsInputAllocationSize, scanGetopts, scanGetoptsSync, withGetoptsIndex } from "./getopts.js";
|
|
67
67
|
import { activateChildCancellation, admitCancellationSubscriptionCapacity, prepareChildCancellation, selectRuntimeCancellationOutcome, subscribeCancellationOwner, unsubscribeCancellationOwner, } from "./cancellation.js";
|
|
68
68
|
import { variablePresence } from "../commands/variable-presence.js";
|
|
69
69
|
import { getArrayAssignment, getArraySelector, copyArraySelector, numericIndex, literalIndex, stringIndex, isQuoteMarker, prefixNameQuoteGroups, setArraySelector } from "./arrays/syntax.js";
|
|
@@ -4242,6 +4242,15 @@ export class Runtime {
|
|
|
4242
4242
|
resolvedSub = rawSub === undefined || rawSub === "" ? "0" : shellValueText(stateMonitor(st)?.values.get(resolvedSub, rawSub) ?? rawSub);
|
|
4243
4243
|
}
|
|
4244
4244
|
}
|
|
4245
|
+
else {
|
|
4246
|
+
const st = this._syncArithState;
|
|
4247
|
+
const binding = arrayStore(st)?.get(variable);
|
|
4248
|
+
if (!binding || !binding.associative) {
|
|
4249
|
+
const subStr = tryEvalSimpleExpandedArith(resolvedSub, st, stateMonitor(st), arrayStore(st), this._syncArithRawWriteOnly ? this._syncArithTouched : undefined);
|
|
4250
|
+
if (subStr !== undefined && !subStr.startsWith("-"))
|
|
4251
|
+
resolvedSub = subStr;
|
|
4252
|
+
}
|
|
4253
|
+
}
|
|
4245
4254
|
if (resolvedSub.length === 0 || resolvedSub.length > 128 || !/^[a-zA-Z0-9_.\-/:@]+$/.test(resolvedSub))
|
|
4246
4255
|
throw new ArrayFailure("complex subscript in sync arithmetic");
|
|
4247
4256
|
return `[idx]${variable}:${resolvedSub}`;
|
|
@@ -4398,11 +4407,28 @@ export class Runtime {
|
|
|
4398
4407
|
switch (tree.kind) {
|
|
4399
4408
|
case "literal": return true;
|
|
4400
4409
|
case "name": {
|
|
4401
|
-
if (tree.
|
|
4410
|
+
if (tree.name === "OPTIND" || tree.name === "PIPESTATUS")
|
|
4402
4411
|
return false;
|
|
4403
4412
|
const monitor = stateMonitor(state);
|
|
4404
4413
|
if (monitor?.hasOverlay(tree.name) || monitor?.store?.watches.has(tree.name))
|
|
4405
4414
|
return false;
|
|
4415
|
+
if (tree.subscript !== undefined) {
|
|
4416
|
+
if (state.nounset || hasUnpreparedLocal(state, tree.name))
|
|
4417
|
+
return false;
|
|
4418
|
+
const binding = arrayStore(state)?.get(tree.name);
|
|
4419
|
+
if (!binding)
|
|
4420
|
+
return false;
|
|
4421
|
+
if (binding.associative) {
|
|
4422
|
+
if (/^\$[a-zA-Z_][a-zA-Z_0-9]*$/.test(tree.subscript)) {
|
|
4423
|
+
const sv = tree.subscript.slice(1);
|
|
4424
|
+
return !arrayStore(state)?.get(sv) && !monitor?.hasOverlay(sv);
|
|
4425
|
+
}
|
|
4426
|
+
return /^[a-zA-Z0-9_.\-/:@]+$/.test(tree.subscript);
|
|
4427
|
+
}
|
|
4428
|
+
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);
|
|
4429
|
+
}
|
|
4430
|
+
if (arrayStore(state)?.get(tree.name))
|
|
4431
|
+
return false;
|
|
4406
4432
|
const value = state.variables[tree.name]
|
|
4407
4433
|
?? (tree.name === "LINENO" ? String(line ?? 1)
|
|
4408
4434
|
: tree.name === "_" ? state.lastArgument ?? ""
|
|
@@ -4709,27 +4735,55 @@ export class Runtime {
|
|
|
4709
4735
|
return state.variables[name];
|
|
4710
4736
|
}
|
|
4711
4737
|
async variablePresent(state, name, io) {
|
|
4738
|
+
const simple = this.tryVariablePresentSync(state, name);
|
|
4739
|
+
if (simple !== undefined)
|
|
4740
|
+
return simple;
|
|
4712
4741
|
name = this.referenceName(state, name);
|
|
4713
4742
|
const bracket = name.indexOf("[");
|
|
4714
4743
|
const base = bracket < 0 ? name : name.slice(0, bracket);
|
|
4715
|
-
const validName = base.length > 0 && [...base].every((character, index) => "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_".includes(character)
|
|
4716
|
-
|| index > 0 && "0123456789".includes(character));
|
|
4717
|
-
if (!validName || bracket >= 0 && !name.endsWith("]"))
|
|
4718
|
-
return false;
|
|
4719
4744
|
const resolved = this.referenceName(state, base);
|
|
4720
4745
|
const binding = arrayStore(state)?.get(resolved);
|
|
4721
|
-
if (bracket < 0)
|
|
4722
|
-
return this.variable(state, base) !== undefined;
|
|
4723
4746
|
const selector = name.slice(bracket + 1, -1);
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
const
|
|
4727
|
-
if (
|
|
4728
|
-
return
|
|
4729
|
-
const index = await this.arrayIndex(binding, { decimal: selector, source: selector }, state, io, store.owner);
|
|
4747
|
+
const entries = this.presenceArrayEntries(state, resolved);
|
|
4748
|
+
const store = requireArrays(state);
|
|
4749
|
+
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) === undefined ? -1 : 0));
|
|
4750
|
+
if (entries)
|
|
4751
|
+
return index !== undefined && entries[index] !== undefined;
|
|
4730
4752
|
return index !== undefined && (binding ? binding.getValue(index) !== undefined
|
|
4731
4753
|
: index === 0 && this.variable(state, base) !== undefined);
|
|
4732
4754
|
}
|
|
4755
|
+
presenceArrayEntries(state, name) {
|
|
4756
|
+
if (name === "DIRSTACK")
|
|
4757
|
+
return [state.cwd, ...state.directoryStack?.entries ?? []];
|
|
4758
|
+
if (name === "FUNCNAME" && state.variables.FUNCNAME === undefined && !arrayStore(state)?.get(name))
|
|
4759
|
+
return state.functionNames ?? [];
|
|
4760
|
+
return undefined;
|
|
4761
|
+
}
|
|
4762
|
+
tryVariablePresentSync(state, name) {
|
|
4763
|
+
name = this.referenceName(state, name);
|
|
4764
|
+
const bracket = name.indexOf("[");
|
|
4765
|
+
const base = bracket < 0 ? name : name.slice(0, bracket);
|
|
4766
|
+
if (!isShellIdentifier(base) || bracket >= 0 && !name.endsWith("]"))
|
|
4767
|
+
return false;
|
|
4768
|
+
const resolved = this.referenceName(state, base);
|
|
4769
|
+
const binding = arrayStore(state)?.get(resolved);
|
|
4770
|
+
const entries = this.presenceArrayEntries(state, resolved);
|
|
4771
|
+
if (bracket < 0)
|
|
4772
|
+
return entries ? entries[0] !== undefined : this.variable(state, base) !== undefined;
|
|
4773
|
+
const selector = name.slice(bracket + 1, -1);
|
|
4774
|
+
if (selector === "@" || selector === "*")
|
|
4775
|
+
return entries ? entries.length > 0 : binding ? binding.values.size > 0 : this.variable(state, base) !== undefined;
|
|
4776
|
+
if (binding?.associative) {
|
|
4777
|
+
if (selector.length === 0 || selector.length > 4096 || [...selector].some(character => "$`\\\"'".includes(character)))
|
|
4778
|
+
return undefined;
|
|
4779
|
+
const key = binding.keys.get(fastStringHexIdentity(selector));
|
|
4780
|
+
return key !== undefined && binding.getValue(key.index) !== undefined;
|
|
4781
|
+
}
|
|
4782
|
+
if (selector.length === 0 || selector.length > 9 || [...selector].some(character => !"0123456789".includes(character)) || selector.length > 1 && selector[0] === "0")
|
|
4783
|
+
return undefined;
|
|
4784
|
+
const index = Number(selector);
|
|
4785
|
+
return entries ? entries[index] !== undefined : binding ? binding.getValue(index) !== undefined : index === 0 && this.variable(state, base) !== undefined;
|
|
4786
|
+
}
|
|
4733
4787
|
requireParameter(value, name, state, io, line) {
|
|
4734
4788
|
if (value === undefined && state.nounset)
|
|
4735
4789
|
throw new NounsetFailure(`${name}: unbound variable`, io.diagnosticLine ?? line);
|
|
@@ -5203,7 +5257,7 @@ export class Runtime {
|
|
|
5203
5257
|
return false;
|
|
5204
5258
|
}
|
|
5205
5259
|
// Cold activation belongs to normal command handling, which maps array refusals.
|
|
5206
|
-
const store = monitor?.store ?? (monitor &&
|
|
5260
|
+
const store = monitor?.store ?? (monitor && (this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity) ? requireArrays(rawState) : undefined);
|
|
5207
5261
|
let current = store?.get(name);
|
|
5208
5262
|
if (!monitor || !store || store.watches.has(name) || monitor.hasOverlay(name) || (current && (current.references !== 1 || (associative !== undefined && current.associative !== associative))) || (!current && rawState.variables[name] !== undefined)) {
|
|
5209
5263
|
return false;
|
|
@@ -5253,7 +5307,7 @@ export class Runtime {
|
|
|
5253
5307
|
let val = "";
|
|
5254
5308
|
if (entry.value.parts.length > 0) {
|
|
5255
5309
|
try {
|
|
5256
|
-
val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, undefined, diagnosticLine);
|
|
5310
|
+
val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, entry.index === undefined ? undefined : 0, diagnosticLine);
|
|
5257
5311
|
}
|
|
5258
5312
|
catch {
|
|
5259
5313
|
return false;
|
|
@@ -5314,7 +5368,7 @@ export class Runtime {
|
|
|
5314
5368
|
let val = "";
|
|
5315
5369
|
if (entry.value.parts.length > 0) {
|
|
5316
5370
|
try {
|
|
5317
|
-
val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, undefined, diagnosticLine);
|
|
5371
|
+
val = this.fastValueWord(entry.value, rawState, io, false, false, false, false, entry.index === undefined ? undefined : 0, diagnosticLine);
|
|
5318
5372
|
}
|
|
5319
5373
|
catch {
|
|
5320
5374
|
return false;
|
|
@@ -5723,7 +5777,7 @@ export class Runtime {
|
|
|
5723
5777
|
continue;
|
|
5724
5778
|
}
|
|
5725
5779
|
const index = entry.index ? (await this.arrayIndex(targetBinding, entry.index, state, io, operation, true)) : undefined;
|
|
5726
|
-
const fields = await this.valueWord(entry.value, state, io, entry.index === undefined);
|
|
5780
|
+
const fields = await this.valueWord(entry.value, state, io, entry.index === undefined, false, false, false, undefined, false, entry.index === undefined, entry.index === undefined ? undefined : 0);
|
|
5727
5781
|
if (index !== undefined) {
|
|
5728
5782
|
const value = await join(fields);
|
|
5729
5783
|
await insert(index, value, entry.append);
|
|
@@ -8145,14 +8199,14 @@ export class Runtime {
|
|
|
8145
8199
|
const r0 = command.redirects[0];
|
|
8146
8200
|
const rOp = r0.operator;
|
|
8147
8201
|
const isDevNull = (r0.descriptor === undefined || r0.descriptor === 1) && !r0.move && !r0.document && (rOp === ">" || rOp === ">>" || rOp === ">|") && r0.target.plain === "/dev/null";
|
|
8148
|
-
const isReadCmd = w0Plain === "read" || (command.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS="));
|
|
8202
|
+
const isReadCmd = w0Plain === "read" || w0Plain === "mapfile" || w0Plain === "readarray" || (command.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS="));
|
|
8149
8203
|
if (!isDevNull && w0Plain !== "echo" && w0Plain !== "printf" && !(isReadCmd && rOp === "<<<")) {
|
|
8150
8204
|
pipeline._skipTrySync = true;
|
|
8151
8205
|
return undefined;
|
|
8152
8206
|
}
|
|
8153
8207
|
}
|
|
8154
8208
|
else if (wordsLen >= 2) {
|
|
8155
|
-
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" && !(command.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS=")) && !(w0Plain !== undefined && state.functions.has(w0Plain))) {
|
|
8209
|
+
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" && !(command.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS=")) && !(w0Plain !== undefined && state.functions.has(w0Plain))) {
|
|
8156
8210
|
return undefined;
|
|
8157
8211
|
}
|
|
8158
8212
|
}
|
|
@@ -8214,6 +8268,16 @@ export class Runtime {
|
|
|
8214
8268
|
return true;
|
|
8215
8269
|
}
|
|
8216
8270
|
}
|
|
8271
|
+
if ((w0Plain === "mapfile" || w0Plain === "readarray") &&
|
|
8272
|
+
(command.words.length === 2 || command.words.length === 3) &&
|
|
8273
|
+
command.words[1]?.plain === "-t" &&
|
|
8274
|
+
!hasShellFunction(rawState, w0Plain) &&
|
|
8275
|
+
!rawState.extensions?.builtins.has(w0Plain)) {
|
|
8276
|
+
const arrVp = command.words[2]?.plain ?? "MAPFILE";
|
|
8277
|
+
const st = stateMonitor(rawState)?.store;
|
|
8278
|
+
if (isShellIdentifier(arrVp) && arrVp !== "OPTIND" && arrVp !== "PIPESTATUS" && !rawState.readonlyVariables?.has(arrVp) && !st?.get(arrVp)?.associative)
|
|
8279
|
+
return true;
|
|
8280
|
+
}
|
|
8217
8281
|
}
|
|
8218
8282
|
return false;
|
|
8219
8283
|
}
|
|
@@ -8238,7 +8302,7 @@ export class Runtime {
|
|
|
8238
8302
|
const fnBody = rawState.functions.get(w0Plain);
|
|
8239
8303
|
return fnBody.kind === "group" && fnBody.redirects.length === 0 && this.canSyncScriptCompound(fnBody.body, rawState, depth + 1);
|
|
8240
8304
|
}
|
|
8241
|
-
const st = stateMonitor(rawState)?.store ?? (stateMonitor(rawState) &&
|
|
8305
|
+
const st = stateMonitor(rawState)?.store ?? (stateMonitor(rawState) && (this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity) ? requireArrays(rawState) : undefined);
|
|
8242
8306
|
const arrayAssign = getArrayAssignment(w0);
|
|
8243
8307
|
if (arrayAssign) {
|
|
8244
8308
|
if (!st)
|
|
@@ -8265,7 +8329,7 @@ export class Runtime {
|
|
|
8265
8329
|
return isNoBraceSyncAssignWord(arrayAssign.value);
|
|
8266
8330
|
}
|
|
8267
8331
|
const assignment = this.assignment(w0);
|
|
8268
|
-
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));
|
|
8332
|
+
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));
|
|
8269
8333
|
}
|
|
8270
8334
|
if (w0Plain !== undefined && command.words.length <= 64 && rawState.functions.has(w0Plain) && this.firstInternalDiscovery(w0Plain, rawState, false) === "function" && !hasActiveExtensions(rawState)) {
|
|
8271
8335
|
const fnBody = rawState.functions.get(w0Plain);
|
|
@@ -8387,12 +8451,12 @@ export class Runtime {
|
|
|
8387
8451
|
const wArg = command.words[idx];
|
|
8388
8452
|
const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : undefined;
|
|
8389
8453
|
if (assignment) {
|
|
8390
|
-
if (assignment.name === "OPTIND" || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
|
|
8454
|
+
if ((assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND"))) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
|
|
8391
8455
|
allValidLocal = false;
|
|
8392
8456
|
break;
|
|
8393
8457
|
}
|
|
8394
8458
|
}
|
|
8395
|
-
else if (!wArg.plain || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(wArg.plain) || wArg.plain === "OPTIND" || wArg.plain === "PIPESTATUS") {
|
|
8459
|
+
else if (!wArg.plain || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(wArg.plain) || (wArg.plain === "OPTIND" && rawState.variableAttributes?.get("OPTIND")) || wArg.plain === "PIPESTATUS") {
|
|
8396
8460
|
allValidLocal = false;
|
|
8397
8461
|
break;
|
|
8398
8462
|
}
|
|
@@ -8400,6 +8464,15 @@ export class Runtime {
|
|
|
8400
8464
|
if (allValidLocal)
|
|
8401
8465
|
return true;
|
|
8402
8466
|
}
|
|
8467
|
+
if ((w0Plain === ":" || w0Plain === "true" || w0Plain === "false") && command.words.length <= 16 && !hasShellFunction(rawState, w0Plain) && !rawState.extensions?.builtins.has(w0Plain) && command.words.slice(1).every(isNoBraceSyncWord)) {
|
|
8468
|
+
return true;
|
|
8469
|
+
}
|
|
8470
|
+
if (command.words.length >= 3 && command.words.length <= 16 && w0Plain === "getopts" && !hasShellFunction(rawState, "getopts") && !rawState.extensions?.builtins.has("getopts")) {
|
|
8471
|
+
const optVar = command.words[2]?.plain;
|
|
8472
|
+
if (optVar && isShellIdentifier(optVar) && optVar !== "OPTIND" && optVar !== "PIPESTATUS" && optVar !== "_" && !rawState.readonlyVariables?.has(optVar) && !rawState.readonlyVariables?.has("OPTIND") && !rawState.readonlyVariables?.has("OPTARG") && isNoBraceSyncWord(command.words[1]) && (command.words.length === 3 || (command.words.length === 4 && (() => { const ne = command.words[3].parts.filter(p => !(p.kind === "text" && p.value === "")); return ne.length === 1 && ne[0].kind === "variable" && ne[0].name === "@" && ne[0].quoted; })()) || command.words.slice(3).every(isNoBraceSyncWord))) {
|
|
8473
|
+
return true;
|
|
8474
|
+
}
|
|
8475
|
+
}
|
|
8403
8476
|
if (w0Plain === "echo" && !hasShellFunction(rawState, "echo") && !rawState.extensions?.builtins.has("echo")) {
|
|
8404
8477
|
const w1Plain = command.words[1]?.plain;
|
|
8405
8478
|
if (w1Plain === undefined || !w1Plain.startsWith("-") || w1Plain === "-n" || w1Plain === "-e" || w1Plain === "-ne" || w1Plain === "-en")
|
|
@@ -8458,8 +8531,35 @@ export class Runtime {
|
|
|
8458
8531
|
return this.isPureSyncValueWord(e.operand, rawState);
|
|
8459
8532
|
if (e.kind === "unary")
|
|
8460
8533
|
return (e.operator === "-n" || e.operator === "-z" || e.operator === "-v") && this.isPureSyncValueWord(e.operand, rawState);
|
|
8461
|
-
if (e.kind === "binary")
|
|
8534
|
+
if (e.kind === "binary") {
|
|
8535
|
+
if (e.operator === "=~") {
|
|
8536
|
+
if (!this.isPureSyncValueWord(e.left, rawState) || !this.extractSimpleErePattern(e.right) || rawState.readonlyVariables?.has("BASH_REMATCH") || rawState.exported.has("BASH_REMATCH") || hasUnpreparedLocal(rawState, "BASH_REMATCH"))
|
|
8537
|
+
return false;
|
|
8538
|
+
const mon = stateMonitor(rawState);
|
|
8539
|
+
if (!mon || (this.budget.limits.maxExpansionBytes !== Infinity || this.budget.limits.maxExpansionFields !== Infinity) || mon.hasOverlay("BASH_REMATCH"))
|
|
8540
|
+
return false;
|
|
8541
|
+
const st = mon.store ?? requireArrays(rawState);
|
|
8542
|
+
if (st.watches.has("BASH_REMATCH"))
|
|
8543
|
+
return false;
|
|
8544
|
+
let rem = st.get("BASH_REMATCH");
|
|
8545
|
+
if (!rem) {
|
|
8546
|
+
if (rawState.variables.BASH_REMATCH !== undefined)
|
|
8547
|
+
return false;
|
|
8548
|
+
const created = IndexedBinding.create(st.owner, false);
|
|
8549
|
+
const prepared = st.prepareExistingName("BASH_REMATCH", 12, st.owner, this.signal);
|
|
8550
|
+
if (!prepared) {
|
|
8551
|
+
void created.release();
|
|
8552
|
+
return false;
|
|
8553
|
+
}
|
|
8554
|
+
const initTickets = st.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
8555
|
+
st.publish("BASH_REMATCH", created, initTickets, prepared, false, st.owner);
|
|
8556
|
+
mon.epoch = initTickets.epoch;
|
|
8557
|
+
rem = created;
|
|
8558
|
+
}
|
|
8559
|
+
return !rem.associative && rem.references === 1;
|
|
8560
|
+
}
|
|
8462
8561
|
return this.isPureSyncValueWord(e.left, rawState) && (e.operator === "==" || e.operator === "=" || e.operator === "!=" ? this.canSyncPatternWordParts(e.right, rawState) : this.isPureSyncValueWord(e.right, rawState));
|
|
8562
|
+
}
|
|
8463
8563
|
if (e.kind === "not")
|
|
8464
8564
|
return checkCondNoFile(e.operand);
|
|
8465
8565
|
if (e.kind === "and" || e.kind === "or")
|
|
@@ -8647,6 +8747,19 @@ export class Runtime {
|
|
|
8647
8747
|
nonIntScalarVars.add(target);
|
|
8648
8748
|
}
|
|
8649
8749
|
}
|
|
8750
|
+
else if (wp0 === "mapfile" || wp0 === "readarray") {
|
|
8751
|
+
arrayVars.add(c.words[2]?.plain ?? "MAPFILE");
|
|
8752
|
+
}
|
|
8753
|
+
else if (wp0 === "getopts") {
|
|
8754
|
+
const ov = c.words[2]?.plain;
|
|
8755
|
+
if (ov && isShellIdentifier(ov)) {
|
|
8756
|
+
scalarVars.add(ov);
|
|
8757
|
+
nonIntScalarVars.add(ov);
|
|
8758
|
+
}
|
|
8759
|
+
scalarVars.add("OPTIND");
|
|
8760
|
+
scalarVars.add("OPTARG");
|
|
8761
|
+
nonIntScalarVars.add("OPTARG");
|
|
8762
|
+
}
|
|
8650
8763
|
else if (wp0 === "read" || (c.words[1]?.plain === "read")) {
|
|
8651
8764
|
for (let k = 1; k < c.words.length; k++) {
|
|
8652
8765
|
const vp = c.words[k]?.plain;
|
|
@@ -8828,36 +8941,8 @@ export class Runtime {
|
|
|
8828
8941
|
if (expr.operator === "-z")
|
|
8829
8942
|
return val.length === 0 ? 0 : 1;
|
|
8830
8943
|
if (expr.operator === "-v") {
|
|
8831
|
-
const
|
|
8832
|
-
|
|
8833
|
-
if (!isShellIdentifier(val))
|
|
8834
|
-
return 1;
|
|
8835
|
-
const b = store?.get(val);
|
|
8836
|
-
if (b)
|
|
8837
|
-
return b.get(b.associative ? b.keys.get("30")?.index ?? -1 : 0) !== undefined ? 0 : 1;
|
|
8838
|
-
return this.variable(rawState, val) !== undefined ? 0 : 1;
|
|
8839
|
-
}
|
|
8840
|
-
if (!val.endsWith("]"))
|
|
8841
|
-
return 1;
|
|
8842
|
-
const base = val.slice(0, bracket);
|
|
8843
|
-
if (!isShellIdentifier(base))
|
|
8844
|
-
return 1;
|
|
8845
|
-
const sub = val.slice(bracket + 1, -1);
|
|
8846
|
-
const b = store?.get(base);
|
|
8847
|
-
if (!b?.associative && (sub === "@" || sub === "*")) {
|
|
8848
|
-
return (b ? b.values.size > 0 : this.variable(rawState, base) !== undefined) ? 0 : 1;
|
|
8849
|
-
}
|
|
8850
|
-
if (b?.associative) {
|
|
8851
|
-
if (sub.length === 0 || sub.length > 4096 || /[$\x60\\"']/.test(sub))
|
|
8852
|
-
return undefined;
|
|
8853
|
-
const ek = b.keys.get(fastStringHexIdentity(sub));
|
|
8854
|
-
return (ek !== undefined && b.getValue(ek.index) !== undefined) ? 0 : 1;
|
|
8855
|
-
}
|
|
8856
|
-
if (/^(?:0|[1-9][0-9]{0,8})$/.test(sub)) {
|
|
8857
|
-
const idx = Number(sub);
|
|
8858
|
-
return (b ? b.getValue(idx) !== undefined : idx === 0 && this.variable(rawState, base) !== undefined) ? 0 : 1;
|
|
8859
|
-
}
|
|
8860
|
-
return undefined;
|
|
8944
|
+
const present = this.tryVariablePresentSync(rawState, val);
|
|
8945
|
+
return present === undefined ? undefined : present ? 0 : 1;
|
|
8861
8946
|
}
|
|
8862
8947
|
if (syncConditionalFileUnaryOps.has(expr.operator)) {
|
|
8863
8948
|
const fileRes = this.tryEvalFastMemoryFileUnary(expr.operator, val, rawState);
|
|
@@ -9067,7 +9152,7 @@ export class Runtime {
|
|
|
9067
9152
|
let existing = store?.get("PIPESTATUS");
|
|
9068
9153
|
if (store && !existing) {
|
|
9069
9154
|
const initTarget = pipelineStatusTarget(rawState);
|
|
9070
|
-
if (
|
|
9155
|
+
if ((this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity) &&
|
|
9071
9156
|
(initTarget === "indexed" || initTarget === "absent") &&
|
|
9072
9157
|
!store.watches.has("PIPESTATUS") &&
|
|
9073
9158
|
!monitor.hasOverlay("PIPESTATUS") &&
|
|
@@ -9353,7 +9438,15 @@ export class Runtime {
|
|
|
9353
9438
|
}
|
|
9354
9439
|
const dynProg = prepareArithmetic(fastSrc, this.budget.parsing);
|
|
9355
9440
|
if (!dynProg.error && isSafeSmiProgram(dynProg) && this.canSyncArithmeticWithoutFault(dynProg.tree, rawState, diagnosticLine)) {
|
|
9356
|
-
|
|
9441
|
+
let nonZero;
|
|
9442
|
+
try {
|
|
9443
|
+
nonZero = this.syncShellArithmeticNonZero(dynProg, rawState, diagnosticLine);
|
|
9444
|
+
}
|
|
9445
|
+
catch (err) {
|
|
9446
|
+
if (err instanceof ArrayFailure)
|
|
9447
|
+
return undefined;
|
|
9448
|
+
throw err;
|
|
9449
|
+
}
|
|
9357
9450
|
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
9358
9451
|
publishCommandSpelling(rawState, commandSpelling(command));
|
|
9359
9452
|
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
@@ -9366,7 +9459,15 @@ export class Runtime {
|
|
|
9366
9459
|
}
|
|
9367
9460
|
}
|
|
9368
9461
|
if (!expr.error && isSafeSmiProgram(expr) && this.canSyncArithmeticWithoutFault(expr.tree, rawState, diagnosticLine)) {
|
|
9369
|
-
|
|
9462
|
+
let nonZero;
|
|
9463
|
+
try {
|
|
9464
|
+
nonZero = this.syncShellArithmeticNonZero(expr, rawState, diagnosticLine);
|
|
9465
|
+
}
|
|
9466
|
+
catch (err) {
|
|
9467
|
+
if (err instanceof ArrayFailure)
|
|
9468
|
+
return undefined;
|
|
9469
|
+
throw err;
|
|
9470
|
+
}
|
|
9370
9471
|
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
9371
9472
|
publishCommandSpelling(rawState, commandSpelling(command));
|
|
9372
9473
|
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
@@ -9488,6 +9589,12 @@ export class Runtime {
|
|
|
9488
9589
|
if (command.kind === "while" || command.kind === "until") {
|
|
9489
9590
|
this.budget.tick();
|
|
9490
9591
|
let lastStatus = 0;
|
|
9592
|
+
const enableBatchRawWrite = !this._syncArithRawWriteOnly && !hasActiveExtensions(rawState) && !hasActiveVariableAttributes(rawState) && !rawState.readonlyVariables?.size && !rawState.allexport;
|
|
9593
|
+
const batchTouched = enableBatchRawWrite ? new Set() : undefined;
|
|
9594
|
+
if (enableBatchRawWrite) {
|
|
9595
|
+
this._syncArithRawWriteOnly = true;
|
|
9596
|
+
this._syncArithTouched = batchTouched;
|
|
9597
|
+
}
|
|
9491
9598
|
rawState.loopDepth++;
|
|
9492
9599
|
this._syncReturnDepth++;
|
|
9493
9600
|
try {
|
|
@@ -9544,6 +9651,17 @@ export class Runtime {
|
|
|
9544
9651
|
finally {
|
|
9545
9652
|
this._syncReturnDepth--;
|
|
9546
9653
|
rawState.loopDepth--;
|
|
9654
|
+
if (enableBatchRawWrite && batchTouched) {
|
|
9655
|
+
this._syncArithRawWriteOnly = false;
|
|
9656
|
+
this._syncArithTouched = undefined;
|
|
9657
|
+
for (const vName of batchTouched) {
|
|
9658
|
+
const vVal = rawState.variables[vName];
|
|
9659
|
+
if (typeof vVal === "string")
|
|
9660
|
+
monitor.publishStringVariable(vName, vVal);
|
|
9661
|
+
else if (vVal === undefined)
|
|
9662
|
+
delete monitor.proxy.variables[vName];
|
|
9663
|
+
}
|
|
9664
|
+
}
|
|
9547
9665
|
}
|
|
9548
9666
|
rawState.status = lastStatus;
|
|
9549
9667
|
return lastStatus;
|
|
@@ -9554,12 +9672,18 @@ export class Runtime {
|
|
|
9554
9672
|
return undefined;
|
|
9555
9673
|
}
|
|
9556
9674
|
this.budget.tick();
|
|
9557
|
-
|
|
9558
|
-
|
|
9675
|
+
const enableBatchRawWrite = !this._syncArithRawWriteOnly && !hasActiveExtensions(rawState) && !hasActiveVariableAttributes(rawState) && !rawState.readonlyVariables?.size && !rawState.allexport;
|
|
9676
|
+
const batchTouched = enableBatchRawWrite ? new Set() : undefined;
|
|
9677
|
+
if (enableBatchRawWrite) {
|
|
9678
|
+
this._syncArithRawWriteOnly = true;
|
|
9679
|
+
this._syncArithTouched = batchTouched;
|
|
9680
|
+
}
|
|
9559
9681
|
let lastStatus = 0;
|
|
9560
9682
|
rawState.loopDepth++;
|
|
9561
9683
|
this._syncReturnDepth++;
|
|
9562
9684
|
try {
|
|
9685
|
+
if (e0)
|
|
9686
|
+
this.syncShellArithmeticNonZero(e0, rawState, diagnosticLine);
|
|
9563
9687
|
let iter = 0;
|
|
9564
9688
|
while (true) {
|
|
9565
9689
|
if (++iter > 4096)
|
|
@@ -9603,6 +9727,17 @@ export class Runtime {
|
|
|
9603
9727
|
finally {
|
|
9604
9728
|
this._syncReturnDepth--;
|
|
9605
9729
|
rawState.loopDepth--;
|
|
9730
|
+
if (enableBatchRawWrite && batchTouched) {
|
|
9731
|
+
this._syncArithRawWriteOnly = false;
|
|
9732
|
+
this._syncArithTouched = undefined;
|
|
9733
|
+
for (const vName of batchTouched) {
|
|
9734
|
+
const vVal = rawState.variables[vName];
|
|
9735
|
+
if (typeof vVal === "string")
|
|
9736
|
+
monitor.publishStringVariable(vName, vVal);
|
|
9737
|
+
else if (vVal === undefined)
|
|
9738
|
+
delete monitor.proxy.variables[vName];
|
|
9739
|
+
}
|
|
9740
|
+
}
|
|
9606
9741
|
}
|
|
9607
9742
|
rawState.status = lastStatus;
|
|
9608
9743
|
return lastStatus;
|
|
@@ -9673,6 +9808,12 @@ export class Runtime {
|
|
|
9673
9808
|
return undefined;
|
|
9674
9809
|
this.budget.tick();
|
|
9675
9810
|
let lastStatus = 0;
|
|
9811
|
+
const enableBatchRawWrite = !this._syncArithRawWriteOnly && !hasActiveExtensions(rawState) && !hasActiveVariableAttributes(rawState) && !rawState.readonlyVariables?.size && !rawState.allexport;
|
|
9812
|
+
const batchTouched = enableBatchRawWrite ? new Set() : undefined;
|
|
9813
|
+
if (enableBatchRawWrite) {
|
|
9814
|
+
this._syncArithRawWriteOnly = true;
|
|
9815
|
+
this._syncArithTouched = batchTouched;
|
|
9816
|
+
}
|
|
9676
9817
|
rawState.loopDepth++;
|
|
9677
9818
|
this._syncReturnDepth++;
|
|
9678
9819
|
try {
|
|
@@ -9683,7 +9824,12 @@ export class Runtime {
|
|
|
9683
9824
|
runYieldCheckpoint(this.signal);
|
|
9684
9825
|
}
|
|
9685
9826
|
this.budget.loop();
|
|
9686
|
-
|
|
9827
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
9828
|
+
rawState.variables[command.name] = items[idx];
|
|
9829
|
+
this._syncArithTouched.add(command.name);
|
|
9830
|
+
}
|
|
9831
|
+
else
|
|
9832
|
+
monitor.publishStringVariable(command.name, items[idx]);
|
|
9687
9833
|
if (rawState.allexport)
|
|
9688
9834
|
rawState.exported.add(command.name);
|
|
9689
9835
|
const bodyRes = this.trySyncScript(command.body, state, io, ignored);
|
|
@@ -9709,6 +9855,17 @@ export class Runtime {
|
|
|
9709
9855
|
finally {
|
|
9710
9856
|
this._syncReturnDepth--;
|
|
9711
9857
|
rawState.loopDepth--;
|
|
9858
|
+
if (enableBatchRawWrite && batchTouched) {
|
|
9859
|
+
this._syncArithRawWriteOnly = false;
|
|
9860
|
+
this._syncArithTouched = undefined;
|
|
9861
|
+
for (const vName of batchTouched) {
|
|
9862
|
+
const vVal = rawState.variables[vName];
|
|
9863
|
+
if (typeof vVal === "string")
|
|
9864
|
+
monitor.publishStringVariable(vName, vVal);
|
|
9865
|
+
else if (vVal === undefined)
|
|
9866
|
+
delete monitor.proxy.variables[vName];
|
|
9867
|
+
}
|
|
9868
|
+
}
|
|
9712
9869
|
}
|
|
9713
9870
|
rawState.status = lastStatus;
|
|
9714
9871
|
return lastStatus;
|
|
@@ -10084,7 +10241,7 @@ export class Runtime {
|
|
|
10084
10241
|
if (assignment) {
|
|
10085
10242
|
const hasSubPart = assignment.value.parts.some(part => part.kind === "substitution");
|
|
10086
10243
|
const existingArrAssign = store?.get(assignment.name);
|
|
10087
|
-
if (assignment.name === "OPTIND" ||
|
|
10244
|
+
if ((assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND"))) ||
|
|
10088
10245
|
assignment.name === "PIPESTATUS" ||
|
|
10089
10246
|
assignment.name.includes("[") ||
|
|
10090
10247
|
(hasSubPart && !this.isPureSyncValueWord(assignment.value, rawState)) ||
|
|
@@ -10103,6 +10260,12 @@ export class Runtime {
|
|
|
10103
10260
|
}
|
|
10104
10261
|
if (typeof fastAssigned !== "string")
|
|
10105
10262
|
return undefined;
|
|
10263
|
+
if (assignment.name === "OPTIND") {
|
|
10264
|
+
const trimmedOptind = fastAssigned.trim();
|
|
10265
|
+
if (!/^[0-9]{1,6}$/.test(trimmedOptind))
|
|
10266
|
+
return undefined;
|
|
10267
|
+
fastAssigned = String(Number(trimmedOptind));
|
|
10268
|
+
}
|
|
10106
10269
|
if (existingArrAssign) {
|
|
10107
10270
|
if (!this.tryFastArraySubscriptWriteSync(rawState, assignment.name, "0", fastAssigned))
|
|
10108
10271
|
return undefined;
|
|
@@ -10161,6 +10324,10 @@ export class Runtime {
|
|
|
10161
10324
|
}
|
|
10162
10325
|
else
|
|
10163
10326
|
monitor.publishStringVariable(assignment.name, finalAssigned);
|
|
10327
|
+
if (assignment.name === "OPTIND") {
|
|
10328
|
+
rawState.variables.OPTIND = finalAssigned;
|
|
10329
|
+
this.syncGetopts(rawState);
|
|
10330
|
+
}
|
|
10164
10331
|
if (rawState.allexport)
|
|
10165
10332
|
monitor.proxy.exported.add(assignment.name);
|
|
10166
10333
|
if (io.assignmentDiagnosticContext)
|
|
@@ -10243,6 +10410,142 @@ export class Runtime {
|
|
|
10243
10410
|
}
|
|
10244
10411
|
}
|
|
10245
10412
|
}
|
|
10413
|
+
if (command.words.length >= 2 && command.words.length <= 16 && (w0Plain === ":" || w0Plain === "true" || w0Plain === "false") && command.redirects.length === 0 && !hasShellFunction(rawState, w0Plain) && !rawState.extensions?.builtins.has(w0Plain)) {
|
|
10414
|
+
const rawStatus = w0Plain === "false" ? 1 : 0;
|
|
10415
|
+
const statusChar = rawStatus === 0 ? "0" : "1";
|
|
10416
|
+
if (!canMutatePipeStatus && elem0.text.shellValue !== statusChar)
|
|
10417
|
+
return undefined;
|
|
10418
|
+
const finalStatus = pipeline.negate ? Number(rawStatus === 0) : rawStatus;
|
|
10419
|
+
if (finalStatus !== 0 && !ignored && rawState.errexit)
|
|
10420
|
+
return undefined;
|
|
10421
|
+
let lastArg = w0Plain;
|
|
10422
|
+
let argsOk = true;
|
|
10423
|
+
try {
|
|
10424
|
+
for (let i = 1; i < command.words.length; i++) {
|
|
10425
|
+
const v = this.fastValueWord(command.words[i], rawState, io, true, false, false, true, undefined, diagnosticLine);
|
|
10426
|
+
if (typeof v !== "string") {
|
|
10427
|
+
argsOk = false;
|
|
10428
|
+
break;
|
|
10429
|
+
}
|
|
10430
|
+
lastArg = v;
|
|
10431
|
+
}
|
|
10432
|
+
}
|
|
10433
|
+
catch {
|
|
10434
|
+
argsOk = false;
|
|
10435
|
+
}
|
|
10436
|
+
if (argsOk) {
|
|
10437
|
+
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
10438
|
+
publishCommandSpelling(rawState, commandSpelling(command));
|
|
10439
|
+
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
10440
|
+
this.budget.tick();
|
|
10441
|
+
rawState.substitutionStatus = 0;
|
|
10442
|
+
if (rawState.variables._ !== undefined)
|
|
10443
|
+
delete rawState.variables._;
|
|
10444
|
+
rawState.lastArgument = lastArg;
|
|
10445
|
+
if (io.assignmentDiagnosticContext)
|
|
10446
|
+
io.assignmentDiagnosticContext.name = undefined;
|
|
10447
|
+
return this.finishSyncPipeStatus(rawState, monitor, monitor.store, monitor.store?.get("PIPESTATUS"), elem0, scope, finalStatus, restEpoch);
|
|
10448
|
+
}
|
|
10449
|
+
}
|
|
10450
|
+
if (command.words.length >= 3 && command.words.length <= 16 && w0Plain === "getopts" && command.redirects.length === 0 && !hasShellFunction(rawState, "getopts") && !rawState.extensions?.builtins.has("getopts")) {
|
|
10451
|
+
const optVar = command.words[2]?.plain;
|
|
10452
|
+
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)) {
|
|
10453
|
+
let optstring;
|
|
10454
|
+
let scanArgs;
|
|
10455
|
+
let lastArg = optVar;
|
|
10456
|
+
try {
|
|
10457
|
+
optstring = command.words[1].plain ?? this.fastValueWord(command.words[1], rawState, io, true, false, false, true, undefined, diagnosticLine);
|
|
10458
|
+
if (typeof optstring === "string") {
|
|
10459
|
+
if (command.words.length === 3) {
|
|
10460
|
+
scanArgs = this._fastSubPositional ?? rawState.positional;
|
|
10461
|
+
}
|
|
10462
|
+
else if (command.words.length === 4 && (() => { const ne = command.words[3].parts.filter(p => !(p.kind === "text" && p.value === "")); return ne.length === 1 && ne[0].kind === "variable" && ne[0].name === "@" && ne[0].quoted; })()) {
|
|
10463
|
+
scanArgs = this._fastSubPositional ?? rawState.positional;
|
|
10464
|
+
if (scanArgs.length > 0)
|
|
10465
|
+
lastArg = scanArgs[scanArgs.length - 1];
|
|
10466
|
+
}
|
|
10467
|
+
else {
|
|
10468
|
+
const customArgs = [];
|
|
10469
|
+
let customOk = true;
|
|
10470
|
+
for (let i = 3; i < command.words.length; i++) {
|
|
10471
|
+
const v = this.fastValueWord(command.words[i], rawState, io, true, false, false, true, undefined, diagnosticLine);
|
|
10472
|
+
if (typeof v !== "string") {
|
|
10473
|
+
customOk = false;
|
|
10474
|
+
break;
|
|
10475
|
+
}
|
|
10476
|
+
customArgs.push(v);
|
|
10477
|
+
lastArg = v;
|
|
10478
|
+
}
|
|
10479
|
+
if (customOk)
|
|
10480
|
+
scanArgs = customArgs;
|
|
10481
|
+
}
|
|
10482
|
+
}
|
|
10483
|
+
}
|
|
10484
|
+
catch {
|
|
10485
|
+
scanArgs = undefined;
|
|
10486
|
+
}
|
|
10487
|
+
if (typeof optstring === "string" && scanArgs !== undefined) {
|
|
10488
|
+
rawState.getopts ??= cloneGetoptsBinding(rawState);
|
|
10489
|
+
const res = scanGetoptsSync(rawState.getopts.cursor, optstring, scanArgs);
|
|
10490
|
+
if (res !== undefined) {
|
|
10491
|
+
const rawStatus = res.status;
|
|
10492
|
+
const statusChar = rawStatus === 0 ? "0" : "1";
|
|
10493
|
+
if (canMutatePipeStatus || elem0.text.shellValue === statusChar) {
|
|
10494
|
+
const finalStatus = pipeline.negate ? Number(rawStatus === 0) : rawStatus;
|
|
10495
|
+
if (finalStatus === 0 || ignored || !rawState.errexit) {
|
|
10496
|
+
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
10497
|
+
publishCommandSpelling(rawState, commandSpelling(command));
|
|
10498
|
+
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
10499
|
+
this.budget.tick();
|
|
10500
|
+
rawState.substitutionStatus = 0;
|
|
10501
|
+
if (rawState.variables._ !== undefined)
|
|
10502
|
+
delete rawState.variables._;
|
|
10503
|
+
rawState.lastArgument = lastArg;
|
|
10504
|
+
rawState.getopts.cursor = res.state;
|
|
10505
|
+
const optindStr = String(res.optind);
|
|
10506
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
10507
|
+
rawState.variables.OPTIND = optindStr;
|
|
10508
|
+
this._syncArithTouched.add("OPTIND");
|
|
10509
|
+
}
|
|
10510
|
+
else
|
|
10511
|
+
monitor.publishStringVariable("OPTIND", optindStr);
|
|
10512
|
+
if (rawState.allexport)
|
|
10513
|
+
monitor.proxy.exported.add("OPTIND");
|
|
10514
|
+
if (res.argument.kind === "set") {
|
|
10515
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
10516
|
+
rawState.variables.OPTARG = res.argument.value;
|
|
10517
|
+
this._syncArithTouched.add("OPTARG");
|
|
10518
|
+
}
|
|
10519
|
+
else
|
|
10520
|
+
monitor.publishStringVariable("OPTARG", res.argument.value);
|
|
10521
|
+
if (rawState.allexport)
|
|
10522
|
+
monitor.proxy.exported.add("OPTARG");
|
|
10523
|
+
}
|
|
10524
|
+
else {
|
|
10525
|
+
delete rawState.variables.OPTARG;
|
|
10526
|
+
rawState.exported.delete("OPTARG");
|
|
10527
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched)
|
|
10528
|
+
this._syncArithTouched.add("OPTARG");
|
|
10529
|
+
else
|
|
10530
|
+
monitor.values.invalidate("OPTARG");
|
|
10531
|
+
}
|
|
10532
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
10533
|
+
rawState.variables[optVar] = res.option;
|
|
10534
|
+
this._syncArithTouched.add(optVar);
|
|
10535
|
+
}
|
|
10536
|
+
else
|
|
10537
|
+
monitor.publishStringVariable(optVar, res.option);
|
|
10538
|
+
if (rawState.allexport)
|
|
10539
|
+
monitor.proxy.exported.add(optVar);
|
|
10540
|
+
if (io.assignmentDiagnosticContext)
|
|
10541
|
+
io.assignmentDiagnosticContext.name = undefined;
|
|
10542
|
+
return this.finishSyncPipeStatus(rawState, monitor, monitor.store, monitor.store?.get("PIPESTATUS"), elem0, scope, finalStatus, restEpoch);
|
|
10543
|
+
}
|
|
10544
|
+
}
|
|
10545
|
+
}
|
|
10546
|
+
}
|
|
10547
|
+
}
|
|
10548
|
+
}
|
|
10246
10549
|
if (command.words.length === 2 && w0Plain === "shift" && command.redirects.length === 0 && canMutatePipeStatus && !pipeline.negate && !hasShellFunction(rawState, "shift") && !rawState.extensions?.builtins.has("shift")) {
|
|
10247
10550
|
let argVal;
|
|
10248
10551
|
try {
|
|
@@ -10406,6 +10709,105 @@ export class Runtime {
|
|
|
10406
10709
|
!command.redirects[0].move &&
|
|
10407
10710
|
!command.redirects[0].document &&
|
|
10408
10711
|
(command.redirects[0].descriptor === undefined || command.redirects[0].descriptor === 0);
|
|
10712
|
+
if ((w0Plain === "mapfile" || w0Plain === "readarray") &&
|
|
10713
|
+
isHereStringRead &&
|
|
10714
|
+
(command.words.length === 2 || command.words.length === 3) &&
|
|
10715
|
+
command.words[1]?.plain === "-t" &&
|
|
10716
|
+
canMutatePipeStatus &&
|
|
10717
|
+
!pipeline.negate &&
|
|
10718
|
+
!rawState.allexport &&
|
|
10719
|
+
!hasShellFunction(rawState, w0Plain) &&
|
|
10720
|
+
!rawState.extensions?.builtins.has(w0Plain)) {
|
|
10721
|
+
const arrayTarget = command.words[2]?.plain ?? "MAPFILE";
|
|
10722
|
+
if (!hasUnpreparedLocal(rawState, arrayTarget) &&
|
|
10723
|
+
isShellIdentifier(arrayTarget) &&
|
|
10724
|
+
!rawState.readonlyVariables?.has(arrayTarget) &&
|
|
10725
|
+
!rawState.exported.has(arrayTarget) &&
|
|
10726
|
+
!rawState.variableAttributes?.get(arrayTarget) &&
|
|
10727
|
+
!controlNames.has(arrayTarget)) {
|
|
10728
|
+
let hv;
|
|
10729
|
+
try {
|
|
10730
|
+
hv = this.fastValueWord(command.redirects[0].target, rawState, io, false, false, false, false, undefined, diagnosticLine);
|
|
10731
|
+
}
|
|
10732
|
+
catch {
|
|
10733
|
+
hv = undefined;
|
|
10734
|
+
}
|
|
10735
|
+
if (typeof hv === "string" &&
|
|
10736
|
+
!hv.includes("\0") &&
|
|
10737
|
+
hv.length + 1 < this.budget.limits.maxExpansionBytes &&
|
|
10738
|
+
hv.length + 1 <= this.budget.limits.maxInputBytes) {
|
|
10739
|
+
const arrStore = monitor.store ?? requireArrays(rawState);
|
|
10740
|
+
let existingArrayBinding = arrStore.get(arrayTarget);
|
|
10741
|
+
if (!existingArrayBinding && rawState.variables[arrayTarget] === undefined && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
|
|
10742
|
+
const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
10743
|
+
const recBinding = arrStore.takeRecycled(arrayTarget, false, true, recTickets);
|
|
10744
|
+
if (recBinding) {
|
|
10745
|
+
monitor.epoch = recTickets.epoch;
|
|
10746
|
+
existingArrayBinding = recBinding;
|
|
10747
|
+
}
|
|
10748
|
+
else {
|
|
10749
|
+
try {
|
|
10750
|
+
const created = IndexedBinding.create(arrStore.owner, false);
|
|
10751
|
+
const prepared = arrStore.prepareExistingName(arrayTarget, shellValueByteLength(arrayTarget), arrStore.owner, this.signal);
|
|
10752
|
+
if (prepared) {
|
|
10753
|
+
const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
10754
|
+
arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
|
|
10755
|
+
monitor.epoch = initTickets.epoch;
|
|
10756
|
+
existingArrayBinding = created;
|
|
10757
|
+
}
|
|
10758
|
+
else {
|
|
10759
|
+
void created.release();
|
|
10760
|
+
}
|
|
10761
|
+
}
|
|
10762
|
+
catch { }
|
|
10763
|
+
}
|
|
10764
|
+
}
|
|
10765
|
+
if (existingArrayBinding && !existingArrayBinding.associative && existingArrayBinding.references === 1 && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
|
|
10766
|
+
const lines = hv.split("\n");
|
|
10767
|
+
const fieldLen = lines.length;
|
|
10768
|
+
if (fieldLen <= 256) {
|
|
10769
|
+
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
10770
|
+
publishCommandSpelling(rawState, commandSpelling(command));
|
|
10771
|
+
const tickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 + fieldLen * 4 });
|
|
10772
|
+
if (existingArrayBinding.values.size !== fieldLen || existingArrayBinding.maximum !== fieldLen - 1) {
|
|
10773
|
+
for (const k of [...existingArrayBinding.values.keys()]) {
|
|
10774
|
+
if (k >= fieldLen)
|
|
10775
|
+
existingArrayBinding.remove(k);
|
|
10776
|
+
}
|
|
10777
|
+
existingArrayBinding.maximum = fieldLen - 1;
|
|
10778
|
+
}
|
|
10779
|
+
for (let idx = 0; idx < fieldLen; idx++) {
|
|
10780
|
+
const val = lines[idx];
|
|
10781
|
+
const byteLen = shellValueByteLength(val);
|
|
10782
|
+
const slot = existingArrayBinding.values.get(idx);
|
|
10783
|
+
if (slot && slot.text.references === 1 && slot.text.bytes === byteLen) {
|
|
10784
|
+
existingArrayBinding.owner.chargeWork(byteLen);
|
|
10785
|
+
slot.text.shellValue = val;
|
|
10786
|
+
}
|
|
10787
|
+
else {
|
|
10788
|
+
existingArrayBinding.owner.chargeWork(byteLen);
|
|
10789
|
+
const token = new OwnedText(val, byteLen, existingArrayBinding.owner.reserve({ payload: byteLen, metadata: 32, work: 4 }));
|
|
10790
|
+
existingArrayBinding.insert(idx, token);
|
|
10791
|
+
}
|
|
10792
|
+
}
|
|
10793
|
+
delete rawState.variables[arrayTarget];
|
|
10794
|
+
monitor.values.invalidate(arrayTarget);
|
|
10795
|
+
monitor.epoch = tickets.epoch;
|
|
10796
|
+
arrStore.revise(arrayTarget, existingArrayBinding, tickets);
|
|
10797
|
+
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
10798
|
+
this.budget.tick();
|
|
10799
|
+
rawState.substitutionStatus = 0;
|
|
10800
|
+
if (rawState.variables._ !== undefined)
|
|
10801
|
+
delete rawState.variables._;
|
|
10802
|
+
rawState.lastArgument = command.words[command.words.length - 1].plain ?? arrayTarget;
|
|
10803
|
+
if (io.assignmentDiagnosticContext)
|
|
10804
|
+
io.assignmentDiagnosticContext.name = undefined;
|
|
10805
|
+
return this.finishSyncPipeStatus(rawState, monitor, monitor.store, monitor.store?.get("PIPESTATUS"), elem0, scope, 0, restEpoch);
|
|
10806
|
+
}
|
|
10807
|
+
}
|
|
10808
|
+
}
|
|
10809
|
+
}
|
|
10810
|
+
}
|
|
10409
10811
|
if ((w0Plain === "read" || (command.words[1]?.plain === "read" && w0.parts[0]?.kind === "text" && w0.parts[0].value.startsWith("IFS="))) &&
|
|
10410
10812
|
canMutatePipeStatus &&
|
|
10411
10813
|
!pipeline.negate &&
|
|
@@ -10470,7 +10872,7 @@ export class Runtime {
|
|
|
10470
10872
|
delimStr = nextW.plain;
|
|
10471
10873
|
else {
|
|
10472
10874
|
try {
|
|
10473
|
-
const fv = this.fastValueWord(nextW, rawState, io,
|
|
10875
|
+
const fv = this.fastValueWord(nextW, rawState, io, true, false, false, false, undefined, diagnosticLine);
|
|
10474
10876
|
if (typeof fv === "string")
|
|
10475
10877
|
delimStr = fv;
|
|
10476
10878
|
}
|
|
@@ -10516,7 +10918,7 @@ export class Runtime {
|
|
|
10516
10918
|
const varCount = command.words.length - readWordIdx;
|
|
10517
10919
|
let existingArrayBinding;
|
|
10518
10920
|
if (arrayTarget !== undefined) {
|
|
10519
|
-
if (
|
|
10921
|
+
if (hasUnpreparedLocal(rawState, arrayTarget))
|
|
10520
10922
|
return undefined;
|
|
10521
10923
|
if (varCount !== 0 || !isShellIdentifier(arrayTarget) || rawState.readonlyVariables?.has(arrayTarget) || rawState.exported.has(arrayTarget) || rawState.variableAttributes?.get(arrayTarget) || controlNames.has(arrayTarget)) {
|
|
10522
10924
|
simpleRead = false;
|
|
@@ -10525,21 +10927,28 @@ export class Runtime {
|
|
|
10525
10927
|
const arrStore = monitor.store ?? requireArrays(rawState);
|
|
10526
10928
|
existingArrayBinding = arrStore.get(arrayTarget);
|
|
10527
10929
|
if (!existingArrayBinding && rawState.variables[arrayTarget] === undefined && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
10534
|
-
arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
|
|
10535
|
-
monitor.epoch = initTickets.epoch;
|
|
10536
|
-
existingArrayBinding = created;
|
|
10537
|
-
}
|
|
10538
|
-
else {
|
|
10539
|
-
void created.release();
|
|
10540
|
-
}
|
|
10930
|
+
const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
10931
|
+
const recBinding = arrStore.takeRecycled(arrayTarget, false, true, recTickets);
|
|
10932
|
+
if (recBinding) {
|
|
10933
|
+
monitor.epoch = recTickets.epoch;
|
|
10934
|
+
existingArrayBinding = recBinding;
|
|
10541
10935
|
}
|
|
10542
|
-
|
|
10936
|
+
else
|
|
10937
|
+
try {
|
|
10938
|
+
const created = IndexedBinding.create(arrStore.owner, false);
|
|
10939
|
+
const nameByteLen = shellValueByteLength(arrayTarget);
|
|
10940
|
+
const prepared = arrStore.prepareExistingName(arrayTarget, nameByteLen, arrStore.owner, this.signal);
|
|
10941
|
+
if (prepared) {
|
|
10942
|
+
const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
10943
|
+
arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
|
|
10944
|
+
monitor.epoch = initTickets.epoch;
|
|
10945
|
+
existingArrayBinding = created;
|
|
10946
|
+
}
|
|
10947
|
+
else {
|
|
10948
|
+
void created.release();
|
|
10949
|
+
}
|
|
10950
|
+
}
|
|
10951
|
+
catch { }
|
|
10543
10952
|
}
|
|
10544
10953
|
if (!existingArrayBinding ||
|
|
10545
10954
|
existingArrayBinding.associative ||
|
|
@@ -11151,7 +11560,7 @@ export class Runtime {
|
|
|
11151
11560
|
const wArg = command.words[idx];
|
|
11152
11561
|
const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : undefined;
|
|
11153
11562
|
if (assignment) {
|
|
11154
|
-
if (assignment.name === "OPTIND" || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || rawState.readonlyVariables?.has(assignment.name) || store?.get(assignment.name)) {
|
|
11563
|
+
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)) {
|
|
11155
11564
|
allValidLocal = false;
|
|
11156
11565
|
break;
|
|
11157
11566
|
}
|
|
@@ -11166,9 +11575,17 @@ export class Runtime {
|
|
|
11166
11575
|
allValidLocal = false;
|
|
11167
11576
|
break;
|
|
11168
11577
|
}
|
|
11578
|
+
if (assignment.name === "OPTIND") {
|
|
11579
|
+
const trimmedOptind = fastAssigned.trim();
|
|
11580
|
+
if (!/^[0-9]{1,6}$/.test(trimmedOptind)) {
|
|
11581
|
+
allValidLocal = false;
|
|
11582
|
+
break;
|
|
11583
|
+
}
|
|
11584
|
+
fastAssigned = String(Number(trimmedOptind));
|
|
11585
|
+
}
|
|
11169
11586
|
parsedLocals.push({ name: assignment.name, val: fastAssigned, append: assignment.append, lastArg: `${assignment.name}=${fastAssigned}` });
|
|
11170
11587
|
}
|
|
11171
|
-
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)) {
|
|
11588
|
+
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)) {
|
|
11172
11589
|
parsedLocals.push({ name: wArg.plain, val: undefined, append: false, lastArg: wArg.plain });
|
|
11173
11590
|
}
|
|
11174
11591
|
else {
|
|
@@ -11177,6 +11594,8 @@ export class Runtime {
|
|
|
11177
11594
|
}
|
|
11178
11595
|
}
|
|
11179
11596
|
if (allValidLocal && parsedLocals.length > 0) {
|
|
11597
|
+
if (rawState.locals.length === 0 && parsedLocals.some(item => item.val === undefined && !rawState.variableAttributes?.has(item.name)))
|
|
11598
|
+
return undefined;
|
|
11180
11599
|
const locals = rawState.locals.length > 0 ? rawState.locals[rawState.locals.length - 1] : undefined;
|
|
11181
11600
|
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
11182
11601
|
this.budget.tick();
|
|
@@ -11191,7 +11610,7 @@ export class Runtime {
|
|
|
11191
11610
|
const curVal = this._syncArithTouched.has(item.name)
|
|
11192
11611
|
? rawState.variables[item.name]
|
|
11193
11612
|
: (rawState.variables[item.name] === undefined ? undefined : (monitor.values.get(item.name, rawState.variables[item.name]) ?? rawState.variables[item.name]));
|
|
11194
|
-
locals.set(item.name, { attributes: undefined, value: typeof curVal === "string" ? curVal : undefined, exported: false, readOnly: false });
|
|
11613
|
+
locals.set(item.name, { attributes: undefined, value: typeof curVal === "string" ? curVal : undefined, exported: false, readOnly: false, ...(item.name === "OPTIND" ? { getopts: cloneGetoptsBinding(rawState) } : {}) });
|
|
11195
11614
|
}
|
|
11196
11615
|
else
|
|
11197
11616
|
locals.set(item.name, saveVariable(state, item.name));
|
|
@@ -11214,18 +11633,27 @@ export class Runtime {
|
|
|
11214
11633
|
}
|
|
11215
11634
|
else
|
|
11216
11635
|
monitor.publishStringVariable(item.name, finalVal);
|
|
11636
|
+
if (item.name === "OPTIND") {
|
|
11637
|
+
rawState.variables.OPTIND = finalVal;
|
|
11638
|
+
this.syncGetopts(rawState);
|
|
11639
|
+
}
|
|
11217
11640
|
if (rawState.allexport)
|
|
11218
11641
|
monitor.proxy.exported.add(item.name);
|
|
11219
11642
|
rawState.lastArgument = `${item.name}=${finalVal}`;
|
|
11220
|
-
if (
|
|
11221
|
-
rawState.variableAttributes
|
|
11222
|
-
rawState.variableAttributes.set(item.name, "");
|
|
11223
|
-
}
|
|
11643
|
+
if (isNewLocal && rawState.variableAttributes?.has(item.name))
|
|
11644
|
+
rawState.variableAttributes.delete(item.name);
|
|
11224
11645
|
}
|
|
11225
11646
|
else {
|
|
11226
|
-
if (
|
|
11227
|
-
|
|
11228
|
-
|
|
11647
|
+
if (item.name === "OPTIND")
|
|
11648
|
+
this.syncGetopts(rawState);
|
|
11649
|
+
if (!locals) {
|
|
11650
|
+
if (!rawState.variableAttributes?.has(item.name)) {
|
|
11651
|
+
rawState.variableAttributes ??= new Map();
|
|
11652
|
+
rawState.variableAttributes.set(item.name, "");
|
|
11653
|
+
}
|
|
11654
|
+
}
|
|
11655
|
+
else if (isNewLocal && rawState.variableAttributes?.has(item.name)) {
|
|
11656
|
+
rawState.variableAttributes.delete(item.name);
|
|
11229
11657
|
}
|
|
11230
11658
|
rawState.lastArgument = item.lastArg;
|
|
11231
11659
|
}
|
|
@@ -11434,11 +11862,15 @@ export class Runtime {
|
|
|
11434
11862
|
rawState.locals.pop();
|
|
11435
11863
|
rawState.functionNames?.shift();
|
|
11436
11864
|
for (const [k, previous] of locals) {
|
|
11437
|
-
if (this._syncArithRawWriteOnly && this._syncArithTouched && !syncLocalArrayVariables.has(previous) && !previous.heldValue && !previous.attributes && !previous.exported && !previous.readOnly
|
|
11865
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched && !syncLocalArrayVariables.has(previous) && !previous.heldValue && !previous.attributes && !previous.exported && !previous.readOnly) {
|
|
11438
11866
|
if (previous.value === undefined)
|
|
11439
11867
|
delete rawState.variables[k];
|
|
11440
11868
|
else
|
|
11441
11869
|
rawState.variables[k] = shellValueText(previous.value);
|
|
11870
|
+
if (k === "OPTIND" && previous.getopts) {
|
|
11871
|
+
rawState.getopts = { integer: previous.getopts.integer, cursor: cloneGetoptsState(previous.getopts.cursor) };
|
|
11872
|
+
}
|
|
11873
|
+
rawState.variableAttributes?.delete(k);
|
|
11442
11874
|
this._syncArithTouched.add(k);
|
|
11443
11875
|
}
|
|
11444
11876
|
else
|
|
@@ -11998,9 +12430,11 @@ export class Runtime {
|
|
|
11998
12430
|
if (part.alternate && part.alternate.parts.length > 0)
|
|
11999
12431
|
return false;
|
|
12000
12432
|
}
|
|
12001
|
-
else if (part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+") {
|
|
12433
|
+
else if (part.operator === "-" || part.operator === ":-" || part.operator === "+" || part.operator === ":+" || part.operator === "=" || part.operator === ":=") {
|
|
12002
12434
|
if (!part.alternate || !part.alternate.parts.every(p => p.kind === "text" || p.kind === "arithmetic" || (p.kind === "variable" && !p.operator && !p.substring)))
|
|
12003
12435
|
return false;
|
|
12436
|
+
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)))
|
|
12437
|
+
return false;
|
|
12004
12438
|
}
|
|
12005
12439
|
else if (part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") {
|
|
12006
12440
|
if (!part.alternate || part.alternate.parts.length === 0)
|
|
@@ -12036,8 +12470,18 @@ export class Runtime {
|
|
|
12036
12470
|
if (rawState.nounset)
|
|
12037
12471
|
return false;
|
|
12038
12472
|
const em = SIMPLE_EXPANDED_ARITH_RE.exec(part.source);
|
|
12039
|
-
if (!em || ((em[2] === "/" || em[2] === "%") && !(em[3] && /^[1-9][0-9]*$/.test(em[3]))))
|
|
12040
|
-
|
|
12473
|
+
if (!em || ((em[2] === "/" || em[2] === "%") && !(em[3] && /^[1-9][0-9]*$/.test(em[3])))) {
|
|
12474
|
+
if (part.source.includes("<<") || part.source.includes(">>") || part.source.includes("**") || /[/%](?!\s*[1-9][0-9]*\b)/.test(part.source))
|
|
12475
|
+
return false;
|
|
12476
|
+
try {
|
|
12477
|
+
const expW = parseArithmeticExpansion(part.source, this.budget.parsing, false, 0, undefined, rawState.extensions?.syntax);
|
|
12478
|
+
if (!this.isPureSyncValueWord(expW, rawState))
|
|
12479
|
+
return false;
|
|
12480
|
+
}
|
|
12481
|
+
catch {
|
|
12482
|
+
return false;
|
|
12483
|
+
}
|
|
12484
|
+
}
|
|
12041
12485
|
}
|
|
12042
12486
|
continue;
|
|
12043
12487
|
}
|
|
@@ -15651,7 +16095,7 @@ export class Runtime {
|
|
|
15651
16095
|
}
|
|
15652
16096
|
if (inlineInput || (state.profile === "sh" || !words.length) && assignments.some(assignment => state.readonlyVariables?.has(assignment.name)))
|
|
15653
16097
|
await assign();
|
|
15654
|
-
if (inlineInput && functionCommand && previous?.size) {
|
|
16098
|
+
if (inlineInput && (functionCommand || words[0] === "read" && !state.extensions?.builtins.has("read")) && previous?.size) {
|
|
15655
16099
|
if (stateMonitor(state)?.lazyPipeStatus !== undefined)
|
|
15656
16100
|
stateMonitor(state).activate(true);
|
|
15657
16101
|
const redirectState = tryCloneStateSync(state) ?? await cloneState(state, this.signal);
|
|
@@ -20050,7 +20494,7 @@ export class Runtime {
|
|
|
20050
20494
|
if (selector?.kind === "members" || part.name === "@" || part.name === "*") {
|
|
20051
20495
|
const members = selector ? await this.arrayMembers(part.name, state, io, part.keys) : this.positionalValues(state);
|
|
20052
20496
|
const ifs = state.variables.IFS ?? " ";
|
|
20053
|
-
const separator = selector?.kind === "members"
|
|
20497
|
+
const separator = !split && (selector?.kind === "members" ? selector.separator === "@" || !part.quoted : part.name === "@") ? " " : ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
|
|
20054
20498
|
const fragments = [];
|
|
20055
20499
|
let bytes = 0;
|
|
20056
20500
|
for (const member of members) {
|
|
@@ -20490,7 +20934,7 @@ export class Runtime {
|
|
|
20490
20934
|
if (part.length)
|
|
20491
20935
|
return String(binding?.values.size ?? (part.name === "FUNCNAME" && state.variables.FUNCNAME === undefined ? state.functionNames?.length ?? 0 : state.variables[part.name] === undefined ? 0 : 1));
|
|
20492
20936
|
const values = await this.arrayMembers(part.name, state, io, selector.kind === "keys" || part.keys === true, part.substring);
|
|
20493
|
-
const space = (selector.kind === "keys" || part.keys === true)
|
|
20937
|
+
const space = (selector.kind === "keys" || part.keys === true) ? Boolean(hereDocument || (selector.separator === "@" ? !part.quoted && !split || state.variables.IFS === "" : !part.quoted && split && state.variables.IFS === "")) : (!split && selector.separator === "@");
|
|
20494
20938
|
return this.arrayJoin(store.owner, values, space ? " " : this.ifsSeparator(state, io));
|
|
20495
20939
|
}
|
|
20496
20940
|
if (part.substring && (part.name === "@" || part.name === "*")) {
|
|
@@ -20504,7 +20948,7 @@ export class Runtime {
|
|
|
20504
20948
|
: part.name === "?" ? String(state.status)
|
|
20505
20949
|
: part.name === "-" ? `${state.allexport ? "a" : ""}${state.errexit ? "e" : ""}${state.noglob ? "f" : ""}${state.noexec ? "n" : ""}${state.nounset ? "u" : ""}${state.braceexpand !== false ? "B" : ""}${state.noclobber ? "C" : ""}`
|
|
20506
20950
|
: part.name === "#" ? String(state.positional.length)
|
|
20507
|
-
: part.name === "@" || part.name === "*" ? state.positional.join(hereString && (part.name === "@" || !part.quoted) ? " " : Array.from(state.variables.IFS ?? " ")[0] ?? "")
|
|
20951
|
+
: part.name === "@" || part.name === "*" ? state.positional.join(part.name === "@" && !split || hereString && (part.name === "@" || !part.quoted) ? " " : Array.from(state.variables.IFS ?? " ")[0] ?? "")
|
|
20508
20952
|
: /^0+$/u.test(part.name) ? state.arg0 ?? "virtual-bash"
|
|
20509
20953
|
: /^\d+$/u.test(part.name) ? state.positional[Number(part.name) - 1]
|
|
20510
20954
|
: 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);
|
|
@@ -20521,7 +20965,7 @@ export class Runtime {
|
|
|
20521
20965
|
else if (/^[0-9]+$/u.test(part.name))
|
|
20522
20966
|
retained = stateMonitor(state)?.positionals.get(String(Number(part.name) - 1), value) ?? value;
|
|
20523
20967
|
else if (part.name === "@" || part.name === "*") {
|
|
20524
|
-
const separator = hereString && (part.name === "@" || !part.quoted) ? " " : this.ifsSeparator(state, io);
|
|
20968
|
+
const separator = part.name === "@" && !split || hereString && (part.name === "@" || !part.quoted) ? " " : this.ifsSeparator(state, io);
|
|
20525
20969
|
const values = this.positionalValues(state);
|
|
20526
20970
|
retained = concatShellValues(values.flatMap((entry, index) => index ? [separator, entry] : [entry]), io[valueScope]);
|
|
20527
20971
|
}
|
|
@@ -21061,7 +21505,7 @@ export class Runtime {
|
|
|
21061
21505
|
}
|
|
21062
21506
|
const ifsVal = monitor?.values.get("IFS", rawVars.IFS ?? " ") ?? rawVars.IFS ?? " ";
|
|
21063
21507
|
if (validElemOp && typeof ifsVal === "string" && (ifsVal.length === 0 || ifsVal.charCodeAt(0) < 128)) {
|
|
21064
|
-
const sep = selector.separator === "@" ? " " : ifsVal.length > 0 ? ifsVal[0] : "";
|
|
21508
|
+
const sep = selector.separator === "@" && (!isKeys || ifsVal.length === 0) ? " " : ifsVal.length > 0 ? ifsVal[0] : "";
|
|
21065
21509
|
const evalSliceInt = (w) => {
|
|
21066
21510
|
if (w.parts.length === 0)
|
|
21067
21511
|
return 0;
|
|
@@ -21574,7 +22018,10 @@ export class Runtime {
|
|
|
21574
22018
|
out += converted;
|
|
21575
22019
|
continue;
|
|
21576
22020
|
}
|
|
21577
|
-
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))) {
|
|
22021
|
+
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))) {
|
|
22022
|
+
const isAssignOp = part.operator === "=" || part.operator === ":=";
|
|
22023
|
+
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))))
|
|
22024
|
+
return undefined;
|
|
21578
22025
|
const raw = rawVars[part.name];
|
|
21579
22026
|
const cur = raw === undefined ? undefined : (this._syncArithRawWriteOnly && this._syncArithTouched?.has(part.name) ? raw : (monitor?.values.get(part.name, raw) ?? raw));
|
|
21580
22027
|
if (cur !== undefined && typeof cur !== "string")
|
|
@@ -21592,11 +22039,25 @@ export class Runtime {
|
|
|
21592
22039
|
resolvedScalar = "";
|
|
21593
22040
|
}
|
|
21594
22041
|
else {
|
|
21595
|
-
const isMissing = cur === undefined || (part.operator === ":-" && cur === "");
|
|
22042
|
+
const isMissing = cur === undefined || ((part.operator === ":-" || part.operator === ":=") && cur === "");
|
|
21596
22043
|
if (isMissing) {
|
|
21597
22044
|
const altVal = this.fastValueWord(part.alternate, rawState, io, false, false, false, false, undefined, part.line ?? overrideDiagnosticLine);
|
|
21598
22045
|
if (typeof altVal !== "string")
|
|
21599
22046
|
return undefined;
|
|
22047
|
+
if (isAssignOp) {
|
|
22048
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
22049
|
+
rawState.variables[part.name] = altVal;
|
|
22050
|
+
this._syncArithTouched.add(part.name);
|
|
22051
|
+
}
|
|
22052
|
+
else if (monitor) {
|
|
22053
|
+
monitor.publishStringVariable(part.name, altVal);
|
|
22054
|
+
}
|
|
22055
|
+
else {
|
|
22056
|
+
rawState.variables[part.name] = altVal;
|
|
22057
|
+
}
|
|
22058
|
+
if (rawState.allexport)
|
|
22059
|
+
(monitor ? monitor.proxy.exported : rawState.exported).add(part.name);
|
|
22060
|
+
}
|
|
21600
22061
|
resolvedScalar = altVal;
|
|
21601
22062
|
}
|
|
21602
22063
|
else
|