@poe-platform/safe-bash 0.1.737 → 0.1.738
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/safe-bash/chunks/{chunk-ZFV5FGGH.js → chunk-E2FTAYLG.js} +15 -16
- package/dist/safe-bash/chunks/{chunk-ZFV5FGGH.js.map → chunk-E2FTAYLG.js.map} +2 -2
- package/dist/safe-bash/chunks/{chunk-DFNSXDHP.js → chunk-JNHKE26E.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-N3RTTKMA.js → chunk-JTKTBT3B.js} +2 -2
- package/dist/safe-bash/command-assets/git_rust-NOIGQE52.wasm +0 -0
- package/dist/safe-bash/command-chunks/{chunk-L6GGCZOK.js → chunk-5EOMWWKN.js} +16 -15
- package/dist/safe-bash/command-chunks/chunk-5EOMWWKN.js.map +7 -0
- package/dist/safe-bash/command-chunks/{chunk-YXAPLUY4.js → chunk-WFMUMKBQ.js} +2 -2
- package/dist/safe-bash/core.browser.js +443 -180
- package/dist/safe-bash/core.browser.js.map +3 -3
- package/dist/safe-bash/shell/runtime.d.ts +3 -0
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +540 -205
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/dist/safe-bash-command-git/index.js +1 -1
- package/dist/safe-bash-regex-engine/index.js +2 -2
- package/dist/safe-bash-regex-engine/text/regex.js +2 -2
- package/dist/safe-bash-regex-engine/text/replacement-buffer.js +1 -1
- package/package.json +2 -2
- package/dist/safe-bash/command-assets/git_rust-CB24IEB6.wasm +0 -0
- package/dist/safe-bash/command-chunks/chunk-L6GGCZOK.js.map +0 -7
- /package/dist/safe-bash/chunks/{chunk-DFNSXDHP.js.map → chunk-JNHKE26E.js.map} +0 -0
- /package/dist/safe-bash/chunks/{chunk-N3RTTKMA.js.map → chunk-JTKTBT3B.js.map} +0 -0
- /package/dist/safe-bash/command-chunks/{chunk-YXAPLUY4.js.map → chunk-WFMUMKBQ.js.map} +0 -0
|
@@ -2098,6 +2098,32 @@ function hasActiveVariableAttributes(state) {
|
|
|
2098
2098
|
}
|
|
2099
2099
|
return false;
|
|
2100
2100
|
}
|
|
2101
|
+
function hasNonNamerefAttributes(state) {
|
|
2102
|
+
const attrs = state.variableAttributes;
|
|
2103
|
+
if (!attrs || attrs.size === 0)
|
|
2104
|
+
return false;
|
|
2105
|
+
for (const [k, val] of attrs.entries()) {
|
|
2106
|
+
if (val.length === 0)
|
|
2107
|
+
continue;
|
|
2108
|
+
if (val !== "n")
|
|
2109
|
+
return true;
|
|
2110
|
+
const ref = state.variables[k];
|
|
2111
|
+
if (!ref || !isShellIdentifier(ref) || ref === k || attrs.get(ref))
|
|
2112
|
+
return true;
|
|
2113
|
+
}
|
|
2114
|
+
return false;
|
|
2115
|
+
}
|
|
2116
|
+
function resolveSyncNameref(state, name) {
|
|
2117
|
+
const attrs = state.variableAttributes;
|
|
2118
|
+
if (!attrs || attrs.size === 0)
|
|
2119
|
+
return name;
|
|
2120
|
+
if (attrs.get(name) === "n") {
|
|
2121
|
+
const ref = state.variables[name];
|
|
2122
|
+
if (ref && isShellIdentifier(ref) && ref !== name && !attrs.get(ref))
|
|
2123
|
+
return ref;
|
|
2124
|
+
}
|
|
2125
|
+
return name;
|
|
2126
|
+
}
|
|
2101
2127
|
function publishVariable(state, name, value) {
|
|
2102
2128
|
const monitor = stateMonitor(state);
|
|
2103
2129
|
if (monitor) {
|
|
@@ -3408,6 +3434,7 @@ function resolveSimpleArithOperand(tok, rawState, monitor, activeArrayStore, syn
|
|
|
3408
3434
|
}
|
|
3409
3435
|
tok = c1 === 123 ? tok.slice(2, -1) : tok.slice(1);
|
|
3410
3436
|
}
|
|
3437
|
+
tok = resolveSyncNameref(rawState, tok);
|
|
3411
3438
|
if (rawState.nounset || activeArrayStore?.bindings.has(tok) || monitor?.hasOverlay(tok) || activeArrayStore?.watches.has(tok))
|
|
3412
3439
|
return undefined;
|
|
3413
3440
|
const raw = rawState.variables[tok];
|
|
@@ -4218,8 +4245,12 @@ export class Runtime {
|
|
|
4218
4245
|
return {
|
|
4219
4246
|
isSync: true, resolve: (variable, subscript) => {
|
|
4220
4247
|
this.signal.throwIfAborted();
|
|
4221
|
-
if (this._syncArithState.variableAttributes?.get(variable)?.includes("n"))
|
|
4222
|
-
|
|
4248
|
+
if (this._syncArithState.variableAttributes?.get(variable)?.includes("n")) {
|
|
4249
|
+
const resolved = resolveSyncNameref(this._syncArithState, variable);
|
|
4250
|
+
if (resolved === variable)
|
|
4251
|
+
throw new ArrayFailure("nameref in sync arithmetic");
|
|
4252
|
+
variable = resolved;
|
|
4253
|
+
}
|
|
4223
4254
|
if (subscript !== undefined) {
|
|
4224
4255
|
let resolvedSub = subscript;
|
|
4225
4256
|
if (resolvedSub.charCodeAt(0) === 36 && /^\$[a-zA-Z_][a-zA-Z_0-9]*$/.test(resolvedSub)) {
|
|
@@ -4402,15 +4433,16 @@ export class Runtime {
|
|
|
4402
4433
|
}
|
|
4403
4434
|
}
|
|
4404
4435
|
canSyncArithmeticOperands(tree, state, line, depth = 0) {
|
|
4405
|
-
if (!tree || depth > 128 ||
|
|
4436
|
+
if (!tree || depth > 128 || hasNonNamerefAttributes(state) || state.readonlyVariables?.size)
|
|
4406
4437
|
return false;
|
|
4407
4438
|
switch (tree.kind) {
|
|
4408
4439
|
case "literal": return true;
|
|
4409
4440
|
case "name": {
|
|
4410
|
-
|
|
4441
|
+
const effName = resolveSyncNameref(state, tree.name);
|
|
4442
|
+
if (effName === "OPTIND" || effName === "PIPESTATUS")
|
|
4411
4443
|
return false;
|
|
4412
4444
|
const monitor = stateMonitor(state);
|
|
4413
|
-
if (monitor?.hasOverlay(
|
|
4445
|
+
if (monitor?.hasOverlay(effName) || monitor?.store?.watches.has(effName))
|
|
4414
4446
|
return false;
|
|
4415
4447
|
if (tree.subscript !== undefined) {
|
|
4416
4448
|
if (state.nounset || hasUnpreparedLocal(state, tree.name))
|
|
@@ -4728,6 +4760,8 @@ export class Runtime {
|
|
|
4728
4760
|
const binding = arrayStore(state)?.get(name);
|
|
4729
4761
|
if (binding)
|
|
4730
4762
|
return binding.get(binding.associative ? binding.keys.get("30")?.index ?? -1 : 0);
|
|
4763
|
+
if (name === "DIRSTACK")
|
|
4764
|
+
return state.cwd;
|
|
4731
4765
|
if (name === "FUNCNAME" && state.variables.FUNCNAME === undefined)
|
|
4732
4766
|
return state.functionNames?.[0];
|
|
4733
4767
|
if (name === "_" && state.variables._ === undefined)
|
|
@@ -4771,14 +4805,14 @@ export class Runtime {
|
|
|
4771
4805
|
if (bracket < 0)
|
|
4772
4806
|
return entries ? entries[0] !== undefined : this.variable(state, base) !== undefined;
|
|
4773
4807
|
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
4808
|
if (binding?.associative) {
|
|
4777
4809
|
if (selector.length === 0 || selector.length > 4096 || [...selector].some(character => "$`\\\"'".includes(character)))
|
|
4778
4810
|
return undefined;
|
|
4779
4811
|
const key = binding.keys.get(fastStringHexIdentity(selector));
|
|
4780
4812
|
return key !== undefined && binding.getValue(key.index) !== undefined;
|
|
4781
4813
|
}
|
|
4814
|
+
if (selector === "@" || selector === "*")
|
|
4815
|
+
return entries ? entries.length > 0 : binding ? binding.values.size > 0 : this.variable(state, base) !== undefined;
|
|
4782
4816
|
if (selector.length === 0 || selector.length > 9 || [...selector].some(character => !"0123456789".includes(character)) || selector.length > 1 && selector[0] === "0")
|
|
4783
4817
|
return undefined;
|
|
4784
4818
|
const index = Number(selector);
|
|
@@ -5241,24 +5275,162 @@ export class Runtime {
|
|
|
5241
5275
|
}
|
|
5242
5276
|
}
|
|
5243
5277
|
}
|
|
5278
|
+
canSyncArrayMembersWord(w, rawState) {
|
|
5279
|
+
if (rawState.nounset)
|
|
5280
|
+
return false;
|
|
5281
|
+
const p0 = w.parts.length === 1 ? w.parts[0] : (w.parts.length === 2 && w.parts[0].kind === "text" && w.parts[0].value === "" ? w.parts[1] : undefined);
|
|
5282
|
+
if (!p0)
|
|
5283
|
+
return false;
|
|
5284
|
+
if (p0.kind !== "variable" || !p0.quoted || p0.indirect || p0.prefixNames || p0.length || p0.transform || p0.operator !== undefined)
|
|
5285
|
+
return false;
|
|
5286
|
+
const sel0 = getArraySelector(p0);
|
|
5287
|
+
if (!sel0 || (sel0.kind !== "members" && sel0.kind !== "keys") || sel0.separator !== "@")
|
|
5288
|
+
return false;
|
|
5289
|
+
if (p0.substring) {
|
|
5290
|
+
if (sel0.kind !== "members" || p0.keys)
|
|
5291
|
+
return false;
|
|
5292
|
+
const b = stateMonitor(rawState)?.store?.get(resolveSyncNameref(rawState, p0.name));
|
|
5293
|
+
if (b && b.associative)
|
|
5294
|
+
return false;
|
|
5295
|
+
if (!this.isPureSyncValueWord(p0.substring.offset, rawState))
|
|
5296
|
+
return false;
|
|
5297
|
+
if (p0.substring.length && !this.isPureSyncValueWord(p0.substring.length, rawState))
|
|
5298
|
+
return false;
|
|
5299
|
+
}
|
|
5300
|
+
return true;
|
|
5301
|
+
}
|
|
5302
|
+
tryExpandSyncArrayMembersWord(w, rawState, io, diagnosticLine) {
|
|
5303
|
+
if (rawState.nounset)
|
|
5304
|
+
return undefined;
|
|
5305
|
+
const p0 = w.parts.length === 1 ? w.parts[0] : (w.parts.length === 2 && w.parts[0].kind === "text" && w.parts[0].value === "" ? w.parts[1] : undefined);
|
|
5306
|
+
if (!p0)
|
|
5307
|
+
return undefined;
|
|
5308
|
+
if (p0.kind !== "variable" || !p0.quoted || p0.indirect || p0.prefixNames || p0.length || p0.transform || p0.operator !== undefined)
|
|
5309
|
+
return undefined;
|
|
5310
|
+
const sel0 = getArraySelector(p0);
|
|
5311
|
+
if (!sel0 || (sel0.kind !== "members" && sel0.kind !== "keys") || sel0.separator !== "@")
|
|
5312
|
+
return undefined;
|
|
5313
|
+
const monitor = stateMonitor(rawState);
|
|
5314
|
+
const activeStore = monitor?.store ?? arrayStore(rawState);
|
|
5315
|
+
const resolvedName = resolveSyncNameref(rawState, p0.name);
|
|
5316
|
+
const b = activeStore?.get(resolvedName);
|
|
5317
|
+
if (p0.substring) {
|
|
5318
|
+
if (sel0.kind !== "members" || p0.keys || (b && b.associative))
|
|
5319
|
+
return undefined;
|
|
5320
|
+
if (b && b.maximum >= 4096)
|
|
5321
|
+
return undefined;
|
|
5322
|
+
const evalSliceInt = (sw) => {
|
|
5323
|
+
if (sw.parts.length === 0)
|
|
5324
|
+
return 0;
|
|
5325
|
+
let expanded;
|
|
5326
|
+
try {
|
|
5327
|
+
expanded = this.fastValueWord(sw, rawState, io, false, false, false, false, undefined, diagnosticLine);
|
|
5328
|
+
}
|
|
5329
|
+
catch {
|
|
5330
|
+
return undefined;
|
|
5331
|
+
}
|
|
5332
|
+
if (typeof expanded !== "string")
|
|
5333
|
+
return undefined;
|
|
5334
|
+
const trimmed = expanded.trim();
|
|
5335
|
+
if (trimmed.length === 0)
|
|
5336
|
+
return 0;
|
|
5337
|
+
const syncTouched = this._syncArithRawWriteOnly ? this._syncArithTouched : undefined;
|
|
5338
|
+
const directOp = resolveSimpleArithOperand(trimmed, rawState, monitor, activeStore, syncTouched);
|
|
5339
|
+
if (directOp !== undefined)
|
|
5340
|
+
return directOp;
|
|
5341
|
+
const simpleExpr = tryEvalSimpleExpandedArith(trimmed, rawState, monitor, activeStore, syncTouched);
|
|
5342
|
+
if (simpleExpr !== undefined)
|
|
5343
|
+
return Number(simpleExpr);
|
|
5344
|
+
return undefined;
|
|
5345
|
+
};
|
|
5346
|
+
const offNum = evalSliceInt(p0.substring.offset);
|
|
5347
|
+
if (offNum === undefined)
|
|
5348
|
+
return undefined;
|
|
5349
|
+
let maxCount = Infinity;
|
|
5350
|
+
if (p0.substring.length) {
|
|
5351
|
+
const lenNum = evalSliceInt(p0.substring.length);
|
|
5352
|
+
if (lenNum === undefined || lenNum < 0)
|
|
5353
|
+
return undefined;
|
|
5354
|
+
maxCount = lenNum;
|
|
5355
|
+
}
|
|
5356
|
+
if (!b) {
|
|
5357
|
+
const sv = rawState.variables[resolvedName];
|
|
5358
|
+
if (sv === undefined)
|
|
5359
|
+
return [];
|
|
5360
|
+
const mv = (this._syncArithRawWriteOnly && this._syncArithTouched?.has(resolvedName)) ? sv : (monitor?.values.get(resolvedName, sv) ?? sv);
|
|
5361
|
+
if (typeof mv !== "string")
|
|
5362
|
+
return undefined;
|
|
5363
|
+
const startIdx = offNum < 0 ? 1 + offNum : offNum;
|
|
5364
|
+
if (startIdx < 0 || startIdx > 0 || maxCount === 0)
|
|
5365
|
+
return [];
|
|
5366
|
+
return [mv];
|
|
5367
|
+
}
|
|
5368
|
+
if (b.values.size === 0 || maxCount === 0)
|
|
5369
|
+
return [];
|
|
5370
|
+
const startIdx = offNum < 0 ? b.maximum + 1 + offNum : offNum;
|
|
5371
|
+
if (startIdx < 0)
|
|
5372
|
+
return [];
|
|
5373
|
+
const out = [];
|
|
5374
|
+
for (let k = startIdx; k <= b.maximum && out.length < maxCount; k++) {
|
|
5375
|
+
const slot = b.values.get(k);
|
|
5376
|
+
if (!slot)
|
|
5377
|
+
continue;
|
|
5378
|
+
const v = slot.text.shellValue;
|
|
5379
|
+
if (typeof v !== "string")
|
|
5380
|
+
return undefined;
|
|
5381
|
+
out.push(v);
|
|
5382
|
+
}
|
|
5383
|
+
return out;
|
|
5384
|
+
}
|
|
5385
|
+
const isKeys = sel0.kind === "keys" || p0.keys === true;
|
|
5386
|
+
if (b) {
|
|
5387
|
+
if (b.maximum >= 4096)
|
|
5388
|
+
return undefined;
|
|
5389
|
+
const out = [];
|
|
5390
|
+
for (let k = 0; k <= b.maximum; k++) {
|
|
5391
|
+
const slot = b.values.get(k);
|
|
5392
|
+
if (!slot)
|
|
5393
|
+
continue;
|
|
5394
|
+
const v = isKeys ? (b.associative ? b.keys.get(b.keyByIndex.get(k))?.text.shellValue : String(k)) : slot.text.shellValue;
|
|
5395
|
+
if (typeof v !== "string")
|
|
5396
|
+
return undefined;
|
|
5397
|
+
out.push(v);
|
|
5398
|
+
}
|
|
5399
|
+
return out;
|
|
5400
|
+
}
|
|
5401
|
+
const sv = rawState.variables[resolvedName];
|
|
5402
|
+
if (sv === undefined)
|
|
5403
|
+
return [];
|
|
5404
|
+
if (isKeys)
|
|
5405
|
+
return ["0"];
|
|
5406
|
+
const mv = (this._syncArithRawWriteOnly && this._syncArithTouched?.has(resolvedName)) ? sv : (monitor?.values.get(resolvedName, sv) ?? sv);
|
|
5407
|
+
if (typeof mv !== "string")
|
|
5408
|
+
return undefined;
|
|
5409
|
+
return [mv];
|
|
5410
|
+
}
|
|
5244
5411
|
tryFastArrayAssignmentSync(assignment, state, io, diagnosticLine, declaration, associative, ignoreYield = false) {
|
|
5245
5412
|
if (!ignoreYield && hasYieldCheckpoint(this.signal))
|
|
5246
5413
|
return false;
|
|
5247
5414
|
if (declaration)
|
|
5248
5415
|
return false;
|
|
5416
|
+
const monitor = stateMonitor(state);
|
|
5417
|
+
const rawState = monitor ? monitor.raw : state;
|
|
5249
5418
|
// Array writes must prepare scope observers before creating or mutating bindings.
|
|
5250
|
-
const name = assignment.name;
|
|
5419
|
+
const name = resolveSyncNameref(rawState, assignment.name);
|
|
5251
5420
|
if (hasUnpreparedLocal(state, name))
|
|
5252
5421
|
return false;
|
|
5253
5422
|
this._syncArithTouched?.delete(name);
|
|
5254
|
-
const monitor = stateMonitor(state);
|
|
5255
|
-
const rawState = monitor ? monitor.raw : state;
|
|
5256
5423
|
if (rawState.readonlyVariables?.has(name) || rawState.variableAttributes?.get(name) || rawState.exported.has(name) || controlNames.has(name)) {
|
|
5257
5424
|
return false;
|
|
5258
5425
|
}
|
|
5259
5426
|
// Cold activation belongs to normal command handling, which maps array refusals.
|
|
5260
5427
|
const store = monitor?.store ?? (monitor && (this.budget.limits.maxExpansionBytes === Infinity && this.budget.limits.maxExpansionFields === Infinity) ? requireArrays(rawState) : undefined);
|
|
5261
5428
|
let current = store?.get(name);
|
|
5429
|
+
if (assignment.kind === "compound" && !(associative ?? current?.associative) && state.braceexpand !== false && assignment.entries.some(entry => {
|
|
5430
|
+
const original = compoundEntryWords.get(entry);
|
|
5431
|
+
return entry.index !== undefined && original?.parts.some(part => part.kind === "text" && !part.quoted && part.value.includes("{"));
|
|
5432
|
+
}))
|
|
5433
|
+
return false;
|
|
5262
5434
|
if (!monitor || !store || store.watches.has(name) || monitor.hasOverlay(name) || (current && (current.references !== 1 || (associative !== undefined && current.associative !== associative))) || (!current && rawState.variables[name] !== undefined)) {
|
|
5263
5435
|
return false;
|
|
5264
5436
|
}
|
|
@@ -5355,6 +5527,8 @@ export class Runtime {
|
|
|
5355
5527
|
const entry = assignment.entries[i];
|
|
5356
5528
|
if (entry.append)
|
|
5357
5529
|
return false;
|
|
5530
|
+
if (rawState.braceexpand !== false && entry.value.parts.some(p => !p.quoted && p.kind === "text" && p.value.includes("{")))
|
|
5531
|
+
return false;
|
|
5358
5532
|
let explicitIdx;
|
|
5359
5533
|
if (entry.index !== undefined) {
|
|
5360
5534
|
const kSrc = (entry.index.source ?? entry.index.decimal).trim();
|
|
@@ -5362,8 +5536,21 @@ export class Runtime {
|
|
|
5362
5536
|
return false;
|
|
5363
5537
|
explicitIdx = Number(kSrc);
|
|
5364
5538
|
}
|
|
5365
|
-
else
|
|
5366
|
-
|
|
5539
|
+
else {
|
|
5540
|
+
const expandedArr = this.tryExpandSyncArrayMembersWord(entry.value, rawState, io, diagnosticLine);
|
|
5541
|
+
if (expandedArr !== undefined) {
|
|
5542
|
+
for (let mIdx = 0; mIdx < expandedArr.length; mIdx++) {
|
|
5543
|
+
const mVal = expandedArr[mIdx];
|
|
5544
|
+
const bLen = shellValueByteLength(mVal);
|
|
5545
|
+
if (bLen > this.budget.limits.maxExpansionBytes)
|
|
5546
|
+
return false;
|
|
5547
|
+
items.push({ explicitIdx: undefined, val: mVal, bLen });
|
|
5548
|
+
}
|
|
5549
|
+
continue;
|
|
5550
|
+
}
|
|
5551
|
+
if (entry.value.parts.length === 0 || !entry.value.parts.every(p => p.quoted || (p.kind === "text" && p.value.length > 0 && !p.value.includes(" ") && !p.value.includes("\t") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)))) {
|
|
5552
|
+
return false;
|
|
5553
|
+
}
|
|
5367
5554
|
}
|
|
5368
5555
|
let val = "";
|
|
5369
5556
|
if (entry.value.parts.length > 0) {
|
|
@@ -6294,6 +6481,9 @@ export class Runtime {
|
|
|
6294
6481
|
if (!watch.valid())
|
|
6295
6482
|
throw new ArrayFailure("binding changed during writer admission");
|
|
6296
6483
|
prepared.validate();
|
|
6484
|
+
// Clearing an indexed destination is an assignment even without elements.
|
|
6485
|
+
if (clear)
|
|
6486
|
+
prepared.binding.assigned = true;
|
|
6297
6487
|
let retirement;
|
|
6298
6488
|
monitor.publish(prepared.tickets, name, () => {
|
|
6299
6489
|
delete state.variables[name];
|
|
@@ -8268,16 +8458,8 @@ export class Runtime {
|
|
|
8268
8458
|
return true;
|
|
8269
8459
|
}
|
|
8270
8460
|
}
|
|
8271
|
-
|
|
8272
|
-
|
|
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
|
-
}
|
|
8461
|
+
// mapfile can require the asynchronous path as its input or binding
|
|
8462
|
+
// changes. Never speculate across a loop that has already made writes.
|
|
8281
8463
|
}
|
|
8282
8464
|
return false;
|
|
8283
8465
|
}
|
|
@@ -8311,7 +8493,7 @@ export class Runtime {
|
|
|
8311
8493
|
return false;
|
|
8312
8494
|
}
|
|
8313
8495
|
if (arrayAssign.kind === "compound") {
|
|
8314
|
-
const isAssoc = Boolean(st?.get(arrayAssign.name)?.associative);
|
|
8496
|
+
const isAssoc = Boolean(st?.get(resolveSyncNameref(rawState, arrayAssign.name))?.associative);
|
|
8315
8497
|
return (arrayAssign.entries.length <= 32 && arrayAssign.entries.every(e => {
|
|
8316
8498
|
if (e.append)
|
|
8317
8499
|
return false;
|
|
@@ -8323,6 +8505,8 @@ export class Runtime {
|
|
|
8323
8505
|
const kSrc = (e.index.source ?? e.index.decimal).trim();
|
|
8324
8506
|
return /^(?:0|[1-9][0-9]{0,8})$/.test(kSrc) && isNoBraceSyncAssignWord(e.value);
|
|
8325
8507
|
}
|
|
8508
|
+
if (this.canSyncArrayMembersWord(e.value, rawState))
|
|
8509
|
+
return true;
|
|
8326
8510
|
return isNoBraceSyncWord(e.value) && e.value.parts.length > 0 && e.value.parts.every(p => p.quoted || (p.kind === "text" && p.value.length > 0 && !p.value.includes(" ") && !p.value.includes("\t") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)));
|
|
8327
8511
|
}));
|
|
8328
8512
|
}
|
|
@@ -8356,7 +8540,7 @@ export class Runtime {
|
|
|
8356
8540
|
}
|
|
8357
8541
|
if (command.words.length >= 2 && command.words.length <= 16) {
|
|
8358
8542
|
if (w0Plain === "unset" &&
|
|
8359
|
-
rawState.locals.length === 0 &&
|
|
8543
|
+
depth === 0 && rawState.locals.length === 0 &&
|
|
8360
8544
|
!hasShellFunction(rawState, "unset") &&
|
|
8361
8545
|
!rawState.extensions?.builtins.has("unset")) {
|
|
8362
8546
|
const uStart = command.words[1]?.plain === "-v" ? 2 : 1;
|
|
@@ -8380,6 +8564,7 @@ export class Runtime {
|
|
|
8380
8564
|
}
|
|
8381
8565
|
if (w0Plain === "export" &&
|
|
8382
8566
|
rawState.locals.length === 0 &&
|
|
8567
|
+
depth === 0 &&
|
|
8383
8568
|
!hasShellFunction(rawState, "export") &&
|
|
8384
8569
|
!rawState.extensions?.builtins.has("export")) {
|
|
8385
8570
|
let allOk = true;
|
|
@@ -8446,12 +8631,14 @@ export class Runtime {
|
|
|
8446
8631
|
// Array locals require the typed declaration and restoration lifecycle.
|
|
8447
8632
|
if (command.words[1]?.plain === "-a" || command.words[1]?.plain === "-A")
|
|
8448
8633
|
return false;
|
|
8634
|
+
const isNamerefDecl = command.words[1]?.plain === "-n" && (rawState.locals.length > 0 || depth > 0) && command.words.length >= 3;
|
|
8635
|
+
const isGlobalDecl = command.words[1]?.plain === "-g" && (w0Plain === "declare" || w0Plain === "typeset") && command.words.length >= 3;
|
|
8449
8636
|
let allValidLocal = true;
|
|
8450
|
-
for (let idx = 1; idx < command.words.length; idx++) {
|
|
8637
|
+
for (let idx = (isNamerefDecl || isGlobalDecl) ? 2 : 1; idx < command.words.length; idx++) {
|
|
8451
8638
|
const wArg = command.words[idx];
|
|
8452
8639
|
const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : undefined;
|
|
8453
8640
|
if (assignment) {
|
|
8454
|
-
if ((assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND"))) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
|
|
8641
|
+
if ((!isNamerefDecl && rawState.variableAttributes?.get(assignment.name)) || (assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND"))) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || !isNoBraceSyncAssignWord(assignment.value)) {
|
|
8455
8642
|
allValidLocal = false;
|
|
8456
8643
|
break;
|
|
8457
8644
|
}
|
|
@@ -8467,12 +8654,10 @@ export class Runtime {
|
|
|
8467
8654
|
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
8655
|
return true;
|
|
8469
8656
|
}
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
}
|
|
8475
|
-
}
|
|
8657
|
+
// The scanner may require diagnostics or exceed its synchronous bounds.
|
|
8658
|
+
// Falling back after an earlier loop iteration would replay its effects.
|
|
8659
|
+
if (w0Plain === "getopts")
|
|
8660
|
+
return false;
|
|
8476
8661
|
if (w0Plain === "echo" && !hasShellFunction(rawState, "echo") && !rawState.extensions?.builtins.has("echo")) {
|
|
8477
8662
|
const w1Plain = command.words[1]?.plain;
|
|
8478
8663
|
if (w1Plain === undefined || !w1Plain.startsWith("-") || w1Plain === "-n" || w1Plain === "-e" || w1Plain === "-ne" || w1Plain === "-en")
|
|
@@ -8503,7 +8688,17 @@ export class Runtime {
|
|
|
8503
8688
|
}
|
|
8504
8689
|
if (w0Plain !== undefined && rawState.functions.has(w0Plain) && command.words.slice(1).every(isNoBraceSyncWord)) {
|
|
8505
8690
|
const fnBody = rawState.functions.get(w0Plain);
|
|
8506
|
-
|
|
8691
|
+
if (fnBody.kind !== "group" || fnBody.redirects.length !== 0)
|
|
8692
|
+
return false;
|
|
8693
|
+
rawState.locals.push(new Map());
|
|
8694
|
+
rawState.functionDepth++;
|
|
8695
|
+
try {
|
|
8696
|
+
return this.canSyncScriptCompound(fnBody.body, rawState, depth + 1);
|
|
8697
|
+
}
|
|
8698
|
+
finally {
|
|
8699
|
+
rawState.functionDepth--;
|
|
8700
|
+
rawState.locals.pop();
|
|
8701
|
+
}
|
|
8507
8702
|
}
|
|
8508
8703
|
return false;
|
|
8509
8704
|
}
|
|
@@ -8597,13 +8792,13 @@ export class Runtime {
|
|
|
8597
8792
|
const sel0 = p0?.kind === "variable" ? getArraySelector(p0) : undefined;
|
|
8598
8793
|
const isArrAt = Boolean(p0?.kind === "variable" && p0.quoted && !p0.indirect && !p0.prefixNames && !p0.length && !p0.substring && !p0.transform && p0.operator === undefined && (sel0?.kind === "members" || sel0?.kind === "keys") && sel0.separator === "@");
|
|
8599
8794
|
const isBraceRange = Boolean(p0?.kind === "text" && !p0.quoted && /^\{-?\d+\.\.-?\d+(?:\.\.-?\d+)?\}$/.test(p0.value));
|
|
8600
|
-
if (!isArrAt && !isBraceRange && !(this.isPureSyncValueWord(w0, rawState) && w0.parts.every(p => p.quoted || (p.kind === "text" && !p.value.includes(" ") && !p.value.includes("\t") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)))))
|
|
8795
|
+
if (!isArrAt && !isBraceRange && !this.canSyncArrayMembersWord(w0, rawState) && !(this.isPureSyncValueWord(w0, rawState) && w0.parts.every(p => p.quoted || (p.kind === "text" && !p.value.includes(" ") && !p.value.includes("\t") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)))))
|
|
8601
8796
|
return false;
|
|
8602
8797
|
}
|
|
8603
8798
|
else {
|
|
8604
8799
|
for (let i = 0; i < command.words.length; i++) {
|
|
8605
8800
|
const w = command.words[i];
|
|
8606
|
-
if (!this.isPureSyncValueWord(w, rawState) || !w.parts.every(p => p.quoted || (p.kind === "text" && !p.value.includes(" ") && !p.value.includes("\t") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true))))
|
|
8801
|
+
if (!this.canSyncArrayMembersWord(w, rawState) && (!this.isPureSyncValueWord(w, rawState) || !w.parts.every(p => p.quoted || (p.kind === "text" && !p.value.includes(" ") && !p.value.includes("\t") && !p.value.includes("\n") && !p.value.includes("{") && !hasGlobOrEscape(p.value, true)))))
|
|
8607
8802
|
return false;
|
|
8608
8803
|
}
|
|
8609
8804
|
}
|
|
@@ -8710,7 +8905,9 @@ export class Runtime {
|
|
|
8710
8905
|
}
|
|
8711
8906
|
else if (wp0 === "local" || wp0 === "declare" || wp0 === "typeset") {
|
|
8712
8907
|
const isArrDecl = c.words[1]?.plain === "-a" || c.words[1]?.plain === "-A";
|
|
8713
|
-
|
|
8908
|
+
const isNameref = c.words[1]?.plain === "-n";
|
|
8909
|
+
const isGlobal = c.words[1]?.plain === "-g";
|
|
8910
|
+
for (let k = (isArrDecl || isNameref || isGlobal) ? 2 : 1; k < c.words.length; k++) {
|
|
8714
8911
|
const wk = c.words[k];
|
|
8715
8912
|
const aa = getArrayAssignment(wk);
|
|
8716
8913
|
if (aa) {
|
|
@@ -8727,6 +8924,9 @@ export class Runtime {
|
|
|
8727
8924
|
if (wp0 === "local" || d > 0)
|
|
8728
8925
|
localArrayVars.add(nm);
|
|
8729
8926
|
}
|
|
8927
|
+
else if (isNameref) {
|
|
8928
|
+
localArrayVars.add(nm);
|
|
8929
|
+
}
|
|
8730
8930
|
else {
|
|
8731
8931
|
scalarVars.add(nm);
|
|
8732
8932
|
const pv = asg?.value.plain;
|
|
@@ -8737,8 +8937,8 @@ export class Runtime {
|
|
|
8737
8937
|
}
|
|
8738
8938
|
}
|
|
8739
8939
|
}
|
|
8740
|
-
else if (wp0 === "printf" && c.words[1]?.plain === "-v" && c.words[2]?.plain) {
|
|
8741
|
-
const target = c.words[2].plain;
|
|
8940
|
+
else if (wp0 === "printf" && c.words[1]?.plain === "-v" && (c.words[2]?.plain || c.words[2]?.parts[0]?.kind === "text")) {
|
|
8941
|
+
const target = c.words[2].plain ?? c.words[2].parts[0].value;
|
|
8742
8942
|
const br = target.indexOf("[");
|
|
8743
8943
|
if (br > 0)
|
|
8744
8944
|
arrayVars.add(target.slice(0, br));
|
|
@@ -9101,7 +9301,24 @@ export class Runtime {
|
|
|
9101
9301
|
}
|
|
9102
9302
|
return undefined;
|
|
9103
9303
|
}
|
|
9104
|
-
|
|
9304
|
+
setSyncPipeStatusCell(existing, status) {
|
|
9305
|
+
const cell = existing.values.get(0);
|
|
9306
|
+
if (cell && cell.text.references === 1 && cell.text.bytes === status.length) {
|
|
9307
|
+
cell.text.shellValue = status;
|
|
9308
|
+
}
|
|
9309
|
+
else {
|
|
9310
|
+
existing.owner.chargeWork(status.length);
|
|
9311
|
+
const token = new OwnedText(status, status.length, existing.owner.reserve({ payload: status.length, metadata: 32, work: 4 }));
|
|
9312
|
+
try {
|
|
9313
|
+
existing.insert(0, token);
|
|
9314
|
+
}
|
|
9315
|
+
catch (error) {
|
|
9316
|
+
token.release();
|
|
9317
|
+
throw error;
|
|
9318
|
+
}
|
|
9319
|
+
}
|
|
9320
|
+
}
|
|
9321
|
+
finishSyncPipeStatus(rawState, monitor, store, existing, _elem0, scope, finalStatus, restEpoch) {
|
|
9105
9322
|
if (!existing) {
|
|
9106
9323
|
if (store) {
|
|
9107
9324
|
if (publishPipelineStatus(rawState, finalStatus === 0 ? singleStatusZero : singleStatusOne, this.signal, scope))
|
|
@@ -9113,7 +9330,7 @@ export class Runtime {
|
|
|
9113
9330
|
}
|
|
9114
9331
|
}
|
|
9115
9332
|
else {
|
|
9116
|
-
(
|
|
9333
|
+
this.setSyncPipeStatusCell(existing, finalStatus === 0 ? "0" : "1");
|
|
9117
9334
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
9118
9335
|
}
|
|
9119
9336
|
rawState.status = finalStatus;
|
|
@@ -9135,7 +9352,7 @@ export class Runtime {
|
|
|
9135
9352
|
return undefined;
|
|
9136
9353
|
const rawState = monitor.raw;
|
|
9137
9354
|
const gArrays = guestArrays(rawState);
|
|
9138
|
-
if (io.terminal || io.asyncDefaultInput || hasActiveExtensions(rawState) ||
|
|
9355
|
+
if (io.terminal || io.asyncDefaultInput || hasActiveExtensions(rawState) || hasNonNamerefAttributes(rawState) || (gArrays && gArrays.watches.size > 0))
|
|
9139
9356
|
return undefined;
|
|
9140
9357
|
if (((this.budget.commands + 1) & 127) === 0) {
|
|
9141
9358
|
if (hasYieldCheckpoint(this.signal) || (this._syncReturnDepth === 0 && ((this.budget.commands + 1) & 8191) === 0))
|
|
@@ -9178,10 +9395,10 @@ export class Runtime {
|
|
|
9178
9395
|
return undefined;
|
|
9179
9396
|
}
|
|
9180
9397
|
const elem0 = existing?.values.get(0);
|
|
9181
|
-
if (existing &&
|
|
9398
|
+
if (existing && !elem0)
|
|
9182
9399
|
return undefined;
|
|
9183
9400
|
const canMutatePipeStatus = !existing || (existing.references === 1 && elem0.text.references === 1);
|
|
9184
|
-
const diagnosticLine = io.diagnosticCommandLines?.get(command) ?? (command.line ?? 1) + (io.diagnosticOffset ?? 0);
|
|
9401
|
+
const diagnosticLine = io.diagnosticCommandLines?.get(command) ?? io.substitutionDiagnosticLines?.get(command) ?? (command.line ?? 1) + (io.diagnosticOffset ?? 0);
|
|
9185
9402
|
if (command.kind === "function") {
|
|
9186
9403
|
if (pipeline.negate || !canMutatePipeStatus || command.redirects.length > 0 || rawState.readonlyFunctions?.has(command.name) || (rawState.profile === "sh" && (specialBuiltinNames.has(command.name) || rawState.extensions?.builtins.get(command.name)?.special))) {
|
|
9187
9404
|
return undefined;
|
|
@@ -9244,7 +9461,7 @@ export class Runtime {
|
|
|
9244
9461
|
}
|
|
9245
9462
|
}
|
|
9246
9463
|
else {
|
|
9247
|
-
|
|
9464
|
+
this.setSyncPipeStatusCell(activeExisting, finalStatus === 0 ? "0" : "1");
|
|
9248
9465
|
activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
9249
9466
|
}
|
|
9250
9467
|
rawState.status = finalStatus;
|
|
@@ -9350,13 +9567,13 @@ export class Runtime {
|
|
|
9350
9567
|
}
|
|
9351
9568
|
const scalarMutMatch = fastSrc.length <= 64 ? SIMPLE_SCALAR_MUT_RE.exec(fastSrc) : null;
|
|
9352
9569
|
if (scalarMutMatch) {
|
|
9353
|
-
const varName = scalarMutMatch[1];
|
|
9570
|
+
const varName = resolveSyncNameref(rawState, scalarMutMatch[1]);
|
|
9354
9571
|
const binOp = scalarMutMatch[2];
|
|
9355
9572
|
const rhs1 = Number(scalarMutMatch[3]);
|
|
9356
9573
|
const rhsOp = scalarMutMatch[4];
|
|
9357
9574
|
const rhs2 = scalarMutMatch[5] !== undefined ? Number(scalarMutMatch[5]) : 0;
|
|
9358
9575
|
const rhsNum = rhsOp === "+" ? rhs1 + rhs2 : rhsOp === "-" ? rhs1 - rhs2 : rhsOp === "*" ? rhs1 * rhs2 : rhs1;
|
|
9359
|
-
if (varName !== "OPTIND" && varName !== "PIPESTATUS" && !store?.get(varName) && !
|
|
9576
|
+
if (varName !== "OPTIND" && varName !== "PIPESTATUS" && !store?.get(varName) && !hasNonNamerefAttributes(rawState)) {
|
|
9360
9577
|
const curVal = (this._syncArithRawWriteOnly && this._syncArithTouched?.has(varName))
|
|
9361
9578
|
? (rawState.variables[varName] ?? "0")
|
|
9362
9579
|
: (monitor.values.get(varName, rawState.variables[varName] ?? "0") ?? rawState.variables[varName] ?? "0");
|
|
@@ -9526,9 +9743,12 @@ export class Runtime {
|
|
|
9526
9743
|
}
|
|
9527
9744
|
return res;
|
|
9528
9745
|
}
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9746
|
+
if (!command._skipTrySyncLoop) {
|
|
9747
|
+
const fastLoopRes = this.trySyncLoop(command, pipeline, rawState, monitor, store, existing, elem0, canMutatePipeStatus, io, diagnosticLine);
|
|
9748
|
+
if (fastLoopRes !== undefined)
|
|
9749
|
+
return fastLoopRes;
|
|
9750
|
+
command._skipTrySyncLoop = true;
|
|
9751
|
+
}
|
|
9532
9752
|
}
|
|
9533
9753
|
if (command.kind === "group" || command.kind === "if" || command.kind === "case" || command.kind === "while" || command.kind === "until" || command.kind === "for" || command.kind === "arithmetic-for") {
|
|
9534
9754
|
if (command.redirects.length !== 0 || pipeline.negate || !canMutatePipeStatus || (!ignored && rawState.errexit) || rawState.nounset || rawState.readonlyVariables?.size || hasYieldCheckpoint(this.signal) || (this._syncReturnDepth === 0 && (((this.budget.commands + 32) & 8191) < 32 || !this.canSyncCommandCompound(command, rawState, 0, rawState.loopDepth)))) {
|
|
@@ -9750,10 +9970,10 @@ export class Runtime {
|
|
|
9750
9970
|
}
|
|
9751
9971
|
else if (command.words.length === 1) {
|
|
9752
9972
|
const w0 = command.words[0];
|
|
9753
|
-
|
|
9754
|
-
const p0 =
|
|
9973
|
+
items = this.tryExpandSyncArrayMembersWord(w0, rawState, io, diagnosticLine);
|
|
9974
|
+
const p0 = items ? undefined : (w0.parts.length === 1 ? w0.parts[0] : (w0.parts.length === 2 && w0.parts[0].kind === "text" && w0.parts[0].value === "" ? w0.parts[1] : undefined));
|
|
9755
9975
|
const sel0 = p0?.kind === "variable" ? getArraySelector(p0) : undefined;
|
|
9756
|
-
if (p0?.kind === "variable" && p0.quoted && (sel0?.kind === "members" || sel0?.kind === "keys") && sel0.separator === "@") {
|
|
9976
|
+
if (p0?.kind === "variable" && p0.quoted && !p0.substring && (sel0?.kind === "members" || sel0?.kind === "keys") && sel0.separator === "@") {
|
|
9757
9977
|
const b = monitor.store?.get(p0.name);
|
|
9758
9978
|
items = [];
|
|
9759
9979
|
if (b) {
|
|
@@ -9792,6 +10012,12 @@ export class Runtime {
|
|
|
9792
10012
|
if (!items && command.words) {
|
|
9793
10013
|
items = [];
|
|
9794
10014
|
for (let i = 0; i < command.words.length; i++) {
|
|
10015
|
+
const expandedArr = this.tryExpandSyncArrayMembersWord(command.words[i], rawState, io, diagnosticLine);
|
|
10016
|
+
if (expandedArr !== undefined) {
|
|
10017
|
+
for (let mIdx = 0; mIdx < expandedArr.length; mIdx++)
|
|
10018
|
+
items.push(expandedArr[mIdx]);
|
|
10019
|
+
continue;
|
|
10020
|
+
}
|
|
9795
10021
|
let fv;
|
|
9796
10022
|
try {
|
|
9797
10023
|
fv = this.fastValueWord(command.words[i], rawState, io, false, false, false, false, undefined, diagnosticLine);
|
|
@@ -9994,7 +10220,7 @@ export class Runtime {
|
|
|
9994
10220
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
9995
10221
|
}
|
|
9996
10222
|
else {
|
|
9997
|
-
|
|
10223
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
9998
10224
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
9999
10225
|
}
|
|
10000
10226
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -10091,7 +10317,7 @@ export class Runtime {
|
|
|
10091
10317
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10092
10318
|
}
|
|
10093
10319
|
else {
|
|
10094
|
-
|
|
10320
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
10095
10321
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10096
10322
|
}
|
|
10097
10323
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -10107,8 +10333,6 @@ export class Runtime {
|
|
|
10107
10333
|
if (w0Plain === "return" && (rawState.functionDepth > 0 || rawState.sourceDepth) && !hasActiveExtensions(rawState) && !hasShellFunction(rawState, "return") && !rawState.extensions?.builtins.has("return") && !pipeline.negate && canMutatePipeStatus) {
|
|
10108
10334
|
const retStatus = rawState.status;
|
|
10109
10335
|
const statusStr = retStatus === 0 ? "0" : retStatus === 1 ? "1" : String(retStatus);
|
|
10110
|
-
if (existing && elem0.text.bytes !== statusStr.length)
|
|
10111
|
-
return undefined;
|
|
10112
10336
|
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
10113
10337
|
this.budget.tick();
|
|
10114
10338
|
rawState.substitutionStatus = 0;
|
|
@@ -10122,7 +10346,7 @@ export class Runtime {
|
|
|
10122
10346
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10123
10347
|
}
|
|
10124
10348
|
else {
|
|
10125
|
-
|
|
10349
|
+
this.setSyncPipeStatusCell(existing, statusStr);
|
|
10126
10350
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10127
10351
|
}
|
|
10128
10352
|
rawState.status = retStatus;
|
|
@@ -10154,7 +10378,7 @@ export class Runtime {
|
|
|
10154
10378
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10155
10379
|
}
|
|
10156
10380
|
else {
|
|
10157
|
-
|
|
10381
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
10158
10382
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10159
10383
|
}
|
|
10160
10384
|
rawState.status = 0;
|
|
@@ -10186,7 +10410,7 @@ export class Runtime {
|
|
|
10186
10410
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10187
10411
|
}
|
|
10188
10412
|
else {
|
|
10189
|
-
|
|
10413
|
+
this.setSyncPipeStatusCell(existing, statusChar);
|
|
10190
10414
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10191
10415
|
}
|
|
10192
10416
|
rawState.status = finalStatus;
|
|
@@ -10227,7 +10451,7 @@ export class Runtime {
|
|
|
10227
10451
|
}
|
|
10228
10452
|
}
|
|
10229
10453
|
else {
|
|
10230
|
-
|
|
10454
|
+
this.setSyncPipeStatusCell(activeExisting, "0");
|
|
10231
10455
|
activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10232
10456
|
}
|
|
10233
10457
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -10239,14 +10463,15 @@ export class Runtime {
|
|
|
10239
10463
|
}
|
|
10240
10464
|
const assignment = this.assignment(w0);
|
|
10241
10465
|
if (assignment) {
|
|
10466
|
+
const targetAssignName = resolveSyncNameref(rawState, assignment.name);
|
|
10242
10467
|
const hasSubPart = assignment.value.parts.some(part => part.kind === "substitution");
|
|
10243
|
-
const existingArrAssign = store?.get(
|
|
10244
|
-
if ((
|
|
10245
|
-
|
|
10246
|
-
|
|
10468
|
+
const existingArrAssign = store?.get(targetAssignName);
|
|
10469
|
+
if ((targetAssignName === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND"))) ||
|
|
10470
|
+
targetAssignName === "PIPESTATUS" ||
|
|
10471
|
+
targetAssignName.includes("[") ||
|
|
10247
10472
|
(hasSubPart && !this.isPureSyncValueWord(assignment.value, rawState)) ||
|
|
10248
|
-
rawState.readonlyVariables?.has(
|
|
10249
|
-
(existingArrAssign && (assignment.append || hasUnpreparedLocal(rawState,
|
|
10473
|
+
rawState.readonlyVariables?.has(targetAssignName) ||
|
|
10474
|
+
(existingArrAssign && (assignment.append || hasUnpreparedLocal(rawState, targetAssignName) || rawState.exported.has(targetAssignName)))) {
|
|
10250
10475
|
return undefined;
|
|
10251
10476
|
}
|
|
10252
10477
|
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
@@ -10260,14 +10485,14 @@ export class Runtime {
|
|
|
10260
10485
|
}
|
|
10261
10486
|
if (typeof fastAssigned !== "string")
|
|
10262
10487
|
return undefined;
|
|
10263
|
-
if (
|
|
10488
|
+
if (targetAssignName === "OPTIND") {
|
|
10264
10489
|
const trimmedOptind = fastAssigned.trim();
|
|
10265
10490
|
if (!/^[0-9]{1,6}$/.test(trimmedOptind))
|
|
10266
10491
|
return undefined;
|
|
10267
10492
|
fastAssigned = String(Number(trimmedOptind));
|
|
10268
10493
|
}
|
|
10269
10494
|
if (existingArrAssign) {
|
|
10270
|
-
if (!this.tryFastArraySubscriptWriteSync(rawState,
|
|
10495
|
+
if (!this.tryFastArraySubscriptWriteSync(rawState, targetAssignName, "0", fastAssigned))
|
|
10271
10496
|
return undefined;
|
|
10272
10497
|
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
10273
10498
|
this.budget.tick();
|
|
@@ -10291,7 +10516,7 @@ export class Runtime {
|
|
|
10291
10516
|
}
|
|
10292
10517
|
}
|
|
10293
10518
|
else {
|
|
10294
|
-
|
|
10519
|
+
this.setSyncPipeStatusCell(activeExisting, "0");
|
|
10295
10520
|
activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10296
10521
|
}
|
|
10297
10522
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -10303,8 +10528,8 @@ export class Runtime {
|
|
|
10303
10528
|
}
|
|
10304
10529
|
let finalAssigned = fastAssigned;
|
|
10305
10530
|
if (assignment.append) {
|
|
10306
|
-
const curRaw = rawState.variables[
|
|
10307
|
-
const curStr = curRaw === undefined ? "" : (monitor.values.get(
|
|
10531
|
+
const curRaw = rawState.variables[targetAssignName];
|
|
10532
|
+
const curStr = curRaw === undefined ? "" : (monitor.values.get(targetAssignName, curRaw) ?? curRaw);
|
|
10308
10533
|
if (typeof curStr !== "string")
|
|
10309
10534
|
return undefined;
|
|
10310
10535
|
finalAssigned = curStr + finalAssigned;
|
|
@@ -10315,21 +10540,21 @@ export class Runtime {
|
|
|
10315
10540
|
this.budget.tick();
|
|
10316
10541
|
if (!hasSubPart)
|
|
10317
10542
|
rawState.substitutionStatus = 0;
|
|
10318
|
-
if (
|
|
10543
|
+
if (targetAssignName !== "_" && rawState.variables._ !== undefined)
|
|
10319
10544
|
delete rawState.variables._;
|
|
10320
10545
|
rawState.lastArgument = "";
|
|
10321
10546
|
if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
10322
|
-
rawState.variables[
|
|
10323
|
-
this._syncArithTouched.add(
|
|
10547
|
+
rawState.variables[targetAssignName] = finalAssigned;
|
|
10548
|
+
this._syncArithTouched.add(targetAssignName);
|
|
10324
10549
|
}
|
|
10325
10550
|
else
|
|
10326
|
-
monitor.publishStringVariable(
|
|
10327
|
-
if (
|
|
10551
|
+
monitor.publishStringVariable(targetAssignName, finalAssigned);
|
|
10552
|
+
if (targetAssignName === "OPTIND") {
|
|
10328
10553
|
rawState.variables.OPTIND = finalAssigned;
|
|
10329
10554
|
this.syncGetopts(rawState);
|
|
10330
10555
|
}
|
|
10331
10556
|
if (rawState.allexport)
|
|
10332
|
-
monitor.proxy.exported.add(
|
|
10557
|
+
monitor.proxy.exported.add(targetAssignName);
|
|
10333
10558
|
if (io.assignmentDiagnosticContext)
|
|
10334
10559
|
io.assignmentDiagnosticContext.name = undefined;
|
|
10335
10560
|
if (!existing) {
|
|
@@ -10337,7 +10562,7 @@ export class Runtime {
|
|
|
10337
10562
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10338
10563
|
}
|
|
10339
10564
|
else {
|
|
10340
|
-
|
|
10565
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
10341
10566
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10342
10567
|
}
|
|
10343
10568
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -10353,60 +10578,98 @@ export class Runtime {
|
|
|
10353
10578
|
if (command.words.length >= 1) {
|
|
10354
10579
|
const w0Plain = command.words[0].plain;
|
|
10355
10580
|
if (this.budget.limits.maxExpansionFields === Infinity && command.words.length >= 4 && w0Plain === "printf" && command.words[1]?.plain === "-v" && command.redirects.length === 0 && canMutatePipeStatus && (!pipeline.negate || ignored || !rawState.errexit) && !hasShellFunction(rawState, "printf") && !rawState.extensions?.builtins.has("printf")) {
|
|
10356
|
-
const targetVar = command.words[2]?.plain;
|
|
10357
10581
|
const def = this.commands.get("printf");
|
|
10358
|
-
if (
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
const v = this.fastValueWord(command.words[i], rawState, io, true, false, false, true, undefined, diagnosticLine);
|
|
10364
|
-
if (typeof v !== "string") {
|
|
10365
|
-
allStrings = false;
|
|
10366
|
-
break;
|
|
10367
|
-
}
|
|
10368
|
-
fastSubScratchArgs.push(v);
|
|
10369
|
-
}
|
|
10370
|
-
}
|
|
10371
|
-
catch {
|
|
10372
|
-
allStrings = false;
|
|
10373
|
-
}
|
|
10374
|
-
const lastArg = fastSubScratchArgs.length > 0 ? fastSubScratchArgs[fastSubScratchArgs.length - 1] : targetVar;
|
|
10375
|
-
const formatted = allStrings ? tryFastPrintf(fastSubScratchArgs) : undefined;
|
|
10376
|
-
fastSubScratchArgs.length = 0;
|
|
10377
|
-
if (formatted !== undefined && formatted.length <= this.budget.limits.maxExpansionBytes && (formatted.length * 3 <= this.budget.limits.maxExpansionBytes || shellValueByteLength(formatted) <= this.budget.limits.maxExpansionBytes)) {
|
|
10378
|
-
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
10379
|
-
publishCommandSpelling(rawState, commandSpelling(command));
|
|
10380
|
-
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
10381
|
-
this.budget.tick();
|
|
10382
|
-
rawState.substitutionStatus = 0;
|
|
10383
|
-
if (rawState.variables._ !== undefined)
|
|
10384
|
-
delete rawState.variables._;
|
|
10385
|
-
rawState.lastArgument = lastArg;
|
|
10386
|
-
if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
10387
|
-
rawState.variables[targetVar] = formatted;
|
|
10388
|
-
this._syncArithTouched.add(targetVar);
|
|
10582
|
+
if (def && def.execute === printfCommand.execute && command.words.length <= this.budget.maxExpansionFieldsSmi && this.arePureArgWords(command.words, rawState)) {
|
|
10583
|
+
let targetSpec = command.words[2]?.plain;
|
|
10584
|
+
if (targetSpec === undefined) {
|
|
10585
|
+
try {
|
|
10586
|
+
targetSpec = this.fastValueWord(command.words[2], rawState, io, true, false, false, true, undefined, diagnosticLine);
|
|
10389
10587
|
}
|
|
10390
|
-
|
|
10391
|
-
|
|
10392
|
-
if (rawState.allexport)
|
|
10393
|
-
monitor.proxy.exported.add(targetVar);
|
|
10394
|
-
if (io.assignmentDiagnosticContext)
|
|
10395
|
-
io.assignmentDiagnosticContext.name = undefined;
|
|
10396
|
-
if (!existing) {
|
|
10397
|
-
monitor.lazyPipeStatus = singleStatusZero;
|
|
10398
|
-
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10588
|
+
catch {
|
|
10589
|
+
targetSpec = undefined;
|
|
10399
10590
|
}
|
|
10400
|
-
|
|
10401
|
-
|
|
10402
|
-
|
|
10591
|
+
}
|
|
10592
|
+
if (typeof targetSpec === "string") {
|
|
10593
|
+
const openBr = targetSpec.indexOf("[");
|
|
10594
|
+
const isSubTarget = openBr > 0 && targetSpec.endsWith("]") && targetSpec.length > openBr + 2;
|
|
10595
|
+
const rawTargetVar = isSubTarget ? targetSpec.slice(0, openBr) : targetSpec;
|
|
10596
|
+
const targetVar = isShellIdentifier(rawTargetVar) ? resolveSyncNameref(rawState, rawTargetVar) : "";
|
|
10597
|
+
if (targetVar && isShellIdentifier(targetVar) && targetVar !== "OPTIND" && targetVar !== "PIPESTATUS" && targetVar !== "_" && !rawState.readonlyVariables?.has(targetVar) && !monitor.hasOverlay(targetVar) && (isSubTarget || !store?.get(targetVar))) {
|
|
10598
|
+
fastSubScratchArgs.length = 0;
|
|
10599
|
+
let allStrings = true;
|
|
10600
|
+
try {
|
|
10601
|
+
for (let i = 3; i < command.words.length; i++) {
|
|
10602
|
+
const v = this.fastValueWord(command.words[i], rawState, io, true, false, false, true, undefined, diagnosticLine);
|
|
10603
|
+
if (typeof v !== "string") {
|
|
10604
|
+
allStrings = false;
|
|
10605
|
+
break;
|
|
10606
|
+
}
|
|
10607
|
+
fastSubScratchArgs.push(v);
|
|
10608
|
+
}
|
|
10609
|
+
}
|
|
10610
|
+
catch {
|
|
10611
|
+
allStrings = false;
|
|
10612
|
+
}
|
|
10613
|
+
const lastArg = fastSubScratchArgs.length > 0 ? fastSubScratchArgs[fastSubScratchArgs.length - 1] : targetSpec;
|
|
10614
|
+
const formatted = allStrings ? tryFastPrintf(fastSubScratchArgs) : undefined;
|
|
10615
|
+
fastSubScratchArgs.length = 0;
|
|
10616
|
+
if (formatted !== undefined && formatted.length <= this.budget.limits.maxExpansionBytes && (formatted.length * 3 <= this.budget.limits.maxExpansionBytes || shellValueByteLength(formatted) <= this.budget.limits.maxExpansionBytes)) {
|
|
10617
|
+
let wroteTarget = true;
|
|
10618
|
+
if (isSubTarget) {
|
|
10619
|
+
let subKey = targetSpec.slice(openBr + 1, -1);
|
|
10620
|
+
const existingArr = store?.get(targetVar);
|
|
10621
|
+
if (!existingArr?.associative && !/^(?:0|[1-9][0-9]{0,8})$/.test(subKey)) {
|
|
10622
|
+
const syncTouched = this._syncArithRawWriteOnly ? this._syncArithTouched : undefined;
|
|
10623
|
+
const directIdx = resolveSimpleArithOperand(subKey.trim(), rawState, monitor, store, syncTouched);
|
|
10624
|
+
if (directIdx !== undefined && directIdx >= 0)
|
|
10625
|
+
subKey = String(directIdx);
|
|
10626
|
+
else {
|
|
10627
|
+
const exprIdx = tryEvalSimpleExpandedArith(subKey.trim(), rawState, monitor, store, syncTouched);
|
|
10628
|
+
if (exprIdx !== undefined && Number(exprIdx) >= 0)
|
|
10629
|
+
subKey = exprIdx;
|
|
10630
|
+
else
|
|
10631
|
+
wroteTarget = false;
|
|
10632
|
+
}
|
|
10633
|
+
}
|
|
10634
|
+
if (wroteTarget && !this.tryFastArraySubscriptWriteSync(rawState, targetVar, subKey, formatted))
|
|
10635
|
+
wroteTarget = false;
|
|
10636
|
+
}
|
|
10637
|
+
else if (this._syncArithRawWriteOnly && this._syncArithTouched) {
|
|
10638
|
+
rawState.variables[targetVar] = formatted;
|
|
10639
|
+
this._syncArithTouched.add(targetVar);
|
|
10640
|
+
}
|
|
10641
|
+
else
|
|
10642
|
+
monitor.publishStringVariable(targetVar, formatted);
|
|
10643
|
+
if (wroteTarget) {
|
|
10644
|
+
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
10645
|
+
publishCommandSpelling(rawState, commandSpelling(command));
|
|
10646
|
+
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
10647
|
+
this.budget.tick();
|
|
10648
|
+
rawState.substitutionStatus = 0;
|
|
10649
|
+
if (rawState.variables._ !== undefined)
|
|
10650
|
+
delete rawState.variables._;
|
|
10651
|
+
rawState.lastArgument = lastArg;
|
|
10652
|
+
if (!isSubTarget && rawState.allexport)
|
|
10653
|
+
monitor.proxy.exported.add(targetVar);
|
|
10654
|
+
if (io.assignmentDiagnosticContext)
|
|
10655
|
+
io.assignmentDiagnosticContext.name = undefined;
|
|
10656
|
+
if (!existing) {
|
|
10657
|
+
monitor.lazyPipeStatus = singleStatusZero;
|
|
10658
|
+
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10659
|
+
}
|
|
10660
|
+
else {
|
|
10661
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
10662
|
+
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10663
|
+
}
|
|
10664
|
+
const finalStatus = pipeline.negate ? 1 : 0;
|
|
10665
|
+
rawState.status = finalStatus;
|
|
10666
|
+
monitor.epoch = restEpoch;
|
|
10667
|
+
if (store)
|
|
10668
|
+
store.epoch = restEpoch;
|
|
10669
|
+
return finalStatus;
|
|
10670
|
+
}
|
|
10671
|
+
}
|
|
10403
10672
|
}
|
|
10404
|
-
const finalStatus = pipeline.negate ? 1 : 0;
|
|
10405
|
-
rawState.status = finalStatus;
|
|
10406
|
-
monitor.epoch = restEpoch;
|
|
10407
|
-
if (store)
|
|
10408
|
-
store.epoch = restEpoch;
|
|
10409
|
-
return finalStatus;
|
|
10410
10673
|
}
|
|
10411
10674
|
}
|
|
10412
10675
|
}
|
|
@@ -10459,7 +10722,7 @@ export class Runtime {
|
|
|
10459
10722
|
if (command.words.length === 3) {
|
|
10460
10723
|
scanArgs = this._fastSubPositional ?? rawState.positional;
|
|
10461
10724
|
}
|
|
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; })()) {
|
|
10725
|
+
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 && !ne[0].length && !ne[0].substring && !ne[0].operator && !ne[0].transform && !ne[0].indirect && !ne[0].prefixNames && getArraySelector(ne[0]) === undefined; })()) {
|
|
10463
10726
|
scanArgs = this._fastSubPositional ?? rawState.positional;
|
|
10464
10727
|
if (scanArgs.length > 0)
|
|
10465
10728
|
lastArg = scanArgs[scanArgs.length - 1];
|
|
@@ -10484,7 +10747,7 @@ export class Runtime {
|
|
|
10484
10747
|
catch {
|
|
10485
10748
|
scanArgs = undefined;
|
|
10486
10749
|
}
|
|
10487
|
-
if (typeof optstring === "string" && scanArgs !== undefined) {
|
|
10750
|
+
if (typeof optstring === "string" && optstring.startsWith(":") && scanArgs !== undefined) {
|
|
10488
10751
|
rawState.getopts ??= cloneGetoptsBinding(rawState);
|
|
10489
10752
|
const res = scanGetoptsSync(rawState.getopts.cursor, optstring, scanArgs);
|
|
10490
10753
|
if (res !== undefined) {
|
|
@@ -10580,7 +10843,7 @@ export class Runtime {
|
|
|
10580
10843
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10581
10844
|
}
|
|
10582
10845
|
else {
|
|
10583
|
-
|
|
10846
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
10584
10847
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10585
10848
|
}
|
|
10586
10849
|
rawState.status = 0;
|
|
@@ -10686,7 +10949,7 @@ export class Runtime {
|
|
|
10686
10949
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
10687
10950
|
}
|
|
10688
10951
|
else {
|
|
10689
|
-
|
|
10952
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
10690
10953
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
10691
10954
|
}
|
|
10692
10955
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -10926,33 +11189,7 @@ export class Runtime {
|
|
|
10926
11189
|
else {
|
|
10927
11190
|
const arrStore = monitor.store ?? requireArrays(rawState);
|
|
10928
11191
|
existingArrayBinding = arrStore.get(arrayTarget);
|
|
10929
|
-
if (
|
|
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;
|
|
10935
|
-
}
|
|
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 { }
|
|
10952
|
-
}
|
|
10953
|
-
if (!existingArrayBinding ||
|
|
10954
|
-
existingArrayBinding.associative ||
|
|
10955
|
-
existingArrayBinding.references !== 1 ||
|
|
11192
|
+
if ((existingArrayBinding ? existingArrayBinding.associative || existingArrayBinding.references !== 1 : rawState.variables[arrayTarget] !== undefined) ||
|
|
10956
11193
|
arrStore.watches.has(arrayTarget) ||
|
|
10957
11194
|
monitor.hasOverlay(arrayTarget)) {
|
|
10958
11195
|
simpleRead = false;
|
|
@@ -11000,6 +11237,36 @@ export class Runtime {
|
|
|
11000
11237
|
else
|
|
11001
11238
|
lineStr = io.stdin.tryReadSimpleRawAsciiLineSync(readDelim, raw);
|
|
11002
11239
|
if (lineStr !== undefined) {
|
|
11240
|
+
// Expand/read the input before publishing the destination array.
|
|
11241
|
+
if (arrayTarget !== undefined && !existingArrayBinding) {
|
|
11242
|
+
const arrStore = monitor.store ?? requireArrays(rawState);
|
|
11243
|
+
if (!existingArrayBinding && rawState.variables[arrayTarget] === undefined && !arrStore.watches.has(arrayTarget) && !monitor.hasOverlay(arrayTarget)) {
|
|
11244
|
+
const recTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
11245
|
+
const recBinding = arrStore.takeRecycled(arrayTarget, false, true, recTickets);
|
|
11246
|
+
if (recBinding) {
|
|
11247
|
+
monitor.epoch = recTickets.epoch;
|
|
11248
|
+
existingArrayBinding = recBinding;
|
|
11249
|
+
}
|
|
11250
|
+
else
|
|
11251
|
+
try {
|
|
11252
|
+
const created = IndexedBinding.create(arrStore.owner, false);
|
|
11253
|
+
const nameByteLen = shellValueByteLength(arrayTarget);
|
|
11254
|
+
const prepared = arrStore.prepareExistingName(arrayTarget, nameByteLen, arrStore.owner, this.signal);
|
|
11255
|
+
if (prepared) {
|
|
11256
|
+
const initTickets = arrStore.owner.charge({ generation: true, version: true, epoch: true, work: 8 });
|
|
11257
|
+
arrStore.publish(arrayTarget, created, initTickets, prepared, false, arrStore.owner);
|
|
11258
|
+
monitor.epoch = initTickets.epoch;
|
|
11259
|
+
existingArrayBinding = created;
|
|
11260
|
+
}
|
|
11261
|
+
else {
|
|
11262
|
+
void created.release();
|
|
11263
|
+
}
|
|
11264
|
+
}
|
|
11265
|
+
catch { }
|
|
11266
|
+
}
|
|
11267
|
+
if (!existingArrayBinding)
|
|
11268
|
+
return undefined;
|
|
11269
|
+
}
|
|
11003
11270
|
if (rawState.extensions && !rawState.extensions.eventDepth)
|
|
11004
11271
|
publishCommandSpelling(rawState, commandSpelling(command));
|
|
11005
11272
|
if (arrayTarget !== undefined && existingArrayBinding) {
|
|
@@ -11059,6 +11326,7 @@ export class Runtime {
|
|
|
11059
11326
|
readArrayScratchFields.length = 0;
|
|
11060
11327
|
delete rawState.variables[arrayTarget];
|
|
11061
11328
|
monitor.epoch = tickets.epoch;
|
|
11329
|
+
existingArrayBinding.assigned = true;
|
|
11062
11330
|
activeArrStore.revise(arrayTarget, existingArrayBinding, tickets);
|
|
11063
11331
|
}
|
|
11064
11332
|
catch (error) {
|
|
@@ -11138,7 +11406,7 @@ export class Runtime {
|
|
|
11138
11406
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
11139
11407
|
}
|
|
11140
11408
|
else {
|
|
11141
|
-
|
|
11409
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
11142
11410
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
11143
11411
|
}
|
|
11144
11412
|
rawState.status = 0;
|
|
@@ -11336,7 +11604,7 @@ export class Runtime {
|
|
|
11336
11604
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
11337
11605
|
}
|
|
11338
11606
|
else {
|
|
11339
|
-
|
|
11607
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
11340
11608
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
11341
11609
|
}
|
|
11342
11610
|
rawState.status = 0;
|
|
@@ -11410,7 +11678,7 @@ export class Runtime {
|
|
|
11410
11678
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
11411
11679
|
}
|
|
11412
11680
|
else {
|
|
11413
|
-
|
|
11681
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
11414
11682
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
11415
11683
|
}
|
|
11416
11684
|
rawState.status = 0;
|
|
@@ -11490,6 +11758,8 @@ export class Runtime {
|
|
|
11490
11758
|
if (isLocalScope) {
|
|
11491
11759
|
let existingLocal = currentFrame.get(an);
|
|
11492
11760
|
if (!existingLocal) {
|
|
11761
|
+
if (this._syncArithRawWriteOnly && this._syncArithTouched?.has(an))
|
|
11762
|
+
monitor.values.invalidate(an);
|
|
11493
11763
|
existingLocal = saveVariable(state, an);
|
|
11494
11764
|
syncLocalArrayVariables.add(existingLocal);
|
|
11495
11765
|
currentFrame.set(an, existingLocal);
|
|
@@ -11554,13 +11824,15 @@ export class Runtime {
|
|
|
11554
11824
|
}
|
|
11555
11825
|
return undefined;
|
|
11556
11826
|
}
|
|
11827
|
+
const isNamerefDecl = command.words[1]?.plain === "-n" && rawState.locals.length > 0 && command.words.length >= 3;
|
|
11828
|
+
const isGlobalDecl = command.words[1]?.plain === "-g" && (w0Plain === "declare" || w0Plain === "typeset") && command.words.length >= 3;
|
|
11557
11829
|
const parsedLocals = [];
|
|
11558
11830
|
let allValidLocal = true;
|
|
11559
|
-
for (let idx = 1; idx < command.words.length; idx++) {
|
|
11831
|
+
for (let idx = (isNamerefDecl || isGlobalDecl) ? 2 : 1; idx < command.words.length; idx++) {
|
|
11560
11832
|
const wArg = command.words[idx];
|
|
11561
11833
|
const assignment = !getArrayAssignment(wArg) ? this.assignment(wArg) : undefined;
|
|
11562
11834
|
if (assignment) {
|
|
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)) {
|
|
11835
|
+
if ((!isNamerefDecl && rawState.variableAttributes?.get(assignment.name)) || (assignment.name === "OPTIND" && (assignment.append || rawState.variableAttributes?.get("OPTIND"))) || assignment.name === "PIPESTATUS" || assignment.name.includes("[") || rawState.readonlyVariables?.has(assignment.name) || store?.get(assignment.name)) {
|
|
11564
11836
|
allValidLocal = false;
|
|
11565
11837
|
break;
|
|
11566
11838
|
}
|
|
@@ -11593,10 +11865,28 @@ export class Runtime {
|
|
|
11593
11865
|
break;
|
|
11594
11866
|
}
|
|
11595
11867
|
}
|
|
11868
|
+
if (isNamerefDecl && allValidLocal) {
|
|
11869
|
+
for (let i = 0; i < parsedLocals.length; i++) {
|
|
11870
|
+
const it = parsedLocals[i];
|
|
11871
|
+
if (!it.val || it.append || !isShellIdentifier(it.val) || it.val === it.name || rawState.variableAttributes?.get(it.val)) {
|
|
11872
|
+
allValidLocal = false;
|
|
11873
|
+
break;
|
|
11874
|
+
}
|
|
11875
|
+
}
|
|
11876
|
+
}
|
|
11877
|
+
if (isGlobalDecl && allValidLocal && rawState.locals.length > 0) {
|
|
11878
|
+
for (let i = 0; i < parsedLocals.length; i++) {
|
|
11879
|
+
const it = parsedLocals[i];
|
|
11880
|
+
if (rawState.locals.some(f => f.has(it.name))) {
|
|
11881
|
+
allValidLocal = false;
|
|
11882
|
+
break;
|
|
11883
|
+
}
|
|
11884
|
+
}
|
|
11885
|
+
}
|
|
11596
11886
|
if (allValidLocal && parsedLocals.length > 0) {
|
|
11597
|
-
if (rawState.locals.length === 0 && parsedLocals.some(item => item.val === undefined && !rawState.variableAttributes?.has(item.name)))
|
|
11887
|
+
if ((rawState.locals.length === 0 || isGlobalDecl) && parsedLocals.some(item => item.val === undefined && !rawState.variableAttributes?.has(item.name)))
|
|
11598
11888
|
return undefined;
|
|
11599
|
-
const locals = rawState.locals.length > 0 ? rawState.locals[rawState.locals.length - 1] : undefined;
|
|
11889
|
+
const locals = (!isGlobalDecl && rawState.locals.length > 0) ? rawState.locals[rawState.locals.length - 1] : undefined;
|
|
11600
11890
|
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
11601
11891
|
this.budget.tick();
|
|
11602
11892
|
rawState.substitutionStatus = 0;
|
|
@@ -11610,7 +11900,7 @@ export class Runtime {
|
|
|
11610
11900
|
const curVal = this._syncArithTouched.has(item.name)
|
|
11611
11901
|
? rawState.variables[item.name]
|
|
11612
11902
|
: (rawState.variables[item.name] === undefined ? undefined : (monitor.values.get(item.name, rawState.variables[item.name]) ?? rawState.variables[item.name]));
|
|
11613
|
-
locals.set(item.name, { attributes: undefined, value: typeof curVal === "string" ? curVal : undefined, exported:
|
|
11903
|
+
locals.set(item.name, { attributes: undefined, value: typeof curVal === "string" ? curVal : undefined, exported: rawState.exported.has(item.name), readOnly: false, ...(item.name === "OPTIND" ? { getopts: cloneGetoptsBinding(rawState) } : {}) });
|
|
11614
11904
|
}
|
|
11615
11905
|
else
|
|
11616
11906
|
locals.set(item.name, saveVariable(state, item.name));
|
|
@@ -11640,7 +11930,11 @@ export class Runtime {
|
|
|
11640
11930
|
if (rawState.allexport)
|
|
11641
11931
|
monitor.proxy.exported.add(item.name);
|
|
11642
11932
|
rawState.lastArgument = `${item.name}=${finalVal}`;
|
|
11643
|
-
if (
|
|
11933
|
+
if (isNamerefDecl) {
|
|
11934
|
+
rawState.variableAttributes ??= new Map();
|
|
11935
|
+
rawState.variableAttributes.set(item.name, "n");
|
|
11936
|
+
}
|
|
11937
|
+
else if (isNewLocal && rawState.variableAttributes?.has(item.name))
|
|
11644
11938
|
rawState.variableAttributes.delete(item.name);
|
|
11645
11939
|
}
|
|
11646
11940
|
else {
|
|
@@ -11671,7 +11965,7 @@ export class Runtime {
|
|
|
11671
11965
|
}
|
|
11672
11966
|
}
|
|
11673
11967
|
else {
|
|
11674
|
-
|
|
11968
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
11675
11969
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
11676
11970
|
}
|
|
11677
11971
|
rawState.status = 0;
|
|
@@ -11697,8 +11991,6 @@ export class Runtime {
|
|
|
11697
11991
|
if (fastArg.length > 0 && fastArg.length <= 15 && /^-?[0-9]+$/.test(fastArg)) {
|
|
11698
11992
|
const retStatus = ((Number(fastArg) % 256) + 256) % 256;
|
|
11699
11993
|
const statusStr = retStatus === 0 ? "0" : retStatus === 1 ? "1" : String(retStatus);
|
|
11700
|
-
if (existing && elem0.text.bytes !== statusStr.length)
|
|
11701
|
-
return undefined;
|
|
11702
11994
|
const prevStatus = rawState.status;
|
|
11703
11995
|
const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
|
|
11704
11996
|
this.budget.tick();
|
|
@@ -11713,7 +12005,7 @@ export class Runtime {
|
|
|
11713
12005
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
11714
12006
|
}
|
|
11715
12007
|
else {
|
|
11716
|
-
|
|
12008
|
+
this.setSyncPipeStatusCell(existing, statusStr);
|
|
11717
12009
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
11718
12010
|
}
|
|
11719
12011
|
rawState.status = retStatus;
|
|
@@ -11767,10 +12059,14 @@ export class Runtime {
|
|
|
11767
12059
|
else {
|
|
11768
12060
|
const savedPos = rawState.positional;
|
|
11769
12061
|
rawState.positional = fnArgs;
|
|
12062
|
+
rawState.locals.push(new Map());
|
|
12063
|
+
rawState.functionDepth++;
|
|
11770
12064
|
try {
|
|
11771
12065
|
canSyncFn = this.canSyncScriptCompound(fnBody.body, rawState, 1);
|
|
11772
12066
|
}
|
|
11773
12067
|
finally {
|
|
12068
|
+
rawState.functionDepth--;
|
|
12069
|
+
rawState.locals.pop();
|
|
11774
12070
|
rawState.positional = savedPos;
|
|
11775
12071
|
}
|
|
11776
12072
|
}
|
|
@@ -11891,8 +12187,8 @@ export class Runtime {
|
|
|
11891
12187
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
11892
12188
|
}
|
|
11893
12189
|
}
|
|
11894
|
-
else
|
|
11895
|
-
|
|
12190
|
+
else {
|
|
12191
|
+
this.setSyncPipeStatusCell(activeExisting, statusStr);
|
|
11896
12192
|
activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
11897
12193
|
}
|
|
11898
12194
|
rawState.status = exitStatus;
|
|
@@ -11963,7 +12259,7 @@ export class Runtime {
|
|
|
11963
12259
|
}
|
|
11964
12260
|
}
|
|
11965
12261
|
else {
|
|
11966
|
-
|
|
12262
|
+
this.setSyncPipeStatusCell(activeExisting, "0");
|
|
11967
12263
|
activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
11968
12264
|
}
|
|
11969
12265
|
rawState.status = 0;
|
|
@@ -11997,7 +12293,7 @@ export class Runtime {
|
|
|
11997
12293
|
rawState.depth++;
|
|
11998
12294
|
let evalStatus;
|
|
11999
12295
|
try {
|
|
12000
|
-
evalStatus = this.trySyncScript(cachedUnit.script, state, io, Boolean(ignored));
|
|
12296
|
+
evalStatus = this.trySyncScript(cachedUnit.script, state, { ...io, diagnosticOffset: (diagnosticLine ?? 1) - 1, functionCommandLines: undefined, assignmentDiagnosticContext: { name: "eval" } }, Boolean(ignored));
|
|
12001
12297
|
}
|
|
12002
12298
|
finally {
|
|
12003
12299
|
rawState.depth--;
|
|
@@ -12017,7 +12313,7 @@ export class Runtime {
|
|
|
12017
12313
|
}
|
|
12018
12314
|
}
|
|
12019
12315
|
else {
|
|
12020
|
-
|
|
12316
|
+
this.setSyncPipeStatusCell(activeExisting, "0");
|
|
12021
12317
|
activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
12022
12318
|
}
|
|
12023
12319
|
}
|
|
@@ -12101,7 +12397,7 @@ export class Runtime {
|
|
|
12101
12397
|
}
|
|
12102
12398
|
}
|
|
12103
12399
|
else {
|
|
12104
|
-
|
|
12400
|
+
this.setSyncPipeStatusCell(existing, statusChar);
|
|
12105
12401
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
12106
12402
|
}
|
|
12107
12403
|
const finalStatus = pipeline.negate ? Number(fastPred === 0) : fastPred;
|
|
@@ -12166,7 +12462,7 @@ export class Runtime {
|
|
|
12166
12462
|
else {
|
|
12167
12463
|
const idxNum = /^(?:0|[1-9][0-9]{0,8})$/.test(subExpr) ? Number(subExpr) : resolveSimpleArithOperand(subExpr, rawState, monitor, arrStore, this._syncArithRawWriteOnly ? this._syncArithTouched : undefined);
|
|
12168
12464
|
if (idxNum !== undefined && idxNum >= 0 && idxNum <= 2147483647) {
|
|
12169
|
-
if (!curB && rawState.variables[arrName] === undefined && !arrStore.watches.has(arrName) && !monitor.hasOverlay(arrName)) {
|
|
12465
|
+
if (!curB && !hasUnpreparedLocal(rawState, arrName) && rawState.variables[arrName] === undefined && !arrStore.watches.has(arrName) && !monitor.hasOverlay(arrName)) {
|
|
12170
12466
|
const created = IndexedBinding.create(arrStore.owner, false);
|
|
12171
12467
|
const prepared = arrStore.prepareExistingName(arrName, shellValueByteLength(arrName), arrStore.owner, this.signal);
|
|
12172
12468
|
if (prepared) {
|
|
@@ -12212,7 +12508,7 @@ export class Runtime {
|
|
|
12212
12508
|
}
|
|
12213
12509
|
}
|
|
12214
12510
|
else {
|
|
12215
|
-
|
|
12511
|
+
this.setSyncPipeStatusCell(activeExisting, "0");
|
|
12216
12512
|
activeStore.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
12217
12513
|
}
|
|
12218
12514
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -12298,7 +12594,7 @@ export class Runtime {
|
|
|
12298
12594
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
12299
12595
|
}
|
|
12300
12596
|
else {
|
|
12301
|
-
|
|
12597
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
12302
12598
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
12303
12599
|
}
|
|
12304
12600
|
const finalStatus = pipeline.negate ? 1 : 0;
|
|
@@ -12353,7 +12649,7 @@ export class Runtime {
|
|
|
12353
12649
|
return false;
|
|
12354
12650
|
continue;
|
|
12355
12651
|
}
|
|
12356
|
-
if (part.prefixNames || part.specialParameter || part.transform || part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || !isShellIdentifier(part.name)) {
|
|
12652
|
+
if (part.prefixNames || part.specialParameter || part.transform || part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || part.name === "DIRSTACK" || !isShellIdentifier(part.name)) {
|
|
12357
12653
|
return false;
|
|
12358
12654
|
}
|
|
12359
12655
|
if (part.indirect) {
|
|
@@ -12850,7 +13146,7 @@ export class Runtime {
|
|
|
12850
13146
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
12851
13147
|
}
|
|
12852
13148
|
else {
|
|
12853
|
-
|
|
13149
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
12854
13150
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
12855
13151
|
}
|
|
12856
13152
|
}
|
|
@@ -13213,7 +13509,7 @@ export class Runtime {
|
|
|
13213
13509
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
13214
13510
|
}
|
|
13215
13511
|
else {
|
|
13216
|
-
|
|
13512
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
13217
13513
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
13218
13514
|
}
|
|
13219
13515
|
}
|
|
@@ -13438,7 +13734,7 @@ export class Runtime {
|
|
|
13438
13734
|
monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
|
|
13439
13735
|
}
|
|
13440
13736
|
else {
|
|
13441
|
-
|
|
13737
|
+
this.setSyncPipeStatusCell(existing, "0");
|
|
13442
13738
|
store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
|
|
13443
13739
|
}
|
|
13444
13740
|
}
|
|
@@ -16070,7 +16366,7 @@ export class Runtime {
|
|
|
16070
16366
|
previous.set(assignment.name, saved);
|
|
16071
16367
|
const existingArray = arrayStore(state)?.get(assignment.name);
|
|
16072
16368
|
const canSkipTypedScalarOverlay = !existingArray && words[0] === "read" && !state.functions.has("read") && !state.extensions?.builtins.has("read") && !words.some(w => w.startsWith("-a") || (w.startsWith("-") && !w.startsWith("--") && w.includes("a")));
|
|
16073
|
-
if (words.length && !canSkipTypedScalarOverlay && (guestArrays(state) ||
|
|
16369
|
+
if (words.length && !canSkipTypedScalarOverlay && (guestArrays(state) || existingArray)) {
|
|
16074
16370
|
const store = requireArrays(state);
|
|
16075
16371
|
await this.prepareVariable(state, assignment.name, saved, !existingArray);
|
|
16076
16372
|
if (existingArray) {
|
|
@@ -16095,7 +16391,7 @@ export class Runtime {
|
|
|
16095
16391
|
}
|
|
16096
16392
|
if (inlineInput || (state.profile === "sh" || !words.length) && assignments.some(assignment => state.readonlyVariables?.has(assignment.name)))
|
|
16097
16393
|
await assign();
|
|
16098
|
-
if (inlineInput &&
|
|
16394
|
+
if (inlineInput && previous?.size) {
|
|
16099
16395
|
if (stateMonitor(state)?.lazyPipeStatus !== undefined)
|
|
16100
16396
|
stateMonitor(state).activate(true);
|
|
16101
16397
|
const redirectState = tryCloneStateSync(state) ?? await cloneState(state, this.signal);
|
|
@@ -16103,10 +16399,26 @@ export class Runtime {
|
|
|
16103
16399
|
const redirectAssignments = new Map();
|
|
16104
16400
|
for (const [name, saved] of previous) {
|
|
16105
16401
|
redirectAssignments.set(name, stateMonitor(state).values.get(name, state.variables[name]));
|
|
16402
|
+
if (saved.exported)
|
|
16403
|
+
redirectState.exported.add(name);
|
|
16404
|
+
else
|
|
16405
|
+
redirectState.exported.delete(name);
|
|
16106
16406
|
if (saved.value === undefined)
|
|
16107
16407
|
delete variables[name];
|
|
16108
16408
|
else
|
|
16109
16409
|
publishVariable(redirectState, name, saved.heldValue?.value ?? saved.value);
|
|
16410
|
+
const binding = typedSavedVariables.get(saved)?.binding;
|
|
16411
|
+
if (binding) {
|
|
16412
|
+
const store = requireArrays(redirectState);
|
|
16413
|
+
const prepared = await store.prepareName(name, store.owner, this.signal);
|
|
16414
|
+
const tickets = store.tickets(name);
|
|
16415
|
+
try {
|
|
16416
|
+
await store.publish(name, binding.retain(), tickets, prepared);
|
|
16417
|
+
}
|
|
16418
|
+
finally {
|
|
16419
|
+
tickets.release();
|
|
16420
|
+
}
|
|
16421
|
+
}
|
|
16110
16422
|
}
|
|
16111
16423
|
redirectState.redirectAssignments = redirectAssignments;
|
|
16112
16424
|
const savedIndex = previous.get("OPTIND");
|
|
@@ -16124,7 +16436,7 @@ export class Runtime {
|
|
|
16124
16436
|
}
|
|
16125
16437
|
const epoch = stateMonitor(state)?.epoch;
|
|
16126
16438
|
try {
|
|
16127
|
-
io = await this.redirect(command.redirects, redirectState, io, inputs, outputs,
|
|
16439
|
+
io = await this.redirect(command.redirects, redirectState, io, inputs, outputs, isolatedInlineInput, !isolatedInlineInput, false, command.line ?? 1);
|
|
16128
16440
|
if (parentStore && stateMonitor(state).epoch !== epoch)
|
|
16129
16441
|
throw new ArrayFailure("stale state snapshot");
|
|
16130
16442
|
}
|
|
@@ -16147,6 +16459,12 @@ export class Runtime {
|
|
|
16147
16459
|
publishVariable(state, name, stateMonitor(redirectState).values.get(name, value));
|
|
16148
16460
|
}
|
|
16149
16461
|
for (const [name, saved] of previous) {
|
|
16462
|
+
const typed = typedSavedVariables.get(saved);
|
|
16463
|
+
const binding = arrayStore(redirectState)?.get(name);
|
|
16464
|
+
if (typed && binding !== typed.binding) {
|
|
16465
|
+
typedSavedVariables.set(saved, { ...typed, binding: binding?.retain() });
|
|
16466
|
+
await typed.binding?.release();
|
|
16467
|
+
}
|
|
16150
16468
|
saved.value = variables[name];
|
|
16151
16469
|
const value = stateMonitor(redirectState).values.get(name, saved.value ?? "");
|
|
16152
16470
|
const held = saved.value === undefined ? undefined : stateMonitor(state).values.scope.hold(value);
|
|
@@ -20341,6 +20659,9 @@ export class Runtime {
|
|
|
20341
20659
|
seen.add(name);
|
|
20342
20660
|
names.push(name);
|
|
20343
20661
|
};
|
|
20662
|
+
await consider("DIRSTACK", true);
|
|
20663
|
+
if (state.functionNames?.length)
|
|
20664
|
+
await consider("FUNCNAME", true);
|
|
20344
20665
|
for (const name in state.variables)
|
|
20345
20666
|
if (Object.hasOwn(state.variables, name))
|
|
20346
20667
|
await consider(name, state.variables[name] !== undefined);
|
|
@@ -20421,7 +20742,7 @@ export class Runtime {
|
|
|
20421
20742
|
setArraySelector(resolved, { kind: "element", index: { decimal: shellValueText(value), word: { offset: word.offset, parts: [{ kind: "text", value: shellValueText(value), quoted: true, ...(typeof value === "string" ? {} : { byteValue: value }) }] } } });
|
|
20422
20743
|
return resolved;
|
|
20423
20744
|
}
|
|
20424
|
-
const maximum = binding?.maximum ?? (state.variables[part.name] === undefined ? -1 : 0);
|
|
20745
|
+
const maximum = binding?.maximum ?? (part.name === "FUNCNAME" && state.variables.FUNCNAME === undefined ? (state.functionNames?.length ?? 0) - 1 : state.variables[part.name] === undefined ? -1 : 0);
|
|
20425
20746
|
const index = await this.arrayIndex(binding, selector.index, state, io, store.owner, false, maximum);
|
|
20426
20747
|
const resolved = { ...part };
|
|
20427
20748
|
copyArraySelector(part, resolved);
|
|
@@ -20493,8 +20814,7 @@ export class Runtime {
|
|
|
20493
20814
|
const selector = getArraySelector(part);
|
|
20494
20815
|
if (selector?.kind === "members" || part.name === "@" || part.name === "*") {
|
|
20495
20816
|
const members = selector ? await this.arrayMembers(part.name, state, io, part.keys) : this.positionalValues(state);
|
|
20496
|
-
const
|
|
20497
|
-
const separator = !split && (selector?.kind === "members" ? selector.separator === "@" || !part.quoted : part.name === "@") ? " " : ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
|
|
20817
|
+
const separator = !split && (selector?.kind === "members" ? selector.separator === "@" : part.name === "@") ? " " : this.ifsSeparator(state, io);
|
|
20498
20818
|
const fragments = [];
|
|
20499
20819
|
let bytes = 0;
|
|
20500
20820
|
for (const member of members) {
|
|
@@ -21350,7 +21670,7 @@ export class Runtime {
|
|
|
21350
21670
|
fastValueWord(word, state, io, split, pattern, hereDocument, braces, assignmentStart, overrideDiagnosticLine) {
|
|
21351
21671
|
const monitor = stateMonitor(state);
|
|
21352
21672
|
const rawState = monitor ? monitor.raw : state;
|
|
21353
|
-
if (pattern || word.parts.length === 0 || (rawState.depth + (io.parameterDepth ?? 0)) >= 32 ||
|
|
21673
|
+
if (pattern || word.parts.length === 0 || (rawState.depth + (io.parameterDepth ?? 0)) >= 32 || hasNonNamerefAttributes(rawState))
|
|
21354
21674
|
return undefined;
|
|
21355
21675
|
if (guestArrays(state) && word.parts.some(part => part.kind === "arithmetic" && !part.expression.error && !isSafeSmiProgram(part.expression)))
|
|
21356
21676
|
return undefined;
|
|
@@ -21359,7 +21679,7 @@ export class Runtime {
|
|
|
21359
21679
|
this.signal.throwIfAborted();
|
|
21360
21680
|
let out = "";
|
|
21361
21681
|
for (let i = 0; i < word.parts.length; i++) {
|
|
21362
|
-
|
|
21682
|
+
let part = word.parts[i];
|
|
21363
21683
|
if (part.kind === "text") {
|
|
21364
21684
|
if (part.byteValue || invokedValues.has(part))
|
|
21365
21685
|
return undefined;
|
|
@@ -21377,8 +21697,17 @@ export class Runtime {
|
|
|
21377
21697
|
out += part.value;
|
|
21378
21698
|
}
|
|
21379
21699
|
else if (part.kind === "variable") {
|
|
21380
|
-
if (rawState.variableAttributes?.get(part.name)?.includes("n"))
|
|
21381
|
-
|
|
21700
|
+
if (rawState.variableAttributes?.get(part.name)?.includes("n")) {
|
|
21701
|
+
if (part.indirect)
|
|
21702
|
+
return undefined;
|
|
21703
|
+
const resolvedName = resolveSyncNameref(rawState, part.name);
|
|
21704
|
+
if (resolvedName === part.name)
|
|
21705
|
+
return undefined;
|
|
21706
|
+
const origSel = getArraySelector(part);
|
|
21707
|
+
part = { ...part, name: resolvedName };
|
|
21708
|
+
if (origSel)
|
|
21709
|
+
setArraySelector(part, origSel);
|
|
21710
|
+
}
|
|
21382
21711
|
if (split && !part.quoted && (rawVars.IFS !== undefined && rawVars.IFS !== " \t\n"))
|
|
21383
21712
|
return undefined;
|
|
21384
21713
|
if (!part.indirect && !part.prefixNames && !part.length && !part.substring && !part.transform && part.operator === undefined && getArraySelector(part) === undefined && (part.name === "?" || part.name === "#" || (part.name.length === 1 && part.name >= "1" && part.name <= "9"))) {
|
|
@@ -21408,7 +21737,7 @@ export class Runtime {
|
|
|
21408
21737
|
const refName = refRaw === undefined ? undefined : (this._syncArithRawWriteOnly && this._syncArithTouched?.has(part.name) ? refRaw : (monitor?.values.get(part.name, refRaw) ?? refRaw));
|
|
21409
21738
|
if (typeof refName !== "string" || !isShellIdentifier(refName))
|
|
21410
21739
|
return undefined;
|
|
21411
|
-
if (activeArrayStore?.get(refName) || rawState.variableAttributes?.get(refName) || refName === "PIPESTATUS" || refName === "LINENO" || refName === "_" || refName === "FUNCNAME") {
|
|
21740
|
+
if (activeArrayStore?.get(refName) || rawState.variableAttributes?.get(refName) || refName === "PIPESTATUS" || refName === "LINENO" || refName === "_" || refName === "FUNCNAME" || refName === "DIRSTACK") {
|
|
21412
21741
|
return undefined;
|
|
21413
21742
|
}
|
|
21414
21743
|
const targetRaw = rawVars[refName];
|
|
@@ -21424,7 +21753,7 @@ export class Runtime {
|
|
|
21424
21753
|
}
|
|
21425
21754
|
if (part.indirect || part.prefixNames || part.specialParameter || part.transform)
|
|
21426
21755
|
return undefined;
|
|
21427
|
-
if (part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME")
|
|
21756
|
+
if (part.name === "@" || part.name === "*" || part.name === "PIPESTATUS" || part.name === "LINENO" || part.name === "_" || part.name === "FUNCNAME" || part.name === "DIRSTACK")
|
|
21428
21757
|
return undefined;
|
|
21429
21758
|
if (!isShellIdentifier(part.name))
|
|
21430
21759
|
return undefined;
|
|
@@ -21506,10 +21835,11 @@ export class Runtime {
|
|
|
21506
21835
|
const ifsVal = monitor?.values.get("IFS", rawVars.IFS ?? " ") ?? rawVars.IFS ?? " ";
|
|
21507
21836
|
if (validElemOp && typeof ifsVal === "string" && (ifsVal.length === 0 || ifsVal.charCodeAt(0) < 128)) {
|
|
21508
21837
|
const sep = selector.separator === "@" && (!isKeys || ifsVal.length === 0) ? " " : ifsVal.length > 0 ? ifsVal[0] : "";
|
|
21838
|
+
const parameterLine = part.line ?? overrideDiagnosticLine;
|
|
21509
21839
|
const evalSliceInt = (w) => {
|
|
21510
21840
|
if (w.parts.length === 0)
|
|
21511
21841
|
return 0;
|
|
21512
|
-
const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, undefined,
|
|
21842
|
+
const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, undefined, parameterLine);
|
|
21513
21843
|
if (typeof expanded !== "string")
|
|
21514
21844
|
return undefined;
|
|
21515
21845
|
const trimmed = expanded.trim();
|
|
@@ -21760,10 +22090,11 @@ export class Runtime {
|
|
|
21760
22090
|
if (part.length || part.operator !== undefined || this.budget.limits.maxExpansionBytes !== Infinity || rawState.depth + (io.parameterDepth ?? 0) >= 60 || !part.substring.offset.parts.every(p => p.kind === "text" || p.kind === "arithmetic" || (p.kind === "variable" && !p.operator && !p.substring)) || (part.substring.length && !part.substring.length.parts.every(p => p.kind === "text" || p.kind === "arithmetic" || (p.kind === "variable" && !p.operator && !p.substring))) || ValueScope.prototype.reserve !== defaultValueScopeReserve || String.prototype.codePointAt !== defaultStringCodePointAt || globalThis.Float64Array !== defaultFloat64Array || (!part.substring.offset.parts.length && !part.substring.length)) {
|
|
21761
22091
|
return undefined;
|
|
21762
22092
|
}
|
|
22093
|
+
const parameterLine = part.line ?? overrideDiagnosticLine;
|
|
21763
22094
|
const evalSubInt = (w) => {
|
|
21764
22095
|
if (w.parts.length === 0)
|
|
21765
22096
|
return 0;
|
|
21766
|
-
const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, undefined,
|
|
22097
|
+
const expanded = this.fastValueWord(w, rawState, io, false, false, false, false, undefined, parameterLine);
|
|
21767
22098
|
if (typeof expanded !== "string")
|
|
21768
22099
|
return undefined;
|
|
21769
22100
|
const trimmed = expanded.trim();
|
|
@@ -21837,7 +22168,8 @@ export class Runtime {
|
|
|
21837
22168
|
if (part.operator !== undefined) {
|
|
21838
22169
|
if (this.budget.limits.maxExpansionBytes !== Infinity || rawState.depth + (io.parameterDepth ?? 0) >= 60 || ValueScope.prototype.reserve !== defaultValueScopeReserve || String.prototype.codePointAt !== defaultStringCodePointAt || globalThis.Float64Array !== defaultFloat64Array)
|
|
21839
22170
|
return undefined;
|
|
21840
|
-
|
|
22171
|
+
const patternQuoted = part.alternate?.parts[0]?.quoted;
|
|
22172
|
+
if (!rawState.nocasematch && (part.operator === "/" || part.operator === "//" || part.operator === "/#" || part.operator === "/%") && part.alternate && part.alternate.parts.length >= 1 && part.alternate.parts.every(p => p.quoted === patternQuoted && ((p.kind === "text" && !p.byteValue) || (p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === undefined && isShellIdentifier(p.name)))) && (!part.replacement || part.replacement.parts.length === 0 || part.replacement.parts.every(p => (p.kind === "text" && !p.byteValue) || (p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === undefined && isShellIdentifier(p.name))))) {
|
|
21841
22173
|
const patQuoted = part.alternate.parts[0].quoted;
|
|
21842
22174
|
const pat = (part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text")
|
|
21843
22175
|
? part.alternate.parts[0].value
|
|
@@ -21911,7 +22243,7 @@ export class Runtime {
|
|
|
21911
22243
|
out += replaced;
|
|
21912
22244
|
continue;
|
|
21913
22245
|
}
|
|
21914
|
-
if ((part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") && part.alternate && part.alternate.parts.length >= 1 && part.alternate.parts.every(p => p.quoted ===
|
|
22246
|
+
if ((part.operator === "#" || part.operator === "##" || part.operator === "%" || part.operator === "%%") && part.alternate && part.alternate.parts.length >= 1 && part.alternate.parts.every(p => p.quoted === patternQuoted && ((p.kind === "text" && !p.byteValue) || (p.kind === "variable" && !p.operator && !p.substring && !p.length && !p.indirect && !p.prefixNames && !p.specialParameter && !p.transform && getArraySelector(p) === undefined && isShellIdentifier(p.name))))) {
|
|
21915
22247
|
const patQuoted = part.alternate.parts[0].quoted;
|
|
21916
22248
|
const pat = (part.alternate.parts.length === 1 && part.alternate.parts[0].kind === "text")
|
|
21917
22249
|
? part.alternate.parts[0].value
|
|
@@ -22182,7 +22514,7 @@ export class Runtime {
|
|
|
22182
22514
|
return false;
|
|
22183
22515
|
continue;
|
|
22184
22516
|
}
|
|
22185
|
-
if (p.prefixNames || p.specialParameter || p.transform || p.name === "@" || p.name === "*" || p.name === "PIPESTATUS" || p.name === "LINENO" || p.name === "_" || p.name === "FUNCNAME" || !isShellIdentifier(p.name)) {
|
|
22517
|
+
if (p.prefixNames || p.specialParameter || p.transform || p.name === "@" || p.name === "*" || p.name === "PIPESTATUS" || p.name === "LINENO" || p.name === "_" || p.name === "FUNCNAME" || p.name === "DIRSTACK" || !isShellIdentifier(p.name)) {
|
|
22186
22518
|
return false;
|
|
22187
22519
|
}
|
|
22188
22520
|
if (p.operator !== undefined && (p.operator === "=" || p.operator === ":=" || p.operator === "?" || p.operator === ":?"))
|
|
@@ -23288,7 +23620,9 @@ export class Runtime {
|
|
|
23288
23620
|
: numericIndex(selector.index, 4294967295);
|
|
23289
23621
|
if (index === undefined && !binding?.associative)
|
|
23290
23622
|
throw new ArrayFailure("index outside 0..4294967295");
|
|
23291
|
-
value = binding ? index === undefined ? undefined : binding.getValue(index)
|
|
23623
|
+
value = binding ? index === undefined ? undefined : binding.getValue(index)
|
|
23624
|
+
: part.name === "FUNCNAME" && state.variables.FUNCNAME === undefined ? (index === undefined ? undefined : state.functionNames?.[index])
|
|
23625
|
+
: index === 0 ? value : undefined;
|
|
23292
23626
|
}
|
|
23293
23627
|
const missing = value === undefined || (part.operator.startsWith(":") && shellValueByteLength(value) === 0);
|
|
23294
23628
|
if (part.operator.endsWith("+") ? !missing : missing) {
|
|
@@ -23639,8 +23973,9 @@ export class Runtime {
|
|
|
23639
23973
|
return this.arithmeticValue(prepareArithmetic(source || "0", this.budget.parsing), state, io);
|
|
23640
23974
|
};
|
|
23641
23975
|
offset = await evaluate(substring.offset);
|
|
23976
|
+
const maximum = binding?.maximum ?? (name === "FUNCNAME" && state.variables.FUNCNAME === undefined ? (state.functionNames?.length ?? 0) - 1 : state.variables[name] === undefined ? -1 : 0);
|
|
23642
23977
|
if (offset < 0n)
|
|
23643
|
-
offset += BigInt(
|
|
23978
|
+
offset += BigInt(maximum + 1);
|
|
23644
23979
|
if (substring.length) {
|
|
23645
23980
|
count = await evaluate(substring.length);
|
|
23646
23981
|
if (count < 0n)
|
|
@@ -23653,7 +23988,7 @@ export class Runtime {
|
|
|
23653
23988
|
if (!binding) {
|
|
23654
23989
|
if (name === "FUNCNAME" && state.variables.FUNCNAME === undefined) {
|
|
23655
23990
|
const stack = state.functionNames ?? [];
|
|
23656
|
-
const start =
|
|
23991
|
+
const start = Number(offset);
|
|
23657
23992
|
const end = count === undefined ? stack.length : start + Number(count);
|
|
23658
23993
|
const sliced = stack.slice(start, end);
|
|
23659
23994
|
return keys ? sliced.map((_v, idx) => String(start + idx)) : sliced;
|