@poe-platform/safe-bash 0.1.526 → 0.1.528
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 +408 -31
- package/dist/safe-bash/core.browser.js.map +4 -4
- package/dist/safe-bash/shell/arrays/bindings.d.ts +4 -1
- package/dist/safe-bash/shell/arrays/bindings.d.ts.map +1 -1
- package/dist/safe-bash/shell/arrays/bindings.js +44 -1
- package/dist/safe-bash/shell/arrays/bindings.js.map +1 -1
- package/dist/safe-bash/shell/display.d.ts.map +1 -1
- package/dist/safe-bash/shell/display.js +3 -0
- package/dist/safe-bash/shell/display.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 +4 -0
- package/dist/safe-bash/shell/parser.d.ts.map +1 -1
- package/dist/safe-bash/shell/parser.js +43 -0
- 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 +215 -30
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/package.json +2 -2
|
@@ -38650,6 +38650,40 @@ var Parser4 = class {
|
|
|
38650
38650
|
const body = this.nonemptyScript(/* @__PURE__ */ new Set(["done"]));
|
|
38651
38651
|
this.expect("done", true);
|
|
38652
38652
|
command7 = { kind, condition, body, redirects: [] };
|
|
38653
|
+
} else if (this.is("for") && this.peek().value === "(" && this.lexer.source.startsWith("((", this.peek().offset)) {
|
|
38654
|
+
this.advance();
|
|
38655
|
+
const start = this.current.offset + 2;
|
|
38656
|
+
let partStart = start;
|
|
38657
|
+
let depth = 0;
|
|
38658
|
+
let end = start;
|
|
38659
|
+
this.budget.admit(4);
|
|
38660
|
+
const sources2 = [];
|
|
38661
|
+
for (; end < this.lexer.source.length; end++) {
|
|
38662
|
+
this.budget.admit();
|
|
38663
|
+
const character = this.lexer.source[end];
|
|
38664
|
+
if (character === "(") depth++;
|
|
38665
|
+
else if (character === ")") {
|
|
38666
|
+
if (!depth && this.lexer.source[end + 1] === ")") break;
|
|
38667
|
+
if (--depth < 0) this.error("Unterminated arithmetic for", true);
|
|
38668
|
+
} else if (character === ";" && !depth) {
|
|
38669
|
+
if (sources2.length === 2) this.error("Arithmetic for requires three expressions");
|
|
38670
|
+
sources2.push(this.lexer.source.slice(partStart, end));
|
|
38671
|
+
partStart = end + 1;
|
|
38672
|
+
}
|
|
38673
|
+
}
|
|
38674
|
+
if (end === this.lexer.source.length) this.error("Unterminated arithmetic for", true);
|
|
38675
|
+
if (sources2.length !== 2) this.error("Arithmetic for requires three expressions");
|
|
38676
|
+
sources2.push(this.lexer.source.slice(partStart, end));
|
|
38677
|
+
const expressions = sources2.map((source2) => source2.trim() ? prepareArithmetic(source2, this.budget) : void 0);
|
|
38678
|
+
this.lexer.position = end + 2;
|
|
38679
|
+
this.lookahead = void 0;
|
|
38680
|
+
this.current = this.lexer.next();
|
|
38681
|
+
if (this.is(";")) this.advance();
|
|
38682
|
+
this.newlines();
|
|
38683
|
+
this.expect("do", true);
|
|
38684
|
+
const body = this.nonemptyScript(/* @__PURE__ */ new Set(["done"]));
|
|
38685
|
+
this.expect("done", true);
|
|
38686
|
+
command7 = { kind: "arithmetic-for", expressions, body, redirects: [] };
|
|
38653
38687
|
} else if (this.is("for") || this.is("select")) {
|
|
38654
38688
|
const kind = this.advance().value;
|
|
38655
38689
|
const name2 = this.advance().value;
|
|
@@ -39654,6 +39688,12 @@ function commandText(command7, indent) {
|
|
|
39654
39688
|
case "arithmetic":
|
|
39655
39689
|
text3 = `(( ${command7.source} ))`;
|
|
39656
39690
|
break;
|
|
39691
|
+
case "arithmetic-for":
|
|
39692
|
+
text3 = `for (( ${command7.expressions.map((expression) => expression?.source ?? "").join("; ")} ));
|
|
39693
|
+
do
|
|
39694
|
+
${nested}${scriptText(command7.body, nested)};
|
|
39695
|
+
${indent}done`;
|
|
39696
|
+
break;
|
|
39657
39697
|
case "conditional":
|
|
39658
39698
|
text3 = `[[${command7.source}]]`;
|
|
39659
39699
|
break;
|
|
@@ -40839,14 +40879,16 @@ var controlNames = /* @__PURE__ */ new Set([
|
|
|
40839
40879
|
"LC_CTYPE"
|
|
40840
40880
|
]);
|
|
40841
40881
|
var OwnedText = class {
|
|
40842
|
-
constructor(value2, bytes3, admission) {
|
|
40882
|
+
constructor(value2, bytes3, admission, rawValue) {
|
|
40843
40883
|
this.value = value2;
|
|
40844
40884
|
this.bytes = bytes3;
|
|
40845
40885
|
this.admission = admission;
|
|
40886
|
+
this.rawValue = rawValue;
|
|
40846
40887
|
}
|
|
40847
40888
|
value;
|
|
40848
40889
|
bytes;
|
|
40849
40890
|
admission;
|
|
40891
|
+
rawValue;
|
|
40850
40892
|
references = 1;
|
|
40851
40893
|
retain() {
|
|
40852
40894
|
if (this.references === Number.MAX_SAFE_INTEGER) throw new ArrayFailure("reference capacity is not representable");
|
|
@@ -40872,6 +40914,38 @@ async function textToken(owner, value2, signal) {
|
|
|
40872
40914
|
const admission = owner.reserve({ payload: bytes3, metadata: 32, work: 4 });
|
|
40873
40915
|
return new OwnedText(value2, bytes3, admission);
|
|
40874
40916
|
}
|
|
40917
|
+
async function valueToken(owner, value2, signal) {
|
|
40918
|
+
if (typeof value2 === "string") return textToken(owner, value2, signal);
|
|
40919
|
+
const bytes3 = shellValueByteLength(value2);
|
|
40920
|
+
const temporary = owner.reserve({ payload: bytes3 * 3, metadata: 64, work: 4 });
|
|
40921
|
+
try {
|
|
40922
|
+
const input3 = shellValueBytes(value2);
|
|
40923
|
+
const decoder2 = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true });
|
|
40924
|
+
let text3 = "";
|
|
40925
|
+
for (let offset = 0; offset < bytes3; offset += 1024) {
|
|
40926
|
+
const end = Math.min(bytes3, offset + 1024);
|
|
40927
|
+
owner.reserve({ work: end - offset }).release();
|
|
40928
|
+
await owner.ledger.checkpoint(signal, end - offset);
|
|
40929
|
+
if (text3 !== void 0) try {
|
|
40930
|
+
text3 += decoder2.decode(input3.subarray(offset, end), { stream: end < bytes3 });
|
|
40931
|
+
} catch (error) {
|
|
40932
|
+
if (!(error instanceof TypeError) || "code" in error && error.code !== "ERR_ENCODING_INVALID_ENCODED_DATA") throw error;
|
|
40933
|
+
text3 = void 0;
|
|
40934
|
+
}
|
|
40935
|
+
}
|
|
40936
|
+
if (text3 !== void 0) return await textToken(owner, text3, signal);
|
|
40937
|
+
const admission = owner.reserve({ payload: bytes3 * 4, metadata: 128, work: 4 });
|
|
40938
|
+
try {
|
|
40939
|
+
const raw = shellValueFromBytes(input3);
|
|
40940
|
+
return new OwnedText(shellValueText(raw), bytes3, admission, raw);
|
|
40941
|
+
} catch (error) {
|
|
40942
|
+
admission.release();
|
|
40943
|
+
throw error;
|
|
40944
|
+
}
|
|
40945
|
+
} finally {
|
|
40946
|
+
temporary.release();
|
|
40947
|
+
}
|
|
40948
|
+
}
|
|
40875
40949
|
var IndexedBinding = class _IndexedBinding {
|
|
40876
40950
|
constructor(owner) {
|
|
40877
40951
|
this.owner = owner;
|
|
@@ -41108,6 +41182,116 @@ var BindingStore = class _BindingStore {
|
|
|
41108
41182
|
}
|
|
41109
41183
|
};
|
|
41110
41184
|
|
|
41185
|
+
// packages/safe-bash/src/shell/mapfile.ts
|
|
41186
|
+
init_platform();
|
|
41187
|
+
var MapfileUsageError = class extends Error {
|
|
41188
|
+
constructor(message3, status2) {
|
|
41189
|
+
super(message3);
|
|
41190
|
+
this.status = status2;
|
|
41191
|
+
}
|
|
41192
|
+
status;
|
|
41193
|
+
};
|
|
41194
|
+
async function mapfileOptions(context2, work, allocation) {
|
|
41195
|
+
const options3 = { name: "MAPFILE", strip: false, delimiter: 10, count: 0, skip: 0, origin: 0, preserve: false, callback: void 0, quantum: 5e3 };
|
|
41196
|
+
const args = getCommandArguments(context2);
|
|
41197
|
+
let cursor = 0;
|
|
41198
|
+
const numeric4 = async (text3, maximum) => {
|
|
41199
|
+
let value2 = 0;
|
|
41200
|
+
let index = 0;
|
|
41201
|
+
const whitespace2 = (code) => code === 32 || code >= 9 && code <= 13;
|
|
41202
|
+
while (index < text3.length && whitespace2(text3.charCodeAt(index))) {
|
|
41203
|
+
const pending = stringCheckpoint(work);
|
|
41204
|
+
if (pending) await pending;
|
|
41205
|
+
index++;
|
|
41206
|
+
}
|
|
41207
|
+
const negative = text3[index] === "-";
|
|
41208
|
+
if (negative || text3[index] === "+") index++;
|
|
41209
|
+
let digits = 0;
|
|
41210
|
+
for (; index < text3.length; index++) {
|
|
41211
|
+
const pending = stringCheckpoint(work);
|
|
41212
|
+
if (pending) await pending;
|
|
41213
|
+
const digit3 = text3.charCodeAt(index) - 48;
|
|
41214
|
+
if (digit3 < 0 || digit3 > 9) break;
|
|
41215
|
+
if (value2 > Math.floor((maximum - digit3) / 10)) throw new MapfileUsageError(`${text3}: invalid number`, 1);
|
|
41216
|
+
value2 = value2 * 10 + digit3;
|
|
41217
|
+
digits++;
|
|
41218
|
+
}
|
|
41219
|
+
for (; index < text3.length; index++) {
|
|
41220
|
+
const pending = stringCheckpoint(work);
|
|
41221
|
+
if (pending) await pending;
|
|
41222
|
+
if (!whitespace2(text3.charCodeAt(index))) throw new MapfileUsageError(`${text3}: invalid number`, 1);
|
|
41223
|
+
}
|
|
41224
|
+
if (!digits || negative && value2 !== 0) throw new MapfileUsageError(`${text3}: invalid number`, 1);
|
|
41225
|
+
return value2;
|
|
41226
|
+
};
|
|
41227
|
+
while (cursor < context2.args.length) {
|
|
41228
|
+
const option = context2.args[cursor];
|
|
41229
|
+
if (option === "--") {
|
|
41230
|
+
cursor++;
|
|
41231
|
+
break;
|
|
41232
|
+
}
|
|
41233
|
+
if (!option.startsWith("-") || option === "-") break;
|
|
41234
|
+
cursor++;
|
|
41235
|
+
for (let index = 1; index < option.length; index++) {
|
|
41236
|
+
const pending = stringCheckpoint(work);
|
|
41237
|
+
if (pending) await pending;
|
|
41238
|
+
const flag = option[index];
|
|
41239
|
+
if (flag === "t") {
|
|
41240
|
+
options3.strip = true;
|
|
41241
|
+
continue;
|
|
41242
|
+
}
|
|
41243
|
+
if (!"dnsOCc".includes(flag)) throw new MapfileUsageError(`-${flag}: invalid option`, 2);
|
|
41244
|
+
const attached = index + 1 < option.length;
|
|
41245
|
+
const operandIndex = attached ? cursor - 1 : cursor++;
|
|
41246
|
+
const operand = attached ? option.slice(index + 1) : context2.args[operandIndex];
|
|
41247
|
+
if (operand === void 0) throw new MapfileUsageError(`-${flag}: option requires an argument`, 2);
|
|
41248
|
+
if (flag === "d") {
|
|
41249
|
+
const bytes3 = shellValueBytes(args.values[operandIndex], allocation);
|
|
41250
|
+
options3.delimiter = bytes3[attached ? index + 1 : 0] ?? 0;
|
|
41251
|
+
} else if (flag === "C") options3.callback = operand;
|
|
41252
|
+
else {
|
|
41253
|
+
const value2 = await numeric4(operand, flag === "O" ? 2147483647 : Number.MAX_SAFE_INTEGER);
|
|
41254
|
+
if (flag === "c") {
|
|
41255
|
+
if (!value2) throw new MapfileUsageError("0: invalid callback quantum", 1);
|
|
41256
|
+
options3.quantum = value2;
|
|
41257
|
+
} else if (flag === "n") options3.count = value2;
|
|
41258
|
+
else if (flag === "s") options3.skip = value2;
|
|
41259
|
+
else {
|
|
41260
|
+
options3.origin = value2;
|
|
41261
|
+
options3.preserve = true;
|
|
41262
|
+
}
|
|
41263
|
+
}
|
|
41264
|
+
break;
|
|
41265
|
+
}
|
|
41266
|
+
}
|
|
41267
|
+
options3.name = context2.args[cursor] ?? "MAPFILE";
|
|
41268
|
+
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(options3.name)) throw new MapfileUsageError(`${options3.name}: invalid identifier`, 1);
|
|
41269
|
+
return options3;
|
|
41270
|
+
}
|
|
41271
|
+
async function collectMapfile(options3, input3, hooks) {
|
|
41272
|
+
let skipped = 0;
|
|
41273
|
+
let written = 0;
|
|
41274
|
+
while (!options3.count || written < options3.count) {
|
|
41275
|
+
hooks.loop();
|
|
41276
|
+
const allocation = hooks.allocation();
|
|
41277
|
+
try {
|
|
41278
|
+
const record4 = await input3.mapfileRecord(options3.delimiter, options3.strip, allocation);
|
|
41279
|
+
if (!record4.present) break;
|
|
41280
|
+
if (skipped < options3.skip) {
|
|
41281
|
+
skipped++;
|
|
41282
|
+
continue;
|
|
41283
|
+
}
|
|
41284
|
+
const index = options3.origin + written;
|
|
41285
|
+
if (index > 2147483647) throw new MapfileUsageError("array index exceeds 2147483647", 1);
|
|
41286
|
+
if (options3.callback !== void 0 && (written + 1) % options3.quantum === 0) await hooks.callback(options3.callback, index, record4.value);
|
|
41287
|
+
await hooks.write(index, record4.value);
|
|
41288
|
+
written++;
|
|
41289
|
+
} finally {
|
|
41290
|
+
allocation.close();
|
|
41291
|
+
}
|
|
41292
|
+
}
|
|
41293
|
+
}
|
|
41294
|
+
|
|
41111
41295
|
// packages/safe-bash/src/shell/arrays/state.ts
|
|
41112
41296
|
init_platform();
|
|
41113
41297
|
var sessions = /* @__PURE__ */ new WeakMap();
|
|
@@ -41869,6 +42053,8 @@ var shellBuiltinNames = /* @__PURE__ */ new Set([
|
|
|
41869
42053
|
"local",
|
|
41870
42054
|
"unset",
|
|
41871
42055
|
"read",
|
|
42056
|
+
"mapfile",
|
|
42057
|
+
"readarray",
|
|
41872
42058
|
"exit",
|
|
41873
42059
|
"return",
|
|
41874
42060
|
"break",
|
|
@@ -42867,6 +43053,7 @@ var InvocationCancellationOwner = class {
|
|
|
42867
43053
|
this.#failures.push(...result2.failures);
|
|
42868
43054
|
}
|
|
42869
43055
|
};
|
|
43056
|
+
var mapfileCallbackStates = /* @__PURE__ */ new WeakSet();
|
|
42870
43057
|
var Runtime = class _Runtime {
|
|
42871
43058
|
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) {
|
|
42872
43059
|
this.fs = fs;
|
|
@@ -43178,6 +43365,18 @@ var Runtime = class _Runtime {
|
|
|
43178
43365
|
this.signal.throwIfAborted();
|
|
43179
43366
|
if (error instanceof NounsetFailure || error instanceof Flow2 || error instanceof ShellLimitError || error instanceof ShellSyntaxError) throw error;
|
|
43180
43367
|
}
|
|
43368
|
+
arithmeticValue(program, state, io) {
|
|
43369
|
+
return evaluatePositionalArithmetic(program, {
|
|
43370
|
+
parseBudget: this.budget.parsing,
|
|
43371
|
+
positional: state.positional,
|
|
43372
|
+
arg0: state.arg0 ?? "virtual-bash",
|
|
43373
|
+
owner: arrayStore(state)?.owner,
|
|
43374
|
+
maximumBytes: this.budget.limits.maxExpansionBytes,
|
|
43375
|
+
checkpoint: () => this.signal.throwIfAborted(),
|
|
43376
|
+
requireParameter: (name2, value2) => this.requireParameter(value2, name2, state, io),
|
|
43377
|
+
limit: () => this.budget.fail("maxExpansionBytes")
|
|
43378
|
+
}, (prepared) => evaluateArithmetic(prepared, this.arithmeticVariables(state, io.diagnosticLine), this.budget.parsing));
|
|
43379
|
+
}
|
|
43181
43380
|
arithmeticVariables(state, line) {
|
|
43182
43381
|
return new Proxy(state.variables, {
|
|
43183
43382
|
get: (target, key) => {
|
|
@@ -43205,7 +43404,7 @@ var Runtime = class _Runtime {
|
|
|
43205
43404
|
this.writeVariable(state, name2, value2, origin);
|
|
43206
43405
|
return;
|
|
43207
43406
|
}
|
|
43208
|
-
await this.arrayZero(state, name2, async () =>
|
|
43407
|
+
await this.arrayZero(state, name2, async () => value2);
|
|
43209
43408
|
}
|
|
43210
43409
|
async prepareVariable(state, name2, saved, scalarLegacy = false) {
|
|
43211
43410
|
const store = requireArrays(state);
|
|
@@ -43362,6 +43561,7 @@ var Runtime = class _Runtime {
|
|
|
43362
43561
|
const store = requireArrays(state);
|
|
43363
43562
|
const operation2 = ArrayOwner.create(store.owner.ledger, store.owner);
|
|
43364
43563
|
const holding = store.owner.hold();
|
|
43564
|
+
const valueAllocation = this.budget.values.scope();
|
|
43365
43565
|
let staged;
|
|
43366
43566
|
try {
|
|
43367
43567
|
const watch = await store.watch(name2, operation2, this.signal);
|
|
@@ -43378,8 +43578,9 @@ var Runtime = class _Runtime {
|
|
|
43378
43578
|
const current = store.get(name2);
|
|
43379
43579
|
if (!current) throw new ArrayFailure("stale binding");
|
|
43380
43580
|
staged = await current.copy(this.signal);
|
|
43381
|
-
const
|
|
43382
|
-
const
|
|
43581
|
+
const previous = current.values.get(0)?.text.rawValue ?? current.get(0) ?? "";
|
|
43582
|
+
const value2 = !append ? expanded : typeof previous === "string" && typeof expanded === "string" ? await this.arrayJoin(operation2, [previous, expanded], "") : concatShellValues([previous, expanded], valueAllocation);
|
|
43583
|
+
const token = await valueToken(staged.owner, value2, this.signal);
|
|
43383
43584
|
try {
|
|
43384
43585
|
staged.insert(0, token);
|
|
43385
43586
|
} catch (error) {
|
|
@@ -43407,6 +43608,7 @@ var Runtime = class _Runtime {
|
|
|
43407
43608
|
await staged?.release();
|
|
43408
43609
|
await operation2.close();
|
|
43409
43610
|
} finally {
|
|
43611
|
+
valueAllocation.close();
|
|
43410
43612
|
holding.release();
|
|
43411
43613
|
}
|
|
43412
43614
|
}
|
|
@@ -43470,7 +43672,7 @@ var Runtime = class _Runtime {
|
|
|
43470
43672
|
const preserve = assignment.kind === "element" || assignment.append;
|
|
43471
43673
|
staged = preserve && current ? await current.copy(this.signal) : IndexedBinding.create(store.owner);
|
|
43472
43674
|
if (preserve && !current && state.variables[name2] !== void 0) {
|
|
43473
|
-
const token = await
|
|
43675
|
+
const token = await valueToken(staged.owner, stateMonitor(state)?.values.get(name2, state.variables[name2]) ?? state.variables[name2], this.signal);
|
|
43474
43676
|
try {
|
|
43475
43677
|
staged.insert(0, token);
|
|
43476
43678
|
} catch (error) {
|
|
@@ -43482,7 +43684,7 @@ var Runtime = class _Runtime {
|
|
|
43482
43684
|
let cursor = assignment.append && assignment.kind === "compound" ? initialMaximum + 1 : 0;
|
|
43483
43685
|
const insert = async (index, value2) => {
|
|
43484
43686
|
if (index > 2147483647) throw new ArrayFailure("index outside 0..2147483647");
|
|
43485
|
-
const token = await
|
|
43687
|
+
const token = await valueToken(staged.owner, value2, this.signal);
|
|
43486
43688
|
try {
|
|
43487
43689
|
staged.insert(index, token);
|
|
43488
43690
|
} catch (error) {
|
|
@@ -43491,11 +43693,12 @@ var Runtime = class _Runtime {
|
|
|
43491
43693
|
}
|
|
43492
43694
|
writes++;
|
|
43493
43695
|
};
|
|
43696
|
+
const join = async (values) => values.every((value2) => typeof value2 === "string") ? this.arrayJoin(operation2, values, "") : concatShellValues(values, io[valueScope]);
|
|
43494
43697
|
if (assignment.kind === "element") {
|
|
43495
43698
|
const index = numericIndex(assignment.index);
|
|
43496
|
-
const fields3 = await this.
|
|
43497
|
-
let value2 = await
|
|
43498
|
-
if (assignment.append) value2 = await
|
|
43699
|
+
const fields3 = await this.valueWord(assignment.value, state, io, false);
|
|
43700
|
+
let value2 = await join(fields3);
|
|
43701
|
+
if (assignment.append) value2 = await join([staged.values.get(index)?.text.rawValue ?? staged.get(index) ?? "", value2]);
|
|
43499
43702
|
await insert(index, value2);
|
|
43500
43703
|
} else for (const entry of assignment.entries) {
|
|
43501
43704
|
const original = compoundEntryWords.get(entry);
|
|
@@ -43506,16 +43709,16 @@ var Runtime = class _Runtime {
|
|
|
43506
43709
|
expandedEntry = true;
|
|
43507
43710
|
const values = await this.valueWord(expanded, state, io, true, false, false, false, void 0, false);
|
|
43508
43711
|
for (const value2 of values) {
|
|
43509
|
-
await insert(cursor,
|
|
43712
|
+
await insert(cursor, value2);
|
|
43510
43713
|
cursor++;
|
|
43511
43714
|
}
|
|
43512
43715
|
}
|
|
43513
43716
|
if (expandedEntry) continue;
|
|
43514
43717
|
}
|
|
43515
|
-
const fields3 = await this.
|
|
43718
|
+
const fields3 = await this.valueWord(entry.value, state, io, entry.index === void 0);
|
|
43516
43719
|
if (entry.index) {
|
|
43517
43720
|
const index = numericIndex(entry.index);
|
|
43518
|
-
await insert(index, await
|
|
43721
|
+
await insert(index, await join(fields3));
|
|
43519
43722
|
cursor = index + 1;
|
|
43520
43723
|
} else for (const value2 of fields3) {
|
|
43521
43724
|
await insert(cursor, value2);
|
|
@@ -43878,16 +44081,7 @@ var Runtime = class _Runtime {
|
|
|
43878
44081
|
}
|
|
43879
44082
|
if (command7.kind === "arithmetic") {
|
|
43880
44083
|
try {
|
|
43881
|
-
return Number(
|
|
43882
|
-
parseBudget: this.budget.parsing,
|
|
43883
|
-
positional: state.positional,
|
|
43884
|
-
arg0: state.arg0 ?? "virtual-bash",
|
|
43885
|
-
owner: arrayStore(state)?.owner,
|
|
43886
|
-
maximumBytes: this.budget.limits.maxExpansionBytes,
|
|
43887
|
-
checkpoint: () => this.signal.throwIfAborted(),
|
|
43888
|
-
requireParameter: (name2, value2) => this.requireParameter(value2, name2, state, io),
|
|
43889
|
-
limit: () => this.budget.fail("maxExpansionBytes")
|
|
43890
|
-
}, (prepared) => evaluateArithmetic(prepared, this.arithmeticVariables(state, io.diagnosticLine), this.budget.parsing)) === 0n);
|
|
44084
|
+
return Number(this.arithmeticValue(command7.expression, state, io) === 0n);
|
|
43891
44085
|
} catch (error) {
|
|
43892
44086
|
this.rethrowArithmeticControl(error);
|
|
43893
44087
|
throw new PublicDiagnostic(`((: ${message2(error, this.budget.onInternalError)}`);
|
|
@@ -43946,6 +44140,29 @@ var Runtime = class _Runtime {
|
|
|
43946
44140
|
status3 = result2.status;
|
|
43947
44141
|
if (result2.stop) break;
|
|
43948
44142
|
}
|
|
44143
|
+
} else if (command7.kind === "arithmetic-for") {
|
|
44144
|
+
const evaluate = async (program) => {
|
|
44145
|
+
if (!program) return 1n;
|
|
44146
|
+
try {
|
|
44147
|
+
return this.arithmeticValue(program, state, io);
|
|
44148
|
+
} catch (error) {
|
|
44149
|
+
this.rethrowArithmeticControl(error);
|
|
44150
|
+
await this.diagnostic(io, `((: ${message2(error, this.budget.onInternalError)}`);
|
|
44151
|
+
return void 0;
|
|
44152
|
+
}
|
|
44153
|
+
};
|
|
44154
|
+
if (await evaluate(command7.expressions[0]) === void 0) return 1;
|
|
44155
|
+
while (true) {
|
|
44156
|
+
this.budget.loop();
|
|
44157
|
+
await yieldTurn(this.signal);
|
|
44158
|
+
const condition = await evaluate(command7.expressions[1]);
|
|
44159
|
+
if (condition === void 0) return 1;
|
|
44160
|
+
if (condition === 0n) break;
|
|
44161
|
+
const result2 = await this.loopBody(command7.body, state, io);
|
|
44162
|
+
status3 = result2.status;
|
|
44163
|
+
if (result2.stop) break;
|
|
44164
|
+
if (await evaluate(command7.expressions[2]) === void 0) return 1;
|
|
44165
|
+
}
|
|
43949
44166
|
} else if (command7.kind === "select") {
|
|
43950
44167
|
const values = command7.words ? await this.valueWords(command7.words, state, io) : this.positionalValues(state);
|
|
43951
44168
|
if (!values.length) return 0;
|
|
@@ -44392,8 +44609,8 @@ var Runtime = class _Runtime {
|
|
|
44392
44609
|
throw new ArrayFailure("indexed binding cannot be a command prefix");
|
|
44393
44610
|
}
|
|
44394
44611
|
await this.arrayZero(state, assignment.name, async () => {
|
|
44395
|
-
const fields3 = await this.
|
|
44396
|
-
return this.arrayJoin(requireArrays(state).owner, fields3, "");
|
|
44612
|
+
const fields3 = await this.valueWord(assignment.value, state, io, false);
|
|
44613
|
+
return fields3.every((value3) => typeof value3 === "string") ? this.arrayJoin(requireArrays(state).owner, fields3, "") : concatShellValues(fields3, io[valueScope]);
|
|
44397
44614
|
}, assignment.append);
|
|
44398
44615
|
continue;
|
|
44399
44616
|
}
|
|
@@ -44712,6 +44929,8 @@ var Runtime = class _Runtime {
|
|
|
44712
44929
|
functionRestoration?.close();
|
|
44713
44930
|
throw error;
|
|
44714
44931
|
}
|
|
44932
|
+
const callerLoopDepth = state.loopDepth;
|
|
44933
|
+
if (mapfileCallbackStates.has(state)) state.loopDepth = 0;
|
|
44715
44934
|
try {
|
|
44716
44935
|
return { exitCode: await this.command(body, state, { ...io, ...context3, scriptName: body.sourceName ?? io.scriptName ?? "shell" }) };
|
|
44717
44936
|
} catch (error) {
|
|
@@ -44725,6 +44944,7 @@ var Runtime = class _Runtime {
|
|
|
44725
44944
|
savedPositionals.close();
|
|
44726
44945
|
state.positionalSetVersion = positionalSetVersion;
|
|
44727
44946
|
state.functionDepth--;
|
|
44947
|
+
state.loopDepth = callerLoopDepth;
|
|
44728
44948
|
state.depth--;
|
|
44729
44949
|
state.locals.pop();
|
|
44730
44950
|
};
|
|
@@ -46196,12 +46416,119 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46196
46416
|
allocation.close();
|
|
46197
46417
|
}
|
|
46198
46418
|
}
|
|
46419
|
+
async mapfileBuiltin(context2, state) {
|
|
46420
|
+
const allocation = this.budget.values.scope();
|
|
46421
|
+
const work = { remaining: this.budget.limits.maxExpansionBytes * 8, signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
|
|
46422
|
+
let pinned;
|
|
46423
|
+
let releaseHolding;
|
|
46424
|
+
try {
|
|
46425
|
+
const options3 = await mapfileOptions(context2, work, allocation);
|
|
46426
|
+
if (state.readonlyVariables?.has(options3.name)) throw new MapfileUsageError(`${options3.name}: readonly variable`, 1);
|
|
46427
|
+
if (controlNames.has(options3.name) || state.exported.has(options3.name)) throw new ArrayFailure("control or exported binding cannot be indexed");
|
|
46428
|
+
const store = requireArrays(state);
|
|
46429
|
+
const holding = store.owner.hold();
|
|
46430
|
+
releaseHolding = () => holding.release();
|
|
46431
|
+
if (!options3.preserve || !store.get(options3.name)) await this.arrayAssignment({ kind: "compound", name: options3.name, append: options3.preserve, entries: [] }, state, context2);
|
|
46432
|
+
const entry = store.bindings.get(options3.name);
|
|
46433
|
+
allocation.reserve(128 + import_buffer.Buffer.byteLength(options3.name) * 2, 0);
|
|
46434
|
+
pinned = entry.binding.retain();
|
|
46435
|
+
const input3 = context2.stdin instanceof ShellInput ? context2.stdin : new ShellInput(context2.stdin, this.budget, this.signal);
|
|
46436
|
+
let pendingFlow;
|
|
46437
|
+
await collectMapfile(options3, input3, {
|
|
46438
|
+
allocation: () => this.budget.values.scope(),
|
|
46439
|
+
loop: () => this.budget.loop(),
|
|
46440
|
+
write: async (index, value2) => {
|
|
46441
|
+
if (pinned !== entry.binding) {
|
|
46442
|
+
const previous = pinned;
|
|
46443
|
+
pinned = entry.binding.retain();
|
|
46444
|
+
await previous.release();
|
|
46445
|
+
}
|
|
46446
|
+
const operation2 = ArrayOwner.create(store.owner.ledger, store.owner);
|
|
46447
|
+
let staged;
|
|
46448
|
+
try {
|
|
46449
|
+
const current = pinned;
|
|
46450
|
+
const attached = store.bindings.get(options3.name) === entry;
|
|
46451
|
+
const watch = attached ? await store.watch(options3.name, operation2, this.signal) : void 0;
|
|
46452
|
+
const supersede = attached ? await stateMonitor(state).prepareTypedPublication(options3.name, operation2, this.signal) : void 0;
|
|
46453
|
+
if (attached) await this.prepareArrayObservers(state, operation2);
|
|
46454
|
+
const tickets = operation2.reserve({ generation: true, version: true, epoch: true, work: 8 });
|
|
46455
|
+
staged = current.references > (attached ? 2 : 1) ? await current.copy(this.signal) : current.retain();
|
|
46456
|
+
const token = await valueToken(staged.owner, value2, this.signal);
|
|
46457
|
+
try {
|
|
46458
|
+
this.signal.throwIfAborted();
|
|
46459
|
+
if (watch && !watch.valid()) throw new ArrayFailure("stale binding");
|
|
46460
|
+
staged.insert(index, token);
|
|
46461
|
+
} catch (error) {
|
|
46462
|
+
token.release();
|
|
46463
|
+
throw error;
|
|
46464
|
+
}
|
|
46465
|
+
if (attached) {
|
|
46466
|
+
let released;
|
|
46467
|
+
stateMonitor(state).publish(tickets, options3.name, () => {
|
|
46468
|
+
supersede();
|
|
46469
|
+
released = store.publish(options3.name, staged, tickets);
|
|
46470
|
+
});
|
|
46471
|
+
staged = void 0;
|
|
46472
|
+
await released;
|
|
46473
|
+
} else {
|
|
46474
|
+
const previous = pinned;
|
|
46475
|
+
pinned = staged;
|
|
46476
|
+
entry.binding = staged;
|
|
46477
|
+
staged = void 0;
|
|
46478
|
+
await previous.release();
|
|
46479
|
+
}
|
|
46480
|
+
} finally {
|
|
46481
|
+
try {
|
|
46482
|
+
await staged?.release();
|
|
46483
|
+
} finally {
|
|
46484
|
+
await operation2.close();
|
|
46485
|
+
}
|
|
46486
|
+
}
|
|
46487
|
+
},
|
|
46488
|
+
callback: async (source2, index, value2) => {
|
|
46489
|
+
if (pendingFlow) return;
|
|
46490
|
+
const callbackAllocation = this.budget.values.scope();
|
|
46491
|
+
const nested = mapfileCallbackStates.has(state);
|
|
46492
|
+
try {
|
|
46493
|
+
const quoted2 = shellValueText(await transformParameter(value2, "Q", { maximumBytes: this.budget.limits.maxExpansionBytes, byteLocale: byteLocale(state.variables), work, allocation: callbackAllocation }));
|
|
46494
|
+
if (import_buffer.Buffer.byteLength(source2) + import_buffer.Buffer.byteLength(quoted2) + String(index).length + 2 > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
46495
|
+
mapfileCallbackStates.add(state);
|
|
46496
|
+
await this.evalBuiltin({ ...context2, args: [source2, String(index), quoted2] }, state, context2, false);
|
|
46497
|
+
} catch (error) {
|
|
46498
|
+
if (error instanceof Flow2 && (error.kind === "break" || error.kind === "continue")) pendingFlow = error;
|
|
46499
|
+
else throw error;
|
|
46500
|
+
} finally {
|
|
46501
|
+
if (!nested) mapfileCallbackStates.delete(state);
|
|
46502
|
+
callbackAllocation.close();
|
|
46503
|
+
}
|
|
46504
|
+
}
|
|
46505
|
+
});
|
|
46506
|
+
if (pendingFlow) throw pendingFlow;
|
|
46507
|
+
return 0;
|
|
46508
|
+
} catch (error) {
|
|
46509
|
+
this.signal.throwIfAborted();
|
|
46510
|
+
if (!(error instanceof MapfileUsageError)) throw error;
|
|
46511
|
+
await this.diagnostic(context2, `${context2.command}: ${error.message}`);
|
|
46512
|
+
return error.status;
|
|
46513
|
+
} finally {
|
|
46514
|
+
try {
|
|
46515
|
+
await pinned?.release();
|
|
46516
|
+
} finally {
|
|
46517
|
+
try {
|
|
46518
|
+
releaseHolding?.();
|
|
46519
|
+
} finally {
|
|
46520
|
+
allocation.close();
|
|
46521
|
+
}
|
|
46522
|
+
}
|
|
46523
|
+
}
|
|
46524
|
+
}
|
|
46199
46525
|
async builtin(context2, state, assignments2, diagnose, suppressSpecial = false) {
|
|
46200
46526
|
const { command: command7, args, stdout, stderr } = context2;
|
|
46201
46527
|
if (command7 === ":" || command7 === "true") return 0;
|
|
46202
46528
|
if (command7 === "false") return 1;
|
|
46203
46529
|
if (command7 === "shopt") return this.shoptBuiltin(context2, state);
|
|
46204
46530
|
if (command7 === "let") return this.letBuiltin(context2, state);
|
|
46531
|
+
if (command7 === "mapfile" || command7 === "readarray") return this.mapfileBuiltin(context2, state);
|
|
46205
46532
|
if (command7 === "getopts") return this.getoptsBuiltin(context2, state);
|
|
46206
46533
|
if (command7 === "pushd" || command7 === "dirs" || command7 === "popd") return this.directoryStackBuiltin(context2, state, diagnose);
|
|
46207
46534
|
if (command7 === "pwd") {
|
|
@@ -46757,7 +47084,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46757
47084
|
if (part.kind === "variable" && part.transform) {
|
|
46758
47085
|
const selector2 = getArraySelector(part);
|
|
46759
47086
|
if (selector2?.kind === "members" || part.name === "@" || part.name === "*") {
|
|
46760
|
-
const members = selector2 ? await this.arrayMembers(part.name, state) : this.positionalValues(state);
|
|
47087
|
+
const members = selector2 ? await this.arrayMembers(part.name, state, io) : this.positionalValues(state);
|
|
46761
47088
|
const ifs = state.variables.IFS ?? " ";
|
|
46762
47089
|
const separator = ifs.length ? String.fromCodePoint(ifs.codePointAt(0)) : "";
|
|
46763
47090
|
const fragments = [];
|
|
@@ -46801,6 +47128,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46801
47128
|
const token = index === void 0 || selector?.kind === "members" ? void 0 : binding?.values.get(index)?.text;
|
|
46802
47129
|
token?.retain();
|
|
46803
47130
|
try {
|
|
47131
|
+
if (token?.rawValue && part.kind === "variable" && !part.length && !part.operator && !part.substring) return shellValueFromBytes(shellValueBytes(token.rawValue, io[valueScope]), io[valueScope]);
|
|
46804
47132
|
const value2 = await this.partValue(part, state, io, hereString);
|
|
46805
47133
|
if (binding) await textToken(requireArrays(state).owner, shellValueText(value2), this.signal);
|
|
46806
47134
|
return value2;
|
|
@@ -46918,8 +47246,11 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46918
47246
|
return part.length ? this.parameterLength(value3 ?? "") : value3 ?? "";
|
|
46919
47247
|
}
|
|
46920
47248
|
if (part.length) return String(binding?.values.size ?? (state.variables[part.name] === void 0 ? 0 : 1));
|
|
46921
|
-
const values = await this.arrayMembers(part.name, state);
|
|
46922
|
-
|
|
47249
|
+
const values = await this.arrayMembers(part.name, state, io);
|
|
47250
|
+
const separator = Array.from(state.variables.IFS ?? " ")[0] ?? "";
|
|
47251
|
+
if (values.every((value3) => typeof value3 === "string")) return this.arrayJoin(store.owner, values, separator);
|
|
47252
|
+
io[valueScope]?.reserve(values.length * 32 + 64, 0);
|
|
47253
|
+
return concatShellValues(values.flatMap((value3, index) => index ? [separator, value3] : [value3]), io[valueScope]);
|
|
46923
47254
|
}
|
|
46924
47255
|
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);
|
|
46925
47256
|
let retained = value2;
|
|
@@ -47328,7 +47659,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
47328
47659
|
emptyNameGroups.add(quoteGroup);
|
|
47329
47660
|
}
|
|
47330
47661
|
} else if (part.kind === "variable" && split4 && (selector?.kind === "members" && !part.length && (!part.quoted || selector.separator === "@") || part.transform && part.name === "@")) {
|
|
47331
|
-
const members = selector?.kind === "members" ? await this.arrayMembers(part.name, state) : this.positionalValues(state);
|
|
47662
|
+
const members = selector?.kind === "members" ? await this.arrayMembers(part.name, state, io) : this.positionalValues(state);
|
|
47332
47663
|
for (let position = 0; position < members.length; position++) {
|
|
47333
47664
|
if (position > 0) addField();
|
|
47334
47665
|
const original = members[position];
|
|
@@ -47470,7 +47801,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
47470
47801
|
for (const value2 of values) if (typeof value2 !== "string") allocation.hold(value2);
|
|
47471
47802
|
return createCommandArguments(values, allocation);
|
|
47472
47803
|
}
|
|
47473
|
-
async arrayMembers(name2, state) {
|
|
47804
|
+
async arrayMembers(name2, state, io) {
|
|
47474
47805
|
const store = requireArrays(state);
|
|
47475
47806
|
const holding = store.owner.hold();
|
|
47476
47807
|
try {
|
|
@@ -47489,8 +47820,9 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
47489
47820
|
const values = [];
|
|
47490
47821
|
for (const index of indices) {
|
|
47491
47822
|
store.owner.reserve({ metadata: 32, allocatedSlots: 1, work: 4 });
|
|
47492
|
-
const
|
|
47493
|
-
|
|
47823
|
+
const token = binding.values.get(index).text;
|
|
47824
|
+
const value2 = token.rawValue === void 0 ? token.value : shellValueFromBytes(shellValueBytes(token.rawValue, io[valueScope]), io[valueScope]);
|
|
47825
|
+
if (typeof value2 === "string") await textToken(store.owner, value2, this.signal);
|
|
47494
47826
|
values.push(value2);
|
|
47495
47827
|
await store.owner.ledger.checkpoint(this.signal);
|
|
47496
47828
|
}
|
|
@@ -48165,6 +48497,51 @@ var ShellInput = class _ShellInput {
|
|
|
48165
48497
|
}
|
|
48166
48498
|
});
|
|
48167
48499
|
}
|
|
48500
|
+
mapfileRecord(delimiter, strip, allocation) {
|
|
48501
|
+
return this.#cursor.consume(this.signal, async () => {
|
|
48502
|
+
this.#cursor.admitBoundedRead();
|
|
48503
|
+
allocation.reserve(64, 0);
|
|
48504
|
+
const parts = [];
|
|
48505
|
+
let length = 0;
|
|
48506
|
+
let truncated = false;
|
|
48507
|
+
let pulls = 0;
|
|
48508
|
+
while (true) {
|
|
48509
|
+
if (++pulls % 128 === 0) await yieldTurn(this.signal);
|
|
48510
|
+
const result2 = await this.#cursor.take(this.signal);
|
|
48511
|
+
if (result2.done) return { value: concatShellValues(parts, allocation), present: length > 0 };
|
|
48512
|
+
const chunk = result2.value;
|
|
48513
|
+
for (let offset = 0; offset < chunk.length; ) {
|
|
48514
|
+
await yieldTurn(this.signal);
|
|
48515
|
+
if (length >= this.budget.limits.maxOutputBytes) this.budget.fail("maxOutputBytes");
|
|
48516
|
+
const end = Math.min(offset + 1024, chunk.length, offset + this.budget.limits.maxOutputBytes - length);
|
|
48517
|
+
allocation.reserve(end - offset + 64, 0);
|
|
48518
|
+
const output2 = new Uint8Array(end - offset);
|
|
48519
|
+
let used = 0;
|
|
48520
|
+
let terminated = false;
|
|
48521
|
+
while (offset < end) {
|
|
48522
|
+
const byte = chunk[offset++];
|
|
48523
|
+
this.#cursor.position++;
|
|
48524
|
+
if (++length > this.budget.limits.maxOutputBytes) this.budget.fail("maxOutputBytes");
|
|
48525
|
+
if (byte === delimiter) {
|
|
48526
|
+
if (!strip && byte !== 0 && !truncated) output2[used++] = byte;
|
|
48527
|
+
terminated = true;
|
|
48528
|
+
break;
|
|
48529
|
+
}
|
|
48530
|
+
if (byte === 0) truncated = true;
|
|
48531
|
+
if (!truncated) output2[used++] = byte;
|
|
48532
|
+
}
|
|
48533
|
+
if (used) {
|
|
48534
|
+
allocation.reserve(32, 0);
|
|
48535
|
+
parts.push(shellValueFromBytes(output2.subarray(0, used), allocation));
|
|
48536
|
+
}
|
|
48537
|
+
if (terminated) {
|
|
48538
|
+
if (offset < chunk.length) this.#cursor.remainder = chunk.subarray(offset);
|
|
48539
|
+
return { value: concatShellValues(parts, allocation), present: true };
|
|
48540
|
+
}
|
|
48541
|
+
}
|
|
48542
|
+
}
|
|
48543
|
+
});
|
|
48544
|
+
}
|
|
48168
48545
|
async readBounded(raw, options3) {
|
|
48169
48546
|
const text3 = new ReadText();
|
|
48170
48547
|
let characters = 0;
|