@poe-platform/safe-bash 0.1.521 → 0.1.522
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/safe-bash/core.browser.js +201 -10
- package/dist/safe-bash/core.browser.js.map +3 -3
- package/dist/safe-bash/shell/runtime.d.ts +4 -0
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +249 -10
- 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 +1 -0
- package/dist/safe-bash/shell/shell.js.map +1 -1
- package/package.json +2 -2
|
@@ -41691,6 +41691,8 @@ var Budget25 = class {
|
|
|
41691
41691
|
iterations = 0;
|
|
41692
41692
|
bytes = 0;
|
|
41693
41693
|
sourceBytes = 0;
|
|
41694
|
+
globstarEntries = 0;
|
|
41695
|
+
globstarStates = 0;
|
|
41694
41696
|
controller = new AbortController();
|
|
41695
41697
|
signal;
|
|
41696
41698
|
#wallClockTimer;
|
|
@@ -44606,6 +44608,7 @@ ${functionDisplay(name2, state.functions.get(name2))}`;
|
|
|
44606
44608
|
getopts: { cursor: createGetoptsState(), integer: true },
|
|
44607
44609
|
directoryStack: { entries: [], bytes: 0 },
|
|
44608
44610
|
dotglob: false,
|
|
44611
|
+
globstar: false,
|
|
44609
44612
|
positional: [...args],
|
|
44610
44613
|
arg0,
|
|
44611
44614
|
profile: context2.command === "sh" ? "sh" : "bash",
|
|
@@ -45680,7 +45683,7 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45680
45683
|
else if (flag === "u") unset2 = true;
|
|
45681
45684
|
else {
|
|
45682
45685
|
await this.diagnostic(context2, `shopt: ${option.startsWith("--") ? option : `-${flag}`}: unsupported option`);
|
|
45683
|
-
await writeDiagnostic(context2.stderr, "shopt: usage: shopt [-pqsu] [--] [dotglob ...]\n");
|
|
45686
|
+
await writeDiagnostic(context2.stderr, "shopt: usage: shopt [-pqsu] [--] [dotglob globstar ...]\n");
|
|
45684
45687
|
return 2;
|
|
45685
45688
|
}
|
|
45686
45689
|
}
|
|
@@ -45689,26 +45692,26 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
45689
45692
|
await this.diagnostic(context2, "shopt: cannot set and unset shell options simultaneously");
|
|
45690
45693
|
return 1;
|
|
45691
45694
|
}
|
|
45692
|
-
const emit2 = async () => {
|
|
45693
|
-
if (!quiet) await writeText(context2.stdout, print ? `shopt -${state
|
|
45694
|
-
` :
|
|
45695
|
+
const emit2 = async (name2) => {
|
|
45696
|
+
if (!quiet) await writeText(context2.stdout, print ? `shopt -${state[name2] ? "s" : "u"} ${name2}
|
|
45697
|
+
` : `${name2.padEnd(20)} ${state[name2] ? "on" : "off"}
|
|
45695
45698
|
`);
|
|
45696
45699
|
};
|
|
45697
45700
|
if (index === context2.args.length) {
|
|
45698
|
-
if ((!set || state
|
|
45701
|
+
for (const name2 of ["dotglob", "globstar"]) if ((!set || state[name2]) && (!unset2 || !state[name2])) await emit2(name2);
|
|
45699
45702
|
return 0;
|
|
45700
45703
|
}
|
|
45701
45704
|
let status2 = 0;
|
|
45702
45705
|
for (; index < context2.args.length; index++) {
|
|
45703
45706
|
this.signal.throwIfAborted();
|
|
45704
45707
|
const name2 = context2.args[index];
|
|
45705
|
-
if (name2 !== "dotglob") {
|
|
45706
|
-
await this.diagnostic(context2, `shopt: ${name2}: unsupported shell option name (
|
|
45708
|
+
if (name2 !== "dotglob" && name2 !== "globstar") {
|
|
45709
|
+
await this.diagnostic(context2, `shopt: ${name2}: unsupported shell option name (supported: dotglob, globstar)`);
|
|
45707
45710
|
status2 = 1;
|
|
45708
|
-
} else if (set || unset2) state
|
|
45711
|
+
} else if (set || unset2) state[name2] = set;
|
|
45709
45712
|
else {
|
|
45710
|
-
await emit2();
|
|
45711
|
-
if (!state
|
|
45713
|
+
await emit2(name2);
|
|
45714
|
+
if (!state[name2]) status2 = 1;
|
|
45712
45715
|
}
|
|
45713
45716
|
}
|
|
45714
45717
|
return status2;
|
|
@@ -46994,8 +46997,195 @@ ${prefix3} line ${offset + line}: \`${source2.split("\n")[line - 1] ?? ""}'
|
|
|
46994
46997
|
holding.release();
|
|
46995
46998
|
}
|
|
46996
46999
|
}
|
|
47000
|
+
async recursiveGlob(value2, pattern, state) {
|
|
47001
|
+
const failWalk = (message3) => {
|
|
47002
|
+
const error = new FsError("EFBIG", { syscall: "glob", message: message3 });
|
|
47003
|
+
this.budget.controller.abort(error);
|
|
47004
|
+
throw error;
|
|
47005
|
+
};
|
|
47006
|
+
const work = { remaining: Math.min(Number.MAX_SAFE_INTEGER, this.budget.limits.maxExpansionBytes * 4 + 1024), signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
|
|
47007
|
+
const scratch = this.budget.values.scope();
|
|
47008
|
+
work.allocation = scratch;
|
|
47009
|
+
try {
|
|
47010
|
+
const segments = [];
|
|
47011
|
+
let start = 0;
|
|
47012
|
+
for (let end = 0; end <= pattern.length; end++) {
|
|
47013
|
+
const pending = stringCheckpoint(work);
|
|
47014
|
+
if (pending) await pending;
|
|
47015
|
+
if (end !== pattern.length && pattern[end] !== "/") continue;
|
|
47016
|
+
if (end > start) {
|
|
47017
|
+
const bytes3 = (await scanString(pattern, work, start, end)).bytes;
|
|
47018
|
+
if (++this.budget.globstarStates > 1e5) failWalk("globstar traversal state limit exceeded");
|
|
47019
|
+
scratch.reserveBytes(bytes3 * 2 + 64);
|
|
47020
|
+
segments.push(pattern.slice(start, end));
|
|
47021
|
+
}
|
|
47022
|
+
start = end + 1;
|
|
47023
|
+
}
|
|
47024
|
+
const make = (parent, suffix2, bytes3, descend, depth) => {
|
|
47025
|
+
const separator = parent.path && parent.path !== "/" ? "/" : "";
|
|
47026
|
+
const size = parent.bytes + separator.length + bytes3;
|
|
47027
|
+
if (size > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
47028
|
+
if (++this.budget.globstarStates > 1e5) failWalk("globstar traversal state limit exceeded");
|
|
47029
|
+
if (depth > 128) failWalk("globstar directory depth limit exceeded");
|
|
47030
|
+
scratch.reserveBytes(size * 2 + 128);
|
|
47031
|
+
return { path: parent.path + separator + suffix2, bytes: size, descend, depth };
|
|
47032
|
+
};
|
|
47033
|
+
const empty2 = { path: "", bytes: 0, descend: true, depth: 0 };
|
|
47034
|
+
let candidates = [make(empty2, pattern.startsWith("/") ? "/" : "", pattern.startsWith("/") ? 1 : 0, true, 0)];
|
|
47035
|
+
const ignored = (error) => {
|
|
47036
|
+
this.signal.throwIfAborted();
|
|
47037
|
+
return ["ENOENT", "ENOTDIR", "EACCES"].includes(errorCode(error) ?? "");
|
|
47038
|
+
};
|
|
47039
|
+
const read = async (candidate) => {
|
|
47040
|
+
const maxEntries = 1e5 - this.budget.globstarEntries;
|
|
47041
|
+
let entries2;
|
|
47042
|
+
try {
|
|
47043
|
+
entries2 = await interruptible3(this.fs.readdir(pathOf(state, candidate.path || "."), { signal: this.signal, maxEntries }), this.signal);
|
|
47044
|
+
} catch (error) {
|
|
47045
|
+
this.signal.throwIfAborted();
|
|
47046
|
+
if (errorCode(error) === "EFBIG") this.budget.controller.abort(error);
|
|
47047
|
+
throw error;
|
|
47048
|
+
}
|
|
47049
|
+
this.signal.throwIfAborted();
|
|
47050
|
+
if (entries2.length > maxEntries) failWalk("globstar directory entry limit exceeded");
|
|
47051
|
+
this.budget.globstarEntries += entries2.length;
|
|
47052
|
+
return entries2;
|
|
47053
|
+
};
|
|
47054
|
+
let wildcardPrefix = false;
|
|
47055
|
+
for (let index = 0; index < segments.length; index++) {
|
|
47056
|
+
const segment2 = segments[index];
|
|
47057
|
+
const terminal = index === segments.length - 1;
|
|
47058
|
+
const next = /* @__PURE__ */ new Map();
|
|
47059
|
+
const add3 = (candidate) => {
|
|
47060
|
+
const prior = next.get(candidate.path);
|
|
47061
|
+
if (!prior || candidate.descend && !prior.descend) next.set(candidate.path, candidate);
|
|
47062
|
+
};
|
|
47063
|
+
if (segment2 === "**") {
|
|
47064
|
+
const visited = /* @__PURE__ */ new Set();
|
|
47065
|
+
for (const root of candidates) {
|
|
47066
|
+
this.signal.throwIfAborted();
|
|
47067
|
+
try {
|
|
47068
|
+
if ((await interruptible3(this.fs.stat(pathOf(state, root.path || "."), { signal: this.signal }), this.signal)).type !== "directory") continue;
|
|
47069
|
+
} catch (error) {
|
|
47070
|
+
if (ignored(error)) continue;
|
|
47071
|
+
throw error;
|
|
47072
|
+
}
|
|
47073
|
+
if (!terminal || root.path) {
|
|
47074
|
+
add3(terminal && !wildcardPrefix && root.path !== "/" ? make(root, "", 0, root.descend, root.depth) : root);
|
|
47075
|
+
}
|
|
47076
|
+
const queue = root.descend ? [root] : [];
|
|
47077
|
+
while (queue.length) {
|
|
47078
|
+
const directory2 = queue.pop();
|
|
47079
|
+
if (visited.has(directory2.path)) continue;
|
|
47080
|
+
visited.add(directory2.path);
|
|
47081
|
+
let entries2;
|
|
47082
|
+
try {
|
|
47083
|
+
entries2 = await read(directory2);
|
|
47084
|
+
} catch (error) {
|
|
47085
|
+
if (ignored(error)) continue;
|
|
47086
|
+
throw error;
|
|
47087
|
+
}
|
|
47088
|
+
for (const entry of entries2) {
|
|
47089
|
+
const pending = stringCheckpoint(work);
|
|
47090
|
+
if (pending) await pending;
|
|
47091
|
+
if (entry.name === "." || entry.name === ".." || !state.dotglob && entry.name.startsWith(".")) continue;
|
|
47092
|
+
const bytes3 = (await scanString(entry.name, work)).bytes;
|
|
47093
|
+
const child = make(directory2, entry.name, bytes3, entry.type === "directory", directory2.depth + (entry.type === "directory" ? 1 : 0));
|
|
47094
|
+
if (terminal || entry.type === "directory" || entry.type === "symlink" && root.path !== "") add3(child);
|
|
47095
|
+
if (entry.type === "directory") queue.push(child);
|
|
47096
|
+
}
|
|
47097
|
+
}
|
|
47098
|
+
}
|
|
47099
|
+
wildcardPrefix = true;
|
|
47100
|
+
} else if (!/(?:^|[^\\])[*?[]/u.test(segment2)) {
|
|
47101
|
+
const literal = segment2.replace(/\\(.)/gu, "$1");
|
|
47102
|
+
const bytes3 = (await scanString(literal, work)).bytes;
|
|
47103
|
+
for (const candidate of candidates) add3(make(candidate, literal, bytes3, true, candidate.depth));
|
|
47104
|
+
} else {
|
|
47105
|
+
const matches3 = await compilePattern(segment2, work);
|
|
47106
|
+
for (const candidate of candidates) {
|
|
47107
|
+
let entries2;
|
|
47108
|
+
try {
|
|
47109
|
+
entries2 = await read(candidate);
|
|
47110
|
+
} catch (error) {
|
|
47111
|
+
if (ignored(error)) continue;
|
|
47112
|
+
throw error;
|
|
47113
|
+
}
|
|
47114
|
+
for (const entry of entries2) {
|
|
47115
|
+
const pending = stringCheckpoint(work);
|
|
47116
|
+
if (pending) await pending;
|
|
47117
|
+
if (entry.name !== "." && entry.name !== ".." && (state.dotglob || !entry.name.startsWith(".") || segment2.startsWith(".")) && await matches3(entry.name)) {
|
|
47118
|
+
add3(make(candidate, entry.name, (await scanString(entry.name, work)).bytes, true, candidate.depth));
|
|
47119
|
+
}
|
|
47120
|
+
}
|
|
47121
|
+
}
|
|
47122
|
+
wildcardPrefix = true;
|
|
47123
|
+
}
|
|
47124
|
+
candidates = [...next.values()];
|
|
47125
|
+
}
|
|
47126
|
+
const found = [];
|
|
47127
|
+
let outputBytes = 0;
|
|
47128
|
+
for (const candidate of candidates) {
|
|
47129
|
+
this.signal.throwIfAborted();
|
|
47130
|
+
try {
|
|
47131
|
+
const path = pathOf(state, candidate.path);
|
|
47132
|
+
const stat = await interruptible3(value2.endsWith("/") ? this.fs.stat(path, { signal: this.signal }) : this.fs.lstat(path, { signal: this.signal }), this.signal);
|
|
47133
|
+
if (value2.endsWith("/") && stat.type !== "directory") continue;
|
|
47134
|
+
const slash = value2.endsWith("/") && !candidate.path.endsWith("/") ? "/" : "";
|
|
47135
|
+
if (found.length >= this.budget.limits.maxExpansionFields) this.budget.fail("maxExpansionFields");
|
|
47136
|
+
outputBytes += candidate.bytes + slash.length;
|
|
47137
|
+
if (outputBytes > this.budget.limits.maxExpansionBytes) this.budget.fail("maxExpansionBytes");
|
|
47138
|
+
scratch.reserveBytes(candidate.bytes * 2 + slash.length + 8);
|
|
47139
|
+
found.push(candidate.path + slash);
|
|
47140
|
+
} catch (error) {
|
|
47141
|
+
if (!ignored(error)) throw error;
|
|
47142
|
+
}
|
|
47143
|
+
}
|
|
47144
|
+
const compare6 = async (left, right) => {
|
|
47145
|
+
for (let index = 0; index < Math.min(left.length, right.length); index++) {
|
|
47146
|
+
const pending = stringCheckpoint(work);
|
|
47147
|
+
if (pending) await pending;
|
|
47148
|
+
const difference = left.charCodeAt(index) - right.charCodeAt(index);
|
|
47149
|
+
if (difference) return difference;
|
|
47150
|
+
}
|
|
47151
|
+
return left.length - right.length;
|
|
47152
|
+
};
|
|
47153
|
+
const sift = async (root, end) => {
|
|
47154
|
+
while (root * 2 + 1 < end) {
|
|
47155
|
+
let child = root * 2 + 1;
|
|
47156
|
+
if (child + 1 < end && await compare6(found[child], found[child + 1]) < 0) child++;
|
|
47157
|
+
if (await compare6(found[root], found[child]) >= 0) return;
|
|
47158
|
+
const saved = found[root];
|
|
47159
|
+
found[root] = found[child];
|
|
47160
|
+
found[child] = saved;
|
|
47161
|
+
root = child;
|
|
47162
|
+
}
|
|
47163
|
+
};
|
|
47164
|
+
for (let index = Math.floor(found.length / 2) - 1; index >= 0; index--) await sift(index, found.length);
|
|
47165
|
+
for (let end = found.length - 1; end > 0; end--) {
|
|
47166
|
+
const saved = found[0];
|
|
47167
|
+
found[0] = found[end];
|
|
47168
|
+
found[end] = saved;
|
|
47169
|
+
await sift(0, end);
|
|
47170
|
+
}
|
|
47171
|
+
return found.length ? found : [value2];
|
|
47172
|
+
} finally {
|
|
47173
|
+
scratch.close();
|
|
47174
|
+
}
|
|
47175
|
+
}
|
|
46997
47176
|
async glob(value2, pattern, state) {
|
|
46998
47177
|
if (!/(?:^|[^\\])[*?[]/u.test(pattern)) return [value2];
|
|
47178
|
+
if (state.globstar) {
|
|
47179
|
+
const work2 = { remaining: Math.min(Number.MAX_SAFE_INTEGER, this.budget.limits.maxExpansionBytes * 4 + 1024), signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
|
|
47180
|
+
let start = 0;
|
|
47181
|
+
for (let end = 0; end <= pattern.length; end++) {
|
|
47182
|
+
const pending = stringCheckpoint(work2);
|
|
47183
|
+
if (pending) await pending;
|
|
47184
|
+
if (end !== pattern.length && pattern[end] !== "/") continue;
|
|
47185
|
+
if (end - start === 2 && pattern[start] === "*" && pattern[start + 1] === "*") return this.recursiveGlob(value2, pattern, state);
|
|
47186
|
+
start = end + 1;
|
|
47187
|
+
}
|
|
47188
|
+
}
|
|
46999
47189
|
const absolute2 = pattern.startsWith("/");
|
|
47000
47190
|
const work = { remaining: Math.min(Number.MAX_SAFE_INTEGER, this.budget.limits.maxExpansionBytes * 4 + 1024), signal: this.signal, exhausted: () => this.budget.fail("maxExpansionBytes") };
|
|
47001
47191
|
let candidates = [absolute2 ? "/" : ""];
|
|
@@ -47838,6 +48028,7 @@ var Shell = class {
|
|
|
47838
48028
|
getopts: { cursor: { index: 0 }, integer: true },
|
|
47839
48029
|
directoryStack: { entries: [], bytes: 0 },
|
|
47840
48030
|
dotglob: false,
|
|
48031
|
+
globstar: false,
|
|
47841
48032
|
status: 0,
|
|
47842
48033
|
substitutionStatus: 0,
|
|
47843
48034
|
depth: 0,
|