@poe-platform/safe-bash 0.1.442 → 0.1.444
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/browser.js +111 -69
- package/dist/safe-bash/browser.js.map +4 -4
- package/dist/safe-bash/commands/archive/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/index.js +2 -1
- package/dist/safe-bash/commands/archive/index.js.map +1 -1
- package/dist/safe-bash/commands/archive/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/internal.js +2 -1
- package/dist/safe-bash/commands/archive/internal.js.map +1 -1
- package/dist/safe-bash/commands/archive/stream.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/stream.js +11 -4
- package/dist/safe-bash/commands/archive/stream.js.map +1 -1
- package/dist/safe-bash/commands/bytes/checksums/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/checksums/index.js +7 -6
- package/dist/safe-bash/commands/bytes/checksums/index.js.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/errors.d.ts +2 -0
- package/dist/safe-bash/commands/bytes/compression/errors.d.ts.map +1 -0
- package/dist/safe-bash/commands/bytes/compression/errors.js +19 -0
- package/dist/safe-bash/commands/bytes/compression/errors.js.map +1 -0
- package/dist/safe-bash/commands/bytes/compression/files.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/files.js +5 -2
- package/dist/safe-bash/commands/bytes/compression/files.js.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/gunzip.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/gunzip.js +20 -12
- package/dist/safe-bash/commands/bytes/compression/gunzip.js.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/index.js +2 -1
- package/dist/safe-bash/commands/bytes/compression/index.js.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/stream.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/stream.js +3 -1
- package/dist/safe-bash/commands/bytes/compression/stream.js.map +1 -1
- package/dist/safe-bash/commands/bytes/encoding/base.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/encoding/base.js +3 -2
- package/dist/safe-bash/commands/bytes/encoding/base.js.map +1 -1
- package/dist/safe-bash/commands/bytes/encoding/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/encoding/shared.js +3 -2
- package/dist/safe-bash/commands/bytes/encoding/shared.js.map +1 -1
- package/dist/safe-bash/commands/bytes/encoding/xxd.d.ts.map +1 -1
- package/dist/safe-bash/commands/bytes/encoding/xxd.js +8 -7
- package/dist/safe-bash/commands/bytes/encoding/xxd.js.map +1 -1
- package/dist/safe-bash/commands/column/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/column/internal.js +2 -1
- package/dist/safe-bash/commands/column/internal.js.map +1 -1
- package/dist/safe-bash/commands/diff-patch/patch-gnu-paths.d.ts.map +1 -1
- package/dist/safe-bash/commands/diff-patch/patch-gnu-paths.js +2 -1
- package/dist/safe-bash/commands/diff-patch/patch-gnu-paths.js.map +1 -1
- package/dist/safe-bash/commands/diff-patch/patch.d.ts.map +1 -1
- package/dist/safe-bash/commands/diff-patch/patch.js +3 -2
- package/dist/safe-bash/commands/diff-patch/patch.js.map +1 -1
- package/dist/safe-bash/commands/diff-patch/shared.d.ts +2 -1
- package/dist/safe-bash/commands/diff-patch/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/diff-patch/shared.js +3 -2
- package/dist/safe-bash/commands/diff-patch/shared.js.map +1 -1
- package/dist/safe-bash/commands/du/budget.d.ts.map +1 -1
- package/dist/safe-bash/commands/du/budget.js +3 -1
- package/dist/safe-bash/commands/du/budget.js.map +1 -1
- package/dist/safe-bash/commands/du/du.d.ts.map +1 -1
- package/dist/safe-bash/commands/du/du.js +8 -7
- package/dist/safe-bash/commands/du/du.js.map +1 -1
- package/dist/safe-bash/commands/du/format.d.ts +2 -1
- package/dist/safe-bash/commands/du/format.d.ts.map +1 -1
- package/dist/safe-bash/commands/du/format.js +2 -1
- package/dist/safe-bash/commands/du/format.js.map +1 -1
- package/dist/safe-bash/commands/expr/command.d.ts.map +1 -1
- package/dist/safe-bash/commands/expr/command.js +3 -1
- package/dist/safe-bash/commands/expr/command.js.map +1 -1
- package/dist/safe-bash/commands/find.d.ts.map +1 -1
- package/dist/safe-bash/commands/find.js +2 -1
- package/dist/safe-bash/commands/find.js.map +1 -1
- package/dist/safe-bash/commands/html-to-markdown/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/html-to-markdown/index.js +2 -1
- package/dist/safe-bash/commands/html-to-markdown/index.js.map +1 -1
- package/dist/safe-bash/commands/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/index.js +2 -1
- package/dist/safe-bash/commands/index.js.map +1 -1
- package/dist/safe-bash/commands/internal.d.ts +2 -1
- package/dist/safe-bash/commands/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/internal.js +3 -2
- package/dist/safe-bash/commands/internal.js.map +1 -1
- package/dist/safe-bash/commands/move.d.ts.map +1 -1
- package/dist/safe-bash/commands/move.js +2 -1
- package/dist/safe-bash/commands/move.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/bounded-provider.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/bounded-provider.js +14 -3
- package/dist/safe-bash/commands/regex-execution/bounded-provider.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/matching.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/matching.js +12 -5
- package/dist/safe-bash/commands/regex-execution/matching.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/portable.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/portable.js +1 -1
- package/dist/safe-bash/commands/regex-execution/portable.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/protocol.d.ts +3 -2
- package/dist/safe-bash/commands/regex-execution/protocol.d.ts.map +1 -1
- package/dist/safe-bash/commands/regex-execution/protocol.js +4 -3
- package/dist/safe-bash/commands/regex-execution/protocol.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/worker.js +6 -3
- package/dist/safe-bash/commands/regex-execution/worker.js.map +1 -1
- package/dist/safe-bash/commands/safejs/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/safejs/index.js +24 -7
- package/dist/safe-bash/commands/safejs/index.js.map +1 -1
- package/dist/safe-bash/commands/search/options.d.ts +2 -1
- package/dist/safe-bash/commands/search/options.d.ts.map +1 -1
- package/dist/safe-bash/commands/search/options.js +2 -1
- package/dist/safe-bash/commands/search/options.js.map +1 -1
- package/dist/safe-bash/commands/search/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/search/shared.js +2 -1
- package/dist/safe-bash/commands/search/shared.js.map +1 -1
- package/dist/safe-bash/commands/split/names.d.ts.map +1 -1
- package/dist/safe-bash/commands/split/names.js +3 -2
- package/dist/safe-bash/commands/split/names.js.map +1 -1
- package/dist/safe-bash/commands/split/options.d.ts.map +1 -1
- package/dist/safe-bash/commands/split/options.js +17 -16
- package/dist/safe-bash/commands/split/options.js.map +1 -1
- package/dist/safe-bash/commands/split/split.d.ts.map +1 -1
- package/dist/safe-bash/commands/split/split.js +2 -1
- package/dist/safe-bash/commands/split/split.js.map +1 -1
- package/dist/safe-bash/commands/standard.d.ts.map +1 -1
- package/dist/safe-bash/commands/standard.js +2 -1
- package/dist/safe-bash/commands/standard.js.map +1 -1
- package/dist/safe-bash/commands/stream-format/rev.d.ts.map +1 -1
- package/dist/safe-bash/commands/stream-format/rev.js +2 -1
- package/dist/safe-bash/commands/stream-format/rev.js.map +1 -1
- package/dist/safe-bash/commands/table-text/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/table-text/internal.js +3 -2
- package/dist/safe-bash/commands/table-text/internal.js.map +1 -1
- package/dist/safe-bash/commands/tail-follow.d.ts.map +1 -1
- package/dist/safe-bash/commands/tail-follow.js +4 -3
- package/dist/safe-bash/commands/tail-follow.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/shared.d.ts +2 -1
- package/dist/safe-bash/commands/text-programs/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/text-programs/shared.js +3 -2
- package/dist/safe-bash/commands/text-programs/shared.js.map +1 -1
- package/dist/safe-bash/commands/text.d.ts.map +1 -1
- package/dist/safe-bash/commands/text.js +2 -1
- package/dist/safe-bash/commands/text.js.map +1 -1
- package/dist/safe-bash/commands/tree/io.d.ts.map +1 -1
- package/dist/safe-bash/commands/tree/io.js +2 -4
- package/dist/safe-bash/commands/tree/io.js.map +1 -1
- package/dist/safe-bash/contracts/command.d.ts +5 -0
- package/dist/safe-bash/contracts/command.d.ts.map +1 -1
- package/dist/safe-bash/contracts/command.js +6 -1
- package/dist/safe-bash/contracts/command.js.map +1 -1
- package/dist/safe-bash/diagnostics.d.ts +5 -0
- package/dist/safe-bash/diagnostics.d.ts.map +1 -0
- package/dist/safe-bash/diagnostics.js +22 -0
- package/dist/safe-bash/diagnostics.js.map +1 -0
- package/dist/safe-bash/plugins/composition.d.ts.map +1 -1
- package/dist/safe-bash/plugins/composition.js +2 -1
- package/dist/safe-bash/plugins/composition.js.map +1 -1
- package/dist/safe-bash/portable.js +238 -150
- package/dist/safe-bash/portable.js.map +4 -4
- package/dist/safe-bash/shell/arithmetic.d.ts.map +1 -1
- package/dist/safe-bash/shell/arithmetic.js +10 -9
- package/dist/safe-bash/shell/arithmetic.js.map +1 -1
- package/dist/safe-bash/shell/input.d.ts.map +1 -1
- package/dist/safe-bash/shell/input.js +2 -1
- package/dist/safe-bash/shell/input.js.map +1 -1
- package/dist/safe-bash/shell/runtime.d.ts +3 -1
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +52 -38
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/dist/safe-bash/shell/shell.d.ts.map +1 -1
- package/dist/safe-bash/shell/shell.js +5 -1
- package/dist/safe-bash/shell/shell.js.map +1 -1
- package/dist/safe-bash/shell/types.d.ts +3 -1
- package/dist/safe-bash/shell/types.d.ts.map +1 -1
- package/dist/safe-bash/shell/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PublicDiagnostic, publicDiagnosticMessage } from "../diagnostics.js";
|
|
1
2
|
import { writeDiagnostic } from "../escaping.js";
|
|
2
3
|
import { cancelTurn, monotonicNow, registerYieldCheckpoint, scheduleTurn, yieldTurn } from "../contracts/yield.js";
|
|
3
4
|
import { ACCESS_MODES, FsError, composeMiddleware, createBytePipe, pipeBytes, resolvePath, toByteSource, validateExitCode, writeText, } from "../contracts/index.js";
|
|
@@ -77,6 +78,7 @@ export function resolveLimits(...limits) {
|
|
|
77
78
|
const budgetedSinks = new WeakMap();
|
|
78
79
|
export class Budget {
|
|
79
80
|
limits;
|
|
81
|
+
onInternalError;
|
|
80
82
|
executionScope = Object.freeze({});
|
|
81
83
|
pathLookup = new PathLookup();
|
|
82
84
|
parsing;
|
|
@@ -92,8 +94,9 @@ export class Budget {
|
|
|
92
94
|
#pipelineStages = 0;
|
|
93
95
|
#fileSystemOperations = 0;
|
|
94
96
|
#cpuStarted = monotonicNow();
|
|
95
|
-
constructor(limits, signal) {
|
|
97
|
+
constructor(limits, signal, onInternalError) {
|
|
96
98
|
this.limits = limits;
|
|
99
|
+
this.onInternalError = onInternalError;
|
|
97
100
|
this.signal = signal ? AbortSignal.any([signal, this.controller.signal]) : this.controller.signal;
|
|
98
101
|
this.parsing = new ParseBudget(limits.maxParseUnits, this.signal, error => this.controller.abort(error));
|
|
99
102
|
this.values = new ValueArena(limits.maxExpansionBytes, limits.maxExpansionFields, () => this.signal.throwIfAborted(), limit => this.fail(limit));
|
|
@@ -539,11 +542,18 @@ function saturatedSum(left, right) {
|
|
|
539
542
|
function errorCode(error) {
|
|
540
543
|
return typeof error === "object" && error !== null && "code" in error ? String(error.code) : undefined;
|
|
541
544
|
}
|
|
542
|
-
function message(error) {
|
|
543
|
-
|
|
545
|
+
function message(error, onInternalError) {
|
|
546
|
+
if (error instanceof ExpansionFailure || error instanceof CommandFailure || error instanceof ArrayFailure || error instanceof BraceExpansionFailure)
|
|
547
|
+
return error.message;
|
|
548
|
+
return publicDiagnosticMessage(error, onInternalError);
|
|
549
|
+
}
|
|
550
|
+
function filesystemDiagnostic(error, target, onInternalError) {
|
|
544
551
|
const descriptions = { ENOENT: "No such file or directory", EACCES: "Permission denied", EPERM: "Operation not permitted", ENOTDIR: "Not a directory", EISDIR: "Is a directory", ELOOP: "Too many levels of symbolic links", ENOSPC: "No space left on device", EROFS: "Read-only file system" };
|
|
545
552
|
const description = descriptions[errorCode(error) ?? ""];
|
|
546
|
-
|
|
553
|
+
if (!description)
|
|
554
|
+
return undefined;
|
|
555
|
+
publicDiagnosticMessage(error, onInternalError);
|
|
556
|
+
return `${target}: ${description}`;
|
|
547
557
|
}
|
|
548
558
|
function cdUtf8Width(codePoint) {
|
|
549
559
|
return codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;
|
|
@@ -583,7 +593,7 @@ class CdLookup {
|
|
|
583
593
|
async charge(amount) {
|
|
584
594
|
this.signal.throwIfAborted();
|
|
585
595
|
if (amount > 8_388_608 - this.spent)
|
|
586
|
-
throw new
|
|
596
|
+
throw new PublicDiagnostic("cd: helper work limit exceeded");
|
|
587
597
|
while (amount > 0) {
|
|
588
598
|
const step = Math.min(amount, 128 - this.spent % 128);
|
|
589
599
|
this.spent += step;
|
|
@@ -605,9 +615,9 @@ class CdLookup {
|
|
|
605
615
|
const codePoint = value.codePointAt(index);
|
|
606
616
|
const width = cdUtf8Width(codePoint);
|
|
607
617
|
if (bytes + width > 65_536)
|
|
608
|
-
throw new
|
|
618
|
+
throw new PublicDiagnostic(search ? "cd: CDPATH exceeds 65536 UTF-8 bytes" : "cd: path exceeds 65536 UTF-8 bytes");
|
|
609
619
|
if (search && codePoint === 58 && ++slots > 4096)
|
|
610
|
-
throw new
|
|
620
|
+
throw new PublicDiagnostic("cd: CDPATH exceeds 4096 components");
|
|
611
621
|
await this.charge(width);
|
|
612
622
|
if (search && codePoint === 58) {
|
|
613
623
|
components.push({ start, end: index, bytes: bytes - startBytes });
|
|
@@ -631,7 +641,7 @@ class CdLookup {
|
|
|
631
641
|
const rawBytes = absolute ? targetBytes : component.startsWith("/") ? componentBytes + 1 + targetBytes
|
|
632
642
|
: cwdBytes + 1 + (component ? componentBytes + 1 : 0) + targetBytes;
|
|
633
643
|
if (rawBytes > 65_536)
|
|
634
|
-
throw new
|
|
644
|
+
throw new PublicDiagnostic("cd: path exceeds 65536 UTF-8 bytes");
|
|
635
645
|
await this.charge(2 * rawBytes);
|
|
636
646
|
const raw = absolute ? target : component.startsWith("/") ? `${component}/${target}`
|
|
637
647
|
: component ? `${cwd}/${component}/${target}` : `${cwd}/${target}`;
|
|
@@ -639,7 +649,7 @@ class CdLookup {
|
|
|
639
649
|
await this.scan(path);
|
|
640
650
|
this.signal.throwIfAborted();
|
|
641
651
|
if (++this.probes > 4097)
|
|
642
|
-
throw new
|
|
652
|
+
throw new PublicDiagnostic("cd: probe limit exceeded");
|
|
643
653
|
await this.charge(1);
|
|
644
654
|
this.signal.throwIfAborted();
|
|
645
655
|
const stat = await fs.stat(path, { signal: this.signal });
|
|
@@ -812,7 +822,7 @@ class DirectoryStackWork {
|
|
|
812
822
|
await this.flushOutput();
|
|
813
823
|
}
|
|
814
824
|
}
|
|
815
|
-
const closedSink = { async write() { throw Object.assign(new
|
|
825
|
+
const closedSink = { async write() { throw Object.assign(new PublicDiagnostic("Bad file descriptor"), { code: "EBADF" }); } };
|
|
816
826
|
const closedSource = { [Symbol.asyncIterator]() {
|
|
817
827
|
let closed = false;
|
|
818
828
|
let completion = Promise.resolve();
|
|
@@ -827,7 +837,7 @@ const closedSource = { [Symbol.asyncIterator]() {
|
|
|
827
837
|
if (closed)
|
|
828
838
|
return { done: true, value: undefined };
|
|
829
839
|
closed = true;
|
|
830
|
-
throw Object.assign(new
|
|
840
|
+
throw Object.assign(new PublicDiagnostic("Bad file descriptor"), { code: "EBADF" });
|
|
831
841
|
});
|
|
832
842
|
},
|
|
833
843
|
return(value) { return enqueue(async () => { closed = true; return { done: true, value: await value }; }); },
|
|
@@ -1307,7 +1317,7 @@ export class Runtime {
|
|
|
1307
1317
|
if (arrayStore(state)?.get(name))
|
|
1308
1318
|
throw new ArrayFailure(origin === "arithmetic" ? "indexed arithmetic is unsupported" : "indexed write requires prepared publication");
|
|
1309
1319
|
if (state.readonlyVariables?.has(name))
|
|
1310
|
-
throw new
|
|
1320
|
+
throw new PublicDiagnostic(`${name}: readonly variable`);
|
|
1311
1321
|
if (shellValueByteLength(value) > this.budget.limits.maxExpansionBytes)
|
|
1312
1322
|
this.budget.fail("maxExpansionBytes");
|
|
1313
1323
|
if (name === "OPTIND" && state.getopts?.integer && origin !== "arithmetic") {
|
|
@@ -1316,7 +1326,7 @@ export class Runtime {
|
|
|
1316
1326
|
}
|
|
1317
1327
|
catch (error) {
|
|
1318
1328
|
this.rethrowArithmeticControl(error);
|
|
1319
|
-
throw new ExpansionFailure(message(error));
|
|
1329
|
+
throw new ExpansionFailure(message(error, this.budget.onInternalError));
|
|
1320
1330
|
}
|
|
1321
1331
|
}
|
|
1322
1332
|
publishVariable(state, name, value);
|
|
@@ -1339,7 +1349,7 @@ export class Runtime {
|
|
|
1339
1349
|
}
|
|
1340
1350
|
unsetVariable(state, name, internal = false) {
|
|
1341
1351
|
if (state.readonlyVariables?.has(name))
|
|
1342
|
-
throw new
|
|
1352
|
+
throw new PublicDiagnostic(`${name}: readonly variable`);
|
|
1343
1353
|
delete state.variables[name];
|
|
1344
1354
|
state.exported.delete(name);
|
|
1345
1355
|
if (name === "OPTIND" && !internal)
|
|
@@ -2140,7 +2150,7 @@ export class Runtime {
|
|
|
2140
2150
|
}
|
|
2141
2151
|
catch (error) {
|
|
2142
2152
|
this.rethrowArithmeticControl(error);
|
|
2143
|
-
throw new
|
|
2153
|
+
throw new PublicDiagnostic(`((: ${message(error, this.budget.onInternalError)}`);
|
|
2144
2154
|
}
|
|
2145
2155
|
}
|
|
2146
2156
|
if (command.kind === "subshell") {
|
|
@@ -2255,9 +2265,10 @@ export class Runtime {
|
|
|
2255
2265
|
this.errexit(141, state, io);
|
|
2256
2266
|
return 141;
|
|
2257
2267
|
}
|
|
2268
|
+
const publicMessage = message(error, this.budget.onInternalError);
|
|
2258
2269
|
const line = error instanceof ExpansionFailure ? error.line ?? io.diagnosticLine ?? 1 : io.diagnosticLine ?? 1;
|
|
2259
2270
|
if (error instanceof NounsetFailure || error instanceof ParameterExpansionFailure) {
|
|
2260
|
-
const detail = error instanceof ParameterExpansionFailure ? diagnostic ??
|
|
2271
|
+
const detail = error instanceof ParameterExpansionFailure ? diagnostic ?? publicMessage : publicMessage;
|
|
2261
2272
|
try {
|
|
2262
2273
|
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${detail}\n`);
|
|
2263
2274
|
}
|
|
@@ -2271,13 +2282,14 @@ export class Runtime {
|
|
|
2271
2282
|
throw completedExit(error instanceof ParameterExpansionFailure && !state.isolated ? 127 : 1);
|
|
2272
2283
|
}
|
|
2273
2284
|
if (error instanceof ArrayFailure)
|
|
2274
|
-
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic ??
|
|
2285
|
+
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic ?? publicMessage}\n`);
|
|
2275
2286
|
else {
|
|
2276
2287
|
try {
|
|
2277
|
-
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic ??
|
|
2288
|
+
await writeDiagnostic(io.stderr, `${io.scriptName ?? "shell"}: line ${line}: ${diagnostic ?? publicMessage}\n`);
|
|
2278
2289
|
}
|
|
2279
|
-
catch {
|
|
2290
|
+
catch (failure) {
|
|
2280
2291
|
this.signal.throwIfAborted();
|
|
2292
|
+
publicDiagnosticMessage(failure, this.budget.onInternalError);
|
|
2281
2293
|
}
|
|
2282
2294
|
}
|
|
2283
2295
|
if (error instanceof ExpansionFailure || error instanceof BraceExpansionFailure)
|
|
@@ -2406,7 +2418,7 @@ export class Runtime {
|
|
|
2406
2418
|
if (error instanceof ParameterExpansionFailure)
|
|
2407
2419
|
throw new CommandFailure(error.message, state.isolated ? 1 : 127);
|
|
2408
2420
|
if (error instanceof ExpansionFailure)
|
|
2409
|
-
throw new
|
|
2421
|
+
throw new PublicDiagnostic(error.message);
|
|
2410
2422
|
throw error;
|
|
2411
2423
|
}
|
|
2412
2424
|
if (hereString) {
|
|
@@ -2421,7 +2433,7 @@ export class Runtime {
|
|
|
2421
2433
|
}
|
|
2422
2434
|
const targets = await this.word(redirect.target, state, currentIO());
|
|
2423
2435
|
if (targets.length !== 1)
|
|
2424
|
-
throw new
|
|
2436
|
+
throw new PublicDiagnostic("Ambiguous redirect");
|
|
2425
2437
|
const target = targets[0];
|
|
2426
2438
|
errorTarget = target;
|
|
2427
2439
|
if (redirect.operator.endsWith("&")) {
|
|
@@ -2429,14 +2441,14 @@ export class Runtime {
|
|
|
2429
2441
|
descriptors.delete(redirect.descriptor);
|
|
2430
2442
|
else {
|
|
2431
2443
|
if (!/^\d+-?$/u.test(target))
|
|
2432
|
-
throw new
|
|
2444
|
+
throw new PublicDiagnostic(`${target}: Bad file descriptor`);
|
|
2433
2445
|
const move = target.endsWith("-");
|
|
2434
2446
|
if (move && !redirect.move)
|
|
2435
|
-
throw new
|
|
2447
|
+
throw new PublicDiagnostic(`${target}: ambiguous redirect`);
|
|
2436
2448
|
const sourceDescriptor = Number(move ? target.slice(0, -1) : target);
|
|
2437
2449
|
const descriptor = descriptors.get(sourceDescriptor);
|
|
2438
2450
|
if (!descriptor || descriptor.closed || (!move && (redirect.operator === "<&" ? !descriptor.input : !descriptor.output)))
|
|
2439
|
-
throw new
|
|
2451
|
+
throw new PublicDiagnostic(`${move ? sourceDescriptor : target}: Bad file descriptor`);
|
|
2440
2452
|
descriptors.set(redirect.descriptor, { ...descriptor });
|
|
2441
2453
|
if (move && sourceDescriptor !== redirect.descriptor) {
|
|
2442
2454
|
descriptors.delete(sourceDescriptor);
|
|
@@ -2452,7 +2464,7 @@ export class Runtime {
|
|
|
2452
2464
|
await interruptible(this.fs.access(path, 4, options), this.signal);
|
|
2453
2465
|
const stat = await interruptible(this.fs.stat(path, options), this.signal);
|
|
2454
2466
|
if (stat.type === "directory" && !fileShortcut)
|
|
2455
|
-
throw new
|
|
2467
|
+
throw new PublicDiagnostic(`${target}: Is a directory`);
|
|
2456
2468
|
const source = stat.type === "directory" ? toByteSource("")
|
|
2457
2469
|
: await fileInput(this.fs, path, this.budget.limits.maxInputBytes, this.signal);
|
|
2458
2470
|
const input = new ShellInput(source, this.budget, this.signal);
|
|
@@ -2761,7 +2773,7 @@ export class Runtime {
|
|
|
2761
2773
|
if (fileShortcut) {
|
|
2762
2774
|
const input = io.descriptors?.get(command.redirects[0].descriptor)?.input;
|
|
2763
2775
|
if (!input)
|
|
2764
|
-
throw new
|
|
2776
|
+
throw new PublicDiagnostic("Bad file descriptor");
|
|
2765
2777
|
await pipeBytes(input, io.stdout, this.signal);
|
|
2766
2778
|
return 0;
|
|
2767
2779
|
}
|
|
@@ -2773,7 +2785,7 @@ export class Runtime {
|
|
|
2773
2785
|
this.signal.throwIfAborted();
|
|
2774
2786
|
const original = error instanceof ExecutionFailure ? error.original : error;
|
|
2775
2787
|
if (special && !(original instanceof ShellLimitError) && !(original instanceof ExpansionFailure) && !(original instanceof Flow) && !(original instanceof ShellSyntaxError)) {
|
|
2776
|
-
throw new ExecutionFailure(new FatalCommandFailure(message(original), 1), error instanceof ExecutionFailure ? error.io : io, error instanceof ExecutionFailure ? error.diagnostic : undefined);
|
|
2788
|
+
throw new ExecutionFailure(new FatalCommandFailure(message(original, this.budget.onInternalError), 1), error instanceof ExecutionFailure ? error.io : io, error instanceof ExecutionFailure ? error.diagnostic : undefined);
|
|
2777
2789
|
}
|
|
2778
2790
|
if (error instanceof ExecutionFailure)
|
|
2779
2791
|
throw error;
|
|
@@ -2822,6 +2834,7 @@ export class Runtime {
|
|
|
2822
2834
|
const context = {
|
|
2823
2835
|
...publicIO, command: name, args: argumentValues.args, argumentValues, env, cwd: state.cwd, fs: this.fs, signal: this.commandSignal,
|
|
2824
2836
|
executionScope: this.budget.executionScope,
|
|
2837
|
+
onInternalError: this.budget.onInternalError,
|
|
2825
2838
|
registerCleanup: (cleanup) => { scope.register(cleanup); },
|
|
2826
2839
|
invoke: (name, args, options) => {
|
|
2827
2840
|
const invocation = this.invoke(name, args, options, context, state, scope);
|
|
@@ -3271,8 +3284,8 @@ export class Runtime {
|
|
|
3271
3284
|
if (code === "ENOENT" || code === "ENOTDIR")
|
|
3272
3285
|
continue;
|
|
3273
3286
|
if (code !== "EACCES" && code !== "EPERM")
|
|
3274
|
-
throw new CommandFailure(filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`, 126);
|
|
3275
|
-
denied ??= new CommandFailure(filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`, 126);
|
|
3287
|
+
throw new CommandFailure(filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`, 126);
|
|
3288
|
+
denied ??= new CommandFailure(filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`, 126);
|
|
3276
3289
|
}
|
|
3277
3290
|
}
|
|
3278
3291
|
if (denied && !matches.length && !discovery)
|
|
@@ -3479,6 +3492,7 @@ export class Runtime {
|
|
|
3479
3492
|
const context = {
|
|
3480
3493
|
...incoming, args: argumentValues.args, argumentValues,
|
|
3481
3494
|
executionScope: this.budget.executionScope,
|
|
3495
|
+
onInternalError: this.budget.onInternalError,
|
|
3482
3496
|
env: Object.assign(Object.create(null), incoming.env),
|
|
3483
3497
|
stdin: input ?? incoming.stdin,
|
|
3484
3498
|
stdout: this.budget.sink(incoming.stdout, runtime.signal), stderr: this.budget.sink(incoming.stderr, runtime.signal),
|
|
@@ -3675,7 +3689,7 @@ export class Runtime {
|
|
|
3675
3689
|
throw error;
|
|
3676
3690
|
if (errorCode(error) === "EFBIG")
|
|
3677
3691
|
this.budget.fail("maxSourceBytes");
|
|
3678
|
-
throw new CommandFailure(filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`, errorCode(error) === "ENOENT" ? 127 : 126);
|
|
3692
|
+
throw new CommandFailure(filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`, errorCode(error) === "ENOENT" ? 127 : 126);
|
|
3679
3693
|
}
|
|
3680
3694
|
if (direct && environmentInterpreter)
|
|
3681
3695
|
return this.envShebang(context, state, io, environmentInterpreter[1], target, args, { path, source });
|
|
@@ -3848,7 +3862,7 @@ export class Runtime {
|
|
|
3848
3862
|
throw error;
|
|
3849
3863
|
if (errorCode(error) === "EFBIG")
|
|
3850
3864
|
this.budget.fail("maxSourceBytes");
|
|
3851
|
-
const diagnostic = error instanceof CommandFailure ? error.message : filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`;
|
|
3865
|
+
const diagnostic = error instanceof CommandFailure ? error.message : filesystemDiagnostic(error, target, this.budget.onInternalError) ?? `${target}: ${message(error, this.budget.onInternalError)}`;
|
|
3852
3866
|
if (special)
|
|
3853
3867
|
throw new FatalCommandFailure(diagnostic, 1);
|
|
3854
3868
|
throw new CommandFailure(diagnostic, error instanceof CommandFailure ? error.status : 1);
|
|
@@ -4095,7 +4109,7 @@ export class Runtime {
|
|
|
4095
4109
|
}
|
|
4096
4110
|
catch (error) {
|
|
4097
4111
|
this.rethrowArithmeticControl(error);
|
|
4098
|
-
throw new
|
|
4112
|
+
throw new PublicDiagnostic(`let: ${message(error, this.budget.onInternalError)}`);
|
|
4099
4113
|
}
|
|
4100
4114
|
if ((index - offset + 1) % 128 === 0)
|
|
4101
4115
|
await checkpoint();
|
|
@@ -4207,7 +4221,7 @@ export class Runtime {
|
|
|
4207
4221
|
else
|
|
4208
4222
|
this.unsetVariable(state, "OPTARG", true);
|
|
4209
4223
|
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(name))
|
|
4210
|
-
throw new
|
|
4224
|
+
throw new PublicDiagnostic(`getopts: \`${name}': not a valid identifier`);
|
|
4211
4225
|
await this.assignVariable(state, name, result.option, "getopts");
|
|
4212
4226
|
return result.status;
|
|
4213
4227
|
}
|
|
@@ -4229,8 +4243,8 @@ export class Runtime {
|
|
|
4229
4243
|
}
|
|
4230
4244
|
catch (error) {
|
|
4231
4245
|
this.signal.throwIfAborted();
|
|
4232
|
-
const description = filesystemDiagnostic(error, "");
|
|
4233
|
-
const text = description ? "" : message(error);
|
|
4246
|
+
const description = filesystemDiagnostic(error, "", this.budget.onInternalError);
|
|
4247
|
+
const text = description ? "" : message(error, this.budget.onInternalError);
|
|
4234
4248
|
diagnose?.(error, cdDiagnostic(description ? [name, ": ", target, description]
|
|
4235
4249
|
: stackHooks && text.startsWith("cd: ") ? [name, text.slice(2)] : [text]));
|
|
4236
4250
|
throw error;
|
|
@@ -5216,7 +5230,7 @@ export class Runtime {
|
|
|
5216
5230
|
}
|
|
5217
5231
|
catch (error) {
|
|
5218
5232
|
this.rethrowArithmeticControl(error);
|
|
5219
|
-
throw new ExpansionFailure(message(error), io.diagnosticLine ?? part.line);
|
|
5233
|
+
throw new ExpansionFailure(message(error, this.budget.onInternalError), io.diagnosticLine ?? part.line);
|
|
5220
5234
|
}
|
|
5221
5235
|
}
|
|
5222
5236
|
if (part.kind === "substitution") {
|
|
@@ -5336,7 +5350,7 @@ export class Runtime {
|
|
|
5336
5350
|
throw new ParameterExpansionFailure(`${part.name}: ${alternate || (part.operator.startsWith(":") ? "parameter null or not set" : "parameter not set")}`, io.diagnosticLine ?? part.line);
|
|
5337
5351
|
if (operator === "=") {
|
|
5338
5352
|
if (!/^[a-zA-Z_][a-zA-Z_0-9]*$/u.test(part.name))
|
|
5339
|
-
throw new
|
|
5353
|
+
throw new PublicDiagnostic("Cannot assign special parameter");
|
|
5340
5354
|
this.writeVariable(state, part.name, retained);
|
|
5341
5355
|
}
|
|
5342
5356
|
value = alternate;
|
|
@@ -5405,7 +5419,7 @@ export class Runtime {
|
|
|
5405
5419
|
}
|
|
5406
5420
|
catch (error) {
|
|
5407
5421
|
this.rethrowArithmeticControl(error);
|
|
5408
|
-
throw new ExpansionFailure(`${part.name}: ${message(error)}`, line);
|
|
5422
|
+
throw new ExpansionFailure(`${part.name}: ${message(error, this.budget.onInternalError)}`, line);
|
|
5409
5423
|
}
|
|
5410
5424
|
finally {
|
|
5411
5425
|
retained?.release();
|