@poe-platform/safe-bash 0.1.40 → 0.1.42
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 +45 -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 +878 -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 +18 -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,22 @@ 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 && !isShallowCopyOfProcessEnv(env)) return;
|
|
4487
|
+
warned.add(env);
|
|
4488
|
+
console.warn("[safe-bash] warning: the shell `env` is the host `process.env` (or a shallow copy of it). 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
|
+
function isShallowCopyOfProcessEnv(env) {
|
|
4491
|
+
const keys = Object.keys(env);
|
|
4492
|
+
if (keys.length !== Object.keys(process.env).length) return false;
|
|
4493
|
+
return keys.every((key) => env[key] === process.env[key]);
|
|
4494
|
+
}
|
|
4495
|
+
|
|
4447
4496
|
// packages/safe-bash/src/shell/parser.ts
|
|
4448
4497
|
init_platform();
|
|
4449
4498
|
|
|
@@ -4538,7 +4587,7 @@ function integer2(text) {
|
|
|
4538
4587
|
for (const character of match[2]) {
|
|
4539
4588
|
const digit2 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_".indexOf(base <= 36 ? character.toLowerCase() : character);
|
|
4540
4589
|
if (digit2 >= base || digit2 < 0) throw new Error("Digit exceeds arithmetic base");
|
|
4541
|
-
value2 = value2 * BigInt(base) + BigInt(digit2);
|
|
4590
|
+
value2 = BigInt.asIntN(64, value2 * BigInt(base) + BigInt(digit2));
|
|
4542
4591
|
}
|
|
4543
4592
|
return value2;
|
|
4544
4593
|
}
|
|
@@ -4864,7 +4913,7 @@ async function tokens(pattern, work) {
|
|
|
4864
4913
|
let steps = 0;
|
|
4865
4914
|
const tick = () => {
|
|
4866
4915
|
if (--work.remaining < 0) work.exhausted();
|
|
4867
|
-
if (++steps % 1024 === 0) return
|
|
4916
|
+
if (++steps % 1024 === 0) return yieldTurn(work.signal);
|
|
4868
4917
|
return void 0;
|
|
4869
4918
|
};
|
|
4870
4919
|
for (let index = 0; index < characters.length; index++) {
|
|
@@ -4941,7 +4990,7 @@ async function matchTokens(patternTokens, value2, work) {
|
|
|
4941
4990
|
while (position < characters.length) {
|
|
4942
4991
|
if (--work.remaining < 0) work.exhausted();
|
|
4943
4992
|
if (++steps % 1024 === 0) {
|
|
4944
|
-
await
|
|
4993
|
+
await yieldTurn(work.signal);
|
|
4945
4994
|
work.signal.throwIfAborted();
|
|
4946
4995
|
}
|
|
4947
4996
|
const token = patternTokens[tokenIndex];
|
|
@@ -4974,7 +5023,7 @@ async function charge(context, amount = 1) {
|
|
|
4974
5023
|
const previous = context.work.remaining;
|
|
4975
5024
|
context.work.remaining -= amount;
|
|
4976
5025
|
if (previous >>> 10 !== context.work.remaining >>> 10) {
|
|
4977
|
-
await
|
|
5026
|
+
await yieldTurn();
|
|
4978
5027
|
context.signal.throwIfAborted();
|
|
4979
5028
|
}
|
|
4980
5029
|
}
|
|
@@ -5176,6 +5225,7 @@ var Lexer = class {
|
|
|
5176
5225
|
this.documentLine = documentLine;
|
|
5177
5226
|
this.partial = partial;
|
|
5178
5227
|
if (depth > 64) throw new ShellSyntaxError("Syntax nesting exceeds 64", 0);
|
|
5228
|
+
for (let offset = source.indexOf("\n"); offset !== -1; offset = source.indexOf("\n", offset + 1)) this.newlineOffsets.push(offset);
|
|
5179
5229
|
}
|
|
5180
5230
|
source;
|
|
5181
5231
|
depth;
|
|
@@ -5191,8 +5241,16 @@ var Lexer = class {
|
|
|
5191
5241
|
conditional = false;
|
|
5192
5242
|
conditionalPattern;
|
|
5193
5243
|
documents = [];
|
|
5244
|
+
newlineOffsets = [];
|
|
5194
5245
|
lineAt(position) {
|
|
5195
|
-
|
|
5246
|
+
let low = 0;
|
|
5247
|
+
let high = this.newlineOffsets.length;
|
|
5248
|
+
while (low < high) {
|
|
5249
|
+
const middle = low + Math.floor((high - low) / 2);
|
|
5250
|
+
if (this.newlineOffsets[middle] < position) low = middle + 1;
|
|
5251
|
+
else high = middle;
|
|
5252
|
+
}
|
|
5253
|
+
return this.lineOffset + low + 1;
|
|
5196
5254
|
}
|
|
5197
5255
|
error(message2, unclosedQuote) {
|
|
5198
5256
|
throw new ShellSyntaxError(message2, this.position, 2, void 0, unclosedQuote);
|
|
@@ -6614,7 +6672,7 @@ var SplitWork = class {
|
|
|
6614
6672
|
return this.work >= this.nextYield;
|
|
6615
6673
|
}
|
|
6616
6674
|
async pause() {
|
|
6617
|
-
await
|
|
6675
|
+
await yieldTurn();
|
|
6618
6676
|
this.signal.throwIfAborted();
|
|
6619
6677
|
this.nextYield = this.work + 4096;
|
|
6620
6678
|
}
|
|
@@ -7884,14 +7942,7 @@ var ArrayLedger = class _ArrayLedger {
|
|
|
7884
7942
|
this.#checkpoint += units;
|
|
7885
7943
|
if (this.#checkpoint >= 128) {
|
|
7886
7944
|
this.#checkpoint %= 128;
|
|
7887
|
-
return
|
|
7888
|
-
try {
|
|
7889
|
-
signal?.throwIfAborted();
|
|
7890
|
-
resolve();
|
|
7891
|
-
} catch (error) {
|
|
7892
|
-
reject(error);
|
|
7893
|
-
}
|
|
7894
|
-
}));
|
|
7945
|
+
return yieldTurn(signal);
|
|
7895
7946
|
}
|
|
7896
7947
|
}
|
|
7897
7948
|
};
|
|
@@ -8768,43 +8819,17 @@ async function publishPipelineStatus(state, statuses, signal, scope) {
|
|
|
8768
8819
|
throwCleanupFailures(scope.failures);
|
|
8769
8820
|
}
|
|
8770
8821
|
|
|
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
|
|
8822
|
+
// packages/safe-bash/src/commands/regex-execution/ere/errors.ts
|
|
8780
8823
|
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;
|
|
8824
|
+
var EreSyntaxError = class extends Error {
|
|
8825
|
+
constructor(message2, offset) {
|
|
8826
|
+
super(`invalid ERE at ${offset}: ${message2}`);
|
|
8798
8827
|
this.offset = offset;
|
|
8799
|
-
this.name = "
|
|
8828
|
+
this.name = "EreSyntaxError";
|
|
8800
8829
|
}
|
|
8801
|
-
category;
|
|
8802
8830
|
offset;
|
|
8803
8831
|
status = 2;
|
|
8804
8832
|
};
|
|
8805
|
-
|
|
8806
|
-
// packages/safe-bash/src/commands/regex-execution/ere/errors.ts
|
|
8807
|
-
init_platform();
|
|
8808
8833
|
var EreUnsupportedError = class extends Error {
|
|
8809
8834
|
constructor(message2, offset) {
|
|
8810
8835
|
super(`unsupported ERE profile at ${offset}: ${message2}`);
|
|
@@ -8825,6 +8850,564 @@ var EreProfileLimitError = class extends Error {
|
|
|
8825
8850
|
limit;
|
|
8826
8851
|
status = 3;
|
|
8827
8852
|
};
|
|
8853
|
+
var EreUsageUnknownError = class extends Error {
|
|
8854
|
+
status = 3;
|
|
8855
|
+
constructor(reason) {
|
|
8856
|
+
super("ERE invocation usage is unknown; further work is refused", { cause: reason });
|
|
8857
|
+
this.name = "EreUsageUnknownError";
|
|
8858
|
+
}
|
|
8859
|
+
};
|
|
8860
|
+
|
|
8861
|
+
// packages/safe-bash/src/commands/regex-execution/ere/limits.ts
|
|
8862
|
+
init_platform();
|
|
8863
|
+
var resources = Object.freeze([
|
|
8864
|
+
"patternBytes",
|
|
8865
|
+
"subjectBytes",
|
|
8866
|
+
"work",
|
|
8867
|
+
"states",
|
|
8868
|
+
"allocationUnits",
|
|
8869
|
+
"captureBytes",
|
|
8870
|
+
"captureSlots"
|
|
8871
|
+
]);
|
|
8872
|
+
function integer5(value2) {
|
|
8873
|
+
if (!Number.isSafeInteger(value2) || value2 < 0) throw new TypeError("ERE bounds must be nonnegative safe integers");
|
|
8874
|
+
}
|
|
8875
|
+
function multiply(value2, factor, ceiling) {
|
|
8876
|
+
return value2 > Math.floor(ceiling / factor) ? ceiling : value2 * factor;
|
|
8877
|
+
}
|
|
8878
|
+
function deriveEreLimits(bounds) {
|
|
8879
|
+
integer5(bounds.maxExpansionBytes);
|
|
8880
|
+
integer5(bounds.maxExpansionFields);
|
|
8881
|
+
const bytes = bounds.maxExpansionBytes;
|
|
8882
|
+
const fields = bounds.maxExpansionFields;
|
|
8883
|
+
const byteUnits = multiply(bytes, 8, 4e6);
|
|
8884
|
+
const fieldUnits = multiply(fields, 128, 4e6);
|
|
8885
|
+
return Object.freeze({
|
|
8886
|
+
patternBytes: Math.min(bytes, 65536),
|
|
8887
|
+
subjectBytes: Math.min(bytes, 1048576),
|
|
8888
|
+
work: multiply(bytes, 32, 5e7),
|
|
8889
|
+
states: multiply(fields, 8, 65536),
|
|
8890
|
+
allocationUnits: byteUnits >= 4e6 - fieldUnits ? 4e6 : byteUnits + fieldUnits,
|
|
8891
|
+
captureBytes: bytes,
|
|
8892
|
+
captureSlots: fields
|
|
8893
|
+
});
|
|
8894
|
+
}
|
|
8895
|
+
var EreLedger = class {
|
|
8896
|
+
limits;
|
|
8897
|
+
#usage = {
|
|
8898
|
+
patternBytes: 0,
|
|
8899
|
+
subjectBytes: 0,
|
|
8900
|
+
work: 0,
|
|
8901
|
+
states: 0,
|
|
8902
|
+
allocationUnits: 0,
|
|
8903
|
+
captureBytes: 0,
|
|
8904
|
+
captureSlots: 0
|
|
8905
|
+
};
|
|
8906
|
+
#poison;
|
|
8907
|
+
#lastYield = 0;
|
|
8908
|
+
constructor(bounds, lowering = {}) {
|
|
8909
|
+
const limits = { ...deriveEreLimits(bounds) };
|
|
8910
|
+
for (const resource of Object.keys(lowering)) {
|
|
8911
|
+
if (!resources.includes(resource)) throw new TypeError("unknown ERE limit");
|
|
8912
|
+
const key = resource;
|
|
8913
|
+
const value2 = lowering[key];
|
|
8914
|
+
if (value2 === void 0) throw new TypeError("undefined ERE limit");
|
|
8915
|
+
integer5(value2);
|
|
8916
|
+
if (value2 > limits[key]) throw new RangeError("ERE limits may only be lowered");
|
|
8917
|
+
limits[key] = value2;
|
|
8918
|
+
}
|
|
8919
|
+
this.limits = Object.freeze(limits);
|
|
8920
|
+
}
|
|
8921
|
+
get usage() {
|
|
8922
|
+
return Object.freeze({ ...this.#usage });
|
|
8923
|
+
}
|
|
8924
|
+
check(signal) {
|
|
8925
|
+
if (signal?.aborted) throw signal.reason;
|
|
8926
|
+
if (this.#poison) throw this.#poison;
|
|
8927
|
+
}
|
|
8928
|
+
charge(resource, amount, signal) {
|
|
8929
|
+
this.check(signal);
|
|
8930
|
+
integer5(amount);
|
|
8931
|
+
if (amount > this.limits[resource] - this.#usage[resource]) {
|
|
8932
|
+
throw new EreProfileLimitError(resource, this.limits[resource]);
|
|
8933
|
+
}
|
|
8934
|
+
this.#usage[resource] += amount;
|
|
8935
|
+
}
|
|
8936
|
+
admitInput(resource, length, signal) {
|
|
8937
|
+
this.check(signal);
|
|
8938
|
+
integer5(length);
|
|
8939
|
+
if (length > this.limits[resource]) throw new EreProfileLimitError(resource, this.limits[resource]);
|
|
8940
|
+
this.#usage[resource] = Math.max(this.#usage[resource], length);
|
|
8941
|
+
}
|
|
8942
|
+
async checkpoint(signal) {
|
|
8943
|
+
this.check(signal);
|
|
8944
|
+
if (this.#usage.work - this.#lastYield >= 256) {
|
|
8945
|
+
this.#lastYield = this.#usage.work;
|
|
8946
|
+
await yieldTurn(signal);
|
|
8947
|
+
this.check(signal);
|
|
8948
|
+
}
|
|
8949
|
+
}
|
|
8950
|
+
markUnknownUsage(reason) {
|
|
8951
|
+
this.#poison ??= new EreUsageUnknownError(reason);
|
|
8952
|
+
}
|
|
8953
|
+
};
|
|
8954
|
+
|
|
8955
|
+
// packages/safe-bash/src/commands/regex-execution/ere/syntax.ts
|
|
8956
|
+
init_platform();
|
|
8957
|
+
var programs = /* @__PURE__ */ new WeakMap();
|
|
8958
|
+
var special = "\\.^$[]()|*+?{}";
|
|
8959
|
+
var classes = /* @__PURE__ */ new Set(["alnum", "alpha", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "xdigit"]);
|
|
8960
|
+
function classMember(name2, code) {
|
|
8961
|
+
const upper = code >= 65 && code <= 90;
|
|
8962
|
+
const lower = code >= 97 && code <= 122;
|
|
8963
|
+
const digit2 = code >= 48 && code <= 57;
|
|
8964
|
+
switch (name2) {
|
|
8965
|
+
case "alnum":
|
|
8966
|
+
return upper || lower || digit2;
|
|
8967
|
+
case "alpha":
|
|
8968
|
+
return upper || lower;
|
|
8969
|
+
case "blank":
|
|
8970
|
+
return code === 9 || code === 32;
|
|
8971
|
+
case "cntrl":
|
|
8972
|
+
return code < 32 || code === 127;
|
|
8973
|
+
case "digit":
|
|
8974
|
+
return digit2;
|
|
8975
|
+
case "graph":
|
|
8976
|
+
return code >= 33 && code <= 126;
|
|
8977
|
+
case "lower":
|
|
8978
|
+
return lower;
|
|
8979
|
+
case "print":
|
|
8980
|
+
return code >= 32 && code <= 126;
|
|
8981
|
+
case "punct":
|
|
8982
|
+
return code >= 33 && code <= 126 && !upper && !lower && !digit2;
|
|
8983
|
+
case "space":
|
|
8984
|
+
return code === 32 || code >= 9 && code <= 13;
|
|
8985
|
+
case "upper":
|
|
8986
|
+
return upper;
|
|
8987
|
+
case "xdigit":
|
|
8988
|
+
return digit2 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
|
|
8989
|
+
default:
|
|
8990
|
+
return false;
|
|
8991
|
+
}
|
|
8992
|
+
}
|
|
8993
|
+
async function admitAscii(text, ledger, signal) {
|
|
8994
|
+
for (let offset = 0; offset < text.length; offset++) {
|
|
8995
|
+
ledger.charge("work", 1, signal);
|
|
8996
|
+
const code = text.charCodeAt(offset);
|
|
8997
|
+
if (code === 0 || code > 127) throw new EreUnsupportedError("only non-NUL ASCII in the C/POSIX profile", offset);
|
|
8998
|
+
await ledger.checkpoint(signal);
|
|
8999
|
+
}
|
|
9000
|
+
}
|
|
9001
|
+
async function flatten(input2, ledger, signal) {
|
|
9002
|
+
if (typeof input2 === "string") {
|
|
9003
|
+
ledger.admitInput("patternBytes", input2.length, signal);
|
|
9004
|
+
await admitAscii(input2, ledger, signal);
|
|
9005
|
+
return { pattern: input2, quoted: null };
|
|
9006
|
+
}
|
|
9007
|
+
let size = 0;
|
|
9008
|
+
for (const fragment of input2) {
|
|
9009
|
+
if (typeof fragment.text !== "string" || typeof fragment.literal !== "boolean") throw new TypeError("invalid ERE fragment");
|
|
9010
|
+
ledger.charge("work", 1, signal);
|
|
9011
|
+
await ledger.checkpoint(signal);
|
|
9012
|
+
ledger.admitInput("patternBytes", fragment.text.length, signal);
|
|
9013
|
+
await admitAscii(fragment.text, ledger, signal);
|
|
9014
|
+
if (fragment.text.length > ledger.limits.patternBytes - size) ledger.admitInput("patternBytes", ledger.limits.patternBytes + 1, signal);
|
|
9015
|
+
size += fragment.text.length;
|
|
9016
|
+
ledger.admitInput("patternBytes", size, signal);
|
|
9017
|
+
}
|
|
9018
|
+
ledger.charge("allocationUnits", size * 2 + input2.length + 2, signal);
|
|
9019
|
+
const output2 = [];
|
|
9020
|
+
const quoted = [];
|
|
9021
|
+
for (const fragment of input2) {
|
|
9022
|
+
for (let offset = 0; offset < fragment.text.length; offset++) {
|
|
9023
|
+
ledger.charge("work", 1, signal);
|
|
9024
|
+
await ledger.checkpoint(signal);
|
|
9025
|
+
quoted.push(fragment.literal);
|
|
9026
|
+
}
|
|
9027
|
+
output2.push(fragment.text);
|
|
9028
|
+
await ledger.checkpoint(signal);
|
|
9029
|
+
}
|
|
9030
|
+
return { pattern: output2.join(""), quoted: Object.freeze(quoted) };
|
|
9031
|
+
}
|
|
9032
|
+
var Parser2 = class {
|
|
9033
|
+
constructor(pattern, quoted, ledger, signal) {
|
|
9034
|
+
this.pattern = pattern;
|
|
9035
|
+
this.quoted = quoted;
|
|
9036
|
+
this.ledger = ledger;
|
|
9037
|
+
this.signal = signal;
|
|
9038
|
+
}
|
|
9039
|
+
pattern;
|
|
9040
|
+
quoted;
|
|
9041
|
+
ledger;
|
|
9042
|
+
signal;
|
|
9043
|
+
offset = 0;
|
|
9044
|
+
groups = 0;
|
|
9045
|
+
nodes = 0;
|
|
9046
|
+
at(character, offset = this.offset) {
|
|
9047
|
+
return !this.quoted?.[offset] && this.pattern[offset] === character;
|
|
9048
|
+
}
|
|
9049
|
+
node(create) {
|
|
9050
|
+
if (this.nodes >= 4096) throw new EreUnsupportedError("4096-node grammar ceiling", this.offset);
|
|
9051
|
+
this.ledger.charge("allocationUnits", 8, this.signal);
|
|
9052
|
+
this.nodes++;
|
|
9053
|
+
return Object.freeze(create());
|
|
9054
|
+
}
|
|
9055
|
+
async expression(depth) {
|
|
9056
|
+
if (depth > 64) throw new EreUnsupportedError("64-level grammar ceiling", this.offset);
|
|
9057
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9058
|
+
const alternatives = [];
|
|
9059
|
+
while (true) {
|
|
9060
|
+
const child = await this.sequence(depth);
|
|
9061
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9062
|
+
alternatives.push(child);
|
|
9063
|
+
if (!this.at("|")) break;
|
|
9064
|
+
this.offset++;
|
|
9065
|
+
}
|
|
9066
|
+
if (alternatives.length === 1) return alternatives[0];
|
|
9067
|
+
this.ledger.charge("work", alternatives.length * 2, this.signal);
|
|
9068
|
+
await this.ledger.checkpoint(this.signal);
|
|
9069
|
+
return this.node(() => ({ kind: "alternative", children: Object.freeze(alternatives), nullable: alternatives.some((value2) => value2.nullable), captured: alternatives.some((value2) => value2.captured) }));
|
|
9070
|
+
}
|
|
9071
|
+
async sequence(depth) {
|
|
9072
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9073
|
+
const children = [];
|
|
9074
|
+
while (this.offset < this.pattern.length && !this.at("|") && !this.at(")")) {
|
|
9075
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9076
|
+
await this.ledger.checkpoint(this.signal);
|
|
9077
|
+
let child = await this.atom(depth);
|
|
9078
|
+
const operator = this.quoted?.[this.offset] ? void 0 : this.pattern[this.offset];
|
|
9079
|
+
if (operator === "*" || operator === "+" || operator === "?" || operator === "{") {
|
|
9080
|
+
const begin = this.offset++;
|
|
9081
|
+
let min = operator === "+" ? 1 : 0;
|
|
9082
|
+
let max = operator === "?" ? 1 : Infinity;
|
|
9083
|
+
if (operator === "{") {
|
|
9084
|
+
min = await this.count();
|
|
9085
|
+
max = min;
|
|
9086
|
+
if (this.at(",")) {
|
|
9087
|
+
this.offset++;
|
|
9088
|
+
max = this.at("}") ? Infinity : await this.count();
|
|
9089
|
+
}
|
|
9090
|
+
if (!this.at("}") || max < min) throw new EreSyntaxError("invalid interval", begin);
|
|
9091
|
+
this.offset++;
|
|
9092
|
+
}
|
|
9093
|
+
if (child.kind === "start" || child.kind === "end") throw new EreUnsupportedError("repeated anchor", begin);
|
|
9094
|
+
if (child.nullable && child.captured && max > 1) throw new EreUnsupportedError("nullable captured repetition", begin);
|
|
9095
|
+
const repeated = child;
|
|
9096
|
+
child = this.node(() => ({ kind: "repeat", child: repeated, min, max, nullable: min === 0 || repeated.nullable, captured: repeated.captured }));
|
|
9097
|
+
const next = this.quoted?.[this.offset] ? void 0 : this.pattern[this.offset];
|
|
9098
|
+
if (next === "*" || next === "+" || next === "?" || next === "{") throw new EreUnsupportedError("stacked repetition", this.offset);
|
|
9099
|
+
}
|
|
9100
|
+
this.ledger.charge("allocationUnits", 1, this.signal);
|
|
9101
|
+
children.push(child);
|
|
9102
|
+
}
|
|
9103
|
+
if (children.length === 0) return this.node(() => ({ kind: "empty", nullable: true, captured: false }));
|
|
9104
|
+
if (children.length === 1) return children[0];
|
|
9105
|
+
this.ledger.charge("work", children.length * 2, this.signal);
|
|
9106
|
+
await this.ledger.checkpoint(this.signal);
|
|
9107
|
+
return this.node(() => ({ kind: "sequence", children: Object.freeze(children), nullable: children.every((value2) => value2.nullable), captured: children.some((value2) => value2.captured) }));
|
|
9108
|
+
}
|
|
9109
|
+
async count() {
|
|
9110
|
+
const begin = this.offset;
|
|
9111
|
+
let value2 = 0;
|
|
9112
|
+
while (!this.quoted?.[this.offset] && this.pattern[this.offset] !== void 0 && this.pattern[this.offset] >= "0" && this.pattern[this.offset] <= "9") {
|
|
9113
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9114
|
+
await this.ledger.checkpoint(this.signal);
|
|
9115
|
+
value2 = value2 * 10 + this.pattern.charCodeAt(this.offset++) - 48;
|
|
9116
|
+
if (value2 > 255) throw new EreUnsupportedError("interval counts exceed 255", begin);
|
|
9117
|
+
}
|
|
9118
|
+
if (begin === this.offset) throw new EreSyntaxError("missing interval count", begin);
|
|
9119
|
+
return value2;
|
|
9120
|
+
}
|
|
9121
|
+
async atom(depth) {
|
|
9122
|
+
const begin = this.offset;
|
|
9123
|
+
const character = this.pattern[this.offset++];
|
|
9124
|
+
if (this.quoted?.[begin]) return this.node(() => ({ kind: "literal", code: character.charCodeAt(0), nullable: false, captured: false }));
|
|
9125
|
+
if (character === "(") {
|
|
9126
|
+
if (this.at("?")) throw new EreUnsupportedError("extended group syntax", begin);
|
|
9127
|
+
if (this.groups >= 32) throw new EreUnsupportedError("32-group grammar ceiling", begin);
|
|
9128
|
+
const index = ++this.groups;
|
|
9129
|
+
const child = await this.expression(depth + 1);
|
|
9130
|
+
if (!this.at(")")) throw new EreSyntaxError("unclosed group", begin);
|
|
9131
|
+
this.offset++;
|
|
9132
|
+
return this.node(() => ({ kind: "group", index, child, nullable: child.nullable, captured: true }));
|
|
9133
|
+
}
|
|
9134
|
+
if (character === "[") return this.set(begin);
|
|
9135
|
+
if (character === "\\") {
|
|
9136
|
+
const escaped = this.pattern[this.offset++];
|
|
9137
|
+
if (escaped === void 0) throw new EreSyntaxError("trailing escape", begin);
|
|
9138
|
+
if (!special.includes(escaped)) throw new EreUnsupportedError("backreference or escape extension", begin);
|
|
9139
|
+
return this.node(() => ({ kind: "literal", code: escaped.charCodeAt(0), nullable: false, captured: false }));
|
|
9140
|
+
}
|
|
9141
|
+
if (character === "*" || character === "+" || character === "?" || character === "{") throw new EreSyntaxError("repetition without operand", begin);
|
|
9142
|
+
if (character === ".") return this.node(() => ({ kind: "dot", nullable: false, captured: false }));
|
|
9143
|
+
if (character === "^") return this.node(() => ({ kind: "start", nullable: true, captured: false }));
|
|
9144
|
+
if (character === "$") return this.node(() => ({ kind: "end", nullable: true, captured: false }));
|
|
9145
|
+
return this.node(() => ({ kind: "literal", code: character.charCodeAt(0), nullable: false, captured: false }));
|
|
9146
|
+
}
|
|
9147
|
+
async set(begin) {
|
|
9148
|
+
this.ledger.charge("allocationUnits", 128, this.signal);
|
|
9149
|
+
const members = new Array(128).fill(false);
|
|
9150
|
+
const negate = this.at("^");
|
|
9151
|
+
if (negate) this.offset++;
|
|
9152
|
+
let first = true;
|
|
9153
|
+
while (this.offset < this.pattern.length) {
|
|
9154
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9155
|
+
await this.ledger.checkpoint(this.signal);
|
|
9156
|
+
if (this.at("]") && !first) {
|
|
9157
|
+
this.offset++;
|
|
9158
|
+
if (negate) for (let code = 1; code < 128; code++) {
|
|
9159
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9160
|
+
await this.ledger.checkpoint(this.signal);
|
|
9161
|
+
members[code] = !members[code];
|
|
9162
|
+
}
|
|
9163
|
+
return this.node(() => ({ kind: "set", members: Object.freeze(members), nullable: false, captured: false }));
|
|
9164
|
+
}
|
|
9165
|
+
first = false;
|
|
9166
|
+
if (this.at("[") && (this.at(".", this.offset + 1) || this.at("=", this.offset + 1))) {
|
|
9167
|
+
throw new EreUnsupportedError("collating or equivalence element", this.offset);
|
|
9168
|
+
}
|
|
9169
|
+
if (this.at("[") && this.at(":", this.offset + 1)) {
|
|
9170
|
+
const classBegin = this.offset;
|
|
9171
|
+
this.offset += 2;
|
|
9172
|
+
let name2 = "";
|
|
9173
|
+
while (this.offset < this.pattern.length && !this.at(":")) {
|
|
9174
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9175
|
+
await this.ledger.checkpoint(this.signal);
|
|
9176
|
+
if (name2.length >= 6) throw new EreSyntaxError("unknown character class", classBegin);
|
|
9177
|
+
name2 += this.pattern[this.offset++];
|
|
9178
|
+
}
|
|
9179
|
+
if (!this.at(":") || !this.at("]", this.offset + 1) || !classes.has(name2)) throw new EreSyntaxError("unknown character class", classBegin);
|
|
9180
|
+
this.offset += 2;
|
|
9181
|
+
for (let code = 1; code < 128; code++) {
|
|
9182
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9183
|
+
await this.ledger.checkpoint(this.signal);
|
|
9184
|
+
if (classMember(name2, code)) members[code] = true;
|
|
9185
|
+
}
|
|
9186
|
+
if (this.at("-") && !this.at("]", this.offset + 1)) throw new EreSyntaxError("class cannot be a range endpoint", this.offset);
|
|
9187
|
+
} else {
|
|
9188
|
+
const lower = this.pattern.charCodeAt(this.offset++);
|
|
9189
|
+
if (this.at("-") && !this.at("]", this.offset + 1) && this.pattern[this.offset + 1] !== void 0) {
|
|
9190
|
+
this.offset++;
|
|
9191
|
+
if (this.at("[")) throw new EreSyntaxError("nonliteral range endpoint", this.offset);
|
|
9192
|
+
const upper = this.pattern.charCodeAt(this.offset++);
|
|
9193
|
+
if (lower > upper) throw new EreSyntaxError("descending range", this.offset - 3);
|
|
9194
|
+
for (let code = lower; code <= upper; code++) {
|
|
9195
|
+
this.ledger.charge("work", 1, this.signal);
|
|
9196
|
+
await this.ledger.checkpoint(this.signal);
|
|
9197
|
+
members[code] = true;
|
|
9198
|
+
}
|
|
9199
|
+
} else members[lower] = true;
|
|
9200
|
+
}
|
|
9201
|
+
}
|
|
9202
|
+
throw new EreSyntaxError("unclosed bracket expression", begin);
|
|
9203
|
+
}
|
|
9204
|
+
};
|
|
9205
|
+
async function compileEre(input2, ledger, signal) {
|
|
9206
|
+
ledger.check(signal);
|
|
9207
|
+
const { pattern, quoted } = await flatten(input2, ledger, signal);
|
|
9208
|
+
const parser = new Parser2(pattern, quoted, ledger, signal);
|
|
9209
|
+
const root = await parser.expression(0);
|
|
9210
|
+
if (parser.offset !== pattern.length) throw new EreSyntaxError("unmatched closing group", parser.offset);
|
|
9211
|
+
ledger.charge("allocationUnits", 3, signal);
|
|
9212
|
+
const program = Object.freeze({ pattern, groups: parser.groups });
|
|
9213
|
+
programs.set(program, { root, ledger });
|
|
9214
|
+
return program;
|
|
9215
|
+
}
|
|
9216
|
+
function resolveEreProgram(program, ledger) {
|
|
9217
|
+
const entry = programs.get(program);
|
|
9218
|
+
if (!entry || entry.ledger !== ledger) throw new TypeError("ERE program is not bound to this invocation ledger");
|
|
9219
|
+
return entry.root;
|
|
9220
|
+
}
|
|
9221
|
+
|
|
9222
|
+
// packages/safe-bash/src/commands/regex-execution/ere/matcher.ts
|
|
9223
|
+
init_platform();
|
|
9224
|
+
function spanOrder(left, right) {
|
|
9225
|
+
if (left === null) return right === null ? 0 : -1;
|
|
9226
|
+
if (right === null) return 1;
|
|
9227
|
+
const length = left.end - left.start - (right.end - right.start);
|
|
9228
|
+
return length === 0 ? right.start - left.start : length;
|
|
9229
|
+
}
|
|
9230
|
+
async function historyOrder(left, right, ledger, signal) {
|
|
9231
|
+
const leftCount = left?.count ?? 0;
|
|
9232
|
+
const rightCount = right?.count ?? 0;
|
|
9233
|
+
for (let ordinal = 1; ordinal <= Math.min(leftCount, rightCount); ordinal++) {
|
|
9234
|
+
ledger.charge("work", 1, signal);
|
|
9235
|
+
await ledger.checkpoint(signal);
|
|
9236
|
+
let leftEntry = left;
|
|
9237
|
+
let rightEntry = right;
|
|
9238
|
+
for (let remaining = leftCount; remaining > ordinal; remaining--) {
|
|
9239
|
+
ledger.charge("work", 1, signal);
|
|
9240
|
+
await ledger.checkpoint(signal);
|
|
9241
|
+
leftEntry = leftEntry.previous;
|
|
9242
|
+
}
|
|
9243
|
+
for (let remaining = rightCount; remaining > ordinal; remaining--) {
|
|
9244
|
+
ledger.charge("work", 1, signal);
|
|
9245
|
+
await ledger.checkpoint(signal);
|
|
9246
|
+
rightEntry = rightEntry.previous;
|
|
9247
|
+
}
|
|
9248
|
+
const compared = spanOrder(leftEntry.span, rightEntry.span);
|
|
9249
|
+
if (compared !== 0) return compared;
|
|
9250
|
+
}
|
|
9251
|
+
return leftCount - rightCount;
|
|
9252
|
+
}
|
|
9253
|
+
async function preferred(candidate, incumbent, ledger, signal) {
|
|
9254
|
+
if (candidate.position !== incumbent.position) return candidate.position > incumbent.position;
|
|
9255
|
+
for (let group = 1; group < candidate.captures.length; group++) {
|
|
9256
|
+
ledger.charge("work", 1, signal);
|
|
9257
|
+
const compared = await historyOrder(candidate.histories[group], incumbent.histories[group], ledger, signal);
|
|
9258
|
+
if (compared !== 0) return compared > 0;
|
|
9259
|
+
}
|
|
9260
|
+
return false;
|
|
9261
|
+
}
|
|
9262
|
+
async function resetDescendants(node, previous, ledger, signal) {
|
|
9263
|
+
ledger.charge("allocationUnits", previous.length + 3, signal);
|
|
9264
|
+
const captures = previous.slice();
|
|
9265
|
+
const pending = [node];
|
|
9266
|
+
while (pending.length > 0) {
|
|
9267
|
+
ledger.charge("work", 1, signal);
|
|
9268
|
+
await ledger.checkpoint(signal);
|
|
9269
|
+
const current = pending.pop();
|
|
9270
|
+
if (current.kind === "group") captures[current.index] = null;
|
|
9271
|
+
if (current.kind === "group" || current.kind === "repeat") {
|
|
9272
|
+
if (current.child.captured) {
|
|
9273
|
+
ledger.charge("allocationUnits", 1, signal);
|
|
9274
|
+
pending.push(current.child);
|
|
9275
|
+
}
|
|
9276
|
+
} else if (current.kind === "sequence" || current.kind === "alternative") {
|
|
9277
|
+
for (const child of current.children) {
|
|
9278
|
+
ledger.charge("work", 1, signal);
|
|
9279
|
+
await ledger.checkpoint(signal);
|
|
9280
|
+
if (child.captured) {
|
|
9281
|
+
ledger.charge("allocationUnits", 1, signal);
|
|
9282
|
+
pending.push(child);
|
|
9283
|
+
}
|
|
9284
|
+
}
|
|
9285
|
+
}
|
|
9286
|
+
}
|
|
9287
|
+
return captures;
|
|
9288
|
+
}
|
|
9289
|
+
async function matchEre(program, subject, ledger, signal) {
|
|
9290
|
+
ledger.check(signal);
|
|
9291
|
+
const root = resolveEreProgram(program, ledger);
|
|
9292
|
+
ledger.admitInput("subjectBytes", subject.length, signal);
|
|
9293
|
+
await admitAscii(subject, ledger, signal);
|
|
9294
|
+
const width = program.groups + 1;
|
|
9295
|
+
ledger.charge("allocationUnits", width * 2 + 1, signal);
|
|
9296
|
+
const emptyCaptures = Object.freeze(new Array(width).fill(null));
|
|
9297
|
+
const emptyHistories = Object.freeze(new Array(width).fill(null));
|
|
9298
|
+
const pending = [];
|
|
9299
|
+
const task = (create) => {
|
|
9300
|
+
ledger.charge("allocationUnits", 5, signal);
|
|
9301
|
+
return create();
|
|
9302
|
+
};
|
|
9303
|
+
const push = (position, next, captures, histories) => {
|
|
9304
|
+
ledger.charge("states", 1, signal);
|
|
9305
|
+
ledger.charge("allocationUnits", 5, signal);
|
|
9306
|
+
pending.push({ position, task: next, captures, histories });
|
|
9307
|
+
};
|
|
9308
|
+
for (let start = 0; start <= subject.length; start++) {
|
|
9309
|
+
push(start, task(() => ({ kind: "node", node: root, next: null })), emptyCaptures, emptyHistories);
|
|
9310
|
+
let best;
|
|
9311
|
+
while (pending.length > 0) {
|
|
9312
|
+
ledger.charge("work", 1, signal);
|
|
9313
|
+
await ledger.checkpoint(signal);
|
|
9314
|
+
const state = pending.pop();
|
|
9315
|
+
const current = state.task;
|
|
9316
|
+
if (current === null) {
|
|
9317
|
+
if (!best || await preferred(state, best, ledger, signal)) best = state;
|
|
9318
|
+
continue;
|
|
9319
|
+
}
|
|
9320
|
+
if (current.kind === "close") {
|
|
9321
|
+
ledger.charge("allocationUnits", width * 2 + 6, signal);
|
|
9322
|
+
const span = Object.freeze({ start: current.start, end: state.position });
|
|
9323
|
+
const captures = state.captures.slice();
|
|
9324
|
+
captures[current.group] = span;
|
|
9325
|
+
const histories = state.histories.slice();
|
|
9326
|
+
const previous = histories[current.group];
|
|
9327
|
+
histories[current.group] = { span, previous, count: (previous?.count ?? 0) + 1 };
|
|
9328
|
+
push(state.position, current.next, captures, histories);
|
|
9329
|
+
continue;
|
|
9330
|
+
}
|
|
9331
|
+
if (current.kind === "repeat") {
|
|
9332
|
+
const { node: node2, count } = current;
|
|
9333
|
+
if (count >= node2.min) push(state.position, current.next, state.captures, state.histories);
|
|
9334
|
+
const noProgress = count > 0 && state.position === current.previous;
|
|
9335
|
+
if (count < node2.max && (!noProgress || count < node2.min)) {
|
|
9336
|
+
const repeat = task(() => ({ kind: "repeat", node: node2, count: count + 1, previous: state.position, next: current.next }));
|
|
9337
|
+
push(state.position, task(() => ({ kind: "node", node: node2.child, next: repeat })), state.captures, state.histories);
|
|
9338
|
+
}
|
|
9339
|
+
continue;
|
|
9340
|
+
}
|
|
9341
|
+
const node = current.node;
|
|
9342
|
+
switch (node.kind) {
|
|
9343
|
+
case "empty":
|
|
9344
|
+
push(state.position, current.next, state.captures, state.histories);
|
|
9345
|
+
break;
|
|
9346
|
+
case "start":
|
|
9347
|
+
if (state.position === 0) push(state.position, current.next, state.captures, state.histories);
|
|
9348
|
+
break;
|
|
9349
|
+
case "end":
|
|
9350
|
+
if (state.position === subject.length) push(state.position, current.next, state.captures, state.histories);
|
|
9351
|
+
break;
|
|
9352
|
+
case "dot":
|
|
9353
|
+
case "literal":
|
|
9354
|
+
case "set": {
|
|
9355
|
+
const code = subject.charCodeAt(state.position);
|
|
9356
|
+
if (state.position < subject.length && (node.kind === "dot" || node.kind === "literal" && node.code === code || node.kind === "set" && node.members[code])) {
|
|
9357
|
+
push(state.position + 1, current.next, state.captures, state.histories);
|
|
9358
|
+
}
|
|
9359
|
+
break;
|
|
9360
|
+
}
|
|
9361
|
+
case "sequence": {
|
|
9362
|
+
let next = current.next;
|
|
9363
|
+
for (let index = node.children.length - 1; index >= 0; index--) {
|
|
9364
|
+
ledger.charge("work", 1, signal);
|
|
9365
|
+
await ledger.checkpoint(signal);
|
|
9366
|
+
const following = next;
|
|
9367
|
+
next = task(() => ({ kind: "node", node: node.children[index], next: following }));
|
|
9368
|
+
}
|
|
9369
|
+
push(state.position, next, state.captures, state.histories);
|
|
9370
|
+
break;
|
|
9371
|
+
}
|
|
9372
|
+
case "alternative":
|
|
9373
|
+
for (let index = node.children.length - 1; index >= 0; index--) {
|
|
9374
|
+
ledger.charge("work", 1, signal);
|
|
9375
|
+
await ledger.checkpoint(signal);
|
|
9376
|
+
push(state.position, task(() => ({ kind: "node", node: node.children[index], next: current.next })), state.captures, state.histories);
|
|
9377
|
+
}
|
|
9378
|
+
break;
|
|
9379
|
+
case "group": {
|
|
9380
|
+
const captures = node.child.captured ? await resetDescendants(node.child, state.captures, ledger, signal) : state.captures;
|
|
9381
|
+
const close = task(() => ({ kind: "close", group: node.index, start: state.position, next: current.next }));
|
|
9382
|
+
push(state.position, task(() => ({ kind: "node", node: node.child, next: close })), captures, state.histories);
|
|
9383
|
+
break;
|
|
9384
|
+
}
|
|
9385
|
+
case "repeat":
|
|
9386
|
+
push(state.position, task(() => ({ kind: "repeat", node, count: 0, previous: -1, next: current.next })), state.captures, state.histories);
|
|
9387
|
+
break;
|
|
9388
|
+
}
|
|
9389
|
+
}
|
|
9390
|
+
if (best) {
|
|
9391
|
+
ledger.charge("captureSlots", width, signal);
|
|
9392
|
+
let bytes = best.position - start;
|
|
9393
|
+
for (let group = 1; group < width; group++) {
|
|
9394
|
+
ledger.charge("work", 1, signal);
|
|
9395
|
+
const span = best.captures[group];
|
|
9396
|
+
if (span) bytes += span.end - span.start;
|
|
9397
|
+
}
|
|
9398
|
+
ledger.charge("captureBytes", bytes, signal);
|
|
9399
|
+
ledger.charge("allocationUnits", width * 2 + bytes + 4, signal);
|
|
9400
|
+
const captures = best.captures.slice();
|
|
9401
|
+
captures[0] = Object.freeze({ start, end: best.position });
|
|
9402
|
+
const values = captures.map((span) => span === null ? "" : subject.slice(span.start, span.end));
|
|
9403
|
+
ledger.check(signal);
|
|
9404
|
+
return Object.freeze({ matched: true, captures: Object.freeze(captures), values: Object.freeze(values) });
|
|
9405
|
+
}
|
|
9406
|
+
}
|
|
9407
|
+
ledger.charge("allocationUnits", 3, signal);
|
|
9408
|
+
ledger.check(signal);
|
|
9409
|
+
return Object.freeze({ matched: false, captures: Object.freeze([]), values: Object.freeze([]) });
|
|
9410
|
+
}
|
|
8828
9411
|
|
|
8829
9412
|
// packages/safe-bash/src/shell/runtime.ts
|
|
8830
9413
|
var defaultLimits = {
|
|
@@ -8836,6 +9419,8 @@ var defaultLimits = {
|
|
|
8836
9419
|
maxSourceBytes: 1024 * 1024,
|
|
8837
9420
|
maxExpansionFields: 1e4,
|
|
8838
9421
|
maxExpansionBytes: 16 * 1024 * 1024,
|
|
9422
|
+
maxWallClockMs: 3e4,
|
|
9423
|
+
maxCpuMs: 3e4,
|
|
8839
9424
|
pipeHighWaterMark: 64 * 1024
|
|
8840
9425
|
};
|
|
8841
9426
|
var shellBuiltinNames = /* @__PURE__ */ new Set([
|
|
@@ -8915,6 +9500,8 @@ var Budget = class {
|
|
|
8915
9500
|
this.limits = limits;
|
|
8916
9501
|
this.signal = signal ? AbortSignal.any([signal, this.controller.signal]) : this.controller.signal;
|
|
8917
9502
|
this.values = new ValueArena(limits.maxExpansionBytes, limits.maxExpansionFields, () => this.signal.throwIfAborted(), (limit) => this.fail(limit));
|
|
9503
|
+
this.#wallClockDeadline = Date.now() + limits.maxWallClockMs;
|
|
9504
|
+
this.#armWallClock();
|
|
8918
9505
|
}
|
|
8919
9506
|
limits;
|
|
8920
9507
|
values;
|
|
@@ -8924,12 +9511,34 @@ var Budget = class {
|
|
|
8924
9511
|
sourceBytes = 0;
|
|
8925
9512
|
controller = new AbortController();
|
|
8926
9513
|
signal;
|
|
9514
|
+
#wallClockTimer;
|
|
9515
|
+
#wallClockDeadline = 0;
|
|
9516
|
+
#cpuStarted = monotonicNow();
|
|
9517
|
+
#armWallClock() {
|
|
9518
|
+
const remaining = this.#wallClockDeadline - Date.now();
|
|
9519
|
+
if (remaining <= 0) {
|
|
9520
|
+
this.controller.abort(new ShellLimitError("maxWallClockMs"));
|
|
9521
|
+
return;
|
|
9522
|
+
}
|
|
9523
|
+
this.#wallClockTimer = setTimeout(() => this.#armWallClock(), Math.min(remaining, 2147483647));
|
|
9524
|
+
const timer = this.#wallClockTimer;
|
|
9525
|
+
timer.unref?.();
|
|
9526
|
+
}
|
|
9527
|
+
close() {
|
|
9528
|
+
if (this.#wallClockTimer !== void 0) clearTimeout(this.#wallClockTimer);
|
|
9529
|
+
this.#wallClockTimer = void 0;
|
|
9530
|
+
}
|
|
8927
9531
|
fail(limit) {
|
|
8928
9532
|
const error = new ShellLimitError(limit);
|
|
8929
9533
|
this.controller.abort(error);
|
|
8930
9534
|
throw error;
|
|
8931
9535
|
}
|
|
9536
|
+
cpuCheckpoint() {
|
|
9537
|
+
this.signal.throwIfAborted();
|
|
9538
|
+
if (monotonicNow() - this.#cpuStarted > this.limits.maxCpuMs) this.fail("maxCpuMs");
|
|
9539
|
+
}
|
|
8932
9540
|
tick() {
|
|
9541
|
+
this.cpuCheckpoint();
|
|
8933
9542
|
this.signal.throwIfAborted();
|
|
8934
9543
|
if (++this.commands > this.limits.maxCommands) this.fail("maxCommands");
|
|
8935
9544
|
}
|
|
@@ -9328,7 +9937,7 @@ var CdLookup = class {
|
|
|
9328
9937
|
amount -= step;
|
|
9329
9938
|
if (this.spent % 128 === 0) {
|
|
9330
9939
|
this.signal.throwIfAborted();
|
|
9331
|
-
await
|
|
9940
|
+
await yieldTurn(this.signal);
|
|
9332
9941
|
this.signal.throwIfAborted();
|
|
9333
9942
|
}
|
|
9334
9943
|
}
|
|
@@ -9424,7 +10033,7 @@ var DirectoryStackWork = class {
|
|
|
9424
10033
|
async flushWork() {
|
|
9425
10034
|
this.signal.throwIfAborted();
|
|
9426
10035
|
if (this.flushed === this.spent) return;
|
|
9427
|
-
await
|
|
10036
|
+
await yieldTurn(this.signal);
|
|
9428
10037
|
this.signal.throwIfAborted();
|
|
9429
10038
|
this.flushed = this.spent;
|
|
9430
10039
|
}
|
|
@@ -9745,6 +10354,7 @@ var Runtime = class _Runtime {
|
|
|
9745
10354
|
this.cancellationDepth = cancellationDepth;
|
|
9746
10355
|
this.cancellationMaxDepth = cancellationMaxDepth;
|
|
9747
10356
|
this.outcomeFrame = outcomeFrame;
|
|
10357
|
+
registerYieldCheckpoint(this.signal, () => this.budget.cpuCheckpoint());
|
|
9748
10358
|
}
|
|
9749
10359
|
fs;
|
|
9750
10360
|
commands;
|
|
@@ -9760,19 +10370,6 @@ var Runtime = class _Runtime {
|
|
|
9760
10370
|
cancellationDepth;
|
|
9761
10371
|
cancellationMaxDepth;
|
|
9762
10372
|
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
10373
|
async ereDiagnostic(io, detail) {
|
|
9777
10374
|
try {
|
|
9778
10375
|
await this.diagnostic(io, detail);
|
|
@@ -9821,32 +10418,21 @@ var Runtime = class _Runtime {
|
|
|
9821
10418
|
await textToken(operation, subject, this.signal);
|
|
9822
10419
|
const name2 = "BASH_REMATCH";
|
|
9823
10420
|
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;
|
|
10421
|
+
const ledger = new EreLedger({
|
|
10422
|
+
maxExpansionBytes: this.budget.limits.maxExpansionBytes,
|
|
10423
|
+
maxExpansionFields: this.budget.limits.maxExpansionFields
|
|
9830
10424
|
});
|
|
9831
|
-
const session = entry.root.openSession((cleanup) => scope.register(cleanup));
|
|
9832
10425
|
let result;
|
|
9833
|
-
let sessionEscaping = false;
|
|
9834
10426
|
try {
|
|
9835
|
-
|
|
10427
|
+
const program = await compileEre(fragments, ledger, this.signal);
|
|
10428
|
+
result = await matchEre(program, subject, ledger, this.signal);
|
|
9836
10429
|
} catch (error) {
|
|
9837
|
-
sessionEscaping = true;
|
|
9838
10430
|
this.signal.throwIfAborted();
|
|
9839
|
-
if (error instanceof
|
|
10431
|
+
if (error instanceof EreSyntaxError || error instanceof EreUnsupportedError) {
|
|
9840
10432
|
await this.ereDiagnostic(io, `[[ ${error.message}`);
|
|
9841
|
-
sessionEscaping = false;
|
|
9842
10433
|
return 2;
|
|
9843
10434
|
}
|
|
9844
10435
|
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
10436
|
}
|
|
9851
10437
|
const status = result.matched ? 0 : 1;
|
|
9852
10438
|
this.signal.throwIfAborted();
|
|
@@ -9861,8 +10447,8 @@ var Runtime = class _Runtime {
|
|
|
9861
10447
|
const tickets = operation.reserve({ generation: true, version: true, epoch: true, work: 8 });
|
|
9862
10448
|
const prepared = await store.prepareName(name2, operation, this.signal);
|
|
9863
10449
|
staged = IndexedBinding.create(store.owner);
|
|
9864
|
-
if (result.matched) for (let index = 0; index < result.
|
|
9865
|
-
const span = result.
|
|
10450
|
+
if (result.matched) for (let index = 0; index < result.captures.length; index++) {
|
|
10451
|
+
const span = result.captures[index];
|
|
9866
10452
|
const size = span === null ? 0 : span.end - span.start;
|
|
9867
10453
|
operation.reserve({ payload: size, metadata: 32, work: size + 2 });
|
|
9868
10454
|
const value2 = span === null ? "" : subject.slice(span.start, span.end);
|
|
@@ -10024,6 +10610,7 @@ var Runtime = class _Runtime {
|
|
|
10024
10610
|
writeVariable(state, name2, value2, origin = "assignment") {
|
|
10025
10611
|
if (arrayStore(state)?.get(name2)) throw new ArrayFailure(origin === "arithmetic" ? "indexed arithmetic is unsupported" : "indexed write requires prepared publication");
|
|
10026
10612
|
if (state.readonlyVariables?.has(name2)) throw new Error(`${name2}: readonly variable`);
|
|
10613
|
+
if (shellValueByteLength(value2) > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
10027
10614
|
if (name2 === "OPTIND" && state.getopts?.integer && origin !== "arithmetic") {
|
|
10028
10615
|
try {
|
|
10029
10616
|
value2 = String(evaluateArithmetic(prepareArithmetic(shellValueText(value2) || "0"), this.arithmeticVariables(state)));
|
|
@@ -10533,7 +11120,7 @@ var Runtime = class _Runtime {
|
|
|
10533
11120
|
completed.add(index);
|
|
10534
11121
|
if (incoming) {
|
|
10535
11122
|
const upstream = index - 1;
|
|
10536
|
-
const close =
|
|
11123
|
+
const close = scheduleTurn(() => {
|
|
10537
11124
|
closing.delete(close);
|
|
10538
11125
|
if (written.has(upstream) && !completed.has(upstream)) controllers[upstream].abort(new PipelineClosed());
|
|
10539
11126
|
});
|
|
@@ -10560,7 +11147,7 @@ var Runtime = class _Runtime {
|
|
|
10560
11147
|
try {
|
|
10561
11148
|
statuses = await interruptible(Promise.all(tasks), this.signal);
|
|
10562
11149
|
} finally {
|
|
10563
|
-
for (const close of closing)
|
|
11150
|
+
for (const close of closing) cancelTurn(close);
|
|
10564
11151
|
for (const [index, controller] of controllers.entries()) if (!completed.has(index) || written.has(index)) controller.abort(new PipelineClosed());
|
|
10565
11152
|
await Promise.all(pipes.map((pipe) => pipe.abort()));
|
|
10566
11153
|
}
|
|
@@ -10625,7 +11212,7 @@ var Runtime = class _Runtime {
|
|
|
10625
11212
|
originalIO = { ...originalIO, diagnosticLine, substitutionDiagnosticLine: originalIO.substitutionDiagnosticLines?.get(command) ?? diagnosticLine };
|
|
10626
11213
|
if (command.kind === "subshell") originalIO = isolateIO(originalIO);
|
|
10627
11214
|
this.budget.tick();
|
|
10628
|
-
if (this.budget.commands % 128 === 0) await
|
|
11215
|
+
if (this.budget.commands % 128 === 0) await yieldTurn(this.signal);
|
|
10629
11216
|
this.signal.throwIfAborted();
|
|
10630
11217
|
const inputs = /* @__PURE__ */ new Set();
|
|
10631
11218
|
const outputs = /* @__PURE__ */ new Set();
|
|
@@ -10672,7 +11259,7 @@ var Runtime = class _Runtime {
|
|
|
10672
11259
|
diagnosticFailure = error;
|
|
10673
11260
|
throw error;
|
|
10674
11261
|
}
|
|
10675
|
-
if (error instanceof EreProfileLimitError
|
|
11262
|
+
if (error instanceof EreProfileLimitError) {
|
|
10676
11263
|
try {
|
|
10677
11264
|
await this.diagnostic(io, `[[ ${error.message}`);
|
|
10678
11265
|
} catch (reason) {
|
|
@@ -10741,7 +11328,7 @@ var Runtime = class _Runtime {
|
|
|
10741
11328
|
for (const clause of command.clauses) {
|
|
10742
11329
|
let matched = fallthrough;
|
|
10743
11330
|
if (!matched) for (const word of clause.patterns) {
|
|
10744
|
-
if (++patterns % 128 === 0) await
|
|
11331
|
+
if (++patterns % 128 === 0) await yieldTurn(this.signal);
|
|
10745
11332
|
const pattern = (await this.word(word, state, io, false, true)).join("");
|
|
10746
11333
|
if (await matchesPattern(pattern, subject, work)) {
|
|
10747
11334
|
matched = true;
|
|
@@ -10862,7 +11449,7 @@ var Runtime = class _Runtime {
|
|
|
10862
11449
|
this.signal.throwIfAborted();
|
|
10863
11450
|
for (const warning of warnings.splice(0)) await writeText(io.stderr, `shell: warning: ${warning}
|
|
10864
11451
|
`);
|
|
10865
|
-
if (++words % 128 === 0) await
|
|
11452
|
+
if (++words % 128 === 0) await yieldTurn(this.signal);
|
|
10866
11453
|
const part = (await this.word(word, state, io, false)).join("");
|
|
10867
11454
|
size += import_buffer.Buffer.byteLength(part);
|
|
10868
11455
|
if (size > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
@@ -11056,7 +11643,7 @@ var Runtime = class _Runtime {
|
|
|
11056
11643
|
}
|
|
11057
11644
|
const wordValues = await this.valueWords(commandWords, state, originalIO, ["export", "local", "readonly"].includes(commandWords[declarationIndex]?.plain ?? ""));
|
|
11058
11645
|
const words = wordValues.map(shellValueText);
|
|
11059
|
-
const
|
|
11646
|
+
const special2 = state.profile === "sh" && specialBuiltinNames.has(words[0] ?? "");
|
|
11060
11647
|
const inlineInput = command.redirects.some((redirect) => redirect.document || redirect.operator === "<<<");
|
|
11061
11648
|
const functionCommand = words.length > 0 && state.functions.has(words[0]);
|
|
11062
11649
|
const isolatedInlineInput = inlineInput && words.length > 0 && !shellBuiltinNames.has(words[0]) && !functionCommand;
|
|
@@ -11084,7 +11671,7 @@ var Runtime = class _Runtime {
|
|
|
11084
11671
|
if (assignment.append) value2 = concatShellValues([stateMonitor(state)?.values.get(assignment.name, state.variables[assignment.name] ?? "") ?? state.variables[assignment.name] ?? "", value2], io[valueScope]);
|
|
11085
11672
|
if (state.readonlyVariables?.has(assignment.name)) {
|
|
11086
11673
|
await this.diagnostic(io, `${assignment.name}: readonly variable`);
|
|
11087
|
-
if (state.profile === "sh" || !words.length) throw new Flow("exit", state.profile === "sh" && (
|
|
11674
|
+
if (state.profile === "sh" || !words.length) throw new Flow("exit", state.profile === "sh" && (special2 || !words.length) ? 127 : 1);
|
|
11088
11675
|
continue;
|
|
11089
11676
|
}
|
|
11090
11677
|
if (!previous.has(assignment.name)) {
|
|
@@ -11175,7 +11762,7 @@ var Runtime = class _Runtime {
|
|
|
11175
11762
|
if (error instanceof Flow) throw error;
|
|
11176
11763
|
this.signal.throwIfAborted();
|
|
11177
11764
|
const original = error instanceof ExecutionFailure ? error.original : error;
|
|
11178
|
-
if (
|
|
11765
|
+
if (special2 && !(original instanceof ShellLimitError) && !(original instanceof ExpansionFailure) && !(original instanceof Flow) && !(original instanceof ShellSyntaxError)) {
|
|
11179
11766
|
throw new ExecutionFailure(new FatalCommandFailure(message(original), 1), error instanceof ExecutionFailure ? error.io : io, error instanceof ExecutionFailure ? error.diagnostic : void 0);
|
|
11180
11767
|
}
|
|
11181
11768
|
if (error instanceof ExecutionFailure) throw error;
|
|
@@ -11415,16 +12002,16 @@ var Runtime = class _Runtime {
|
|
|
11415
12002
|
}
|
|
11416
12003
|
if (selected?.kind === "builtin") {
|
|
11417
12004
|
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 },
|
|
12005
|
+
const special2 = state.profile === "sh" && !bypassFunctions && specialBuiltinNames.has(context2.command);
|
|
12006
|
+
if (special2) assignments2.clear();
|
|
12007
|
+
if (context2.command === "." || context2.command === "source") return { exitCode: await this.sourceBuiltin(context2, state, { ...io, ...context2 }, special2) };
|
|
12008
|
+
if (context2.command === "eval") return { exitCode: await this.evalBuiltin(context2, state, { ...io, ...context2 }, special2) };
|
|
11422
12009
|
const builtinWork = this.builtin(context2, state, assignments2, (error, diagnostic2) => {
|
|
11423
12010
|
builtinFailure = { error, diagnostic: diagnostic2 };
|
|
11424
12011
|
}, bypassFunctions);
|
|
11425
12012
|
const builtin = arrayStore(state) ? await interruptible(builtinWork, this.signal) : await builtinWork;
|
|
11426
12013
|
if (builtin !== void 0) {
|
|
11427
|
-
if (
|
|
12014
|
+
if (special2 && builtin !== 0 && context2.command !== "shift") throw new Flow("exit", builtin);
|
|
11428
12015
|
return { exitCode: builtin };
|
|
11429
12016
|
}
|
|
11430
12017
|
}
|
|
@@ -11736,7 +12323,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
11736
12323
|
let status = 0;
|
|
11737
12324
|
let lines2 = 0;
|
|
11738
12325
|
while (true) {
|
|
11739
|
-
if (++lines2 % 32 === 0) await
|
|
12326
|
+
if (++lines2 % 32 === 0) await yieldTurn(this.signal);
|
|
11740
12327
|
this.signal.throwIfAborted();
|
|
11741
12328
|
const bytes = await input2.sourceLine();
|
|
11742
12329
|
const eof = bytes === void 0;
|
|
@@ -12056,13 +12643,13 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12056
12643
|
return status2;
|
|
12057
12644
|
}
|
|
12058
12645
|
}
|
|
12059
|
-
async evalBuiltin(context, state, io,
|
|
12646
|
+
async evalBuiltin(context, state, io, special2) {
|
|
12060
12647
|
const args = [...context.args];
|
|
12061
12648
|
if (args[0] === "--") args.shift();
|
|
12062
12649
|
else if (args[0]?.startsWith("-") && args[0] !== "-") {
|
|
12063
12650
|
await this.diagnostic(io, `eval: -${args[0][1]}: invalid option`);
|
|
12064
12651
|
await writeText(io.stderr, "eval: usage: eval [arg ...]\n");
|
|
12065
|
-
if (
|
|
12652
|
+
if (special2) throw new Flow("exit", 2);
|
|
12066
12653
|
return 2;
|
|
12067
12654
|
}
|
|
12068
12655
|
if (!args.length) return 0;
|
|
@@ -12078,7 +12665,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12078
12665
|
throw error;
|
|
12079
12666
|
}
|
|
12080
12667
|
try {
|
|
12081
|
-
return await this.runCurrentText(source, state, { ...io, diagnosticOffset: (io.diagnosticLine ?? 1) - 1 },
|
|
12668
|
+
return await this.runCurrentText(source, state, { ...io, diagnosticOffset: (io.diagnosticLine ?? 1) - 1 }, special2, `${io.scriptName ?? "shell"}: eval`);
|
|
12082
12669
|
} finally {
|
|
12083
12670
|
const restore = () => {
|
|
12084
12671
|
state.depth--;
|
|
@@ -12087,12 +12674,12 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12087
12674
|
else restore();
|
|
12088
12675
|
}
|
|
12089
12676
|
}
|
|
12090
|
-
async sourceBuiltin(context, state, io,
|
|
12677
|
+
async sourceBuiltin(context, state, io, special2) {
|
|
12091
12678
|
const args = [...context.args];
|
|
12092
12679
|
if (args[0] === "--") args.shift();
|
|
12093
12680
|
else if (args[0]?.startsWith("-") && args[0] !== "-") {
|
|
12094
12681
|
await this.diagnostic(io, `${context.command}: ${args[0]}: unsupported option`);
|
|
12095
|
-
if (
|
|
12682
|
+
if (special2) throw new Flow("exit", 2);
|
|
12096
12683
|
return 2;
|
|
12097
12684
|
}
|
|
12098
12685
|
const filename = args.shift();
|
|
@@ -12100,7 +12687,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12100
12687
|
await this.diagnostic(io, `${context.command}: filename argument required`);
|
|
12101
12688
|
await writeText(io.stderr, `${context.command}: usage: ${context.command} [-p path] filename [arguments]
|
|
12102
12689
|
`);
|
|
12103
|
-
if (
|
|
12690
|
+
if (special2) throw new Flow("exit", 2);
|
|
12104
12691
|
return 2;
|
|
12105
12692
|
}
|
|
12106
12693
|
if (state.depth >= this.budget.limits.maxSubstitutionDepth) this.budget.fail("maxSubstitutionDepth");
|
|
@@ -12146,7 +12733,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12146
12733
|
if (error instanceof ShellLimitError) throw error;
|
|
12147
12734
|
if (errorCode(error) === "EFBIG") this.budget.fail("maxSourceBytes");
|
|
12148
12735
|
const diagnostic2 = error instanceof CommandFailure ? error.message : filesystemDiagnostic(error, target) ?? `${target}: ${message(error)}`;
|
|
12149
|
-
if (
|
|
12736
|
+
if (special2) throw new FatalCommandFailure(diagnostic2, 1);
|
|
12150
12737
|
throw new CommandFailure(diagnostic2, error instanceof CommandFailure ? error.status : 1);
|
|
12151
12738
|
}
|
|
12152
12739
|
const positional = state.positional;
|
|
@@ -12175,7 +12762,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12175
12762
|
throw error;
|
|
12176
12763
|
}
|
|
12177
12764
|
try {
|
|
12178
|
-
return await this.runCurrentText(source, state, { ...io, scriptName: target, diagnosticOffset: 0, diagnosticLine: 1 },
|
|
12765
|
+
return await this.runCurrentText(source, state, { ...io, scriptName: target, diagnosticOffset: 0, diagnosticLine: 1 }, special2);
|
|
12179
12766
|
} catch (error) {
|
|
12180
12767
|
if (error instanceof Flow && error.kind === "return") return error.status;
|
|
12181
12768
|
throw error;
|
|
@@ -12317,7 +12904,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12317
12904
|
};
|
|
12318
12905
|
const checkpoint = async () => {
|
|
12319
12906
|
this.signal.throwIfAborted();
|
|
12320
|
-
await
|
|
12907
|
+
await yieldTurn(this.signal);
|
|
12321
12908
|
this.signal.throwIfAborted();
|
|
12322
12909
|
};
|
|
12323
12910
|
const { args } = context;
|
|
@@ -12362,7 +12949,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
12362
12949
|
};
|
|
12363
12950
|
const checkpoint = async () => {
|
|
12364
12951
|
this.signal.throwIfAborted();
|
|
12365
|
-
await
|
|
12952
|
+
await yieldTurn(this.signal);
|
|
12366
12953
|
this.signal.throwIfAborted();
|
|
12367
12954
|
};
|
|
12368
12955
|
if (!Array.isArray(context.args)) throw new CommandFailure("getopts: argument array required", 2);
|
|
@@ -13395,7 +13982,7 @@ ${prefix2} line ${offset + line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
13395
13982
|
const match = async (start, end) => {
|
|
13396
13983
|
work.remaining -= end - start + 1;
|
|
13397
13984
|
if (work.remaining < 0) work.exhausted();
|
|
13398
|
-
if (++attempts % 256 === 0) await
|
|
13985
|
+
if (++attempts % 256 === 0) await yieldTurn(this.signal);
|
|
13399
13986
|
this.signal.throwIfAborted();
|
|
13400
13987
|
if (owner) await owner.ledger.checkpoint(this.signal, end - start + 1);
|
|
13401
13988
|
return matches(slice(start, end));
|
|
@@ -13904,7 +14491,7 @@ var ShellInput = class _ShellInput {
|
|
|
13904
14491
|
let length = 0;
|
|
13905
14492
|
let pulls = 0;
|
|
13906
14493
|
while (true) {
|
|
13907
|
-
if (++pulls % 128 === 0) await
|
|
14494
|
+
if (++pulls % 128 === 0) await yieldTurn(this.signal);
|
|
13908
14495
|
const result = await this.#cursor.take(this.signal);
|
|
13909
14496
|
if (result.done) {
|
|
13910
14497
|
if (!length) return void 0;
|
|
@@ -13946,7 +14533,7 @@ var ShellInput = class _ShellInput {
|
|
|
13946
14533
|
try {
|
|
13947
14534
|
while (!terminated) {
|
|
13948
14535
|
if (offset === chunk.length) {
|
|
13949
|
-
if (++pulls % 128 === 0) await
|
|
14536
|
+
if (++pulls % 128 === 0) await yieldTurn(this.signal);
|
|
13950
14537
|
const result = await this.#cursor.take(this.signal);
|
|
13951
14538
|
if (result.done) {
|
|
13952
14539
|
break;
|
|
@@ -13962,7 +14549,7 @@ var ShellInput = class _ShellInput {
|
|
|
13962
14549
|
}
|
|
13963
14550
|
if (++length > this.budget.limits.maxOutputBytes) this.budget.fail("maxOutputBytes");
|
|
13964
14551
|
if (length % 1024 === 0) {
|
|
13965
|
-
await
|
|
14552
|
+
await yieldTurn(this.signal);
|
|
13966
14553
|
this.signal.throwIfAborted();
|
|
13967
14554
|
}
|
|
13968
14555
|
if (byte === 0) continue;
|
|
@@ -14155,6 +14742,7 @@ var Shell = class {
|
|
|
14155
14742
|
#active = /* @__PURE__ */ new Set();
|
|
14156
14743
|
constructor(options2) {
|
|
14157
14744
|
if (!options2?.fs) throw new TypeError("Shell requires an explicit filesystem");
|
|
14745
|
+
warnIfHostProcessEnv(options2.env);
|
|
14158
14746
|
resolveLimits(options2.limits);
|
|
14159
14747
|
this.#options = { ...options2, cwd: resolvePath("/", options2.cwd ?? "/"), env: { ...options2.env }, limits: { ...options2.limits } };
|
|
14160
14748
|
this.commands = options2.commands ?? new CommandRegistry();
|
|
@@ -14217,6 +14805,7 @@ var Shell = class {
|
|
|
14217
14805
|
}
|
|
14218
14806
|
async exec(source, options2 = {}) {
|
|
14219
14807
|
if (this.#disposed) throw new Error("Shell is disposed");
|
|
14808
|
+
warnIfHostProcessEnv(options2.env);
|
|
14220
14809
|
const budget = new Budget(resolveLimits(this.#options.limits, options2.limits), options2.signal);
|
|
14221
14810
|
const scope = new InvocationScope(options2.signal);
|
|
14222
14811
|
const cancellationState = new RuntimeCancellationState();
|
|
@@ -14227,7 +14816,6 @@ var Shell = class {
|
|
|
14227
14816
|
controls: [{ role: "budget-control", signal: budget.controller.signal }]
|
|
14228
14817
|
});
|
|
14229
14818
|
try {
|
|
14230
|
-
Runtime.registerEreRoot(budget, scope);
|
|
14231
14819
|
owner.activate(boundary);
|
|
14232
14820
|
} catch (error) {
|
|
14233
14821
|
scope.failures.push(...boundary.close().failures);
|
|
@@ -14241,6 +14829,7 @@ var Shell = class {
|
|
|
14241
14829
|
try {
|
|
14242
14830
|
captured = await owner.capture(() => this.#execute(source, options2, scope, budget, boundary, cancellationState, owner));
|
|
14243
14831
|
} finally {
|
|
14832
|
+
budget.close();
|
|
14244
14833
|
await scope.close();
|
|
14245
14834
|
}
|
|
14246
14835
|
const selection = owner.finish(captured);
|
|
@@ -14413,6 +15002,22 @@ shell: -c: line ${line}: \`${source.split("\n")[line - 1] ?? ""}'
|
|
|
14413
15002
|
}
|
|
14414
15003
|
};
|
|
14415
15004
|
|
|
15005
|
+
// packages/safe-bash/src/shell/worker-limits.ts
|
|
15006
|
+
init_platform();
|
|
15007
|
+
var cloudflareWorkerLimits = Object.freeze({
|
|
15008
|
+
maxInputBytes: 4 * 1024 * 1024,
|
|
15009
|
+
maxOutputBytes: 4 * 1024 * 1024,
|
|
15010
|
+
maxCommands: 1e3,
|
|
15011
|
+
maxLoopIterations: 1e3,
|
|
15012
|
+
maxSubstitutionDepth: 16,
|
|
15013
|
+
maxSourceBytes: 256 * 1024,
|
|
15014
|
+
maxExpansionFields: 1e3,
|
|
15015
|
+
maxExpansionBytes: 4 * 1024 * 1024,
|
|
15016
|
+
maxWallClockMs: 1e4,
|
|
15017
|
+
maxCpuMs: 1e4,
|
|
15018
|
+
pipeHighWaterMark: 16 * 1024
|
|
15019
|
+
});
|
|
15020
|
+
|
|
14416
15021
|
// packages/safe-bash/src/fs/memory/index.ts
|
|
14417
15022
|
init_platform();
|
|
14418
15023
|
import { createMemoryFileSystem, MemoryFileSystem } from "@poe-platform/safe-fs/core";
|
|
@@ -14429,6 +15034,153 @@ import { createMountFileSystem, MountFileSystem } from "@poe-platform/safe-fs/co
|
|
|
14429
15034
|
init_platform();
|
|
14430
15035
|
import { createOverlayFileSystem, OverlayFileSystem } from "@poe-platform/safe-fs/core";
|
|
14431
15036
|
|
|
15037
|
+
// packages/safe-bash/src/commands/network/fetch-transport.ts
|
|
15038
|
+
init_platform();
|
|
15039
|
+
|
|
15040
|
+
// packages/safe-bash/src/commands/network/types.ts
|
|
15041
|
+
init_platform();
|
|
15042
|
+
var defaultNetworkLimits = Object.freeze({
|
|
15043
|
+
maxUploadBytes: 64 * 1024 * 1024,
|
|
15044
|
+
maxDownloadBytes: 64 * 1024 * 1024,
|
|
15045
|
+
maxBufferBytes: 8 * 1024 * 1024,
|
|
15046
|
+
maxHeaderBytes: 64 * 1024,
|
|
15047
|
+
maxRedirects: 10,
|
|
15048
|
+
maxRetries: 5,
|
|
15049
|
+
maxUrls: 32,
|
|
15050
|
+
maxTimeMs: 12e4
|
|
15051
|
+
});
|
|
15052
|
+
var cloudflareWorkerNetworkLimits = Object.freeze({
|
|
15053
|
+
maxUploadBytes: 4 * 1024 * 1024,
|
|
15054
|
+
maxDownloadBytes: 4 * 1024 * 1024,
|
|
15055
|
+
maxBufferBytes: 1024 * 1024,
|
|
15056
|
+
maxHeaderBytes: 32 * 1024,
|
|
15057
|
+
maxRedirects: 2,
|
|
15058
|
+
maxRetries: 1,
|
|
15059
|
+
maxUrls: 8,
|
|
15060
|
+
maxTimeMs: 1e4
|
|
15061
|
+
});
|
|
15062
|
+
var CurlError = class extends Error {
|
|
15063
|
+
constructor(exitCode, message2) {
|
|
15064
|
+
super(message2);
|
|
15065
|
+
this.exitCode = exitCode;
|
|
15066
|
+
this.name = "CurlError";
|
|
15067
|
+
}
|
|
15068
|
+
exitCode;
|
|
15069
|
+
};
|
|
15070
|
+
|
|
15071
|
+
// packages/safe-bash/src/commands/network/fetch-transport.ts
|
|
15072
|
+
function requestBody(source, signal) {
|
|
15073
|
+
if (!source) return void 0;
|
|
15074
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
15075
|
+
return new ReadableStream({
|
|
15076
|
+
async pull(controller) {
|
|
15077
|
+
try {
|
|
15078
|
+
signal.throwIfAborted();
|
|
15079
|
+
const next = await iterator.next();
|
|
15080
|
+
if (next.done) controller.close();
|
|
15081
|
+
else controller.enqueue(next.value);
|
|
15082
|
+
} catch (error) {
|
|
15083
|
+
controller.error(error);
|
|
15084
|
+
}
|
|
15085
|
+
},
|
|
15086
|
+
async cancel(reason) {
|
|
15087
|
+
await iterator.return?.(reason);
|
|
15088
|
+
}
|
|
15089
|
+
});
|
|
15090
|
+
}
|
|
15091
|
+
function createFetchTransport(options2 = {}) {
|
|
15092
|
+
const fetchRequest = options2.fetch ?? globalThis.fetch;
|
|
15093
|
+
if (typeof fetchRequest !== "function") throw new TypeError("Fetch is unavailable");
|
|
15094
|
+
return async (input2) => {
|
|
15095
|
+
input2.signal.throwIfAborted();
|
|
15096
|
+
const url = new URL(input2.url);
|
|
15097
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") throw new CurlError(1, "Unsupported protocol");
|
|
15098
|
+
const stopped = new AbortController();
|
|
15099
|
+
const signal = AbortSignal.any([input2.signal, stopped.signal]);
|
|
15100
|
+
const body = requestBody(input2.body, signal);
|
|
15101
|
+
const headers = new Headers();
|
|
15102
|
+
for (const [name2, value2] of input2.headers) headers.append(name2, value2);
|
|
15103
|
+
const request = new Request(url, {
|
|
15104
|
+
method: input2.method,
|
|
15105
|
+
headers,
|
|
15106
|
+
body,
|
|
15107
|
+
credentials: "omit",
|
|
15108
|
+
redirect: "manual",
|
|
15109
|
+
signal,
|
|
15110
|
+
...body ? { duplex: "half" } : {}
|
|
15111
|
+
});
|
|
15112
|
+
let response;
|
|
15113
|
+
const dispose = async () => {
|
|
15114
|
+
stopped.abort();
|
|
15115
|
+
if (response?.body) await response.body.cancel().catch(() => void 0);
|
|
15116
|
+
};
|
|
15117
|
+
input2.registerCleanup?.(dispose);
|
|
15118
|
+
response = await fetchRequest(request);
|
|
15119
|
+
const reader = response.body?.getReader();
|
|
15120
|
+
const responseBody = reader ? (async function* () {
|
|
15121
|
+
try {
|
|
15122
|
+
while (true) {
|
|
15123
|
+
input2.signal.throwIfAborted();
|
|
15124
|
+
const next = await reader.read();
|
|
15125
|
+
if (next.done) return;
|
|
15126
|
+
yield next.value;
|
|
15127
|
+
}
|
|
15128
|
+
} finally {
|
|
15129
|
+
reader.releaseLock();
|
|
15130
|
+
}
|
|
15131
|
+
})() : (async function* () {
|
|
15132
|
+
})();
|
|
15133
|
+
return {
|
|
15134
|
+
status: response.status,
|
|
15135
|
+
statusText: response.statusText,
|
|
15136
|
+
headers: [...response.headers.entries()],
|
|
15137
|
+
body: responseBody,
|
|
15138
|
+
dispose
|
|
15139
|
+
};
|
|
15140
|
+
};
|
|
15141
|
+
}
|
|
15142
|
+
|
|
15143
|
+
// packages/safe-bash/src/commands/network/authorizer.ts
|
|
15144
|
+
init_platform();
|
|
15145
|
+
function privateHostname(input2) {
|
|
15146
|
+
const hostname = input2.toLowerCase().replace(/\.$/u, "").replace(/^\[|\]$/gu, "");
|
|
15147
|
+
if (hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "::1") return true;
|
|
15148
|
+
if (hostname.includes(":")) {
|
|
15149
|
+
const first2 = hostname.split(":", 1)[0] ?? "";
|
|
15150
|
+
return first2.startsWith("fc") || first2.startsWith("fd") || ["fe8", "fe9", "fea", "feb"].some((prefix2) => first2.startsWith(prefix2));
|
|
15151
|
+
}
|
|
15152
|
+
const parts = hostname.split(".");
|
|
15153
|
+
if (parts.length !== 4 || parts.some((part) => !part || Array.from(part).some((character) => character < "0" || character > "9"))) return false;
|
|
15154
|
+
const octets = parts.map(Number);
|
|
15155
|
+
if (octets.some((value2) => value2 < 0 || value2 > 255)) return false;
|
|
15156
|
+
const [first, second] = octets;
|
|
15157
|
+
return first === 10 || first === 127 || first === 0 || first === 169 && second === 254 || first === 192 && second === 168 || first === 172 && second >= 16 && second <= 31;
|
|
15158
|
+
}
|
|
15159
|
+
function createOriginAuthorizer(allowlist = "*", options2 = {}) {
|
|
15160
|
+
const origins = /* @__PURE__ */ new Set();
|
|
15161
|
+
const hosts = /* @__PURE__ */ new Set();
|
|
15162
|
+
for (const entry of allowlist === "*" ? [] : allowlist) {
|
|
15163
|
+
const value2 = entry.trim();
|
|
15164
|
+
if (!value2) throw new TypeError("Origin allowlist entries must not be empty");
|
|
15165
|
+
if (value2.includes("://")) {
|
|
15166
|
+
const url = new URL(value2);
|
|
15167
|
+
if (url.pathname !== "/" || url.search || url.hash || url.username || url.password) {
|
|
15168
|
+
throw new TypeError(`Origin allowlist entry must be an origin: ${entry}`);
|
|
15169
|
+
}
|
|
15170
|
+
origins.add(url.origin);
|
|
15171
|
+
} else {
|
|
15172
|
+
if (value2.includes("/") || value2.includes("@")) throw new TypeError(`Invalid hostname allowlist entry: ${entry}`);
|
|
15173
|
+
hosts.add(value2.toLowerCase().replace(/\.$/u, ""));
|
|
15174
|
+
}
|
|
15175
|
+
}
|
|
15176
|
+
return (request) => {
|
|
15177
|
+
const url = new URL(request.url);
|
|
15178
|
+
const hostname = url.hostname.toLowerCase().replace(/\.$/u, "");
|
|
15179
|
+
if (options2.denyPrivateNetworks && privateHostname(hostname)) return false;
|
|
15180
|
+
return allowlist === "*" || origins.has(url.origin) || hosts.has(hostname);
|
|
15181
|
+
};
|
|
15182
|
+
}
|
|
15183
|
+
|
|
14432
15184
|
// packages/safe-bash/src/browser.ts
|
|
14433
15185
|
function createBrowserCommands() {
|
|
14434
15186
|
return [
|
|
@@ -14467,14 +15219,18 @@ export {
|
|
|
14467
15219
|
assertPathWithin,
|
|
14468
15220
|
basename,
|
|
14469
15221
|
browserCommands,
|
|
15222
|
+
cloudflareWorkerLimits,
|
|
15223
|
+
cloudflareWorkerNetworkLimits,
|
|
14470
15224
|
collectBytes2 as collectBytes,
|
|
14471
15225
|
collectText,
|
|
14472
15226
|
composeMiddleware,
|
|
14473
15227
|
createBrowserCommands,
|
|
14474
15228
|
createBytePipe,
|
|
14475
15229
|
createCommandArguments,
|
|
15230
|
+
createFetchTransport,
|
|
14476
15231
|
createMemoryFileSystem,
|
|
14477
15232
|
createMountFileSystem,
|
|
15233
|
+
createOriginAuthorizer,
|
|
14478
15234
|
createOutputOperation,
|
|
14479
15235
|
createOverlayFileSystem,
|
|
14480
15236
|
createReadOnlyFileSystem,
|