@poe-platform/safe-bash 0.1.41 → 0.1.43
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/README.md +11 -2
- package/dist/safe-bash/browser.d.ts +5 -0
- package/dist/safe-bash/browser.d.ts.map +1 -1
- package/dist/safe-bash/browser.js +873 -122
- package/dist/safe-bash/browser.js.map +4 -4
- package/dist/safe-bash/commands/apply-patch/shared.js +2 -2
- package/dist/safe-bash/commands/apply-patch/shared.js.map +1 -1
- package/dist/safe-bash/commands/archive/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/archive/internal.js +3 -2
- package/dist/safe-bash/commands/archive/internal.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 +3 -2
- package/dist/safe-bash/commands/bytes/checksums/index.js.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/gunzip.js +2 -2
- package/dist/safe-bash/commands/bytes/compression/gunzip.js.map +1 -1
- package/dist/safe-bash/commands/bytes/compression/stream.js +2 -2
- package/dist/safe-bash/commands/bytes/compression/stream.js.map +1 -1
- package/dist/safe-bash/commands/bytes/encoding/shared.js +3 -3
- package/dist/safe-bash/commands/bytes/encoding/shared.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/shared.js +2 -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 -2
- package/dist/safe-bash/commands/du/budget.js.map +1 -1
- package/dist/safe-bash/commands/env-split.d.ts.map +1 -1
- package/dist/safe-bash/commands/env-split.js +2 -1
- package/dist/safe-bash/commands/env-split.js.map +1 -1
- package/dist/safe-bash/commands/expr/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/expr/internal.js +2 -1
- package/dist/safe-bash/commands/expr/internal.js.map +1 -1
- package/dist/safe-bash/commands/file/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/file/shared.js +3 -2
- package/dist/safe-bash/commands/file/shared.js.map +1 -1
- package/dist/safe-bash/commands/find.d.ts.map +1 -1
- package/dist/safe-bash/commands/find.js +12 -31
- package/dist/safe-bash/commands/find.js.map +1 -1
- package/dist/safe-bash/commands/html-to-markdown/budget.js +2 -2
- package/dist/safe-bash/commands/html-to-markdown/budget.js.map +1 -1
- package/dist/safe-bash/commands/metadata/internal.d.ts.map +1 -1
- package/dist/safe-bash/commands/metadata/internal.js +2 -1
- package/dist/safe-bash/commands/metadata/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/network/authorizer.d.ts +7 -0
- package/dist/safe-bash/commands/network/authorizer.d.ts.map +1 -0
- package/dist/safe-bash/commands/network/authorizer.js +48 -0
- package/dist/safe-bash/commands/network/authorizer.js.map +1 -0
- package/dist/safe-bash/commands/network/body.js +2 -2
- package/dist/safe-bash/commands/network/body.js.map +1 -1
- package/dist/safe-bash/commands/network/curl.js +2 -2
- package/dist/safe-bash/commands/network/curl.js.map +1 -1
- package/dist/safe-bash/commands/network/fetch-transport.d.ts +6 -0
- package/dist/safe-bash/commands/network/fetch-transport.d.ts.map +1 -0
- package/dist/safe-bash/commands/network/fetch-transport.js +80 -0
- package/dist/safe-bash/commands/network/fetch-transport.js.map +1 -0
- package/dist/safe-bash/commands/network/index.d.ts +2 -0
- package/dist/safe-bash/commands/network/index.d.ts.map +1 -1
- package/dist/safe-bash/commands/network/index.js +2 -0
- package/dist/safe-bash/commands/network/index.js.map +1 -1
- package/dist/safe-bash/commands/network/types.d.ts +1 -0
- package/dist/safe-bash/commands/network/types.d.ts.map +1 -1
- package/dist/safe-bash/commands/network/types.js +10 -0
- package/dist/safe-bash/commands/network/types.js.map +1 -1
- package/dist/safe-bash/commands/regex-execution/ere/limits.js +2 -2
- package/dist/safe-bash/commands/regex-execution/ere/limits.js.map +1 -1
- package/dist/safe-bash/commands/safejs/io.js +2 -2
- package/dist/safe-bash/commands/safejs/io.js.map +1 -1
- package/dist/safe-bash/commands/search/shared.js +2 -2
- package/dist/safe-bash/commands/search/shared.js.map +1 -1
- package/dist/safe-bash/commands/split/io.js +2 -2
- package/dist/safe-bash/commands/split/io.js.map +1 -1
- package/dist/safe-bash/commands/stream-format/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/stream-format/shared.js +2 -1
- package/dist/safe-bash/commands/stream-format/shared.js.map +1 -1
- package/dist/safe-bash/commands/stream-inspection/shared.d.ts.map +1 -1
- package/dist/safe-bash/commands/stream-inspection/shared.js +2 -1
- package/dist/safe-bash/commands/stream-inspection/shared.js.map +1 -1
- package/dist/safe-bash/commands/structured/limits.js +2 -2
- package/dist/safe-bash/commands/structured/limits.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 +2 -1
- package/dist/safe-bash/commands/table-text/internal.js.map +1 -1
- package/dist/safe-bash/commands/text-programs/shared.js +2 -2
- package/dist/safe-bash/commands/text-programs/shared.js.map +1 -1
- package/dist/safe-bash/commands/tree/io.js +2 -2
- package/dist/safe-bash/commands/tree/io.js.map +1 -1
- package/dist/safe-bash/contracts/yield.d.ts +13 -0
- package/dist/safe-bash/contracts/yield.d.ts.map +1 -0
- package/dist/safe-bash/contracts/yield.js +41 -0
- package/dist/safe-bash/contracts/yield.js.map +1 -0
- package/dist/safe-bash/shell/arithmetic.js +1 -1
- package/dist/safe-bash/shell/arithmetic.js.map +1 -1
- package/dist/safe-bash/shell/arrays/ledger.d.ts.map +1 -1
- package/dist/safe-bash/shell/arrays/ledger.js +2 -9
- package/dist/safe-bash/shell/arrays/ledger.js.map +1 -1
- package/dist/safe-bash/shell/conditional.d.ts.map +1 -1
- package/dist/safe-bash/shell/conditional.js +2 -1
- package/dist/safe-bash/shell/conditional.js.map +1 -1
- package/dist/safe-bash/shell/env-warning.d.ts +2 -0
- package/dist/safe-bash/shell/env-warning.d.ts.map +1 -0
- package/dist/safe-bash/shell/env-warning.js +12 -0
- package/dist/safe-bash/shell/env-warning.js.map +1 -0
- package/dist/safe-bash/shell/index.d.ts +1 -0
- package/dist/safe-bash/shell/index.d.ts.map +1 -1
- package/dist/safe-bash/shell/index.js +1 -0
- package/dist/safe-bash/shell/index.js.map +1 -1
- package/dist/safe-bash/shell/input.d.ts.map +1 -1
- package/dist/safe-bash/shell/input.js +4 -3
- package/dist/safe-bash/shell/input.js.map +1 -1
- package/dist/safe-bash/shell/parser.d.ts.map +1 -1
- package/dist/safe-bash/shell/parser.js +15 -1
- package/dist/safe-bash/shell/parser.js.map +1 -1
- package/dist/safe-bash/shell/pattern.d.ts.map +1 -1
- package/dist/safe-bash/shell/pattern.js +3 -2
- package/dist/safe-bash/shell/pattern.js.map +1 -1
- package/dist/safe-bash/shell/runtime.d.ts +3 -2
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +57 -55
- 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 +4 -1
- package/dist/safe-bash/shell/shell.js.map +1 -1
- package/dist/safe-bash/shell/types.d.ts +2 -0
- package/dist/safe-bash/shell/types.d.ts.map +1 -1
- package/dist/safe-bash/shell/types.js.map +1 -1
- package/dist/safe-bash/shell/worker-limits.d.ts +3 -0
- package/dist/safe-bash/shell/worker-limits.d.ts.map +1 -0
- package/dist/safe-bash/shell/worker-limits.js +14 -0
- package/dist/safe-bash/shell/worker-limits.js.map +1 -0
- package/package.json +2 -2
|
@@ -1816,14 +1816,12 @@ var require_buffer = __commonJS({
|
|
|
1816
1816
|
});
|
|
1817
1817
|
|
|
1818
1818
|
// packages/safe-bash/browser/platform.mjs
|
|
1819
|
-
var import_buffer, TransformStream
|
|
1819
|
+
var import_buffer, TransformStream;
|
|
1820
1820
|
var init_platform = __esm({
|
|
1821
1821
|
"packages/safe-bash/browser/platform.mjs"() {
|
|
1822
1822
|
"use strict";
|
|
1823
1823
|
import_buffer = __toESM(require_buffer(), 1);
|
|
1824
1824
|
TransformStream = globalThis.TransformStream;
|
|
1825
|
-
setImmediate = (callback, ...args) => setTimeout(callback, 0, ...args);
|
|
1826
|
-
clearImmediate = clearTimeout;
|
|
1827
1825
|
}
|
|
1828
1826
|
});
|
|
1829
1827
|
|
|
@@ -1833,9 +1831,6 @@ init_platform();
|
|
|
1833
1831
|
// packages/safe-bash/src/commands/basic.ts
|
|
1834
1832
|
init_platform();
|
|
1835
1833
|
|
|
1836
|
-
// packages/safe-bash/src/contracts/index.ts
|
|
1837
|
-
init_platform();
|
|
1838
|
-
|
|
1839
1834
|
// packages/safe-bash/src/contracts/command.ts
|
|
1840
1835
|
init_platform();
|
|
1841
1836
|
|
|
@@ -3054,6 +3049,44 @@ async function compareObservedEntries(fs, path, stat, peer, peerPath, peerStat,
|
|
|
3054
3049
|
|
|
3055
3050
|
// packages/safe-bash/src/commands/move.ts
|
|
3056
3051
|
init_platform();
|
|
3052
|
+
|
|
3053
|
+
// packages/safe-bash/src/contracts/yield.ts
|
|
3054
|
+
init_platform();
|
|
3055
|
+
var checkpoints = /* @__PURE__ */ new WeakMap();
|
|
3056
|
+
function monotonicNow() {
|
|
3057
|
+
return globalThis.performance?.now() ?? Date.now();
|
|
3058
|
+
}
|
|
3059
|
+
function registerYieldCheckpoint(signal, checkpoint) {
|
|
3060
|
+
checkpoints.set(signal, checkpoint);
|
|
3061
|
+
}
|
|
3062
|
+
function scheduleTurn(callback) {
|
|
3063
|
+
const host = globalThis;
|
|
3064
|
+
return host.setImmediate ? { kind: "immediate", value: host.setImmediate(callback) } : { kind: "timeout", value: setTimeout(callback, 0) };
|
|
3065
|
+
}
|
|
3066
|
+
function cancelTurn(handle) {
|
|
3067
|
+
if (handle?.kind === "immediate") globalThis.clearImmediate?.(handle.value);
|
|
3068
|
+
else if (handle) clearTimeout(handle.value);
|
|
3069
|
+
}
|
|
3070
|
+
function yieldTurn(signal) {
|
|
3071
|
+
signal?.throwIfAborted();
|
|
3072
|
+
if (signal) checkpoints.get(signal)?.();
|
|
3073
|
+
return new Promise((resolve, reject) => {
|
|
3074
|
+
let handle;
|
|
3075
|
+
const finish = () => {
|
|
3076
|
+
signal?.removeEventListener("abort", abort);
|
|
3077
|
+
resolve();
|
|
3078
|
+
};
|
|
3079
|
+
const abort = () => {
|
|
3080
|
+
cancelTurn(handle);
|
|
3081
|
+
reject(signal.reason);
|
|
3082
|
+
};
|
|
3083
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
3084
|
+
if (signal?.aborted) abort();
|
|
3085
|
+
else handle = scheduleTurn(finish);
|
|
3086
|
+
});
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
// packages/safe-bash/src/commands/move.ts
|
|
3057
3090
|
var MoveBudget = class {
|
|
3058
3091
|
constructor(signal) {
|
|
3059
3092
|
this.signal = signal;
|
|
@@ -3066,7 +3099,7 @@ var MoveBudget = class {
|
|
|
3066
3099
|
async step() {
|
|
3067
3100
|
this.signal.throwIfAborted();
|
|
3068
3101
|
if (++this.steps > 1e5) throw new FsError("EFBIG", { message: "cross-device move entry limit exceeded" });
|
|
3069
|
-
if (this.steps % 128 === 0) await
|
|
3102
|
+
if (this.steps % 128 === 0) await yieldTurn();
|
|
3070
3103
|
this.signal.throwIfAborted();
|
|
3071
3104
|
}
|
|
3072
3105
|
};
|
|
@@ -3801,7 +3834,7 @@ function headTail(name2) {
|
|
|
3801
3834
|
});
|
|
3802
3835
|
}
|
|
3803
3836
|
function characterSet(specification) {
|
|
3804
|
-
const
|
|
3837
|
+
const classes2 = {
|
|
3805
3838
|
lower: Array.from({ length: 26 }, (_, offset) => 97 + offset),
|
|
3806
3839
|
upper: Array.from({ length: 26 }, (_, offset) => 65 + offset),
|
|
3807
3840
|
digit: Array.from({ length: 10 }, (_, offset) => 48 + offset),
|
|
@@ -3811,15 +3844,15 @@ function characterSet(specification) {
|
|
|
3811
3844
|
graph: Array.from({ length: 94 }, (_, offset) => 33 + offset),
|
|
3812
3845
|
print: Array.from({ length: 95 }, (_, offset) => 32 + offset)
|
|
3813
3846
|
};
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3847
|
+
classes2.alpha = [...classes2.upper, ...classes2.lower];
|
|
3848
|
+
classes2.alnum = [...classes2.digit, ...classes2.alpha];
|
|
3849
|
+
classes2.xdigit = [...classes2.digit, ...classes2.upper.slice(0, 6), ...classes2.lower.slice(0, 6)];
|
|
3850
|
+
classes2.punct = classes2.graph.filter((byte) => !classes2.alnum.includes(byte));
|
|
3818
3851
|
const tokens2 = [];
|
|
3819
3852
|
for (let offset = 0; offset < specification.length; ) {
|
|
3820
3853
|
const classMatch = /^\[:([a-z]+):\]/u.exec(specification.slice(offset));
|
|
3821
3854
|
if (classMatch) {
|
|
3822
|
-
const bytes =
|
|
3855
|
+
const bytes = classes2[classMatch[1]];
|
|
3823
3856
|
if (!bytes) throw new UsageError(`unknown character class '${classMatch[1]}'`);
|
|
3824
3857
|
tokens2.push({ bytes, literal: false });
|
|
3825
3858
|
offset += classMatch[0].length;
|
|
@@ -4444,6 +4477,17 @@ init_platform();
|
|
|
4444
4477
|
// packages/safe-bash/src/shell/shell.ts
|
|
4445
4478
|
init_platform();
|
|
4446
4479
|
|
|
4480
|
+
// packages/safe-bash/src/shell/env-warning.ts
|
|
4481
|
+
init_platform();
|
|
4482
|
+
var warned = /* @__PURE__ */ new WeakSet();
|
|
4483
|
+
function warnIfHostProcessEnv(env) {
|
|
4484
|
+
if (!env || typeof process === "undefined" || !process.env) return;
|
|
4485
|
+
if (warned.has(env)) return;
|
|
4486
|
+
if (env !== process.env) return;
|
|
4487
|
+
warned.add(env);
|
|
4488
|
+
console.warn("[safe-bash] warning: the shell `env` is the host `process.env`. Scripts executed in this shell can read every value in it, including secrets; on Cloudflare Workers with nodejs_compat, process.env contains the Worker's secret bindings. Pass only the variables your scripts need. See docs/issues/safe-bash-cloudflare-security-audit.md (finding 1).");
|
|
4489
|
+
}
|
|
4490
|
+
|
|
4447
4491
|
// packages/safe-bash/src/shell/parser.ts
|
|
4448
4492
|
init_platform();
|
|
4449
4493
|
|
|
@@ -4538,7 +4582,7 @@ function integer2(text) {
|
|
|
4538
4582
|
for (const character of match[2]) {
|
|
4539
4583
|
const digit2 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_".indexOf(base <= 36 ? character.toLowerCase() : character);
|
|
4540
4584
|
if (digit2 >= base || digit2 < 0) throw new Error("Digit exceeds arithmetic base");
|
|
4541
|
-
value2 = value2 * BigInt(base) + BigInt(digit2);
|
|
4585
|
+
value2 = BigInt.asIntN(64, value2 * BigInt(base) + BigInt(digit2));
|
|
4542
4586
|
}
|
|
4543
4587
|
return value2;
|
|
4544
4588
|
}
|
|
@@ -4864,7 +4908,7 @@ async function tokens(pattern, work) {
|
|
|
4864
4908
|
let steps = 0;
|
|
4865
4909
|
const tick = () => {
|
|
4866
4910
|
if (--work.remaining < 0) work.exhausted();
|
|
4867
|
-
if (++steps % 1024 === 0) return
|
|
4911
|
+
if (++steps % 1024 === 0) return yieldTurn(work.signal);
|
|
4868
4912
|
return void 0;
|
|
4869
4913
|
};
|
|
4870
4914
|
for (let index = 0; index < characters.length; index++) {
|
|
@@ -4941,7 +4985,7 @@ async function matchTokens(patternTokens, value2, work) {
|
|
|
4941
4985
|
while (position < characters.length) {
|
|
4942
4986
|
if (--work.remaining < 0) work.exhausted();
|
|
4943
4987
|
if (++steps % 1024 === 0) {
|
|
4944
|
-
await
|
|
4988
|
+
await yieldTurn(work.signal);
|
|
4945
4989
|
work.signal.throwIfAborted();
|
|
4946
4990
|
}
|
|
4947
4991
|
const token = patternTokens[tokenIndex];
|
|
@@ -4974,7 +5018,7 @@ async function charge(context, amount = 1) {
|
|
|
4974
5018
|
const previous = context.work.remaining;
|
|
4975
5019
|
context.work.remaining -= amount;
|
|
4976
5020
|
if (previous >>> 10 !== context.work.remaining >>> 10) {
|
|
4977
|
-
await
|
|
5021
|
+
await yieldTurn();
|
|
4978
5022
|
context.signal.throwIfAborted();
|
|
4979
5023
|
}
|
|
4980
5024
|
}
|
|
@@ -5176,6 +5220,7 @@ var Lexer = class {
|
|
|
5176
5220
|
this.documentLine = documentLine;
|
|
5177
5221
|
this.partial = partial;
|
|
5178
5222
|
if (depth > 64) throw new ShellSyntaxError("Syntax nesting exceeds 64", 0);
|
|
5223
|
+
for (let offset = source.indexOf("\n"); offset !== -1; offset = source.indexOf("\n", offset + 1)) this.newlineOffsets.push(offset);
|
|
5179
5224
|
}
|
|
5180
5225
|
source;
|
|
5181
5226
|
depth;
|
|
@@ -5191,8 +5236,16 @@ var Lexer = class {
|
|
|
5191
5236
|
conditional = false;
|
|
5192
5237
|
conditionalPattern;
|
|
5193
5238
|
documents = [];
|
|
5239
|
+
newlineOffsets = [];
|
|
5194
5240
|
lineAt(position) {
|
|
5195
|
-
|
|
5241
|
+
let low = 0;
|
|
5242
|
+
let high = this.newlineOffsets.length;
|
|
5243
|
+
while (low < high) {
|
|
5244
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
5245
|
+
if (this.newlineOffsets[middle] < position) low = middle + 1;
|
|
5246
|
+
else high = middle;
|
|
5247
|
+
}
|
|
5248
|
+
return this.lineOffset + low + 1;
|
|
5196
5249
|
}
|
|
5197
5250
|
error(message2, unclosedQuote) {
|
|
5198
5251
|
throw new ShellSyntaxError(message2, this.position, 2, void 0, unclosedQuote);
|
|
@@ -6614,7 +6667,7 @@ var SplitWork = class {
|
|
|
6614
6667
|
return this.work >= this.nextYield;
|
|
6615
6668
|
}
|
|
6616
6669
|
async pause() {
|
|
6617
|
-
await
|
|
6670
|
+
await yieldTurn();
|
|
6618
6671
|
this.signal.throwIfAborted();
|
|
6619
6672
|
this.nextYield = this.work + 4096;
|
|
6620
6673
|
}
|
|
@@ -7884,14 +7937,7 @@ var ArrayLedger = class _ArrayLedger {
|
|
|
7884
7937
|
this.#checkpoint += units;
|
|
7885
7938
|
if (this.#checkpoint >= 128) {
|
|
7886
7939
|
this.#checkpoint %= 128;
|
|
7887
|
-
return
|
|
7888
|
-
try {
|
|
7889
|
-
signal?.throwIfAborted();
|
|
7890
|
-
resolve();
|
|
7891
|
-
} catch (error) {
|
|
7892
|
-
reject(error);
|
|
7893
|
-
}
|
|
7894
|
-
}));
|
|
7940
|
+
return yieldTurn(signal);
|
|
7895
7941
|
}
|
|
7896
7942
|
}
|
|
7897
7943
|
};
|
|
@@ -8768,43 +8814,17 @@ async function publishPipelineStatus(state, statuses, signal, scope) {
|
|
|
8768
8814
|
throwCleanupFailures(scope.failures);
|
|
8769
8815
|
}
|
|
8770
8816
|
|
|
8771
|
-
// packages/safe-bash/
|
|
8772
|
-
init_platform();
|
|
8773
|
-
var EreTransportRoot = class {
|
|
8774
|
-
constructor() {
|
|
8775
|
-
throw new ConditionalUnsupported("[[ =~ ]] is not supported by the browser shell entry");
|
|
8776
|
-
}
|
|
8777
|
-
};
|
|
8778
|
-
|
|
8779
|
-
// packages/safe-bash/src/commands/regex-execution/ere/transport/protocol.ts
|
|
8817
|
+
// packages/safe-bash/src/commands/regex-execution/ere/errors.ts
|
|
8780
8818
|
init_platform();
|
|
8781
|
-
var
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
constructor(resource, limit) {
|
|
8785
|
-
super(`ERE transport profile limit exceeded: ${resource} (${limit})`);
|
|
8786
|
-
this.resource = resource;
|
|
8787
|
-
this.limit = limit;
|
|
8788
|
-
this.name = "EreTransportProfileLimitError";
|
|
8789
|
-
}
|
|
8790
|
-
resource;
|
|
8791
|
-
limit;
|
|
8792
|
-
status = 3;
|
|
8793
|
-
};
|
|
8794
|
-
var EreTransportSemanticError = class extends Error {
|
|
8795
|
-
constructor(category, offset) {
|
|
8796
|
-
super(category === "syntax" ? "invalid ERE" : "unsupported ERE profile");
|
|
8797
|
-
this.category = category;
|
|
8819
|
+
var EreSyntaxError = class extends Error {
|
|
8820
|
+
constructor(message2, offset) {
|
|
8821
|
+
super(`invalid ERE at ${offset}: ${message2}`);
|
|
8798
8822
|
this.offset = offset;
|
|
8799
|
-
this.name = "
|
|
8823
|
+
this.name = "EreSyntaxError";
|
|
8800
8824
|
}
|
|
8801
|
-
category;
|
|
8802
8825
|
offset;
|
|
8803
8826
|
status = 2;
|
|
8804
8827
|
};
|
|
8805
|
-
|
|
8806
|
-
// packages/safe-bash/src/commands/regex-execution/ere/errors.ts
|
|
8807
|
-
init_platform();
|
|
8808
8828
|
var EreUnsupportedError = class extends Error {
|
|
8809
8829
|
constructor(message2, offset) {
|
|
8810
8830
|
super(`unsupported ERE profile at ${offset}: ${message2}`);
|
|
@@ -8825,6 +8845,564 @@ var EreProfileLimitError = class extends Error {
|
|
|
8825
8845
|
limit;
|
|
8826
8846
|
status = 3;
|
|
8827
8847
|
};
|
|
8848
|
+
var EreUsageUnknownError = class extends Error {
|
|
8849
|
+
status = 3;
|
|
8850
|
+
constructor(reason) {
|
|
8851
|
+
super("ERE invocation usage is unknown; further work is refused", { cause: reason });
|
|
8852
|
+
this.name = "EreUsageUnknownError";
|
|
8853
|
+
}
|
|
8854
|
+
};
|
|
8855
|
+
|
|
8856
|
+
// packages/safe-bash/src/commands/regex-execution/ere/limits.ts
|
|
8857
|
+
init_platform();
|
|
8858
|
+
var resources = Object.freeze([
|
|
8859
|
+
"patternBytes",
|
|
8860
|
+
"subjectBytes",
|
|
8861
|
+
"work",
|
|
8862
|
+
"states",
|
|
8863
|
+
"allocationUnits",
|
|
8864
|
+
"captureBytes",
|
|
8865
|
+
"captureSlots"
|
|
8866
|
+
]);
|
|
8867
|
+
function integer5(value2) {
|
|
8868
|
+
if (!Number.isSafeInteger(value2) || value2 < 0) throw new TypeError("ERE bounds must be nonnegative safe integers");
|
|
8869
|
+
}
|
|
8870
|
+
function multiply(value2, factor, ceiling) {
|
|
8871
|
+
return value2 > Math.floor(ceiling / factor) ? ceiling : value2 * factor;
|
|
8872
|
+
}
|
|
8873
|
+
function deriveEreLimits(bounds) {
|
|
8874
|
+
integer5(bounds.maxExpansionBytes);
|
|
8875
|
+
integer5(bounds.maxExpansionFields);
|
|
8876
|
+
const bytes = bounds.maxExpansionBytes;
|
|
8877
|
+
const fields = bounds.maxExpansionFields;
|
|
8878
|
+
const byteUnits = multiply(bytes, 8, 4e6);
|
|
8879
|
+
const fieldUnits = multiply(fields, 128, 4e6);
|
|
8880
|
+
return Object.freeze({
|
|
8881
|
+
patternBytes: Math.min(bytes, 65536),
|
|
8882
|
+
subjectBytes: Math.min(bytes, 1048576),
|
|
8883
|
+
work: multiply(bytes, 32, 5e7),
|
|
8884
|
+
states: multiply(fields, 8, 65536),
|
|
8885
|
+
allocationUnits: byteUnits >= 4e6 - fieldUnits ? 4e6 : byteUnits + fieldUnits,
|
|
8886
|
+
captureBytes: bytes,
|
|
8887
|
+
captureSlots: fields
|
|
8888
|
+
});
|
|
8889
|
+
}
|
|
8890
|
+
var EreLedger = class {
|
|
8891
|
+
limits;
|
|
8892
|
+
#usage = {
|
|
8893
|
+
patternBytes: 0,
|
|
8894
|
+
subjectBytes: 0,
|
|
8895
|
+
work: 0,
|
|
8896
|
+
states: 0,
|
|
8897
|
+
allocationUnits: 0,
|
|
8898
|
+
captureBytes: 0,
|
|
8899
|
+
captureSlots: 0
|
|
8900
|
+
};
|
|
8901
|
+
#poison;
|
|
8902
|
+
#lastYield = 0;
|
|
8903
|
+
constructor(bounds, lowering = {}) {
|
|
8904
|
+
const limits = { ...deriveEreLimits(bounds) };
|
|
8905
|
+
for (const resource of Object.keys(lowering)) {
|
|
8906
|
+
if (!resources.includes(resource)) throw new TypeError("unknown ERE limit");
|
|
8907
|
+
const key = resource;
|
|
8908
|
+
const value2 = lowering[key];
|
|
8909
|
+
if (value2 === void 0) throw new TypeError("undefined ERE limit");
|
|
8910
|
+
integer5(value2);
|
|
8911
|
+
if (value2 > limits[key]) throw new RangeError("ERE limits may only be lowered");
|
|
8912
|
+
limits[key] = value2;
|
|
8913
|
+
}
|
|
8914
|
+
this.limits = Object.freeze(limits);
|
|
8915
|
+
}
|
|
8916
|
+
get usage() {
|
|
8917
|
+
return Object.freeze({ ...this.#usage });
|
|
8918
|
+
}
|
|
8919
|
+
check(signal) {
|
|
8920
|
+
if (signal?.aborted) throw signal.reason;
|
|
8921
|
+
if (this.#poison) throw this.#poison;
|
|
8922
|
+
}
|
|
8923
|
+
charge(resource, amount, signal) {
|
|
8924
|
+
this.check(signal);
|
|
8925
|
+
integer5(amount);
|
|
8926
|
+
if (amount > this.limits[resource] - this.#usage[resource]) {
|
|
8927
|
+
throw new EreProfileLimitError(resource, this.limits[resource]);
|
|
8928
|
+
}
|
|
8929
|
+
this.#usage[resource] += amount;
|
|
8930
|
+
}
|
|
8931
|
+
admitInput(resource, length, signal) {
|
|
8932
|
+
this.check(signal);
|
|
8933
|
+
integer5(length);
|
|
8934
|
+
if (length > this.limits[resource]) throw new EreProfileLimitError(resource, this.limits[resource]);
|
|
8935
|
+
this.#usage[resource] = Math.max(this.#usage[resource], length);
|
|
8936
|
+
}
|
|
8937
|
+
async checkpoint(signal) {
|
|
8938
|
+
this.check(signal);
|
|
8939
|
+
if (this.#usage.work - this.#lastYield >= 256) {
|
|
8940
|
+
this.#lastYield = this.#usage.work;
|
|
8941
|
+
await yieldTurn(signal);
|
|
8942
|
+
this.check(signal);
|
|
8943
|
+
}
|
|
8944
|
+
}
|
|
8945
|
+
markUnknownUsage(reason) {
|
|
8946
|
+
this.#poison ??= new EreUsageUnknownError(reason);
|
|
8947
|
+
}
|
|
8948
|
+
};
|
|
8949
|
+
|
|
8950
|
+
// packages/safe-bash/src/commands/regex-execution/ere/syntax.ts
|
|
8951
|
+
init_platform();
|
|
8952
|
+
var programs = /* @__PURE__ */ new WeakMap();
|
|
8953
|
+
var special = "\\.^$[]()|*+?{}";
|
|
8954
|
+
var classes = /* @__PURE__ */ new Set(["alnum", "alpha", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "xdigit"]);
|
|
8955
|
+
function classMember(name2, code) {
|
|
8956
|
+
const upper = code >= 65 && code <= 90;
|
|
8957
|
+
const lower = code >= 97 && code <= 122;
|
|
8958
|
+
const digit2 = code >= 48 && code <= 57;
|
|
8959
|
+
switch (name2) {
|
|
8960
|
+
case "alnum":
|
|
8961
|
+
return upper || lower || digit2;
|
|
8962
|
+
case "alpha":
|
|
8963
|
+
return upper || lower;
|
|
8964
|
+
case "blank":
|
|
8965
|
+
return code === 9 || code === 32;
|
|
8966
|
+
case "cntrl":
|
|
8967
|
+
return code < 32 || code === 127;
|
|
8968
|
+
case "digit":
|
|
8969
|
+
return digit2;
|
|
8970
|
+
case "graph":
|
|
8971
|
+
return code >= 33 && code <= 126;
|
|
8972
|
+
case "lower":
|
|
8973
|
+
return lower;
|
|
8974
|
+
case "print":
|
|
8975
|
+
return code >= 32 && code <= 126;
|
|
8976
|
+
case "punct":
|
|
8977
|
+
return code >= 33 && code <= 126 && !upper && !lower && !digit2;
|
|
8978
|
+
case "space":
|
|
8979
|
+
return code === 32 || code >= 9 && code <= 13;
|
|
8980
|
+
case "upper":
|
|
8981
|
+
return upper;
|
|
8982
|
+
case "xdigit":
|
|
8983
|
+
return digit2 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
|
|
8984
|
+
default:
|
|
8985
|
+
return false;
|
|
8986
|
+
}
|
|
8987
|
+
}
|
|
8988
|
+
async function admitAscii(text, ledger, signal) {
|
|
8989
|
+
for (let offset = 0; offset < text.length; offset++) {
|
|
8990
|
+
ledger.charge("work", 1, signal);
|
|
8991
|
+
const code = text.charCodeAt(offset);
|
|
8992
|
+
if (code === 0 || code > 127) throw new EreUnsupportedError("only non-NUL ASCII in the C/POSIX profile", offset);
|
|
8993
|
+
await ledger.checkpoint(signal);
|
|
8994
|
+
}
|
|
8995
|
+
}
|
|
8996
|
+
async function flatten(input2, ledger, signal) {
|
|
8997
|
+
if (typeof input2 === "string") {
|
|
8998
|
+
ledger.admitInput("patternBytes", input2.length, signal);
|
|
8999
|
+
await admitAscii(input2, ledger, signal);
|
|
9000
|
+
return { pattern: input2, quoted: null };
|
|
9001
|
+
}
|
|
9002
|
+
let size = 0;
|
|
9003
|
+
for (const fragment of input2) {
|
|
9004
|
+
if (typeof fragment.text !== "string" || typeof fragment.literal !== "boolean") throw new TypeError("invalid ERE fragment");
|
|
9005
|
+
ledger.charge("work", 1, signal);
|
|
9006
|
+
await ledger.checkpoint(signal);
|
|
9007
|
+
ledger.admitInput("patternBytes", fragment.text.length, signal);
|
|
9008
|
+
await admitAscii(fragment.text, ledger, signal);
|
|
9009
|
+
if (fragment.text.length > ledger.limits.patternBytes - size) ledger.admitInput("patternBytes", ledger.limits.patternBytes + 1, signal);
|
|
9010
|
+
size += fragment.text.length;
|
|
9011
|
+
ledger.admitInput("patternBytes", size, signal);
|
|
9012
|
+
}
|
|
9013
|
+
ledger.charge("allocationUnits", size * 2 + input2.length + 2, signal);
|
|
9014
|
+
const output2 = [];
|
|
9015
|
+
const quoted = [];
|
|
9016
|
+
for (const fragment of input2) {
|
|
9017
|
+
for (let offset = 0; offset < fragment.text.length; offset++) {
|
|
9018
|
+
ledger.charge("work", 1, signal);
|
|
9019
|
+
await ledger.checkpoint(signal);
|
|
9020
|
+
quoted.push(fragment.literal);
|
|
9021
|
+
}
|
|
9022
|
+
output2.push(fragment.text);
|
|
9023
|
+
await ledger.checkpoint(signal);
|
|
9024
|
+
}
|
|
9025
|
+
return { pattern: output2.join(""), quoted: Object.freeze(quoted) };
|
|
9026
|
+
}
|
|
9027
|
+
var Parser2 = class {
|
|
9028
|
+
constructor(pattern, quoted, ledger, signal) {
|
|
9029
|
+
this.pattern = pattern;
|
|
9030
|
+
this.quoted = quoted;
|
|
9031
|
+
this.ledger = ledger;
|
|
9032
|
+
this.signal = signal;
|
|
9033
|
+
}
|
|
9034
|
+
pattern;
|
|
9035
|
+
quoted;
|
|
9036
|
+
ledger;
|
|
9037
|
+
signal;
|
|
9038
|
+
offset = 0;
|
|
9039
|
+
groups = 0;
|
|
9040
|
+
nodes = 0;
|
|
9041
|
+
at(character, offset = this.offset) {
|
|
9042
|
+
return !this.quoted?.[offset] && this.pattern[offset] === character;
|
|
9043
|
+
}
|
|
9044
|
+
node(create) {
|
|
9045
|
+
if (this.nodes >= 4096) throw new EreUnsupportedError("4096-node grammar ceiling", this.offset);
|
|
9046
|
+
this.ledger.charge("allocationUnits", 8, this.signal);
|
|
9047
|
+
this.nodes++;
|
|
9048
|
+
return Object.freeze(create());
|
|
9049
|
+
}
|
|
9050
|
+
async expression(depth) {
|
|
9051
|
+
if (depth > 64) throw new EreUnsupportedError("64-level grammar ceiling", this.offset);
|
|
9052
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9053
|
+
const alternatives = [];
|
|
9054
|
+
while (true) {
|
|
9055
|
+
const child = await this.sequence(depth);
|
|
9056
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9057
|
+
alternatives.push(child);
|
|
9058
|
+
if (!this.at("|")) break;
|
|
9059
|
+
this.offset++;
|
|
9060
|
+
}
|
|
9061
|
+
if (alternatives.length === 1) return alternatives[0];
|
|
9062
|
+
this.ledger.charge("work", alternatives.length * 2, this.signal);
|
|
9063
|
+
await this.ledger.checkpoint(this.signal);
|
|
9064
|
+
return this.node(() => ({ kind: "alternative", children: Object.freeze(alternatives), nullable: alternatives.some((value2) => value2.nullable), captured: alternatives.some((value2) => value2.captured) }));
|
|
9065
|
+
}
|
|
9066
|
+
async sequence(depth) {
|
|
9067
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9068
|
+
const children = [];
|
|
9069
|
+
while (this.offset < this.pattern.length && !this.at("|") && !this.at(")")) {
|
|
9070
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9071
|
+
await this.ledger.checkpoint(this.signal);
|
|
9072
|
+
let child = await this.atom(depth);
|
|
9073
|
+
const operator = this.quoted?.[this.offset] ? void 0 : this.pattern[this.offset];
|
|
9074
|
+
if (operator === "*" || operator === "+" || operator === "?" || operator === "{") {
|
|
9075
|
+
const begin = this.offset++;
|
|
9076
|
+
let min = operator === "+" ? 1 : 0;
|
|
9077
|
+
let max = operator === "?" ? 1 : Infinity;
|
|
9078
|
+
if (operator === "{") {
|
|
9079
|
+
min = await this.count();
|
|
9080
|
+
max = min;
|
|
9081
|
+
if (this.at(",")) {
|
|
9082
|
+
this.offset++;
|
|
9083
|
+
max = this.at("}") ? Infinity : await this.count();
|
|
9084
|
+
}
|
|
9085
|
+
if (!this.at("}") || max < min) throw new EreSyntaxError("invalid interval", begin);
|
|
9086
|
+
this.offset++;
|
|
9087
|
+
}
|
|
9088
|
+
if (child.kind === "start" || child.kind === "end") throw new EreUnsupportedError("repeated anchor", begin);
|
|
9089
|
+
if (child.nullable && child.captured && max > 1) throw new EreUnsupportedError("nullable captured repetition", begin);
|
|
9090
|
+
const repeated = child;
|
|
9091
|
+
child = this.node(() => ({ kind: "repeat", child: repeated, min, max, nullable: min === 0 || repeated.nullable, captured: repeated.captured }));
|
|
9092
|
+
const next = this.quoted?.[this.offset] ? void 0 : this.pattern[this.offset];
|
|
9093
|
+
if (next === "*" || next === "+" || next === "?" || next === "{") throw new EreUnsupportedError("stacked repetition", this.offset);
|
|
9094
|
+
}
|
|
9095
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9096
|
+
children.push(child);
|
|
9097
|
+
}
|
|
9098
|
+
if (children.length === 0) return this.node(() => ({ kind: "empty", nullable: true, captured: false }));
|
|
9099
|
+
if (children.length === 1) return children[0];
|
|
9100
|
+
this.ledger.charge("work", children.length * 2, this.signal);
|
|
9101
|
+
await this.ledger.checkpoint(this.signal);
|
|
9102
|
+
return this.node(() => ({ kind: "sequence", children: Object.freeze(children), nullable: children.every((value2) => value2.nullable), captured: children.some((value2) => value2.captured) }));
|
|
9103
|
+
}
|
|
9104
|
+
async count() {
|
|
9105
|
+
const begin = this.offset;
|
|
9106
|
+
let value2 = 0;
|
|
9107
|
+
while (!this.quoted?.[this.offset] && this.pattern[this.offset] !== void 0 && this.pattern[this.offset] >= "0" && this.pattern[this.offset] <= "9") {
|
|
9108
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9109
|
+
await this.ledger.checkpoint(this.signal);
|
|
9110
|
+
value2 = value2 * 10 + this.pattern.charCodeAt(this.offset++) - 48;
|
|
9111
|
+
if (value2 > 255) throw new EreUnsupportedError("interval counts exceed 255", begin);
|
|
9112
|
+
}
|
|
9113
|
+
if (begin === this.offset) throw new EreSyntaxError("missing interval count", begin);
|
|
9114
|
+
return value2;
|
|
9115
|
+
}
|
|
9116
|
+
async atom(depth) {
|
|
9117
|
+
const begin = this.offset;
|
|
9118
|
+
const character = this.pattern[this.offset++];
|
|
9119
|
+
if (this.quoted?.[begin]) return this.node(() => ({ kind: "literal", code: character.charCodeAt(0), nullable: false, captured: false }));
|
|
9120
|
+
if (character === "(") {
|
|
9121
|
+
if (this.at("?")) throw new EreUnsupportedError("extended group syntax", begin);
|
|
9122
|
+
if (this.groups >= 32) throw new EreUnsupportedError("32-group grammar ceiling", begin);
|
|
9123
|
+
const index = ++this.groups;
|
|
9124
|
+
const child = await this.expression(depth + 1);
|
|
9125
|
+
if (!this.at(")")) throw new EreSyntaxError("unclosed group", begin);
|
|
9126
|
+
this.offset++;
|
|
9127
|
+
return this.node(() => ({ kind: "group", index, child, nullable: child.nullable, captured: true }));
|
|
9128
|
+
}
|
|
9129
|
+
if (character === "[") return this.set(begin);
|
|
9130
|
+
if (character === "\\") {
|
|
9131
|
+
const escaped = this.pattern[this.offset++];
|
|
9132
|
+
if (escaped === void 0) throw new EreSyntaxError("trailing escape", begin);
|
|
9133
|
+
if (!special.includes(escaped)) throw new EreUnsupportedError("backreference or escape extension", begin);
|
|
9134
|
+
return this.node(() => ({ kind: "literal", code: escaped.charCodeAt(0), nullable: false, captured: false }));
|
|
9135
|
+
}
|
|
9136
|
+
if (character === "*" || character === "+" || character === "?" || character === "{") throw new EreSyntaxError("repetition without operand", begin);
|
|
9137
|
+
if (character === ".") return this.node(() => ({ kind: "dot", nullable: false, captured: false }));
|
|
9138
|
+
if (character === "^") return this.node(() => ({ kind: "start", nullable: true, captured: false }));
|
|
9139
|
+
if (character === "$") return this.node(() => ({ kind: "end", nullable: true, captured: false }));
|
|
9140
|
+
return this.node(() => ({ kind: "literal", code: character.charCodeAt(0), nullable: false, captured: false }));
|
|
9141
|
+
}
|
|
9142
|
+
async set(begin) {
|
|
9143
|
+
this.ledger.charge("allocationUnits", 128, this.signal);
|
|
9144
|
+
const members = new Array(128).fill(false);
|
|
9145
|
+
const negate = this.at("^");
|
|
9146
|
+
if (negate) this.offset++;
|
|
9147
|
+
let first = true;
|
|
9148
|
+
while (this.offset < this.pattern.length) {
|
|
9149
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9150
|
+
await this.ledger.checkpoint(this.signal);
|
|
9151
|
+
if (this.at("]") && !first) {
|
|
9152
|
+
this.offset++;
|
|
9153
|
+
if (negate) for (let code = 1; code < 128; code++) {
|
|
9154
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9155
|
+
await this.ledger.checkpoint(this.signal);
|
|
9156
|
+
members[code] = !members[code];
|
|
9157
|
+
}
|
|
9158
|
+
return this.node(() => ({ kind: "set", members: Object.freeze(members), nullable: false, captured: false }));
|
|
9159
|
+
}
|
|
9160
|
+
first = false;
|
|
9161
|
+
if (this.at("[") && (this.at(".", this.offset + 1) || this.at("=", this.offset + 1))) {
|
|
9162
|
+
throw new EreUnsupportedError("collating or equivalence element", this.offset);
|
|
9163
|
+
}
|
|
9164
|
+
if (this.at("[") && this.at(":", this.offset + 1)) {
|
|
9165
|
+
const classBegin = this.offset;
|
|
9166
|
+
this.offset += 2;
|
|
9167
|
+
let name2 = "";
|
|
9168
|
+
while (this.offset < this.pattern.length && !this.at(":")) {
|
|
9169
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9170
|
+
await this.ledger.checkpoint(this.signal);
|
|
9171
|
+
if (name2.length >= 6) throw new EreSyntaxError("unknown character class", classBegin);
|
|
9172
|
+
name2 += this.pattern[this.offset++];
|
|
9173
|
+
}
|
|
9174
|
+
if (!this.at(":") || !this.at("]", this.offset + 1) || !classes.has(name2)) throw new EreSyntaxError("unknown character class", classBegin);
|
|
9175
|
+
this.offset += 2;
|
|
9176
|
+
for (let code = 1; code < 128; code++) {
|
|
9177
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9178
|
+
await this.ledger.checkpoint(this.signal);
|
|
9179
|
+
if (classMember(name2, code)) members[code] = true;
|
|
9180
|
+
}
|
|
9181
|
+
if (this.at("-") && !this.at("]", this.offset + 1)) throw new EreSyntaxError("class cannot be a range endpoint", this.offset);
|
|
9182
|
+
} else {
|
|
9183
|
+
const lower = this.pattern.charCodeAt(this.offset++);
|
|
9184
|
+
if (this.at("-") && !this.at("]", this.offset + 1) && this.pattern[this.offset + 1] !== void 0) {
|
|
9185
|
+
this.offset++;
|
|
9186
|
+
if (this.at("[")) throw new EreSyntaxError("nonliteral range endpoint", this.offset);
|
|
9187
|
+
const upper = this.pattern.charCodeAt(this.offset++);
|
|
9188
|
+
if (lower > upper) throw new EreSyntaxError("descending range", this.offset - 3);
|
|
9189
|
+
for (let code = lower; code <= upper; code++) {
|
|
9190
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9191
|
+
await this.ledger.checkpoint(this.signal);
|
|
9192
|
+
members[code] = true;
|
|
9193
|
+
}
|
|
9194
|
+
} else members[lower] = true;
|
|
9195
|
+
}
|
|
9196
|
+
}
|
|
9197
|
+
throw new EreSyntaxError("unclosed bracket expression", begin);
|
|
9198
|
+
}
|
|
9199
|
+
};
|
|
9200
|
+
async function compileEre(input2, ledger, signal) {
|
|
9201
|
+
ledger.check(signal);
|
|
9202
|
+
const { pattern, quoted } = await flatten(input2, ledger, signal);
|
|
9203
|
+
const parser = new Parser2(pattern, quoted, ledger, signal);
|
|
9204
|
+
const root = await parser.expression(0);
|
|
9205
|
+
if (parser.offset !== pattern.length) throw new EreSyntaxError("unmatched closing group", parser.offset);
|
|
9206
|
+
ledger.charge("allocationUnits", 3, signal);
|
|
9207
|
+
const program = Object.freeze({ pattern, groups: parser.groups });
|
|
9208
|
+
programs.set(program, { root, ledger });
|
|
9209
|
+
return program;
|
|
9210
|
+
}
|
|
9211
|
+
function resolveEreProgram(program, ledger) {
|
|
9212
|
+
const entry = programs.get(program);
|
|
9213
|
+
if (!entry || entry.ledger !== ledger) throw new TypeError("ERE program is not bound to this invocation ledger");
|
|
9214
|
+
return entry.root;
|
|
9215
|
+
}
|
|
9216
|
+
|
|
9217
|
+
// packages/safe-bash/src/commands/regex-execution/ere/matcher.ts
|
|
9218
|
+
init_platform();
|
|
9219
|
+
function spanOrder(left, right) {
|
|
9220
|
+
if (left === null) return right === null ? 0 : -1;
|
|
9221
|
+
if (right === null) return 1;
|
|
9222
|
+
const length = left.end - left.start - (right.end - right.start);
|
|
9223
|
+
return length === 0 ? right.start - left.start : length;
|
|
9224
|
+
}
|
|
9225
|
+
async function historyOrder(left, right, ledger, signal) {
|
|
9226
|
+
const leftCount = left?.count ?? 0;
|
|
9227
|
+
const rightCount = right?.count ?? 0;
|
|
9228
|
+
for (let ordinal = 1; ordinal <= Math.min(leftCount, rightCount); ordinal++) {
|
|
9229
|
+
ledger.charge("work", 1, signal);
|
|
9230
|
+
await ledger.checkpoint(signal);
|
|
9231
|
+
let leftEntry = left;
|
|
9232
|
+
let rightEntry = right;
|
|
9233
|
+
for (let remaining = leftCount; remaining > ordinal; remaining--) {
|
|
9234
|
+
ledger.charge("work", 1, signal);
|
|
9235
|
+
await ledger.checkpoint(signal);
|
|
9236
|
+
leftEntry = leftEntry.previous;
|
|
9237
|
+
}
|
|
9238
|
+
for (let remaining = rightCount; remaining > ordinal; remaining--) {
|
|
9239
|
+
ledger.charge("work", 1, signal);
|
|
9240
|
+
await ledger.checkpoint(signal);
|
|
9241
|
+
rightEntry = rightEntry.previous;
|
|
9242
|
+
}
|
|
9243
|
+
const compared = spanOrder(leftEntry.span, rightEntry.span);
|
|
9244
|
+
if (compared !== 0) return compared;
|
|
9245
|
+
}
|
|
9246
|
+
return leftCount - rightCount;
|
|
9247
|
+
}
|
|
9248
|
+
async function preferred(candidate, incumbent, ledger, signal) {
|
|
9249
|
+
if (candidate.position !== incumbent.position) return candidate.position > incumbent.position;
|
|
9250
|
+
for (let group = 1; group < candidate.captures.length; group++) {
|
|
9251
|
+
ledger.charge("work", 1, signal);
|
|
9252
|
+
const compared = await historyOrder(candidate.histories[group], incumbent.histories[group], ledger, signal);
|
|
9253
|
+
if (compared !== 0) return compared > 0;
|
|
9254
|
+
}
|
|
9255
|
+
return false;
|
|
9256
|
+
}
|
|
9257
|
+
async function resetDescendants(node, previous, ledger, signal) {
|
|
9258
|
+
ledger.charge("allocationUnits", previous.length + 3, signal);
|
|
9259
|
+
const captures = previous.slice();
|
|
9260
|
+
const pending = [node];
|
|
9261
|
+
while (pending.length > 0) {
|
|
9262
|
+
ledger.charge("work", 1, signal);
|
|
9263
|
+
await ledger.checkpoint(signal);
|
|
9264
|
+
const current = pending.pop();
|
|
9265
|
+
if (current.kind === "group") captures[current.index] = null;
|
|
9266
|
+
if (current.kind === "group" || current.kind === "repeat") {
|
|
9267
|
+
if (current.child.captured) {
|
|
9268
|
+
ledger.charge("allocationUnits", 1, signal);
|
|
9269
|
+
pending.push(current.child);
|
|
9270
|
+
}
|
|
9271
|
+
} else if (current.kind === "sequence" || current.kind === "alternative") {
|
|
9272
|
+
for (const child of current.children) {
|
|
9273
|
+
ledger.charge("work", 1, signal);
|
|
9274
|
+
await ledger.checkpoint(signal);
|
|
9275
|
+
if (child.captured) {
|
|
9276
|
+
ledger.charge("allocationUnits", 1, signal);
|
|
9277
|
+
pending.push(child);
|
|
9278
|
+
}
|
|
9279
|
+
}
|
|
9280
|
+
}
|
|
9281
|
+
}
|
|
9282
|
+
return captures;
|
|
9283
|
+
}
|
|
9284
|
+
async function matchEre(program, subject, ledger, signal) {
|
|
9285
|
+
ledger.check(signal);
|
|
9286
|
+
const root = resolveEreProgram(program, ledger);
|
|
9287
|
+
ledger.admitInput("subjectBytes", subject.length, signal);
|
|
9288
|
+
await admitAscii(subject, ledger, signal);
|
|
9289
|
+
const width = program.groups + 1;
|
|
9290
|
+
ledger.charge("allocationUnits", width * 2 + 1, signal);
|
|
9291
|
+
const emptyCaptures = Object.freeze(new Array(width).fill(null));
|
|
9292
|
+
const emptyHistories = Object.freeze(new Array(width).fill(null));
|
|
9293
|
+
const pending = [];
|
|
9294
|
+
const task = (create) => {
|
|
9295
|
+
ledger.charge("allocationUnits", 5, signal);
|
|
9296
|
+
return create();
|
|
9297
|
+
};
|
|
9298
|
+
const push = (position, next, captures, histories) => {
|
|
9299
|
+
ledger.charge("states", 1, signal);
|
|
9300
|
+
ledger.charge("allocationUnits", 5, signal);
|
|
9301
|
+
pending.push({ position, task: next, captures, histories });
|
|
9302
|
+
};
|
|
9303
|
+
for (let start = 0; start <= subject.length; start++) {
|
|
9304
|
+
push(start, task(() => ({ kind: "node", node: root, next: null })), emptyCaptures, emptyHistories);
|
|
9305
|
+
let best;
|
|
9306
|
+
while (pending.length > 0) {
|
|
9307
|
+
ledger.charge("work", 1, signal);
|
|
9308
|
+
await ledger.checkpoint(signal);
|
|
9309
|
+
const state = pending.pop();
|
|
9310
|
+
const current = state.task;
|
|
9311
|
+
if (current === null) {
|
|
9312
|
+
if (!best || await preferred(state, best, ledger, signal)) best = state;
|
|
9313
|
+
continue;
|
|
9314
|
+
}
|
|
9315
|
+
if (current.kind === "close") {
|
|
9316
|
+
ledger.charge("allocationUnits", width * 2 + 6, signal);
|
|
9317
|
+
const span = Object.freeze({ start: current.start, end: state.position });
|
|
9318
|
+
const captures = state.captures.slice();
|
|
9319
|
+
captures[current.group] = span;
|
|
9320
|
+
const histories = state.histories.slice();
|
|
9321
|
+
const previous = histories[current.group];
|
|
9322
|
+
histories[current.group] = { span, previous, count: (previous?.count ?? 0) + 1 };
|
|
9323
|
+
push(state.position, current.next, captures, histories);
|
|
9324
|
+
continue;
|
|
9325
|
+
}
|
|
9326
|
+
if (current.kind === "repeat") {
|
|
9327
|
+
const { node: node2, count } = current;
|
|
9328
|
+
if (count >= node2.min) push(state.position, current.next, state.captures, state.histories);
|
|
9329
|
+
const noProgress = count > 0 && state.position === current.previous;
|
|
9330
|
+
if (count < node2.max && (!noProgress || count < node2.min)) {
|
|
9331
|
+
const repeat = task(() => ({ kind: "repeat", node: node2, count: count + 1, previous: state.position, next: current.next }));
|
|
9332
|
+
push(state.position, task(() => ({ kind: "node", node: node2.child, next: repeat })), state.captures, state.histories);
|
|
9333
|
+
}
|
|
9334
|
+
continue;
|
|
9335
|
+
}
|
|
9336
|
+
const node = current.node;
|
|
9337
|
+
switch (node.kind) {
|
|
9338
|
+
case "empty":
|
|
9339
|
+
push(state.position, current.next, state.captures, state.histories);
|
|
9340
|
+
break;
|
|
9341
|
+
case "start":
|
|
9342
|
+
if (state.position === 0) push(state.position, current.next, state.captures, state.histories);
|
|
9343
|
+
break;
|
|
9344
|
+
case "end":
|
|
9345
|
+
if (state.position === subject.length) push(state.position, current.next, state.captures, state.histories);
|
|
9346
|
+
break;
|
|
9347
|
+
case "dot":
|
|
9348
|
+
case "literal":
|
|
9349
|
+
case "set": {
|
|
9350
|
+
const code = subject.charCodeAt(state.position);
|
|
9351
|
+
if (state.position < subject.length && (node.kind === "dot" || node.kind === "literal" && node.code === code || node.kind === "set" && node.members[code])) {
|
|
9352
|
+
push(state.position + 1, current.next, state.captures, state.histories);
|
|
9353
|
+
}
|
|
9354
|
+
break;
|
|
9355
|
+
}
|
|
9356
|
+
case "sequence": {
|
|
9357
|
+
let next = current.next;
|
|
9358
|
+
for (let index = node.children.length - 1; index >= 0; index--) {
|
|
9359
|
+
ledger.charge("work", 1, signal);
|
|
9360
|
+
await ledger.checkpoint(signal);
|
|
9361
|
+
const following = next;
|
|
9362
|
+
next = task(() => ({ kind: "node", node: node.children[index], next: following }));
|
|
9363
|
+
}
|
|
9364
|
+
push(state.position, next, state.captures, state.histories);
|
|
9365
|
+
break;
|
|
9366
|
+
}
|
|
9367
|
+
case "alternative":
|
|
9368
|
+
for (let index = node.children.length - 1; index >= 0; index--) {
|
|
9369
|
+
ledger.charge("work", 1, signal);
|
|
9370
|
+
await ledger.checkpoint(signal);
|
|
9371
|
+
push(state.position, task(() => ({ kind: "node", node: node.children[index], next: current.next })), state.captures, state.histories);
|
|
9372
|
+
}
|
|
9373
|
+
break;
|
|
9374
|
+
case "group": {
|
|
9375
|
+
const captures = node.child.captured ? await resetDescendants(node.child, state.captures, ledger, signal) : state.captures;
|
|
9376
|
+
const close = task(() => ({ kind: "close", group: node.index, start: state.position, next: current.next }));
|
|
9377
|
+
push(state.position, task(() => ({ kind: "node", node: node.child, next: close })), captures, state.histories);
|
|
9378
|
+
break;
|
|
9379
|
+
}
|
|
9380
|
+
case "repeat":
|
|
9381
|
+
push(state.position, task(() => ({ kind: "repeat", node, count: 0, previous: -1, next: current.next })), state.captures, state.histories);
|
|
9382
|
+
break;
|
|
9383
|
+
}
|
|
9384
|
+
}
|
|
9385
|
+
if (best) {
|
|
9386
|
+
ledger.charge("captureSlots", width, signal);
|
|
9387
|
+
let bytes = best.position - start;
|
|
9388
|
+
for (let group = 1; group < width; group++) {
|
|
9389
|
+
ledger.charge("work", 1, signal);
|
|
9390
|
+
const span = best.captures[group];
|
|
9391
|
+
if (span) bytes += span.end - span.start;
|
|
9392
|
+
}
|
|
9393
|
+
ledger.charge("captureBytes", bytes, signal);
|
|
9394
|
+
ledger.charge("allocationUnits", width * 2 + bytes + 4, signal);
|
|
9395
|
+
const captures = best.captures.slice();
|
|
9396
|
+
captures[0] = Object.freeze({ start, end: best.position });
|
|
9397
|
+
const values = captures.map((span) => span === null ? "" : subject.slice(span.start, span.end));
|
|
9398
|
+
ledger.check(signal);
|
|
9399
|
+
return Object.freeze({ matched: true, captures: Object.freeze(captures), values: Object.freeze(values) });
|
|
9400
|
+
}
|
|
9401
|
+
}
|
|
9402
|
+
ledger.charge("allocationUnits", 3, signal);
|
|
9403
|
+
ledger.check(signal);
|
|
9404
|
+
return Object.freeze({ matched: false, captures: Object.freeze([]), values: Object.freeze([]) });
|
|
9405
|
+
}
|
|
8828
9406
|
|
|
8829
9407
|
// packages/safe-bash/src/shell/runtime.ts
|
|
8830
9408
|
var defaultLimits = {
|
|
@@ -8836,6 +9414,8 @@ var defaultLimits = {
|
|
|
8836
9414
|
maxSourceBytes: 1024 * 1024,
|
|
8837
9415
|
maxExpansionFields: 1e4,
|
|
8838
9416
|
maxExpansionBytes: 16 * 1024 * 1024,
|
|
9417
|
+
maxWallClockMs: 3e4,
|
|
9418
|
+
maxCpuMs: 3e4,
|
|
8839
9419
|
pipeHighWaterMark: 64 * 1024
|
|
8840
9420
|
};
|
|
8841
9421
|
var shellBuiltinNames = /* @__PURE__ */ new Set([
|
|
@@ -8915,6 +9495,8 @@ var Budget = class {
|
|
|
8915
9495
|
this.limits = limits;
|
|
8916
9496
|
this.signal = signal ? AbortSignal.any([signal, this.controller.signal]) : this.controller.signal;
|
|
8917
9497
|
this.values = new ValueArena(limits.maxExpansionBytes, limits.maxExpansionFields, () => this.signal.throwIfAborted(), (limit) => this.fail(limit));
|
|
9498
|
+
this.#wallClockDeadline = Date.now() + limits.maxWallClockMs;
|
|
9499
|
+
this.#armWallClock();
|
|
8918
9500
|
}
|
|
8919
9501
|
limits;
|
|
8920
9502
|
values;
|
|
@@ -8924,12 +9506,34 @@ var Budget = class {
|
|
|
8924
9506
|
sourceBytes = 0;
|
|
8925
9507
|
controller = new AbortController();
|
|
8926
9508
|
signal;
|
|
9509
|
+
#wallClockTimer;
|
|
9510
|
+
#wallClockDeadline = 0;
|
|
9511
|
+
#cpuStarted = monotonicNow();
|
|
9512
|
+
#armWallClock() {
|
|
9513
|
+
const remaining = this.#wallClockDeadline - Date.now();
|
|
9514
|
+
if (remaining <= 0) {
|
|
9515
|
+
this.controller.abort(new ShellLimitError("maxWallClockMs"));
|
|
9516
|
+
return;
|
|
9517
|
+
}
|
|
9518
|
+
this.#wallClockTimer = setTimeout(() => this.#armWallClock(), Math.min(remaining, 2147483647));
|
|
9519
|
+
const timer = this.#wallClockTimer;
|
|
9520
|
+
timer.unref?.();
|
|
9521
|
+
}
|
|
9522
|
+
close() {
|
|
9523
|
+
if (this.#wallClockTimer !== void 0) clearTimeout(this.#wallClockTimer);
|
|
9524
|
+
this.#wallClockTimer = void 0;
|
|
9525
|
+
}
|
|
8927
9526
|
fail(limit) {
|
|
8928
9527
|
const error = new ShellLimitError(limit);
|
|
8929
9528
|
this.controller.abort(error);
|
|
8930
9529
|
throw error;
|
|
8931
9530
|
}
|
|
9531
|
+
cpuCheckpoint() {
|
|
9532
|
+
this.signal.throwIfAborted();
|
|
9533
|
+
if (monotonicNow() - this.#cpuStarted > this.limits.maxCpuMs) this.fail("maxCpuMs");
|
|
9534
|
+
}
|
|
8932
9535
|
tick() {
|
|
9536
|
+
this.cpuCheckpoint();
|
|
8933
9537
|
this.signal.throwIfAborted();
|
|
8934
9538
|
if (++this.commands > this.limits.maxCommands) this.fail("maxCommands");
|
|
8935
9539
|
}
|
|
@@ -9328,7 +9932,7 @@ var CdLookup = class {
|
|
|
9328
9932
|
amount -= step;
|
|
9329
9933
|
if (this.spent % 128 === 0) {
|
|
9330
9934
|
this.signal.throwIfAborted();
|
|
9331
|
-
await
|
|
9935
|
+
await yieldTurn(this.signal);
|
|
9332
9936
|
this.signal.throwIfAborted();
|
|
9333
9937
|
}
|
|
9334
9938
|
}
|
|
@@ -9424,7 +10028,7 @@ var DirectoryStackWork = class {
|
|
|
9424
10028
|
async flushWork() {
|
|
9425
10029
|
this.signal.throwIfAborted();
|
|
9426
10030
|
if (this.flushed === this.spent) return;
|
|
9427
|
-
await
|
|
10031
|
+
await yieldTurn(this.signal);
|
|
9428
10032
|
this.signal.throwIfAborted();
|
|
9429
10033
|
this.flushed = this.spent;
|
|
9430
10034
|
}
|
|
@@ -9745,6 +10349,7 @@ var Runtime = class _Runtime {
|
|
|
9745
10349
|
this.cancellationDepth = cancellationDepth;
|
|
9746
10350
|
this.cancellationMaxDepth = cancellationMaxDepth;
|
|
9747
10351
|
this.outcomeFrame = outcomeFrame;
|
|
10352
|
+
registerYieldCheckpoint(this.signal, () => this.budget.cpuCheckpoint());
|
|
9748
10353
|
}
|
|
9749
10354
|
fs;
|
|
9750
10355
|
commands;
|
|
@@ -9760,19 +10365,6 @@ var Runtime = class _Runtime {
|
|
|
9760
10365
|
cancellationDepth;
|
|
9761
10366
|
cancellationMaxDepth;
|
|
9762
10367
|
outcomeFrame;
|
|
9763
|
-
static #ereRoots = /* @__PURE__ */ new WeakMap();
|
|
9764
|
-
static registerEreRoot(budget, scope) {
|
|
9765
|
-
const entry = { closed: false };
|
|
9766
|
-
scope.register(async () => {
|
|
9767
|
-
entry.closed = true;
|
|
9768
|
-
try {
|
|
9769
|
-
await entry.cleanup?.();
|
|
9770
|
-
} finally {
|
|
9771
|
-
_Runtime.#ereRoots.delete(budget);
|
|
9772
|
-
}
|
|
9773
|
-
});
|
|
9774
|
-
_Runtime.#ereRoots.set(budget, entry);
|
|
9775
|
-
}
|
|
9776
10368
|
async ereDiagnostic(io, detail) {
|
|
9777
10369
|
try {
|
|
9778
10370
|
await this.diagnostic(io, detail);
|
|
@@ -9821,32 +10413,21 @@ var Runtime = class _Runtime {
|
|
|
9821
10413
|
await textToken(operation, subject, this.signal);
|
|
9822
10414
|
const name2 = "BASH_REMATCH";
|
|
9823
10415
|
const watch = await store.watch(name2, operation, this.signal);
|
|
9824
|
-
const
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
scope.assertOpen();
|
|
9828
|
-
if (entry.closed) throw new Error("ERE invocation owner is closed");
|
|
9829
|
-
entry.cleanup = cleanup;
|
|
10416
|
+
const ledger = new EreLedger({
|
|
10417
|
+
maxExpansionBytes: this.budget.limits.maxExpansionBytes,
|
|
10418
|
+
maxExpansionFields: this.budget.limits.maxExpansionFields
|
|
9830
10419
|
});
|
|
9831
|
-
const session = entry.root.openSession((cleanup) => scope.register(cleanup));
|
|
9832
10420
|
let result;
|
|
9833
|
-
let sessionEscaping = false;
|
|
9834
10421
|
try {
|
|
9835
|
-
|
|
10422
|
+
const program = await compileEre(fragments, ledger, this.signal);
|
|
10423
|
+
result = await matchEre(program, subject, ledger, this.signal);
|
|
9836
10424
|
} catch (error) {
|
|
9837
|
-
sessionEscaping = true;
|
|
9838
10425
|
this.signal.throwIfAborted();
|
|
9839
|
-
if (error instanceof
|
|
10426
|
+
if (error instanceof EreSyntaxError || error instanceof EreUnsupportedError) {
|
|
9840
10427
|
await this.ereDiagnostic(io, `[[ ${error.message}`);
|
|
9841
|
-
sessionEscaping = false;
|
|
9842
10428
|
return 2;
|
|
9843
10429
|
}
|
|
9844
10430
|
throw error;
|
|
9845
|
-
} finally {
|
|
9846
|
-
await session.close().catch((error) => {
|
|
9847
|
-
if (sessionEscaping) scope.failures.push(error);
|
|
9848
|
-
else throw new NounsetDiagnosticFailure(error);
|
|
9849
|
-
});
|
|
9850
10431
|
}
|
|
9851
10432
|
const status = result.matched ? 0 : 1;
|
|
9852
10433
|
this.signal.throwIfAborted();
|
|
@@ -9861,8 +10442,8 @@ var Runtime = class _Runtime {
|
|
|
9861
10442
|
const tickets = operation.reserve({ generation: true, version: true, epoch: true, work: 8 });
|
|
9862
10443
|
const prepared = await store.prepareName(name2, operation, this.signal);
|
|
9863
10444
|
staged = IndexedBinding.create(store.owner);
|
|
9864
|
-
if (result.matched) for (let index = 0; index < result.
|
|
9865
|
-
const span = result.
|
|
10445
|
+
if (result.matched) for (let index = 0; index < result.captures.length; index++) {
|
|
10446
|
+
const span = result.captures[index];
|
|
9866
10447
|
const size = span === null ? 0 : span.end - span.start;
|
|
9867
10448
|
operation.reserve({ payload: size, metadata: 32, work: size + 2 });
|
|
9868
10449
|
const value2 = span === null ? "" : subject.slice(span.start, span.end);
|
|
@@ -10024,6 +10605,7 @@ var Runtime = class _Runtime {
|
|
|
10024
10605
|
writeVariable(state, name2, value2, origin = "assignment") {
|
|
10025
10606
|
if (arrayStore(state)?.get(name2)) throw new ArrayFailure(origin === "arithmetic" ? "indexed arithmetic is unsupported" : "indexed write requires prepared publication");
|
|
10026
10607
|
if (state.readonlyVariables?.has(name2)) throw new Error(`${name2}: readonly variable`);
|
|
10608
|
+
if (shellValueByteLength(value2) > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
10027
10609
|
if (name2 === "OPTIND" && state.getopts?.integer && origin !== "arithmetic") {
|
|
10028
10610
|
try {
|
|
10029
10611
|
value2 = String(evaluateArithmetic(prepareArithmetic(shellValueText(value2) || "0"), this.arithmeticVariables(state)));
|
|
@@ -10533,7 +11115,7 @@ var Runtime = class _Runtime {
|
|
|
10533
11115
|
completed.add(index);
|
|
10534
11116
|
if (incoming) {
|
|
10535
11117
|
const upstream = index - 1;
|
|
10536
|
-
const close =
|
|
11118
|
+
const close = scheduleTurn(() => {
|
|
10537
11119
|
closing.delete(close);
|
|
10538
11120
|
if (written.has(upstream) && !completed.has(upstream)) controllers[upstream].abort(new PipelineClosed());
|
|
10539
11121
|
});
|
|
@@ -10560,7 +11142,7 @@ var Runtime = class _Runtime {
|
|
|
10560
11142
|
try {
|
|
10561
11143
|
statuses = await interruptible(Promise.all(tasks), this.signal);
|
|
10562
11144
|
} finally {
|
|
10563
|
-
for (const close of closing)
|
|
11145
|
+
for (const close of closing) cancelTurn(close);
|
|
10564
11146
|
for (const [index, controller] of controllers.entries()) if (!completed.has(index) || written.has(index)) controller.abort(new PipelineClosed());
|
|
10565
11147
|
await Promise.all(pipes.map((pipe) => pipe.abort()));
|
|
10566
11148
|
}
|
|
@@ -10625,7 +11207,7 @@ var Runtime = class _Runtime {
|
|
|
10625
11207
|
originalIO = { ...originalIO, diagnosticLine, substitutionDiagnosticLine: originalIO.substitutionDiagnosticLines?.get(command) ?? diagnosticLine };
|
|
10626
11208
|
if (command.kind === "subshell") originalIO = isolateIO(originalIO);
|
|
10627
11209
|
this.budget.tick();
|
|
10628
|
-
if (this.budget.commands % 128 === 0) await
|
|
11210
|
+
if (this.budget.commands % 128 === 0) await yieldTurn(this.signal);
|
|
10629
11211
|
this.signal.throwIfAborted();
|
|
10630
11212
|
const inputs = /* @__PURE__ */ new Set();
|
|
10631
11213
|
const outputs = /* @__PURE__ */ new Set();
|
|
@@ -10672,7 +11254,7 @@ var Runtime = class _Runtime {
|
|
|
10672
11254
|
diagnosticFailure = error;
|
|
10673
11255
|
throw error;
|
|
10674
11256
|
}
|
|
10675
|
-
if (error instanceof EreProfileLimitError
|
|
11257
|
+
if (error instanceof EreProfileLimitError) {
|
|
10676
11258
|
try {
|
|
10677
11259
|
await this.diagnostic(io, `[[ ${error.message}`);
|
|
10678
11260
|
} catch (reason) {
|
|
@@ -10741,7 +11323,7 @@ var Runtime = class _Runtime {
|
|
|
10741
11323
|
for (const clause of command.clauses) {
|
|
10742
11324
|
let matched = fallthrough;
|
|
10743
11325
|
if (!matched) for (const word of clause.patterns) {
|
|
10744
|
-
if (++patterns % 128 === 0) await
|
|
11326
|
+
if (++patterns % 128 === 0) await yieldTurn(this.signal);
|
|
10745
11327
|
const pattern = (await this.word(word, state, io, false, true)).join("");
|
|
10746
11328
|
if (await matchesPattern(pattern, subject, work)) {
|
|
10747
11329
|
matched = true;
|
|
@@ -10862,7 +11444,7 @@ var Runtime = class _Runtime {
|
|
|
10862
11444
|
this.signal.throwIfAborted();
|
|
10863
11445
|
for (const warning of warnings.splice(0)) await writeText(io.stderr, `shell: warning: ${warning}
|
|
10864
11446
|
`);
|
|
10865
|
-
if (++words % 128 === 0) await
|
|
11447
|
+
if (++words % 128 === 0) await yieldTurn(this.signal);
|
|
10866
11448
|
const part = (await this.word(word, state, io, false)).join("");
|
|
10867
11449
|
size += import_buffer.Buffer.byteLength(part);
|
|
10868
11450
|
if (size > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
@@ -11056,7 +11638,7 @@ var Runtime = class _Runtime {
|
|
|
11056
11638
|
}
|
|
11057
11639
|
const wordValues = await this.valueWords(commandWords, state, originalIO, ["export", "local", "readonly"].includes(commandWords[declarationIndex]?.plain ?? ""));
|
|
11058
11640
|
const words = wordValues.map(shellValueText);
|
|
11059
|
-
const
|
|
11641
|
+
const special2 = state.profile === "sh" && specialBuiltinNames.has(words[0] ?? "");
|
|
11060
11642
|
const inlineInput = command.redirects.some((redirect) => redirect.document || redirect.operator === "<<<");
|
|
11061
11643
|
const functionCommand = words.length > 0 && state.functions.has(words[0]);
|
|
11062
11644
|
const isolatedInlineInput = inlineInput && words.length > 0 && !shellBuiltinNames.has(words[0]) && !functionCommand;
|
|
@@ -11084,7 +11666,7 @@ var Runtime = class _Runtime {
|
|
|
11084
11666
|
if (assignment.append) value2 = concatShellValues([stateMonitor(state)?.values.get(assignment.name, state.variables[assignment.name] ?? "") ?? state.variables[assignment.name] ?? "", value2], io[valueScope]);
|
|
11085
11667
|
if (state.readonlyVariables?.has(assignment.name)) {
|
|
11086
11668
|
await this.diagnostic(io, `${assignment.name}: readonly variable`);
|
|
11087
|
-
if (state.profile === "sh" || !words.length) throw new Flow("exit", state.profile === "sh" && (
|
|
11669
|
+
if (state.profile === "sh" || !words.length) throw new Flow("exit", state.profile === "sh" && (special2 || !words.length) ? 127 : 1);
|
|
11088
11670
|
continue;
|
|
11089
11671
|
}
|
|
11090
11672
|
if (!previous.has(assignment.name)) {
|
|
@@ -11175,7 +11757,7 @@ var Runtime = class _Runtime {
|
|
|
11175
11757
|
if (error instanceof Flow) throw error;
|
|
11176
11758
|
this.signal.throwIfAborted();
|
|
11177
11759
|
const original = error instanceof ExecutionFailure ? error.original : error;
|
|
11178
|
-
if (
|
|
11760
|
+
if (special2 && !(original instanceof ShellLimitError) && !(original instanceof ExpansionFailure) && !(original instanceof Flow) && !(original instanceof ShellSyntaxError)) {
|
|
11179
11761
|
throw new ExecutionFailure(new FatalCommandFailure(message(original), 1), error instanceof ExecutionFailure ? error.io : io, error instanceof ExecutionFailure ? error.diagnostic : void 0);
|
|
11180
11762
|
}
|
|
11181
11763
|
if (error instanceof ExecutionFailure) throw error;
|
|
@@ -11415,16 +11997,16 @@ var Runtime = class _Runtime {
|
|
|
11415
11997
|
}
|
|
11416
11998
|
if (selected?.kind === "builtin") {
|
|
11417
11999
|
if (context2.command === "command" || context2.command === "builtin" || context2.command === "type") return { exitCode: await this.discoveryBuiltin(context2, state, io, assignments2) };
|
|
11418
|
-
const
|
|
11419
|
-
if (
|
|
11420
|
-
if (context2.command === "." || context2.command === "source") return { exitCode: await this.sourceBuiltin(context2, state, { ...io, ...context2 },
|
|
11421
|
-
if (context2.command === "eval") return { exitCode: await this.evalBuiltin(context2, state, { ...io, ...context2 },
|
|
12000
|
+
const special2 = state.profile === "sh" && !bypassFunctions && specialBuiltinNames.has(context2.command);
|
|
12001
|
+
if (special2) assignments2.clear();
|
|
12002
|
+
if (context2.command === "." || context2.command === "source") return { exitCode: await this.sourceBuiltin(context2, state, { ...io, ...context2 }, special2) };
|
|
12003
|
+
if (context2.command === "eval") return { exitCode: await this.evalBuiltin(context2, state, { ...io, ...context2 }, special2) };
|
|
11422
12004
|
const builtinWork = this.builtin(context2, state, assignments2, (error, diagnostic2) => {
|
|
11423
12005
|
builtinFailure = { error, diagnostic: diagnostic2 };
|
|
11424
12006
|
}, bypassFunctions);
|
|
11425
12007
|
const builtin = arrayStore(state) ? await interruptible(builtinWork, this.signal) : await builtinWork;
|
|
11426
12008
|
if (builtin !== void 0) {
|
|
11427
|
-
if (
|
|
12009
|
+
if (special2 && builtin !== 0 && context2.command !== "shift") throw new Flow("exit", builtin);
|
|
11428
12010
|
return { exitCode: builtin };
|
|
11429
12011
|
}
|
|
11430
12012
|
}
|
|
@@ -11736,7 +12318,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
11736
12318
|
let status = 0;
|
|
11737
12319
|
let lines2 = 0;
|
|
11738
12320
|
while (true) {
|
|
11739
|
-
if (++lines2 % 32 === 0) await
|
|
12321
|
+
if (++lines2 % 32 === 0) await yieldTurn(this.signal);
|
|
11740
12322
|
this.signal.throwIfAborted();
|
|
11741
12323
|
const bytes = await input2.sourceLine();
|
|
11742
12324
|
const eof = bytes === void 0;
|
|
@@ -12056,13 +12638,13 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12056
12638
|
return status2;
|
|
12057
12639
|
}
|
|
12058
12640
|
}
|
|
12059
|
-
async evalBuiltin(context, state, io,
|
|
12641
|
+
async evalBuiltin(context, state, io, special2) {
|
|
12060
12642
|
const args = [...context.args];
|
|
12061
12643
|
if (args[0] === "--") args.shift();
|
|
12062
12644
|
else if (args[0]?.startsWith("-") && args[0] !== "-") {
|
|
12063
12645
|
await this.diagnostic(io, `eval: -${args[0][1]}: invalid option`);
|
|
12064
12646
|
await writeText(io.stderr, "eval: usage: eval [arg ...]\n");
|
|
12065
|
-
if (
|
|
12647
|
+
if (special2) throw new Flow("exit", 2);
|
|
12066
12648
|
return 2;
|
|
12067
12649
|
}
|
|
12068
12650
|
if (!args.length) return 0;
|
|
@@ -12078,7 +12660,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12078
12660
|
throw error;
|
|
12079
12661
|
}
|
|
12080
12662
|
try {
|
|
12081
|
-
return await this.runCurrentText(source, state, { ...io, diagnosticOffset: (io.diagnosticLine ?? 1) - 1 },
|
|
12663
|
+
return await this.runCurrentText(source, state, { ...io, diagnosticOffset: (io.diagnosticLine ?? 1) - 1 }, special2, `${io.scriptName ?? "shell"}: eval`);
|
|
12082
12664
|
} finally {
|
|
12083
12665
|
const restore = () => {
|
|
12084
12666
|
state.depth--;
|
|
@@ -12087,12 +12669,12 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12087
12669
|
else restore();
|
|
12088
12670
|
}
|
|
12089
12671
|
}
|
|
12090
|
-
async sourceBuiltin(context, state, io,
|
|
12672
|
+
async sourceBuiltin(context, state, io, special2) {
|
|
12091
12673
|
const args = [...context.args];
|
|
12092
12674
|
if (args[0] === "--") args.shift();
|
|
12093
12675
|
else if (args[0]?.startsWith("-") && args[0] !== "-") {
|
|
12094
12676
|
await this.diagnostic(io, `${context.command}: ${args[0]}: unsupported option`);
|
|
12095
|
-
if (
|
|
12677
|
+
if (special2) throw new Flow("exit", 2);
|
|
12096
12678
|
return 2;
|
|
12097
12679
|
}
|
|
12098
12680
|
const filename = args.shift();
|
|
@@ -12100,7 +12682,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12100
12682
|
await this.diagnostic(io, `${context.command}: filename argument required`);
|
|
12101
12683
|
await writeText(io.stderr, `${context.command}: usage: ${context.command} [-p path] filename [arguments]
|
|
12102
12684
|
`);
|
|
12103
|
-
if (
|
|
12685
|
+
if (special2) throw new Flow("exit", 2);
|
|
12104
12686
|
return 2;
|
|
12105
12687
|
}
|
|
12106
12688
|
if (state.depth >= this.budget.limits.maxSubstitutionDepth) this.budget.fail("maxSubstitutionDepth");
|
|
@@ -12146,7 +12728,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12146
12728
|
if (error instanceof ShellLimitError) throw error;
|
|
12147
12729
|
if (errorCode(error) === "EFBIG") this.budget.fail("maxSourceBytes");
|
|
12148
12730
|
const diagnostic2 = error instanceof CommandFailure ? error.message : filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`;
|
|
12149
|
-
if (
|
|
12731
|
+
if (special2) throw new FatalCommandFailure(diagnostic2, 1);
|
|
12150
12732
|
throw new CommandFailure(diagnostic2, error instanceof CommandFailure ? error.status : 1);
|
|
12151
12733
|
}
|
|
12152
12734
|
const positional = state.positional;
|
|
@@ -12175,7 +12757,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12175
12757
|
throw error;
|
|
12176
12758
|
}
|
|
12177
12759
|
try {
|
|
12178
|
-
return await this.runCurrentText(source, state, { ...io, scriptName: target, diagnosticOffset: 0, diagnosticLine: 1 },
|
|
12760
|
+
return await this.runCurrentText(source, state, { ...io, scriptName: target, diagnosticOffset: 0, diagnosticLine: 1 }, special2);
|
|
12179
12761
|
} catch (error) {
|
|
12180
12762
|
if (error instanceof Flow && error.kind === "return") return error.status;
|
|
12181
12763
|
throw error;
|
|
@@ -12317,7 +12899,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12317
12899
|
};
|
|
12318
12900
|
const checkpoint = async () => {
|
|
12319
12901
|
this.signal.throwIfAborted();
|
|
12320
|
-
await
|
|
12902
|
+
await yieldTurn(this.signal);
|
|
12321
12903
|
this.signal.throwIfAborted();
|
|
12322
12904
|
};
|
|
12323
12905
|
const { args } = context;
|
|
@@ -12362,7 +12944,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12362
12944
|
};
|
|
12363
12945
|
const checkpoint = async () => {
|
|
12364
12946
|
this.signal.throwIfAborted();
|
|
12365
|
-
await
|
|
12947
|
+
await yieldTurn(this.signal);
|
|
12366
12948
|
this.signal.throwIfAborted();
|
|
12367
12949
|
};
|
|
12368
12950
|
if (!Array.isArray(context.args)) throw new CommandFailure("getopts: argument array required", 2);
|
|
@@ -13395,7 +13977,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
13395
13977
|
const match = async (start, end) => {
|
|
13396
13978
|
work.remaining -= end - start + 1;
|
|
13397
13979
|
if (work.remaining < 0) work.exhausted();
|
|
13398
|
-
if (++attempts % 256 === 0) await
|
|
13980
|
+
if (++attempts % 256 === 0) await yieldTurn(this.signal);
|
|
13399
13981
|
this.signal.throwIfAborted();
|
|
13400
13982
|
if (owner) await owner.ledger.checkpoint(this.signal, end - start + 1);
|
|
13401
13983
|
return matches(slice(start, end));
|
|
@@ -13904,7 +14486,7 @@ var ShellInput = class _ShellInput {
|
|
|
13904
14486
|
let length = 0;
|
|
13905
14487
|
let pulls = 0;
|
|
13906
14488
|
while (true) {
|
|
13907
|
-
if (++pulls % 128 === 0) await
|
|
14489
|
+
if (++pulls % 128 === 0) await yieldTurn(this.signal);
|
|
13908
14490
|
const result = await this.#cursor.take(this.signal);
|
|
13909
14491
|
if (result.done) {
|
|
13910
14492
|
if (!length) return void 0;
|
|
@@ -13946,7 +14528,7 @@ var ShellInput = class _ShellInput {
|
|
|
13946
14528
|
try {
|
|
13947
14529
|
while (!terminated) {
|
|
13948
14530
|
if (offset === chunk.length) {
|
|
13949
|
-
if (++pulls % 128 === 0) await
|
|
14531
|
+
if (++pulls % 128 === 0) await yieldTurn(this.signal);
|
|
13950
14532
|
const result = await this.#cursor.take(this.signal);
|
|
13951
14533
|
if (result.done) {
|
|
13952
14534
|
break;
|
|
@@ -13962,7 +14544,7 @@ var ShellInput = class _ShellInput {
|
|
|
13962
14544
|
}
|
|
13963
14545
|
if (++length > this.budget.limits.maxOutputBytes) this.budget.fail("maxOutputBytes");
|
|
13964
14546
|
if (length % 1024 === 0) {
|
|
13965
|
-
await
|
|
14547
|
+
await yieldTurn(this.signal);
|
|
13966
14548
|
this.signal.throwIfAborted();
|
|
13967
14549
|
}
|
|
13968
14550
|
if (byte === 0) continue;
|
|
@@ -14155,6 +14737,7 @@ var Shell = class {
|
|
|
14155
14737
|
#active = /* @__PURE__ */ new Set();
|
|
14156
14738
|
constructor(options2) {
|
|
14157
14739
|
if (!options2?.fs) throw new TypeError("Shell requires an explicit filesystem");
|
|
14740
|
+
warnIfHostProcessEnv(options2.env);
|
|
14158
14741
|
resolveLimits(options2.limits);
|
|
14159
14742
|
this.#options = { ...options2, cwd: resolvePath("/", options2.cwd ?? "/"), env: { ...options2.env }, limits: { ...options2.limits } };
|
|
14160
14743
|
this.commands = options2.commands ?? new CommandRegistry();
|
|
@@ -14217,6 +14800,7 @@ var Shell = class {
|
|
|
14217
14800
|
}
|
|
14218
14801
|
async exec(source, options2 = {}) {
|
|
14219
14802
|
if (this.#disposed) throw new Error("Shell is disposed");
|
|
14803
|
+
warnIfHostProcessEnv(options2.env);
|
|
14220
14804
|
const budget = new Budget(resolveLimits(this.#options.limits, options2.limits), options2.signal);
|
|
14221
14805
|
const scope = new InvocationScope(options2.signal);
|
|
14222
14806
|
const cancellationState = new RuntimeCancellationState();
|
|
@@ -14227,7 +14811,6 @@ var Shell = class {
|
|
|
14227
14811
|
controls: [{ role: "budget-control", signal: budget.controller.signal }]
|
|
14228
14812
|
});
|
|
14229
14813
|
try {
|
|
14230
|
-
Runtime.registerEreRoot(budget, scope);
|
|
14231
14814
|
owner.activate(boundary);
|
|
14232
14815
|
} catch (error) {
|
|
14233
14816
|
scope.failures.push(...boundary.close().failures);
|
|
@@ -14241,6 +14824,7 @@ var Shell = class {
|
|
|
14241
14824
|
try {
|
|
14242
14825
|
captured = await owner.capture(() => this.#execute(source, options2, scope, budget, boundary, cancellationState, owner));
|
|
14243
14826
|
} finally {
|
|
14827
|
+
budget.close();
|
|
14244
14828
|
await scope.close();
|
|
14245
14829
|
}
|
|
14246
14830
|
const selection = owner.finish(captured);
|
|
@@ -14413,6 +14997,22 @@ shell: -c: line ${line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
14413
14997
|
}
|
|
14414
14998
|
};
|
|
14415
14999
|
|
|
15000
|
+
// packages/safe-bash/src/shell/worker-limits.ts
|
|
15001
|
+
init_platform();
|
|
15002
|
+
var cloudflareWorkerLimits = Object.freeze({
|
|
15003
|
+
maxInputBytes: 4 * 1024 * 1024,
|
|
15004
|
+
maxOutputBytes: 4 * 1024 * 1024,
|
|
15005
|
+
maxCommands: 1e3,
|
|
15006
|
+
maxLoopIterations: 1e3,
|
|
15007
|
+
maxSubstitutionDepth: 16,
|
|
15008
|
+
maxSourceBytes: 256 * 1024,
|
|
15009
|
+
maxExpansionFields: 1e3,
|
|
15010
|
+
maxExpansionBytes: 4 * 1024 * 1024,
|
|
15011
|
+
maxWallClockMs: 1e4,
|
|
15012
|
+
maxCpuMs: 1e4,
|
|
15013
|
+
pipeHighWaterMark: 16 * 1024
|
|
15014
|
+
});
|
|
15015
|
+
|
|
14416
15016
|
// packages/safe-bash/src/fs/memory/index.ts
|
|
14417
15017
|
init_platform();
|
|
14418
15018
|
import { createMemoryFileSystem, MemoryFileSystem } from "@poe-platform/safe-fs/core";
|
|
@@ -14429,6 +15029,153 @@ import { createMountFileSystem, MountFileSystem } from "@poe-platform/safe-fs/co
|
|
|
14429
15029
|
init_platform();
|
|
14430
15030
|
import { createOverlayFileSystem, OverlayFileSystem } from "@poe-platform/safe-fs/core";
|
|
14431
15031
|
|
|
15032
|
+
// packages/safe-bash/src/commands/network/fetch-transport.ts
|
|
15033
|
+
init_platform();
|
|
15034
|
+
|
|
15035
|
+
// packages/safe-bash/src/commands/network/types.ts
|
|
15036
|
+
init_platform();
|
|
15037
|
+
var defaultNetworkLimits = Object.freeze({
|
|
15038
|
+
maxUploadBytes: 64 * 1024 * 1024,
|
|
15039
|
+
maxDownloadBytes: 64 * 1024 * 1024,
|
|
15040
|
+
maxBufferBytes: 8 * 1024 * 1024,
|
|
15041
|
+
maxHeaderBytes: 64 * 1024,
|
|
15042
|
+
maxRedirects: 10,
|
|
15043
|
+
maxRetries: 5,
|
|
15044
|
+
maxUrls: 32,
|
|
15045
|
+
maxTimeMs: 12e4
|
|
15046
|
+
});
|
|
15047
|
+
var cloudflareWorkerNetworkLimits = Object.freeze({
|
|
15048
|
+
maxUploadBytes: 4 * 1024 * 1024,
|
|
15049
|
+
maxDownloadBytes: 4 * 1024 * 1024,
|
|
15050
|
+
maxBufferBytes: 1024 * 1024,
|
|
15051
|
+
maxHeaderBytes: 32 * 1024,
|
|
15052
|
+
maxRedirects: 2,
|
|
15053
|
+
maxRetries: 1,
|
|
15054
|
+
maxUrls: 8,
|
|
15055
|
+
maxTimeMs: 1e4
|
|
15056
|
+
});
|
|
15057
|
+
var CurlError = class extends Error {
|
|
15058
|
+
constructor(exitCode, message2) {
|
|
15059
|
+
super(message2);
|
|
15060
|
+
this.exitCode = exitCode;
|
|
15061
|
+
this.name = "CurlError";
|
|
15062
|
+
}
|
|
15063
|
+
exitCode;
|
|
15064
|
+
};
|
|
15065
|
+
|
|
15066
|
+
// packages/safe-bash/src/commands/network/fetch-transport.ts
|
|
15067
|
+
function requestBody(source, signal) {
|
|
15068
|
+
if (!source) return void 0;
|
|
15069
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
15070
|
+
return new ReadableStream({
|
|
15071
|
+
async pull(controller) {
|
|
15072
|
+
try {
|
|
15073
|
+
signal.throwIfAborted();
|
|
15074
|
+
const next = await iterator.next();
|
|
15075
|
+
if (next.done) controller.close();
|
|
15076
|
+
else controller.enqueue(next.value);
|
|
15077
|
+
} catch (error) {
|
|
15078
|
+
controller.error(error);
|
|
15079
|
+
}
|
|
15080
|
+
},
|
|
15081
|
+
async cancel(reason) {
|
|
15082
|
+
await iterator.return?.(reason);
|
|
15083
|
+
}
|
|
15084
|
+
});
|
|
15085
|
+
}
|
|
15086
|
+
function createFetchTransport(options2 = {}) {
|
|
15087
|
+
const fetchRequest = options2.fetch ?? globalThis.fetch;
|
|
15088
|
+
if (typeof fetchRequest !== "function") throw new TypeError("Fetch is unavailable");
|
|
15089
|
+
return async (input2) => {
|
|
15090
|
+
input2.signal.throwIfAborted();
|
|
15091
|
+
const url = new URL(input2.url);
|
|
15092
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") throw new CurlError(1, "Unsupported protocol");
|
|
15093
|
+
const stopped = new AbortController();
|
|
15094
|
+
const signal = AbortSignal.any([input2.signal, stopped.signal]);
|
|
15095
|
+
const body = requestBody(input2.body, signal);
|
|
15096
|
+
const headers = new Headers();
|
|
15097
|
+
for (const [name2, value2] of input2.headers) headers.append(name2, value2);
|
|
15098
|
+
const request = new Request(url, {
|
|
15099
|
+
method: input2.method,
|
|
15100
|
+
headers,
|
|
15101
|
+
body,
|
|
15102
|
+
credentials: "omit",
|
|
15103
|
+
redirect: "manual",
|
|
15104
|
+
signal,
|
|
15105
|
+
...body ? { duplex: "half" } : {}
|
|
15106
|
+
});
|
|
15107
|
+
let response;
|
|
15108
|
+
const dispose = async () => {
|
|
15109
|
+
stopped.abort();
|
|
15110
|
+
if (response?.body) await response.body.cancel().catch(() => void 0);
|
|
15111
|
+
};
|
|
15112
|
+
input2.registerCleanup?.(dispose);
|
|
15113
|
+
response = await fetchRequest(request);
|
|
15114
|
+
const reader = response.body?.getReader();
|
|
15115
|
+
const responseBody = reader ? (async function* () {
|
|
15116
|
+
try {
|
|
15117
|
+
while (true) {
|
|
15118
|
+
input2.signal.throwIfAborted();
|
|
15119
|
+
const next = await reader.read();
|
|
15120
|
+
if (next.done) return;
|
|
15121
|
+
yield next.value;
|
|
15122
|
+
}
|
|
15123
|
+
} finally {
|
|
15124
|
+
reader.releaseLock();
|
|
15125
|
+
}
|
|
15126
|
+
})() : (async function* () {
|
|
15127
|
+
})();
|
|
15128
|
+
return {
|
|
15129
|
+
status: response.status,
|
|
15130
|
+
statusText: response.statusText,
|
|
15131
|
+
headers: [...response.headers.entries()],
|
|
15132
|
+
body: responseBody,
|
|
15133
|
+
dispose
|
|
15134
|
+
};
|
|
15135
|
+
};
|
|
15136
|
+
}
|
|
15137
|
+
|
|
15138
|
+
// packages/safe-bash/src/commands/network/authorizer.ts
|
|
15139
|
+
init_platform();
|
|
15140
|
+
function privateHostname(input2) {
|
|
15141
|
+
const hostname = input2.toLowerCase().replace(/\.$/u, "").replace(/^\[|\]$/gu, "");
|
|
15142
|
+
if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "::1") return true;
|
|
15143
|
+
if (hostname.includes(":")) {
|
|
15144
|
+
const first2 = hostname.split(":", 1)[0] ?? "";
|
|
15145
|
+
return first2.startsWith("fc") || first2.startsWith("fd") || ["fe8", "fe9", "fea", "feb"].some((prefix2) => first2.startsWith(prefix2));
|
|
15146
|
+
}
|
|
15147
|
+
const parts = hostname.split(".");
|
|
15148
|
+
if (parts.length !== 4 || parts.some((part) => !part || Array.from(part).some((character) => character < "0" || character > "9"))) return false;
|
|
15149
|
+
const octets = parts.map(Number);
|
|
15150
|
+
if (octets.some((value2) => value2 < 0 || value2 > 255)) return false;
|
|
15151
|
+
const [first, second] = octets;
|
|
15152
|
+
return first === 10 || first === 127 || first === 0 || first === 169 && second === 254 || first === 192 && second === 168 || first === 172 && second >= 16 && second <= 31;
|
|
15153
|
+
}
|
|
15154
|
+
function createOriginAuthorizer(allowlist = "*", options2 = {}) {
|
|
15155
|
+
const origins = /* @__PURE__ */ new Set();
|
|
15156
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
15157
|
+
for (const entry of allowlist === "*" ? [] : allowlist) {
|
|
15158
|
+
const value2 = entry.trim();
|
|
15159
|
+
if (!value2) throw new TypeError("Origin allowlist entries must not be empty");
|
|
15160
|
+
if (value2.includes("://")) {
|
|
15161
|
+
const url = new URL(value2);
|
|
15162
|
+
if (url.pathname !== "/" || url.search || url.hash || url.username || url.password) {
|
|
15163
|
+
throw new TypeError(`Origin allowlist entry must be an origin: ${entry}`);
|
|
15164
|
+
}
|
|
15165
|
+
origins.add(url.origin);
|
|
15166
|
+
} else {
|
|
15167
|
+
if (value2.includes("/") || value2.includes("@")) throw new TypeError(`Invalid hostname allowlist entry: ${entry}`);
|
|
15168
|
+
hosts.add(value2.toLowerCase().replace(/\.$/u, ""));
|
|
15169
|
+
}
|
|
15170
|
+
}
|
|
15171
|
+
return (request) => {
|
|
15172
|
+
const url = new URL(request.url);
|
|
15173
|
+
const hostname = url.hostname.toLowerCase().replace(/\.$/u, "");
|
|
15174
|
+
if (options2.denyPrivateNetworks && privateHostname(hostname)) return false;
|
|
15175
|
+
return allowlist === "*" || origins.has(url.origin) || hosts.has(hostname);
|
|
15176
|
+
};
|
|
15177
|
+
}
|
|
15178
|
+
|
|
14432
15179
|
// packages/safe-bash/src/browser.ts
|
|
14433
15180
|
function createBrowserCommands() {
|
|
14434
15181
|
return [
|
|
@@ -14467,14 +15214,18 @@ export {
|
|
|
14467
15214
|
assertPathWithin,
|
|
14468
15215
|
basename,
|
|
14469
15216
|
browserCommands,
|
|
15217
|
+
cloudflareWorkerLimits,
|
|
15218
|
+
cloudflareWorkerNetworkLimits,
|
|
14470
15219
|
collectBytes2 as collectBytes,
|
|
14471
15220
|
collectText,
|
|
14472
15221
|
composeMiddleware,
|
|
14473
15222
|
createBrowserCommands,
|
|
14474
15223
|
createBytePipe,
|
|
14475
15224
|
createCommandArguments,
|
|
15225
|
+
createFetchTransport,
|
|
14476
15226
|
createMemoryFileSystem,
|
|
14477
15227
|
createMountFileSystem,
|
|
15228
|
+
createOriginAuthorizer,
|
|
14478
15229
|
createOutputOperation,
|
|
14479
15230
|
createOverlayFileSystem,
|
|
14480
15231
|
createReadOnlyFileSystem,
|