@poe-platform/safe-bash 0.1.527 → 0.1.529
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/core.browser.js +511 -55
- package/dist/safe-bash/core.browser.js.map +4 -4
- package/dist/safe-bash/shell/arrays/bindings.d.ts +15 -2
- package/dist/safe-bash/shell/arrays/bindings.d.ts.map +1 -1
- package/dist/safe-bash/shell/arrays/bindings.js +118 -5
- package/dist/safe-bash/shell/arrays/bindings.js.map +1 -1
- package/dist/safe-bash/shell/arrays/syntax.d.ts +5 -2
- package/dist/safe-bash/shell/arrays/syntax.d.ts.map +1 -1
- package/dist/safe-bash/shell/arrays/syntax.js +19 -6
- package/dist/safe-bash/shell/arrays/syntax.js.map +1 -1
- package/dist/safe-bash/shell/input.d.ts +4 -0
- package/dist/safe-bash/shell/input.d.ts.map +1 -1
- package/dist/safe-bash/shell/input.js +53 -0
- package/dist/safe-bash/shell/input.js.map +1 -1
- package/dist/safe-bash/shell/mapfile.d.ts +29 -0
- package/dist/safe-bash/shell/mapfile.d.ts.map +1 -0
- package/dist/safe-bash/shell/mapfile.js +134 -0
- package/dist/safe-bash/shell/mapfile.js.map +1 -0
- package/dist/safe-bash/shell/parser.d.ts +2 -0
- package/dist/safe-bash/shell/parser.d.ts.map +1 -1
- package/dist/safe-bash/shell/parser.js +14 -5
- package/dist/safe-bash/shell/parser.js.map +1 -1
- package/dist/safe-bash/shell/runtime.d.ts +4 -2
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +255 -42
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/package.json +2 -2
|
@@ -37498,12 +37498,23 @@ function literalIndex(source2, offset, budget = new ParseBudget()) {
|
|
|
37498
37498
|
return { decimal: decimal4 };
|
|
37499
37499
|
}
|
|
37500
37500
|
function numericIndex(index) {
|
|
37501
|
+
if (index.source !== void 0) {
|
|
37502
|
+
try {
|
|
37503
|
+
return numericIndex(literalIndex(index.source, 0));
|
|
37504
|
+
} catch {
|
|
37505
|
+
return void 0;
|
|
37506
|
+
}
|
|
37507
|
+
}
|
|
37501
37508
|
if (index.decimal.length > 10 || index.decimal.length === 10 && index.decimal > "2147483647") return void 0;
|
|
37502
37509
|
return Number(index.decimal);
|
|
37503
37510
|
}
|
|
37504
|
-
function
|
|
37511
|
+
function stringIndex(source2, budget, word) {
|
|
37512
|
+
budget.admit(2);
|
|
37513
|
+
return { decimal: source2, source: source2, ...word ? { word } : {} };
|
|
37514
|
+
}
|
|
37515
|
+
function arraySelector(source2, offset, budget = new ParseBudget(), word) {
|
|
37505
37516
|
budget.admit();
|
|
37506
|
-
return source2 === "@" || source2 === "*" ? { kind: "members", separator: source2 } : { kind: "element", index: literalIndex(source2, offset, budget) };
|
|
37517
|
+
return source2 === "@" || source2 === "*" ? { kind: "members", separator: source2 } : { kind: "element", index: word ? stringIndex(source2, budget, word) : literalIndex(source2, offset, budget) };
|
|
37507
37518
|
}
|
|
37508
37519
|
function setArraySelector(part, selector) {
|
|
37509
37520
|
selectors.set(part, selector);
|
|
@@ -37543,21 +37554,22 @@ function removePrefix(word, length, budget) {
|
|
|
37543
37554
|
if (length !== 0) throw new ShellSyntaxError("Invalid indexed-array assignment", word.offset);
|
|
37544
37555
|
return { offset: word.offset, parts };
|
|
37545
37556
|
}
|
|
37546
|
-
function elementAssignment(word, budget = new ParseBudget()) {
|
|
37557
|
+
function elementAssignment(word, budget = new ParseBudget(), parseWord, subscriptEnd) {
|
|
37547
37558
|
const source2 = word.spelling;
|
|
37548
37559
|
const first = word.parts[0];
|
|
37549
37560
|
if (source2 === void 0 || first?.kind !== "text" || first.quoted) return void 0;
|
|
37550
37561
|
const name2 = /^([a-zA-Z_][a-zA-Z_0-9]*)\[/u.exec(source2)?.[1];
|
|
37551
37562
|
if (!name2) return void 0;
|
|
37552
|
-
const end = source2.indexOf("]", name2.length + 1);
|
|
37563
|
+
const end = subscriptEnd ? subscriptEnd(source2, name2.length + 1) : source2.indexOf("]", name2.length + 1);
|
|
37553
37564
|
if (end < 0 || !/^(?:\+?=)/u.test(source2.slice(end + 1))) {
|
|
37554
37565
|
if (source2.includes("=")) throw new ShellSyntaxError("Invalid indexed-array assignment", word.offset);
|
|
37555
37566
|
return void 0;
|
|
37556
37567
|
}
|
|
37557
37568
|
budget.admit();
|
|
37558
|
-
const
|
|
37569
|
+
const keySource = source2.slice(name2.length + 1, end);
|
|
37570
|
+
const index = parseWord ? stringIndex(keySource, budget, parseWord(keySource)) : literalIndex(keySource, word.offset + name2.length + 1, budget);
|
|
37559
37571
|
const append = source2[end + 1] === "+";
|
|
37560
|
-
const value2 = removePrefix(word, name2.length + index.decimal.length + (append ? 4 : 3), budget);
|
|
37572
|
+
const value2 = parseWord ? parseWord(source2.slice(end + (append ? 3 : 2))) : removePrefix(word, name2.length + index.decimal.length + (append ? 4 : 3), budget);
|
|
37561
37573
|
return { kind: "element", name: name2, index, append, value: value2 };
|
|
37562
37574
|
}
|
|
37563
37575
|
function compoundHead(word, budget = new ParseBudget()) {
|
|
@@ -38316,7 +38328,7 @@ shell: command substitution: line ${line}: \`${sourceLine}'
|
|
|
38316
38328
|
if (!name2) this.error("Unsupported parameter expansion");
|
|
38317
38329
|
this.position += name2.length;
|
|
38318
38330
|
let prefixNames;
|
|
38319
|
-
if (listing) {
|
|
38331
|
+
if (listing && this.source[this.position] !== "[") {
|
|
38320
38332
|
const separator = this.source[this.position];
|
|
38321
38333
|
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name2) || separator !== "*" && separator !== "@" || this.source[this.position + 1] !== "}") this.error("Unsupported indirect parameter expansion");
|
|
38322
38334
|
prefixNames = separator;
|
|
@@ -38326,12 +38338,14 @@ shell: command substitution: line ${line}: \`${sourceLine}'
|
|
|
38326
38338
|
if (this.source[this.position] === "[") {
|
|
38327
38339
|
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name2)) this.error("Unsupported indexed-array parameter");
|
|
38328
38340
|
const start = ++this.position;
|
|
38329
|
-
const
|
|
38330
|
-
|
|
38331
|
-
|
|
38341
|
+
const keyWord = this.word("]");
|
|
38342
|
+
const end = this.position;
|
|
38343
|
+
if (this.source[end] !== "]") this.error("Unterminated indexed-array subscript");
|
|
38344
|
+
selector = arraySelector(this.source.slice(start, end), start, this.budget, keyWord);
|
|
38332
38345
|
this.position = end + 1;
|
|
38333
38346
|
if (this.source[this.position] !== "}" && this.source[this.position] !== "@") this.error("Unsupported indexed-array operator");
|
|
38334
38347
|
}
|
|
38348
|
+
if (listing && selector?.kind === "element") this.error("Unsupported indirect parameter expansion");
|
|
38335
38349
|
let transform2;
|
|
38336
38350
|
if (this.source[this.position] === "@") {
|
|
38337
38351
|
const operation2 = this.source[this.position + 1];
|
|
@@ -38382,6 +38396,7 @@ shell: command substitution: line ${line}: \`${sourceLine}'
|
|
|
38382
38396
|
} else {
|
|
38383
38397
|
this.position++;
|
|
38384
38398
|
const part = { kind: "variable", name: name2, quoted: quoted2, line, ...prefixNames ? { prefixNames } : {}, ...transform2 ? { transform: transform2 } : {}, ...length ? { length } : {}, ...operator ? { operator, alternate } : {}, ...replacement ? { replacement } : {}, ...substring ? { substring } : {} };
|
|
38399
|
+
if (listing && selector) part.keys = true;
|
|
38385
38400
|
if (selector) setArraySelector(part, selector);
|
|
38386
38401
|
parts.push(part);
|
|
38387
38402
|
}
|
|
@@ -38756,7 +38771,12 @@ var Parser4 = class {
|
|
|
38756
38771
|
word = { offset: word.offset, parts: word.parts, spelling: this.lexer.source.slice(word.offset, end) };
|
|
38757
38772
|
setArrayAssignment(word, { kind: "compound", ...head, entries: entries2 });
|
|
38758
38773
|
} else {
|
|
38759
|
-
const assignment = words.every((previous) => getArrayAssignment(previous) || scalarAssignmentName(previous)) ? elementAssignment(word, this.budget)
|
|
38774
|
+
const assignment = words.every((previous) => getArrayAssignment(previous) || scalarAssignmentName(previous)) ? elementAssignment(word, this.budget, (source2) => parseArraySubscript(source2, this.budget, this.lexer.byteLocale, this.lexer.depth), (source2, start) => {
|
|
38775
|
+
const lexer = new Lexer2(this.budget, source2, this.lexer.depth, [], 0, this.lexer.byteLocale);
|
|
38776
|
+
lexer.position = start;
|
|
38777
|
+
lexer.word("]");
|
|
38778
|
+
return lexer.source[lexer.position] === "]" ? lexer.position : -1;
|
|
38779
|
+
}) : void 0;
|
|
38760
38780
|
if (assignment) setArrayAssignment(word, assignment);
|
|
38761
38781
|
}
|
|
38762
38782
|
words.push(word);
|
|
@@ -38798,6 +38818,10 @@ function parseShell(source2, depth = 0, options3 = {}) {
|
|
|
38798
38818
|
budget.admit();
|
|
38799
38819
|
return { ...script, ...warnings.length ? { warnings } : {} };
|
|
38800
38820
|
}
|
|
38821
|
+
function parseArraySubscript(source2, budget, byteLocale2 = false, depth = 0) {
|
|
38822
|
+
const lexer = new Lexer2(budget, source2, depth, [], 0, byteLocale2);
|
|
38823
|
+
return lexer.word("\0");
|
|
38824
|
+
}
|
|
38801
38825
|
function parseBraceWord(source2, opaque, budget) {
|
|
38802
38826
|
budget.admit(source2.length + 1);
|
|
38803
38827
|
const lexer = new Lexer2(budget, source2, 0);
|
|
@@ -40879,14 +40903,16 @@ var controlNames = /* @__PURE__ */ new Set([
|
|
|
40879
40903
|
"LC_CTYPE"
|
|
40880
40904
|
]);
|
|
40881
40905
|
var OwnedText = class {
|
|
40882
|
-
constructor(value2, bytes3, admission) {
|
|
40906
|
+
constructor(value2, bytes3, admission, rawValue) {
|
|
40883
40907
|
this.value = value2;
|
|
40884
40908
|
this.bytes = bytes3;
|
|
40885
40909
|
this.admission = admission;
|
|
40910
|
+
this.rawValue = rawValue;
|
|
40886
40911
|
}
|
|
40887
40912
|
value;
|
|
40888
40913
|
bytes;
|
|
40889
40914
|
admission;
|
|
40915
|
+
rawValue;
|
|
40890
40916
|
references = 1;
|
|
40891
40917
|
retain() {
|
|
40892
40918
|
if (this.references === Number.MAX_SAFE_INTEGER) throw new ArrayFailure("reference capacity is not representable");
|
|
@@ -40912,27 +40938,110 @@ async function textToken(owner, value2, signal) {
|
|
|
40912
40938
|
const admission = owner.reserve({ payload: bytes3, metadata: 32, work: 4 });
|
|
40913
40939
|
return new OwnedText(value2, bytes3, admission);
|
|
40914
40940
|
}
|
|
40941
|
+
async function valueToken(owner, value2, signal) {
|
|
40942
|
+
if (typeof value2 === "string") return textToken(owner, value2, signal);
|
|
40943
|
+
const bytes3 = shellValueByteLength(value2);
|
|
40944
|
+
const temporary = owner.reserve({ payload: bytes3 * 3, metadata: 64, work: 4 });
|
|
40945
|
+
try {
|
|
40946
|
+
const input3 = shellValueBytes(value2);
|
|
40947
|
+
const decoder2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
40948
|
+
let text3 = "";
|
|
40949
|
+
for (let offset = 0; offset < bytes3; offset += 1024) {
|
|
40950
|
+
const end = Math.min(bytes3, offset + 1024);
|
|
40951
|
+
owner.reserve({ work: end - offset }).release();
|
|
40952
|
+
await owner.ledger.checkpoint(signal, end - offset);
|
|
40953
|
+
if (text3 !== void 0) try {
|
|
40954
|
+
text3 += decoder2.decode(input3.subarray(offset, end), { stream: end < bytes3 });
|
|
40955
|
+
} catch (error) {
|
|
40956
|
+
if (!(error instanceof TypeError) || "code" in error && error.code !== "ERR_ENCODING_INVALID_ENCODED_DATA") throw error;
|
|
40957
|
+
text3 = void 0;
|
|
40958
|
+
}
|
|
40959
|
+
}
|
|
40960
|
+
if (text3 !== void 0) return await textToken(owner, text3, signal);
|
|
40961
|
+
const admission = owner.reserve({ payload: bytes3 * 4, metadata: 128, work: 4 });
|
|
40962
|
+
try {
|
|
40963
|
+
const raw = shellValueFromBytes(input3);
|
|
40964
|
+
return new OwnedText(shellValueText(raw), bytes3, admission, raw);
|
|
40965
|
+
} catch (error) {
|
|
40966
|
+
admission.release();
|
|
40967
|
+
throw error;
|
|
40968
|
+
}
|
|
40969
|
+
} finally {
|
|
40970
|
+
temporary.release();
|
|
40971
|
+
}
|
|
40972
|
+
}
|
|
40915
40973
|
var IndexedBinding = class _IndexedBinding {
|
|
40916
|
-
constructor(owner) {
|
|
40974
|
+
constructor(owner, associative = false) {
|
|
40917
40975
|
this.owner = owner;
|
|
40976
|
+
this.associative = associative;
|
|
40918
40977
|
}
|
|
40919
40978
|
owner;
|
|
40979
|
+
associative;
|
|
40920
40980
|
values = /* @__PURE__ */ new Map();
|
|
40981
|
+
keys = /* @__PURE__ */ new Map();
|
|
40982
|
+
keyByIndex = /* @__PURE__ */ new Map();
|
|
40921
40983
|
maximum = -1;
|
|
40922
40984
|
generation = 0;
|
|
40923
40985
|
version = 0;
|
|
40924
40986
|
references = 1;
|
|
40925
40987
|
assigned = false;
|
|
40926
|
-
static create(parent) {
|
|
40988
|
+
static create(parent, associative = false) {
|
|
40927
40989
|
const owner = ArrayOwner.create(parent.ledger, parent);
|
|
40928
40990
|
try {
|
|
40929
40991
|
owner.reserve({ wrappers: 1, metadata: 128, work: 7 });
|
|
40930
|
-
return new _IndexedBinding(owner);
|
|
40992
|
+
return new _IndexedBinding(owner, associative);
|
|
40931
40993
|
} catch (error) {
|
|
40932
40994
|
void owner.close();
|
|
40933
40995
|
throw error;
|
|
40934
40996
|
}
|
|
40935
40997
|
}
|
|
40998
|
+
async keyIdentity(value2, owner, signal) {
|
|
40999
|
+
const length = shellValueByteLength(value2);
|
|
41000
|
+
if (!length) throw new ArrayFailure("bad array subscript");
|
|
41001
|
+
const admission = owner.reserve({ payload: length * 5, metadata: 64 + length * 16, work: length + 2 });
|
|
41002
|
+
try {
|
|
41003
|
+
const bytes3 = shellValueBytes(value2);
|
|
41004
|
+
const parts = [];
|
|
41005
|
+
for (const byte of bytes3) {
|
|
41006
|
+
parts.push(byte.toString(16).padStart(2, "0"));
|
|
41007
|
+
await owner.ledger.checkpoint(signal);
|
|
41008
|
+
}
|
|
41009
|
+
return parts.join("");
|
|
41010
|
+
} finally {
|
|
41011
|
+
admission.release();
|
|
41012
|
+
}
|
|
41013
|
+
}
|
|
41014
|
+
async keyIndex(value2, owner, signal, create = false) {
|
|
41015
|
+
const identity2 = await this.keyIdentity(value2, owner, signal);
|
|
41016
|
+
const existing2 = this.keys.get(identity2);
|
|
41017
|
+
if (existing2 || !create) return existing2?.index;
|
|
41018
|
+
const index = this.maximum + 1;
|
|
41019
|
+
const admission = this.owner.reserve({ metadata: 128 + identity2.length * 2, work: 8 });
|
|
41020
|
+
let text3;
|
|
41021
|
+
try {
|
|
41022
|
+
text3 = await valueToken(this.owner, value2, signal);
|
|
41023
|
+
} catch (error) {
|
|
41024
|
+
admission.release();
|
|
41025
|
+
throw error;
|
|
41026
|
+
}
|
|
41027
|
+
const entry = { index, text: text3, admission };
|
|
41028
|
+
admission.cleanup = () => {
|
|
41029
|
+
if (this.keys.get(identity2) === entry) {
|
|
41030
|
+
this.keys.delete(identity2);
|
|
41031
|
+
this.keyByIndex.delete(index);
|
|
41032
|
+
}
|
|
41033
|
+
text3.release();
|
|
41034
|
+
};
|
|
41035
|
+
this.keys.set(identity2, entry);
|
|
41036
|
+
this.keyByIndex.set(index, identity2);
|
|
41037
|
+
this.maximum = index;
|
|
41038
|
+
return index;
|
|
41039
|
+
}
|
|
41040
|
+
remove(index) {
|
|
41041
|
+
this.values.get(index)?.slot.release();
|
|
41042
|
+
const identity2 = this.keyByIndex.get(index);
|
|
41043
|
+
if (identity2 !== void 0) this.keys.get(identity2)?.admission.release();
|
|
41044
|
+
}
|
|
40936
41045
|
get(index) {
|
|
40937
41046
|
return this.values.get(index)?.text.value;
|
|
40938
41047
|
}
|
|
@@ -40959,13 +41068,30 @@ var IndexedBinding = class _IndexedBinding {
|
|
|
40959
41068
|
previous?.slot.release();
|
|
40960
41069
|
}
|
|
40961
41070
|
async copy(signal) {
|
|
40962
|
-
const copy2 = _IndexedBinding.create(this.owner.parent);
|
|
41071
|
+
const copy2 = _IndexedBinding.create(this.owner.parent, this.associative);
|
|
40963
41072
|
copy2.assigned = this.assigned;
|
|
40964
41073
|
this.retain();
|
|
40965
41074
|
try {
|
|
41075
|
+
for (const [identity2, entry] of this.keys) {
|
|
41076
|
+
const admission = copy2.owner.reserve({ metadata: 128 + identity2.length * 2, work: identity2.length + 8 });
|
|
41077
|
+
copy2.owner.parent.adopt(entry.text.admission);
|
|
41078
|
+
const text3 = entry.text.retain();
|
|
41079
|
+
const cloned = { index: entry.index, text: text3, admission };
|
|
41080
|
+
admission.cleanup = () => {
|
|
41081
|
+
if (copy2.keys.get(identity2) === cloned) {
|
|
41082
|
+
copy2.keys.delete(identity2);
|
|
41083
|
+
copy2.keyByIndex.delete(entry.index);
|
|
41084
|
+
}
|
|
41085
|
+
text3.release();
|
|
41086
|
+
};
|
|
41087
|
+
copy2.keys.set(identity2, cloned);
|
|
41088
|
+
copy2.keyByIndex.set(entry.index, identity2);
|
|
41089
|
+
await copy2.owner.ledger.checkpoint(signal, identity2.length + 8);
|
|
41090
|
+
}
|
|
40966
41091
|
for (const [index, element] of this.values) {
|
|
40967
41092
|
copy2.owner.reserve({ work: 2 }).release();
|
|
40968
41093
|
const slot = copy2.owner.reserve({ slots: 1, metadata: 32, work: 5 });
|
|
41094
|
+
copy2.owner.parent.adopt(element.text.admission);
|
|
40969
41095
|
const text3 = element.text.retain();
|
|
40970
41096
|
const cloned = { text: text3, slot };
|
|
40971
41097
|
slot.cleanup = () => {
|
|
@@ -41148,6 +41274,116 @@ var BindingStore = class _BindingStore {
|
|
|
41148
41274
|
}
|
|
41149
41275
|
};
|
|
41150
41276
|
|
|
41277
|
+
// packages/safe-bash/src/shell/mapfile.ts
|
|
41278
|
+
init_platform();
|
|
41279
|
+
var MapfileUsageError = class extends Error {
|
|
41280
|
+
constructor(message3, status2) {
|
|
41281
|
+
super(message3);
|
|
41282
|
+
this.status = status2;
|
|
41283
|
+
}
|
|
41284
|
+
status;
|
|
41285
|
+
};
|
|
41286
|
+
async function mapfileOptions(context2, work, allocation) {
|
|
41287
|
+
const options3 = { name: "MAPFILE", strip: false, delimiter: 10, count: 0, skip: 0, origin: 0, preserve: false, callback: void 0, quantum: 5e3 };
|
|
41288
|
+
const args = getCommandArguments(context2);
|
|
41289
|
+
let cursor = 0;
|
|
41290
|
+
const numeric4 = async (text3, maximum) => {
|
|
41291
|
+
let value2 = 0;
|
|
41292
|
+
let index = 0;
|
|
41293
|
+
const whitespace2 = (code) => code === 32 || code >= 9 && code <= 13;
|
|
41294
|
+
while (index < text3.length && whitespace2(text3.charCodeAt(index))) {
|
|
41295
|
+
const pending = stringCheckpoint(work);
|
|
41296
|
+
if (pending) await pending;
|
|
41297
|
+
index++;
|
|
41298
|
+
}
|
|
41299
|
+
const negative = text3[index] === "-";
|
|
41300
|
+
if (negative || text3[index] === "+") index++;
|
|
41301
|
+
let digits = 0;
|
|
41302
|
+
for (; index < text3.length; index++) {
|
|
41303
|
+
const pending = stringCheckpoint(work);
|
|
41304
|
+
if (pending) await pending;
|
|
41305
|
+
const digit3 = text3.charCodeAt(index) - 48;
|
|
41306
|
+
if (digit3 < 0 || digit3 > 9) break;
|
|
41307
|
+
if (value2 > Math.floor((maximum - digit3) / 10)) throw new MapfileUsageError(`${text3}: invalid number`, 1);
|
|
41308
|
+
value2 = value2 * 10 + digit3;
|
|
41309
|
+
digits++;
|
|
41310
|
+
}
|
|
41311
|
+
for (; index < text3.length; index++) {
|
|
41312
|
+
const pending = stringCheckpoint(work);
|
|
41313
|
+
if (pending) await pending;
|
|
41314
|
+
if (!whitespace2(text3.charCodeAt(index))) throw new MapfileUsageError(`${text3}: invalid number`, 1);
|
|
41315
|
+
}
|
|
41316
|
+
if (!digits || negative && value2 !== 0) throw new MapfileUsageError(`${text3}: invalid number`, 1);
|
|
41317
|
+
return value2;
|
|
41318
|
+
};
|
|
41319
|
+
while (cursor < context2.args.length) {
|
|
41320
|
+
const option = context2.args[cursor];
|
|
41321
|
+
if (option === "--") {
|
|
41322
|
+
cursor++;
|
|
41323
|
+
break;
|
|
41324
|
+
}
|
|
41325
|
+
if (!option.startsWith("-") || option === "-") break;
|
|
41326
|
+
cursor++;
|
|
41327
|
+
for (let index = 1; index < option.length; index++) {
|
|
41328
|
+
const pending = stringCheckpoint(work);
|
|
41329
|
+
if (pending) await pending;
|
|
41330
|
+
const flag = option[index];
|
|
41331
|
+
if (flag === "t") {
|
|
41332
|
+
options3.strip = true;
|
|
41333
|
+
continue;
|
|
41334
|
+
}
|
|
41335
|
+
if (!"dnsOCc".includes(flag)) throw new MapfileUsageError(`-${flag}: invalid option`, 2);
|
|
41336
|
+
const attached = index + 1 < option.length;
|
|
41337
|
+
const operandIndex = attached ? cursor - 1 : cursor++;
|
|
41338
|
+
const operand = attached ? option.slice(index + 1) : context2.args[operandIndex];
|
|
41339
|
+
if (operand === void 0) throw new MapfileUsageError(`-${flag}: option requires an argument`, 2);
|
|
41340
|
+
if (flag === "d") {
|
|
41341
|
+
const bytes3 = shellValueBytes(args.values[operandIndex], allocation);
|
|
41342
|
+
options3.delimiter = bytes3[attached ? index + 1 : 0] ?? 0;
|
|
41343
|
+
} else if (flag === "C") options3.callback = operand;
|
|
41344
|
+
else {
|
|
41345
|
+
const value2 = await numeric4(operand, flag === "O" ? 2147483647 : Number.MAX_SAFE_INTEGER);
|
|
41346
|
+
if (flag === "c") {
|
|
41347
|
+
if (!value2) throw new MapfileUsageError("0: invalid callback quantum", 1);
|
|
41348
|
+
options3.quantum = value2;
|
|
41349
|
+
} else if (flag === "n") options3.count = value2;
|
|
41350
|
+
else if (flag === "s") options3.skip = value2;
|
|
41351
|
+
else {
|
|
41352
|
+
options3.origin = value2;
|
|
41353
|
+
options3.preserve = true;
|
|
41354
|
+
}
|
|
41355
|
+
}
|
|
41356
|
+
break;
|
|
41357
|
+
}
|
|
41358
|
+
}
|
|
41359
|
+
options3.name = context2.args[cursor] ?? "MAPFILE";
|
|
41360
|
+
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(options3.name)) throw new MapfileUsageError(`${options3.name}: invalid identifier`, 1);
|
|
41361
|
+
return options3;
|
|
41362
|
+
}
|
|
41363
|
+
async function collectMapfile(options3, input3, hooks) {
|
|
41364
|
+
let skipped = 0;
|
|
41365
|
+
let written = 0;
|
|
41366
|
+
while (!options3.count || written < options3.count) {
|
|
41367
|
+
hooks.loop();
|
|
41368
|
+
const allocation = hooks.allocation();
|
|
41369
|
+
try {
|
|
41370
|
+
const record4 = await input3.mapfileRecord(options3.delimiter, options3.strip, allocation);
|
|
41371
|
+
if (!record4.present) break;
|
|
41372
|
+
if (skipped < options3.skip) {
|
|
41373
|
+
skipped++;
|
|
41374
|
+
continue;
|
|
41375
|
+
}
|
|
41376
|
+
const index = options3.origin + written;
|
|
41377
|
+
if (index > 2147483647) throw new MapfileUsageError("array index exceeds 2147483647", 1);
|
|
41378
|
+
if (options3.callback !== void 0 && (written + 1) % options3.quantum === 0) await hooks.callback(options3.callback, index, record4.value);
|
|
41379
|
+
await hooks.write(index, record4.value);
|
|
41380
|
+
written++;
|
|
41381
|
+
} finally {
|
|
41382
|
+
allocation.close();
|
|
41383
|
+
}
|
|
41384
|
+
}
|
|
41385
|
+
}
|
|
41386
|
+
|
|
41151
41387
|
// packages/safe-bash/src/shell/arrays/state.ts
|
|
41152
41388
|
init_platform();
|
|
41153
41389
|
var sessions = /* @__PURE__ */ new WeakMap();
|
|
@@ -41909,6 +42145,9 @@ var shellBuiltinNames = /* @__PURE__ */ new Set([
|
|
|
41909
42145
|
"local",
|
|
41910
42146
|
"unset",
|
|
41911
42147
|
"read",
|
|
42148
|
+
"declare",
|
|
42149
|
+
"mapfile",
|
|
42150
|
+
"readarray",
|
|
41912
42151
|
"exit",
|
|
41913
42152
|
"return",
|
|
41914
42153
|
"break",
|
|
@@ -42907,6 +43146,7 @@ var InvocationCancellationOwner = class {
|
|
|
42907
43146
|
this.#failures.push(...result2.failures);
|
|
42908
43147
|
}
|
|
42909
43148
|
};
|
|
43149
|
+
var mapfileCallbackStates = /* @__PURE__ */ new WeakSet();
|
|
42910
43150
|
var Runtime = class _Runtime {
|
|
42911
43151
|
constructor(fs, commands, middleware, budget, signal = budget.signal, fileWrites = /* @__PURE__ */ new Map(), outputFiles = /* @__PURE__ */ new Map(), commandSignal = signal, cancellation, cancellationState, cancellationOwner, cancellationDepth, cancellationMaxDepth, outcomeFrame = void 0, inputProfile = fs) {
|
|
42912
43152
|
this.fs = fs;
|
|
@@ -43247,7 +43487,7 @@ var Runtime = class _Runtime {
|
|
|
43247
43487
|
}
|
|
43248
43488
|
variable(state, name2) {
|
|
43249
43489
|
const binding = arrayStore(state)?.get(name2);
|
|
43250
|
-
return binding ? binding.get(0) : state.variables[name2];
|
|
43490
|
+
return binding ? binding.get(binding.associative ? binding.keys.get("30")?.index ?? -1 : 0) : state.variables[name2];
|
|
43251
43491
|
}
|
|
43252
43492
|
requireParameter(value2, name2, state, io, line) {
|
|
43253
43493
|
if (state.nounset && value2 === void 0) throw new NounsetFailure(`${name2}: unbound variable`, io.diagnosticLine ?? line);
|
|
@@ -43257,7 +43497,7 @@ var Runtime = class _Runtime {
|
|
|
43257
43497
|
this.writeVariable(state, name2, value2, origin);
|
|
43258
43498
|
return;
|
|
43259
43499
|
}
|
|
43260
|
-
await this.arrayZero(state, name2, async () =>
|
|
43500
|
+
await this.arrayZero(state, name2, async () => value2);
|
|
43261
43501
|
}
|
|
43262
43502
|
async prepareVariable(state, name2, saved, scalarLegacy = false) {
|
|
43263
43503
|
const store = requireArrays(state);
|
|
@@ -43383,7 +43623,7 @@ var Runtime = class _Runtime {
|
|
|
43383
43623
|
if (key !== index && key > maximum) maximum = key;
|
|
43384
43624
|
await operation2.ledger.checkpoint(this.signal, 2);
|
|
43385
43625
|
}
|
|
43386
|
-
if (typeof index === "number") staged.
|
|
43626
|
+
if (typeof index === "number") staged.remove(index);
|
|
43387
43627
|
staged.maximum = maximum;
|
|
43388
43628
|
}
|
|
43389
43629
|
this.signal.throwIfAborted();
|
|
@@ -43414,6 +43654,7 @@ var Runtime = class _Runtime {
|
|
|
43414
43654
|
const store = requireArrays(state);
|
|
43415
43655
|
const operation2 = ArrayOwner.create(store.owner.ledger, store.owner);
|
|
43416
43656
|
const holding = store.owner.hold();
|
|
43657
|
+
const valueAllocation = this.budget.values.scope();
|
|
43417
43658
|
let staged;
|
|
43418
43659
|
try {
|
|
43419
43660
|
const watch = await store.watch(name2, operation2, this.signal);
|
|
@@ -43430,10 +43671,12 @@ var Runtime = class _Runtime {
|
|
|
43430
43671
|
const current = store.get(name2);
|
|
43431
43672
|
if (!current) throw new ArrayFailure("stale binding");
|
|
43432
43673
|
staged = await current.copy(this.signal);
|
|
43433
|
-
const
|
|
43434
|
-
const
|
|
43674
|
+
const index = staged.associative ? await staged.keyIndex("0", operation2, this.signal, true) : 0;
|
|
43675
|
+
const previous = current.values.get(index)?.text.rawValue ?? current.get(index) ?? "";
|
|
43676
|
+
const value2 = !append ? expanded : typeof previous === "string" && typeof expanded === "string" ? await this.arrayJoin(operation2, [previous, expanded], "") : concatShellValues([previous, expanded], valueAllocation);
|
|
43677
|
+
const token = await valueToken(staged.owner, value2, this.signal);
|
|
43435
43678
|
try {
|
|
43436
|
-
staged.insert(
|
|
43679
|
+
staged.insert(index, token);
|
|
43437
43680
|
} catch (error) {
|
|
43438
43681
|
token.release();
|
|
43439
43682
|
throw error;
|
|
@@ -43459,6 +43702,7 @@ var Runtime = class _Runtime {
|
|
|
43459
43702
|
await staged?.release();
|
|
43460
43703
|
await operation2.close();
|
|
43461
43704
|
} finally {
|
|
43705
|
+
valueAllocation.close();
|
|
43462
43706
|
holding.release();
|
|
43463
43707
|
}
|
|
43464
43708
|
}
|
|
@@ -43477,10 +43721,33 @@ var Runtime = class _Runtime {
|
|
|
43477
43721
|
await owner.ledger.checkpoint(this.signal);
|
|
43478
43722
|
return result2;
|
|
43479
43723
|
}
|
|
43724
|
+
async arrayIndex(binding, index, state, io, owner, create = false) {
|
|
43725
|
+
if (!binding?.associative) {
|
|
43726
|
+
const selected = index.source === void 0 ? index : literalIndex(index.source, 0, this.budget.parsing);
|
|
43727
|
+
const number5 = numericIndex(selected);
|
|
43728
|
+
if (number5 === void 0) throw new ArrayFailure("index outside 0..2147483647");
|
|
43729
|
+
return number5;
|
|
43730
|
+
}
|
|
43731
|
+
const word = index.word ?? parseArraySubscript(index.source ?? index.decimal, this.budget.parsing, byteLocale(state.variables), state.depth);
|
|
43732
|
+
const fields3 = await this.valueWord(word, state, io, false);
|
|
43733
|
+
const value2 = fields3.length === 1 ? fields3[0] : concatShellValues(fields3, io[valueScope]);
|
|
43734
|
+
if (shellValueByteLength(value2) === 0) {
|
|
43735
|
+
await this.diagnostic(io, "associative array: bad array subscript");
|
|
43736
|
+
if (create) throw completedExit(1);
|
|
43737
|
+
return void 0;
|
|
43738
|
+
}
|
|
43739
|
+
return binding.keyIndex(value2, owner, this.signal, create);
|
|
43740
|
+
}
|
|
43480
43741
|
async arrayAssignment(assignment, state, io) {
|
|
43481
43742
|
const name2 = assignment.name;
|
|
43482
43743
|
this.signal.throwIfAborted();
|
|
43483
|
-
if (state.readonlyVariables?.has(name2))
|
|
43744
|
+
if (state.readonlyVariables?.has(name2)) {
|
|
43745
|
+
if (arrayStore(state)?.get(name2)?.associative) {
|
|
43746
|
+
await this.diagnostic(io, `${name2}: readonly variable`);
|
|
43747
|
+
throw completedExit(1);
|
|
43748
|
+
}
|
|
43749
|
+
throw new ArrayFailure("readonly binding");
|
|
43750
|
+
}
|
|
43484
43751
|
if (controlNames.has(name2)) throw new ArrayFailure("control binding cannot be indexed");
|
|
43485
43752
|
if (state.exported.has(name2)) throw new ArrayFailure("exported binding cannot be indexed");
|
|
43486
43753
|
const store = requireArrays(state);
|
|
@@ -43490,11 +43757,12 @@ var Runtime = class _Runtime {
|
|
|
43490
43757
|
try {
|
|
43491
43758
|
const watch = await store.watch(name2, operation2, this.signal);
|
|
43492
43759
|
const current = store.get(name2);
|
|
43760
|
+
if (current?.associative && assignment.kind === "compound" && assignment.entries.length) throw new ArrayFailure("nonempty associative compound assignment is unsupported");
|
|
43493
43761
|
const initialMaximum = current?.maximum ?? (state.variables[name2] === void 0 ? -1 : 0);
|
|
43494
43762
|
let planned = assignment.append && assignment.kind === "compound" ? initialMaximum + 1 : 0;
|
|
43495
43763
|
if (assignment.kind === "element") {
|
|
43496
43764
|
operation2.reserve({ work: assignment.index.decimal.length + 1 }).release();
|
|
43497
|
-
if (numericIndex(assignment.index) === void 0) throw new ArrayFailure("index outside 0..2147483647");
|
|
43765
|
+
if (!current?.associative && numericIndex(literalIndex(assignment.index.source ?? assignment.index.decimal, 0, this.budget.parsing)) === void 0) throw new ArrayFailure("index outside 0..2147483647");
|
|
43498
43766
|
} else for (const entry of assignment.entries) {
|
|
43499
43767
|
operation2.reserve({ work: entry.value.parts.length + (entry.index?.decimal.length ?? 0) + 2 }).release();
|
|
43500
43768
|
if (entry.index) {
|
|
@@ -43520,9 +43788,9 @@ var Runtime = class _Runtime {
|
|
|
43520
43788
|
const tickets = operation2.reserve({ generation: true, version: true, epoch: true, work: 8 });
|
|
43521
43789
|
const prepared = await store.prepareName(name2, operation2, this.signal);
|
|
43522
43790
|
const preserve = assignment.kind === "element" || assignment.append;
|
|
43523
|
-
staged = preserve && current ? await current.copy(this.signal) : IndexedBinding.create(store.owner);
|
|
43791
|
+
staged = preserve && current ? await current.copy(this.signal) : IndexedBinding.create(store.owner, current?.associative);
|
|
43524
43792
|
if (preserve && !current && state.variables[name2] !== void 0) {
|
|
43525
|
-
const token = await
|
|
43793
|
+
const token = await valueToken(staged.owner, stateMonitor(state)?.values.get(name2, state.variables[name2]) ?? state.variables[name2], this.signal);
|
|
43526
43794
|
try {
|
|
43527
43795
|
staged.insert(0, token);
|
|
43528
43796
|
} catch (error) {
|
|
@@ -43534,7 +43802,7 @@ var Runtime = class _Runtime {
|
|
|
43534
43802
|
let cursor = assignment.append && assignment.kind === "compound" ? initialMaximum + 1 : 0;
|
|
43535
43803
|
const insert = async (index, value2) => {
|
|
43536
43804
|
if (index > 2147483647) throw new ArrayFailure("index outside 0..2147483647");
|
|
43537
|
-
const token = await
|
|
43805
|
+
const token = await valueToken(staged.owner, value2, this.signal);
|
|
43538
43806
|
try {
|
|
43539
43807
|
staged.insert(index, token);
|
|
43540
43808
|
} catch (error) {
|
|
@@ -43543,11 +43811,12 @@ var Runtime = class _Runtime {
|
|
|
43543
43811
|
}
|
|
43544
43812
|
writes++;
|
|
43545
43813
|
};
|
|
43814
|
+
const join = async (values) => values.every((value2) => typeof value2 === "string") ? this.arrayJoin(operation2, values, "") : concatShellValues(values, io[valueScope]);
|
|
43546
43815
|
if (assignment.kind === "element") {
|
|
43547
|
-
const index =
|
|
43548
|
-
const fields3 = await this.
|
|
43549
|
-
let value2 = await
|
|
43550
|
-
if (assignment.append) value2 = await
|
|
43816
|
+
const index = await this.arrayIndex(staged, assignment.index, state, io, operation2, true);
|
|
43817
|
+
const fields3 = await this.valueWord(assignment.value, state, io, false);
|
|
43818
|
+
let value2 = await join(fields3);
|
|
43819
|
+
if (assignment.append) value2 = await join([staged.values.get(index)?.text.rawValue ?? staged.get(index) ?? "", value2]);
|
|
43551
43820
|
await insert(index, value2);
|
|
43552
43821
|
} else for (const entry of assignment.entries) {
|
|
43553
43822
|
const original = compoundEntryWords.get(entry);
|
|
@@ -43558,16 +43827,16 @@ var Runtime = class _Runtime {
|
|
|
43558
43827
|
expandedEntry = true;
|
|
43559
43828
|
const values = await this.valueWord(expanded, state, io, true, false, false, false, void 0, false);
|
|
43560
43829
|
for (const value2 of values) {
|
|
43561
|
-
await insert(cursor,
|
|
43830
|
+
await insert(cursor, value2);
|
|
43562
43831
|
cursor++;
|
|
43563
43832
|
}
|
|
43564
43833
|
}
|
|
43565
43834
|
if (expandedEntry) continue;
|
|
43566
43835
|
}
|
|
43567
|
-
const fields3 = await this.
|
|
43836
|
+
const fields3 = await this.valueWord(entry.value, state, io, entry.index === void 0);
|
|
43568
43837
|
if (entry.index) {
|
|
43569
43838
|
const index = numericIndex(entry.index);
|
|
43570
|
-
await insert(index, await
|
|
43839
|
+
await insert(index, await join(fields3));
|
|
43571
43840
|
cursor = index + 1;
|
|
43572
43841
|
} else for (const value2 of fields3) {
|
|
43573
43842
|
await insert(cursor, value2);
|
|
@@ -44458,8 +44727,8 @@ var Runtime = class _Runtime {
|
|
|
44458
44727
|
throw new ArrayFailure("indexed binding cannot be a command prefix");
|
|
44459
44728
|
}
|
|
44460
44729
|
await this.arrayZero(state, assignment.name, async () => {
|
|
44461
|
-
const fields3 = await this.
|
|
44462
|
-
return this.arrayJoin(requireArrays(state).owner, fields3, "");
|
|
44730
|
+
const fields3 = await this.valueWord(assignment.value, state, io, false);
|
|
44731
|
+
return fields3.every((value3) => typeof value3 === "string") ? this.arrayJoin(requireArrays(state).owner, fields3, "") : concatShellValues(fields3, io[valueScope]);
|
|
44463
44732
|
}, assignment.append);
|
|
44464
44733
|
continue;
|
|
44465
44734
|
}
|
|
@@ -44778,6 +45047,8 @@ var Runtime = class _Runtime {
|
|
|
44778
45047
|
functionRestoration?.close();
|
|
44779
45048
|
throw error;
|
|
44780
45049
|
}
|
|
45050
|
+
const callerLoopDepth = state.loopDepth;
|
|
45051
|
+
if (mapfileCallbackStates.has(state)) state.loopDepth = 0;
|
|
44781
45052
|
try {
|
|
44782
45053
|
return { exitCode: await this.command(body, state, { ...io, ...context3, scriptName: body.sourceName ?? io.scriptName ?? "shell" }) };
|
|
44783
45054
|
} catch (error) {
|
|
@@ -44791,6 +45062,7 @@ var Runtime = class _Runtime {
|
|
|
44791
45062
|
savedPositionals.close();
|
|
44792
45063
|
state.positionalSetVersion = positionalSetVersion;
|
|
44793
45064
|
state.functionDepth--;
|
|
45065
|
+
state.loopDepth = callerLoopDepth;
|
|
44794
45066
|
state.depth--;
|
|
44795
45067
|
state.locals.pop();
|
|
44796
45068
|
};
|
|
@@ -46262,12 +46534,120 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46262
46534
|
allocation.close();
|
|
46263
46535
|
}
|
|
46264
46536
|
}
|
|
46537
|
+
async mapfileBuiltin(context2, state) {
|
|
46538
|
+
const allocation = this.budget.values.scope();
|
|
46539
|
+
const work = { remaining: this.budget.limits.maxExpansionBytes * 8, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
|
|
46540
|
+
let pinned;
|
|
46541
|
+
let releaseHolding;
|
|
46542
|
+
try {
|
|
46543
|
+
const options3 = await mapfileOptions(context2, work, allocation);
|
|
46544
|
+
if (arrayStore(state)?.get(options3.name)?.associative) throw new MapfileUsageError(`${options3.name}: not an indexed array`, 1);
|
|
46545
|
+
if (state.readonlyVariables?.has(options3.name)) throw new MapfileUsageError(`${options3.name}: readonly variable`, 1);
|
|
46546
|
+
if (controlNames.has(options3.name) || state.exported.has(options3.name)) throw new ArrayFailure("control or exported binding cannot be indexed");
|
|
46547
|
+
const store = requireArrays(state);
|
|
46548
|
+
const holding = store.owner.hold();
|
|
46549
|
+
releaseHolding = () => holding.release();
|
|
46550
|
+
if (!options3.preserve || !store.get(options3.name)) await this.arrayAssignment({ kind: "compound", name: options3.name, append: options3.preserve, entries: [] }, state, context2);
|
|
46551
|
+
const entry = store.bindings.get(options3.name);
|
|
46552
|
+
allocation.reserve(128 + import_buffer.Buffer.byteLength(options3.name) * 2, 0);
|
|
46553
|
+
pinned = entry.binding.retain();
|
|
46554
|
+
const input3 = context2.stdin instanceof ShellInput ? context2.stdin : new ShellInput(context2.stdin, this.budget, this.signal);
|
|
46555
|
+
let pendingFlow;
|
|
46556
|
+
await collectMapfile(options3, input3, {
|
|
46557
|
+
allocation: () => this.budget.values.scope(),
|
|
46558
|
+
loop: () => this.budget.loop(),
|
|
46559
|
+
write: async (index, value2) => {
|
|
46560
|
+
if (pinned !== entry.binding) {
|
|
46561
|
+
const previous = pinned;
|
|
46562
|
+
pinned = entry.binding.retain();
|
|
46563
|
+
await previous.release();
|
|
46564
|
+
}
|
|
46565
|
+
const operation2 = ArrayOwner.create(store.owner.ledger, store.owner);
|
|
46566
|
+
let staged;
|
|
46567
|
+
try {
|
|
46568
|
+
const current = pinned;
|
|
46569
|
+
const attached = store.bindings.get(options3.name) === entry;
|
|
46570
|
+
const watch = attached ? await store.watch(options3.name, operation2, this.signal) : void 0;
|
|
46571
|
+
const supersede = attached ? await stateMonitor(state).prepareTypedPublication(options3.name, operation2, this.signal) : void 0;
|
|
46572
|
+
if (attached) await this.prepareArrayObservers(state, operation2);
|
|
46573
|
+
const tickets = operation2.reserve({ generation: true, version: true, epoch: true, work: 8 });
|
|
46574
|
+
staged = current.references > (attached ? 2 : 1) ? await current.copy(this.signal) : current.retain();
|
|
46575
|
+
const token = await valueToken(staged.owner, value2, this.signal);
|
|
46576
|
+
try {
|
|
46577
|
+
this.signal.throwIfAborted();
|
|
46578
|
+
if (watch && !watch.valid()) throw new ArrayFailure("stale binding");
|
|
46579
|
+
staged.insert(index, token);
|
|
46580
|
+
} catch (error) {
|
|
46581
|
+
token.release();
|
|
46582
|
+
throw error;
|
|
46583
|
+
}
|
|
46584
|
+
if (attached) {
|
|
46585
|
+
let released;
|
|
46586
|
+
stateMonitor(state).publish(tickets, options3.name, () => {
|
|
46587
|
+
supersede();
|
|
46588
|
+
released = store.publish(options3.name, staged, tickets);
|
|
46589
|
+
});
|
|
46590
|
+
staged = void 0;
|
|
46591
|
+
await released;
|
|
46592
|
+
} else {
|
|
46593
|
+
const previous = pinned;
|
|
46594
|
+
pinned = staged;
|
|
46595
|
+
entry.binding = staged;
|
|
46596
|
+
staged = void 0;
|
|
46597
|
+
await previous.release();
|
|
46598
|
+
}
|
|
46599
|
+
} finally {
|
|
46600
|
+
try {
|
|
46601
|
+
await staged?.release();
|
|
46602
|
+
} finally {
|
|
46603
|
+
await operation2.close();
|
|
46604
|
+
}
|
|
46605
|
+
}
|
|
46606
|
+
},
|
|
46607
|
+
callback: async (source2, index, value2) => {
|
|
46608
|
+
if (pendingFlow) return;
|
|
46609
|
+
const callbackAllocation = this.budget.values.scope();
|
|
46610
|
+
const nested = mapfileCallbackStates.has(state);
|
|
46611
|
+
try {
|
|
46612
|
+
const quoted2 = shellValueText(await transformParameter(value2, "Q", { maximumBytes: this.budget.limits.maxExpansionBytes, byteLocale: byteLocale(state.variables), work, allocation: callbackAllocation }));
|
|
46613
|
+
if (import_buffer.Buffer.byteLength(source2) + import_buffer.Buffer.byteLength(quoted2) + String(index).length + 2 > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
46614
|
+
mapfileCallbackStates.add(state);
|
|
46615
|
+
await this.evalBuiltin({ ...context2, args: [source2, String(index), quoted2] }, state, context2, false);
|
|
46616
|
+
} catch (error) {
|
|
46617
|
+
if (error instanceof Flow2 && (error.kind === "break" || error.kind === "continue")) pendingFlow = error;
|
|
46618
|
+
else throw error;
|
|
46619
|
+
} finally {
|
|
46620
|
+
if (!nested) mapfileCallbackStates.delete(state);
|
|
46621
|
+
callbackAllocation.close();
|
|
46622
|
+
}
|
|
46623
|
+
}
|
|
46624
|
+
});
|
|
46625
|
+
if (pendingFlow) throw pendingFlow;
|
|
46626
|
+
return 0;
|
|
46627
|
+
} catch (error) {
|
|
46628
|
+
this.signal.throwIfAborted();
|
|
46629
|
+
if (!(error instanceof MapfileUsageError)) throw error;
|
|
46630
|
+
await this.diagnostic(context2, `${context2.command}: ${error.message}`);
|
|
46631
|
+
return error.status;
|
|
46632
|
+
} finally {
|
|
46633
|
+
try {
|
|
46634
|
+
await pinned?.release();
|
|
46635
|
+
} finally {
|
|
46636
|
+
try {
|
|
46637
|
+
releaseHolding?.();
|
|
46638
|
+
} finally {
|
|
46639
|
+
allocation.close();
|
|
46640
|
+
}
|
|
46641
|
+
}
|
|
46642
|
+
}
|
|
46643
|
+
}
|
|
46265
46644
|
async builtin(context2, state, assignments2, diagnose, suppressSpecial = false) {
|
|
46266
46645
|
const { command: command7, args, stdout, stderr } = context2;
|
|
46267
46646
|
if (command7 === ":" || command7 === "true") return 0;
|
|
46268
46647
|
if (command7 === "false") return 1;
|
|
46269
46648
|
if (command7 === "shopt") return this.shoptBuiltin(context2, state);
|
|
46270
46649
|
if (command7 === "let") return this.letBuiltin(context2, state);
|
|
46650
|
+
if (command7 === "mapfile" || command7 === "readarray") return this.mapfileBuiltin(context2, state);
|
|
46271
46651
|
if (command7 === "getopts") return this.getoptsBuiltin(context2, state);
|
|
46272
46652
|
if (command7 === "pushd" || command7 === "dirs" || command7 === "popd") return this.directoryStackBuiltin(context2, state, diagnose);
|
|
46273
46653
|
if (command7 === "pwd") {
|
|
@@ -46332,9 +46712,16 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46332
46712
|
this.replacePositionals(state, this.positionalValues(state).slice(count2));
|
|
46333
46713
|
return 0;
|
|
46334
46714
|
}
|
|
46335
|
-
if (command7 === "export" || command7 === "local" || command7 === "readonly") {
|
|
46715
|
+
if (command7 === "export" || command7 === "local" || command7 === "readonly" || command7 === "declare") {
|
|
46716
|
+
const associativeDeclaration = command7 === "declare";
|
|
46336
46717
|
const declarationArgs = [...args];
|
|
46337
|
-
let indexedLocal =
|
|
46718
|
+
let indexedLocal = associativeDeclaration;
|
|
46719
|
+
if (associativeDeclaration) {
|
|
46720
|
+
if (declarationArgs.shift() !== "-A" || !declarationArgs.length) {
|
|
46721
|
+
await this.diagnostic(context2, "declare: only -A NAME is supported");
|
|
46722
|
+
return 2;
|
|
46723
|
+
}
|
|
46724
|
+
}
|
|
46338
46725
|
if (command7 === "local") {
|
|
46339
46726
|
const options3 = localDeclarationOptions(declarationArgs, this.signal);
|
|
46340
46727
|
if (options3.error !== void 0) {
|
|
@@ -46397,11 +46784,11 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46397
46784
|
status2 = 1;
|
|
46398
46785
|
continue;
|
|
46399
46786
|
}
|
|
46400
|
-
if (command7 === "local" && indexedLocal) {
|
|
46787
|
+
if ((command7 === "local" || associativeDeclaration) && indexedLocal) {
|
|
46401
46788
|
if (controlNames.has(name2)) throw new ArrayFailure("control binding cannot be indexed");
|
|
46402
46789
|
if (state.exported.has(name2)) throw new ArrayFailure("exported binding cannot be indexed");
|
|
46403
|
-
const existingLocal = locals
|
|
46404
|
-
const saved = existingLocal ? void 0 : assignments2.get(name2) ?? saveVariable(state, name2);
|
|
46790
|
+
const existingLocal = locals?.get(name2);
|
|
46791
|
+
const saved = !locals || existingLocal ? void 0 : assignments2.get(name2) ?? saveVariable(state, name2);
|
|
46405
46792
|
let operation2;
|
|
46406
46793
|
let holding;
|
|
46407
46794
|
let shadow;
|
|
@@ -46426,12 +46813,14 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46426
46813
|
const tickets = operation2.reserve({ generation: true, version: true, epoch: true, work: 8 });
|
|
46427
46814
|
const prepared = await store.prepareName(name2, operation2, this.signal);
|
|
46428
46815
|
const current = store.get(name2);
|
|
46429
|
-
|
|
46816
|
+
if (!saved && current && current.associative !== associativeDeclaration) throw new ArrayFailure("cannot convert array kind");
|
|
46817
|
+
shadow = !saved && current ? await current.copy(this.signal) : IndexedBinding.create(store.owner, associativeDeclaration);
|
|
46430
46818
|
const value2 = match[2] ?? (!saved && !current && Object.hasOwn(state.variables, name2) ? state.variables[name2] : void 0);
|
|
46431
46819
|
if (value2 !== void 0) {
|
|
46432
|
-
const
|
|
46820
|
+
const retained = associativeDeclaration && match[2] === void 0 ? stateMonitor(state).values.get(name2, value2) : value2;
|
|
46821
|
+
const token = await valueToken(shadow.owner, retained, this.signal);
|
|
46433
46822
|
try {
|
|
46434
|
-
shadow.insert(0, token);
|
|
46823
|
+
shadow.insert(associativeDeclaration ? await shadow.keyIndex("0", operation2, this.signal, true) : 0, token);
|
|
46435
46824
|
} catch (error) {
|
|
46436
46825
|
token.release();
|
|
46437
46826
|
throw error;
|
|
@@ -46579,7 +46968,8 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46579
46968
|
}
|
|
46580
46969
|
if (command7 === "unset") {
|
|
46581
46970
|
let status2 = 0;
|
|
46582
|
-
for (
|
|
46971
|
+
for (let argument2 = 0; argument2 < args.length; argument2++) {
|
|
46972
|
+
const name2 = args[argument2];
|
|
46583
46973
|
const selected = /^([a-zA-Z_][a-zA-Z_0-9]*)\[(.*)\]$/su.exec(name2);
|
|
46584
46974
|
if (selected) {
|
|
46585
46975
|
const base = selected[1];
|
|
@@ -46589,7 +46979,12 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46589
46979
|
status2 = 1;
|
|
46590
46980
|
continue;
|
|
46591
46981
|
}
|
|
46592
|
-
|
|
46982
|
+
const binding = arrayStore(state)?.get(base);
|
|
46983
|
+
if (binding?.associative) {
|
|
46984
|
+
const original = getCommandArguments(context2).values[argument2];
|
|
46985
|
+
const index = typeof original === "string" ? await this.arrayIndex(binding, { decimal: selector, source: selector }, state, context2, binding.owner) : await binding.keyIndex(shellValueFromBytes(shellValueBytes(original, context2[valueScope]).subarray(base.length + 1, shellValueByteLength(original) - 1), context2[valueScope]), binding.owner, this.signal);
|
|
46986
|
+
if (index !== void 0) await this.unsetIndexed(state, base, index);
|
|
46987
|
+
} else if (selector === "@" || selector === "*") await this.unsetIndexed(state, base, "members");
|
|
46593
46988
|
else {
|
|
46594
46989
|
let index;
|
|
46595
46990
|
try {
|
|
@@ -46823,7 +47218,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46823
47218
|
if (part.kind === "variable" && part.transform) {
|
|
46824
47219
|
const selector2 = getArraySelector(part);
|
|
46825
47220
|
if (selector2?.kind === "members" || part.name === "@" || part.name === "*") {
|
|
46826
|
-
const members = selector2 ? await this.arrayMembers(part.name, state) : this.positionalValues(state);
|
|
47221
|
+
const members = selector2 ? await this.arrayMembers(part.name, state, io, part.keys) : this.positionalValues(state);
|
|
46827
47222
|
const ifs = state.variables.IFS ?? " ";
|
|
46828
47223
|
const separator = ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
|
|
46829
47224
|
const fragments = [];
|
|
@@ -46863,10 +47258,22 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46863
47258
|
const binding = part.kind === "variable" ? arrayStore(state)?.get(part.name) : void 0;
|
|
46864
47259
|
const holding = binding ? requireArrays(state).owner.hold() : void 0;
|
|
46865
47260
|
const selector = getArraySelector(part);
|
|
46866
|
-
|
|
47261
|
+
if (selector?.kind === "element" && binding?.associative) {
|
|
47262
|
+
try {
|
|
47263
|
+
const index2 = await this.arrayIndex(binding, selector.index, state, io, binding.owner);
|
|
47264
|
+
const token2 = index2 === void 0 ? void 0 : binding.values.get(index2)?.text;
|
|
47265
|
+
this.requireParameter(token2?.value, part.kind === "variable" ? part.name : "", state, io);
|
|
47266
|
+
if (part.kind === "variable" && part.length) return this.parameterLength(token2?.value ?? "");
|
|
47267
|
+
return token2?.rawValue ? shellValueFromBytes(shellValueBytes(token2.rawValue, io[valueScope]), io[valueScope]) : token2?.value ?? "";
|
|
47268
|
+
} finally {
|
|
47269
|
+
holding?.release();
|
|
47270
|
+
}
|
|
47271
|
+
}
|
|
47272
|
+
const index = selector?.kind === "element" ? numericIndex(selector.index) : binding?.associative ? binding.keys.get("30")?.index : 0;
|
|
46867
47273
|
const token = index === void 0 || selector?.kind === "members" ? void 0 : binding?.values.get(index)?.text;
|
|
46868
47274
|
token?.retain();
|
|
46869
47275
|
try {
|
|
47276
|
+
if (token?.rawValue && part.kind === "variable" && !part.length && !part.operator && !part.substring) return shellValueFromBytes(shellValueBytes(token.rawValue, io[valueScope]), io[valueScope]);
|
|
46870
47277
|
const value2 = await this.partValue(part, state, io, hereString);
|
|
46871
47278
|
if (binding) await textToken(requireArrays(state).owner, shellValueText(value2), this.signal);
|
|
46872
47279
|
return value2;
|
|
@@ -46984,8 +47391,11 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46984
47391
|
return part.length ? this.parameterLength(value3 ?? "") : value3 ?? "";
|
|
46985
47392
|
}
|
|
46986
47393
|
if (part.length) return String(binding?.values.size ?? (state.variables[part.name] === void 0 ? 0 : 1));
|
|
46987
|
-
const values = await this.arrayMembers(part.name, state);
|
|
46988
|
-
|
|
47394
|
+
const values = await this.arrayMembers(part.name, state, io, part.keys);
|
|
47395
|
+
const separator = Array.from(state.variables.IFS ?? " ")[0] ?? "";
|
|
47396
|
+
if (values.every((value3) => typeof value3 === "string")) return this.arrayJoin(store.owner, values, separator);
|
|
47397
|
+
io[valueScope]?.reserve(values.length * 32 + 64, 0);
|
|
47398
|
+
return concatShellValues(values.flatMap((value3, index) => index ? [separator, value3] : [value3]), io[valueScope]);
|
|
46989
47399
|
}
|
|
46990
47400
|
let value2 = part.name === "?" ? String(state.status) : part.name === "-" ? `${state.errexit ? "e" : ""}${state.nounset ? "u" : ""}${state.braceexpand !== false ? "B" : ""}` : part.name === "#" ? String(state.positional.length) : part.name === "@" || part.name === "*" ? state.positional.join(hereString && (part.name === "@" || !part.quoted) ? " " : Array.from(state.variables.IFS ?? " ")[0] ?? "") : /^0+$/u.test(part.name) ? state.arg0 ?? "virtual-bash" : /^\d+$/u.test(part.name) ? state.positional[Number(part.name) - 1] : this.variable(state, part.name);
|
|
46991
47401
|
let retained = value2;
|
|
@@ -47394,7 +47804,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
47394
47804
|
emptyNameGroups.add(quoteGroup);
|
|
47395
47805
|
}
|
|
47396
47806
|
} else if (part.kind === "variable" && split4 && (selector?.kind === "members" && !part.length && (!part.quoted || selector.separator === "@") || part.transform && part.name === "@")) {
|
|
47397
|
-
const members = selector?.kind === "members" ? await this.arrayMembers(part.name, state) : this.positionalValues(state);
|
|
47807
|
+
const members = selector?.kind === "members" ? await this.arrayMembers(part.name, state, io, part.keys) : this.positionalValues(state);
|
|
47398
47808
|
for (let position = 0; position < members.length; position++) {
|
|
47399
47809
|
if (position > 0) addField();
|
|
47400
47810
|
const original = members[position];
|
|
@@ -47536,7 +47946,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
47536
47946
|
for (const value2 of values) if (typeof value2 !== "string") allocation.hold(value2);
|
|
47537
47947
|
return createCommandArguments(values, allocation);
|
|
47538
47948
|
}
|
|
47539
|
-
async arrayMembers(name2, state) {
|
|
47949
|
+
async arrayMembers(name2, state, io, keys = false) {
|
|
47540
47950
|
const store = requireArrays(state);
|
|
47541
47951
|
const holding = store.owner.hold();
|
|
47542
47952
|
try {
|
|
@@ -47547,7 +47957,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
47547
47957
|
if (value2 === void 0) return [];
|
|
47548
47958
|
store.owner.reserve({ metadata: 32, allocatedSlots: 1, work: 3 });
|
|
47549
47959
|
await textToken(store.owner, value2, this.signal);
|
|
47550
|
-
return [value2];
|
|
47960
|
+
return [keys ? "0" : value2];
|
|
47551
47961
|
}
|
|
47552
47962
|
binding.retain();
|
|
47553
47963
|
try {
|
|
@@ -47555,8 +47965,9 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
47555
47965
|
const values = [];
|
|
47556
47966
|
for (const index of indices) {
|
|
47557
47967
|
store.owner.reserve({ metadata: 32, allocatedSlots: 1, work: 4 });
|
|
47558
|
-
const
|
|
47559
|
-
|
|
47968
|
+
const token = keys ? binding.associative ? binding.keys.get(binding.keyByIndex.get(index)).text : await textToken(store.owner, String(index), this.signal) : binding.values.get(index).text;
|
|
47969
|
+
const value2 = token.rawValue === void 0 ? token.value : shellValueFromBytes(shellValueBytes(token.rawValue, io[valueScope]), io[valueScope]);
|
|
47970
|
+
if (typeof value2 === "string") await textToken(store.owner, value2, this.signal);
|
|
47560
47971
|
values.push(value2);
|
|
47561
47972
|
await store.owner.ledger.checkpoint(this.signal);
|
|
47562
47973
|
}
|
|
@@ -48231,6 +48642,51 @@ var ShellInput = class _ShellInput {
|
|
|
48231
48642
|
}
|
|
48232
48643
|
});
|
|
48233
48644
|
}
|
|
48645
|
+
mapfileRecord(delimiter, strip, allocation) {
|
|
48646
|
+
return this.#cursor.consume(this.signal, async () => {
|
|
48647
|
+
this.#cursor.admitBoundedRead();
|
|
48648
|
+
allocation.reserve(64, 0);
|
|
48649
|
+
const parts = [];
|
|
48650
|
+
let length = 0;
|
|
48651
|
+
let truncated = false;
|
|
48652
|
+
let pulls = 0;
|
|
48653
|
+
while (true) {
|
|
48654
|
+
if (++pulls % 128 === 0) await yieldTurn(this.signal);
|
|
48655
|
+
const result2 = await this.#cursor.take(this.signal);
|
|
48656
|
+
if (result2.done) return { value: concatShellValues(parts, allocation), present: length > 0 };
|
|
48657
|
+
const chunk = result2.value;
|
|
48658
|
+
for (let offset = 0; offset < chunk.length; ) {
|
|
48659
|
+
await yieldTurn(this.signal);
|
|
48660
|
+
if (length >= this.budget.limits.maxOutputBytes) this.budget.fail("maxOutputBytes");
|
|
48661
|
+
const end = Math.min(offset + 1024, chunk.length, offset + this.budget.limits.maxOutputBytes - length);
|
|
48662
|
+
allocation.reserve(end - offset + 64, 0);
|
|
48663
|
+
const output2 = new Uint8Array(end - offset);
|
|
48664
|
+
let used = 0;
|
|
48665
|
+
let terminated = false;
|
|
48666
|
+
while (offset < end) {
|
|
48667
|
+
const byte = chunk[offset++];
|
|
48668
|
+
this.#cursor.position++;
|
|
48669
|
+
if (++length > this.budget.limits.maxOutputBytes) this.budget.fail("maxOutputBytes");
|
|
48670
|
+
if (byte === delimiter) {
|
|
48671
|
+
if (!strip && byte !== 0 && !truncated) output2[used++] = byte;
|
|
48672
|
+
terminated = true;
|
|
48673
|
+
break;
|
|
48674
|
+
}
|
|
48675
|
+
if (byte === 0) truncated = true;
|
|
48676
|
+
if (!truncated) output2[used++] = byte;
|
|
48677
|
+
}
|
|
48678
|
+
if (used) {
|
|
48679
|
+
allocation.reserve(32, 0);
|
|
48680
|
+
parts.push(shellValueFromBytes(output2.subarray(0, used), allocation));
|
|
48681
|
+
}
|
|
48682
|
+
if (terminated) {
|
|
48683
|
+
if (offset < chunk.length) this.#cursor.remainder = chunk.subarray(offset);
|
|
48684
|
+
return { value: concatShellValues(parts, allocation), present: true };
|
|
48685
|
+
}
|
|
48686
|
+
}
|
|
48687
|
+
}
|
|
48688
|
+
});
|
|
48689
|
+
}
|
|
48234
48690
|
async readBounded(raw, options3) {
|
|
48235
48691
|
const text3 = new ReadText();
|
|
48236
48692
|
let characters = 0;
|