@poe-platform/safe-bash 0.1.50 → 0.1.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/safe-bash/browser.js +189 -137
- package/dist/safe-bash/browser.js.map +2 -2
- package/dist/safe-bash/shell/arithmetic.d.ts.map +1 -1
- package/dist/safe-bash/shell/arithmetic.js +76 -52
- package/dist/safe-bash/shell/arithmetic.js.map +1 -1
- package/dist/safe-bash/shell/runtime.d.ts +1 -0
- package/dist/safe-bash/shell/runtime.d.ts.map +1 -1
- package/dist/safe-bash/shell/runtime.js +139 -94
- package/dist/safe-bash/shell/runtime.js.map +1 -1
- package/dist/safe-bash/shell/types.d.ts +1 -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.map +1 -1
- package/dist/safe-bash/shell/worker-limits.js +1 -0
- package/dist/safe-bash/shell/worker-limits.js.map +1 -1
- package/package.json +2 -2
|
@@ -4822,47 +4822,62 @@ function evaluateArithmetic(program, variables) {
|
|
|
4822
4822
|
throw new Error(`Unsupported arithmetic operator ${operator}`);
|
|
4823
4823
|
}
|
|
4824
4824
|
};
|
|
4825
|
-
const evaluate = (node) => {
|
|
4826
|
-
if (++steps > 1e4) throw new Error("Arithmetic operation limit exceeded");
|
|
4827
|
-
let value2;
|
|
4828
|
-
if (node.kind === "literal") return node.value;
|
|
4829
|
-
if (node.kind === "name") {
|
|
4830
|
-
if (visiting.has(node.name) || visiting.size >= 64) throw new Error("Arithmetic variable recursion");
|
|
4831
|
-
visiting.add(node.name);
|
|
4832
|
-
try {
|
|
4833
|
-
return evaluate(parseArithmetic(variables[node.name] ?? "0"));
|
|
4834
|
-
} finally {
|
|
4835
|
-
visiting.delete(node.name);
|
|
4836
|
-
}
|
|
4837
|
-
}
|
|
4838
|
-
if (node.kind === "conditional") return evaluate(evaluate(node.condition) ? node.yes : node.no);
|
|
4839
|
-
if (node.kind === "unary") {
|
|
4840
|
-
const operand = evaluate(node.operand);
|
|
4841
|
-
if (node.operator === "+") value2 = operand;
|
|
4842
|
-
else if (node.operator === "-") value2 = -operand;
|
|
4843
|
-
else if (node.operator === "!") value2 = BigInt(!operand);
|
|
4844
|
-
else if (node.operator === "~") value2 = ~operand;
|
|
4845
|
-
else {
|
|
4846
|
-
value2 = BigInt.asIntN(64, operand + (node.operator === "++" ? 1n : -1n));
|
|
4847
|
-
variables[node.operand.name] = String(value2);
|
|
4848
|
-
if (node.postfix) value2 = operand;
|
|
4849
|
-
}
|
|
4850
|
-
} else {
|
|
4851
|
-
if (node.operator === "=") value2 = evaluate(node.right);
|
|
4852
|
-
else {
|
|
4853
|
-
const left = evaluate(node.left);
|
|
4854
|
-
if (node.operator === "&&") return left ? BigInt(evaluate(node.right) !== 0n) : 0n;
|
|
4855
|
-
if (node.operator === "||") return left ? 1n : BigInt(evaluate(node.right) !== 0n);
|
|
4856
|
-
if (node.operator === ",") return evaluate(node.right);
|
|
4857
|
-
value2 = binary(precedence[node.operator] === 2 ? node.operator.slice(0, -1) : node.operator, left, evaluate(node.right), node.right.start ?? 0);
|
|
4858
|
-
}
|
|
4859
|
-
if (precedence[node.operator] === 2) variables[node.left.name] = String(BigInt.asIntN(64, value2));
|
|
4860
|
-
}
|
|
4861
|
-
return BigInt.asIntN(64, value2);
|
|
4862
|
-
};
|
|
4863
4825
|
try {
|
|
4864
4826
|
if (program.error) throw program.error;
|
|
4865
|
-
|
|
4827
|
+
const pending = [{ kind: "evaluate", node: program.tree }];
|
|
4828
|
+
let value2 = 0n;
|
|
4829
|
+
while (pending.length) {
|
|
4830
|
+
const frame = pending.pop();
|
|
4831
|
+
if (frame.kind === "evaluate") {
|
|
4832
|
+
if (++steps > 1e4) throw new Error("Arithmetic operation limit exceeded");
|
|
4833
|
+
const node = frame.node;
|
|
4834
|
+
if (node.kind === "literal") value2 = node.value;
|
|
4835
|
+
else if (node.kind === "name") {
|
|
4836
|
+
if (visiting.has(node.name) || visiting.size >= 64) throw new Error("Arithmetic variable recursion");
|
|
4837
|
+
visiting.add(node.name);
|
|
4838
|
+
pending.push({ kind: "variable", name: node.name }, { kind: "evaluate", node: parseArithmetic(variables[node.name] ?? "0") });
|
|
4839
|
+
} else if (node.kind === "conditional") {
|
|
4840
|
+
pending.push({ kind: "conditional", node }, { kind: "evaluate", node: node.condition });
|
|
4841
|
+
} else if (node.kind === "unary") {
|
|
4842
|
+
pending.push({ kind: "unary", node }, { kind: "evaluate", node: node.operand });
|
|
4843
|
+
} else if (node.operator === "=") {
|
|
4844
|
+
pending.push({ kind: "right", node }, { kind: "evaluate", node: node.right });
|
|
4845
|
+
} else {
|
|
4846
|
+
pending.push({ kind: "left", node }, { kind: "evaluate", node: node.left });
|
|
4847
|
+
}
|
|
4848
|
+
} else if (frame.kind === "variable") visiting.delete(frame.name);
|
|
4849
|
+
else if (frame.kind === "conditional") {
|
|
4850
|
+
pending.push({ kind: "evaluate", node: value2 ? frame.node.yes : frame.node.no });
|
|
4851
|
+
} else if (frame.kind === "unary") {
|
|
4852
|
+
const { node } = frame;
|
|
4853
|
+
const operand = value2;
|
|
4854
|
+
if (node.operator === "+") value2 = operand;
|
|
4855
|
+
else if (node.operator === "-") value2 = -operand;
|
|
4856
|
+
else if (node.operator === "!") value2 = BigInt(!operand);
|
|
4857
|
+
else if (node.operator === "~") value2 = ~operand;
|
|
4858
|
+
else {
|
|
4859
|
+
value2 = BigInt.asIntN(64, operand + (node.operator === "++" ? 1n : -1n));
|
|
4860
|
+
variables[node.operand.name] = String(value2);
|
|
4861
|
+
if (node.postfix) value2 = operand;
|
|
4862
|
+
}
|
|
4863
|
+
value2 = BigInt.asIntN(64, value2);
|
|
4864
|
+
} else if (frame.kind === "left") {
|
|
4865
|
+
const { node } = frame;
|
|
4866
|
+
if (node.operator === "&&" || node.operator === "||") {
|
|
4867
|
+
if (node.operator === "&&" ? value2 === 0n : value2 !== 0n) value2 = BigInt(value2 !== 0n);
|
|
4868
|
+
else pending.push({ kind: "logical" }, { kind: "evaluate", node: node.right });
|
|
4869
|
+
} else {
|
|
4870
|
+
if (node.operator !== ",") pending.push({ kind: "right", node, left: value2 });
|
|
4871
|
+
pending.push({ kind: "evaluate", node: node.right });
|
|
4872
|
+
}
|
|
4873
|
+
} else if (frame.kind === "right") {
|
|
4874
|
+
const { node } = frame;
|
|
4875
|
+
if (node.operator !== "=") value2 = binary(precedence[node.operator] === 2 ? node.operator.slice(0, -1) : node.operator, frame.left, value2, node.right.start ?? 0);
|
|
4876
|
+
if (precedence[node.operator] === 2) variables[node.left.name] = String(BigInt.asIntN(64, value2));
|
|
4877
|
+
value2 = BigInt.asIntN(64, value2);
|
|
4878
|
+
} else value2 = BigInt(value2 !== 0n);
|
|
4879
|
+
}
|
|
4880
|
+
return value2;
|
|
4866
4881
|
} catch (error) {
|
|
4867
4882
|
if (error instanceof ArithmeticFailure) throw new Error(`${program.source.trimStart()}: ${error.message} (error token is "${program.source.slice(error.offset)}")`);
|
|
4868
4883
|
if (error instanceof ShellSyntaxError) {
|
|
@@ -9513,6 +9528,7 @@ var defaultLimits = {
|
|
|
9513
9528
|
maxInputBytes: 32 * 1024 * 1024,
|
|
9514
9529
|
maxOutputBytes: 16 * 1024 * 1024,
|
|
9515
9530
|
maxCommands: 1e4,
|
|
9531
|
+
maxPipelineStages: 64,
|
|
9516
9532
|
maxLoopIterations: 1e4,
|
|
9517
9533
|
maxSubstitutionDepth: 64,
|
|
9518
9534
|
maxSourceBytes: 1024 * 1024,
|
|
@@ -9612,6 +9628,7 @@ var Budget = class {
|
|
|
9612
9628
|
signal;
|
|
9613
9629
|
#wallClockTimer;
|
|
9614
9630
|
#wallClockDeadline = 0;
|
|
9631
|
+
#pipelineStages = 0;
|
|
9615
9632
|
#cpuStarted = monotonicNow();
|
|
9616
9633
|
#armWallClock() {
|
|
9617
9634
|
const remaining = this.#wallClockDeadline - Date.now();
|
|
@@ -9641,6 +9658,17 @@ var Budget = class {
|
|
|
9641
9658
|
this.signal.throwIfAborted();
|
|
9642
9659
|
if (++this.commands > this.limits.maxCommands) this.fail("maxCommands");
|
|
9643
9660
|
}
|
|
9661
|
+
reservePipelineStages(count) {
|
|
9662
|
+
this.signal.throwIfAborted();
|
|
9663
|
+
if (count > this.limits.maxPipelineStages - this.#pipelineStages) this.fail("maxPipelineStages");
|
|
9664
|
+
this.#pipelineStages += count;
|
|
9665
|
+
let released = false;
|
|
9666
|
+
return () => {
|
|
9667
|
+
if (released) return;
|
|
9668
|
+
released = true;
|
|
9669
|
+
this.#pipelineStages -= count;
|
|
9670
|
+
};
|
|
9671
|
+
}
|
|
9644
9672
|
loop() {
|
|
9645
9673
|
this.signal.throwIfAborted();
|
|
9646
9674
|
if (++this.iterations > this.limits.maxLoopIterations) this.fail("maxLoopIterations");
|
|
@@ -11136,119 +11164,142 @@ var Runtime = class _Runtime {
|
|
|
11136
11164
|
let status;
|
|
11137
11165
|
if (pipeline.commands.length === 1) status = await this.command(pipeline.commands[0], state, io, false, pipeline.negate);
|
|
11138
11166
|
else {
|
|
11139
|
-
const
|
|
11140
|
-
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
11167
|
+
const release = this.budget.reservePipelineStages(pipeline.commands.length);
|
|
11168
|
+
const retained = /* @__PURE__ */ new Set();
|
|
11169
|
+
let setupClosed = false;
|
|
11170
|
+
const retain = (work) => {
|
|
11171
|
+
retained.add(work);
|
|
11172
|
+
const settled = () => {
|
|
11173
|
+
retained.delete(work);
|
|
11174
|
+
if (setupClosed && !retained.size) release();
|
|
11175
|
+
};
|
|
11176
|
+
void work.then(settled, settled);
|
|
11177
|
+
};
|
|
11178
|
+
const pipes = [];
|
|
11179
|
+
const controllers = [];
|
|
11144
11180
|
const written = /* @__PURE__ */ new Set();
|
|
11145
11181
|
const completed = /* @__PURE__ */ new Set();
|
|
11146
11182
|
const closing = /* @__PURE__ */ new Set();
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
const
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
this.
|
|
11158
|
-
controls
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
const frame = {};
|
|
11170
|
-
const runtime = new _Runtime(
|
|
11171
|
-
this.fs,
|
|
11172
|
-
this.commands,
|
|
11173
|
-
this.middleware,
|
|
11174
|
-
this.budget,
|
|
11175
|
-
signal,
|
|
11176
|
-
this.fileWrites,
|
|
11177
|
-
this.outputFiles,
|
|
11178
|
-
boundary.deliverySignal,
|
|
11179
|
-
boundary,
|
|
11180
|
-
this.cancellationState,
|
|
11181
|
-
owner,
|
|
11182
|
-
childDepth,
|
|
11183
|
-
this.cancellationMaxDepth,
|
|
11184
|
-
frame
|
|
11185
|
-
);
|
|
11186
|
-
const input2 = new ShellInput(incoming?.readable ?? io.stdin, this.budget, signal);
|
|
11187
|
-
const pipeOutput = outgoing && { ownedOutput: outgoing.writable.ownedOutput, write: async (chunk) => {
|
|
11183
|
+
let statuses;
|
|
11184
|
+
try {
|
|
11185
|
+
for (let index = 1; index < pipeline.commands.length; index++) pipes.push(createBytePipe({
|
|
11186
|
+
highWaterMark: this.budget.limits.pipeHighWaterMark,
|
|
11187
|
+
signal: this.signal
|
|
11188
|
+
}));
|
|
11189
|
+
for (let index = 0; index < pipeline.commands.length; index++) controllers.push(new AbortController());
|
|
11190
|
+
const tasks = pipeline.commands.map(async (command, index) => {
|
|
11191
|
+
const incoming = pipes[index - 1];
|
|
11192
|
+
const outgoing = pipes[index];
|
|
11193
|
+
const childDepth = this.cancellationDepth + 1;
|
|
11194
|
+
const controls = [
|
|
11195
|
+
{ role: "pipeline-control", signal: controllers[index].signal }
|
|
11196
|
+
];
|
|
11197
|
+
const prepared = prepareChildCancellation(
|
|
11198
|
+
this.cancellation,
|
|
11199
|
+
void 0,
|
|
11200
|
+
this.cancellationAdmission(childDepth, controls.length),
|
|
11201
|
+
controls
|
|
11202
|
+
);
|
|
11203
|
+
const owner = new InvocationCancellationOwner(io[invocationScope], prepared, this.cancellationState);
|
|
11204
|
+
let boundary;
|
|
11188
11205
|
try {
|
|
11189
|
-
|
|
11190
|
-
if (chunk.byteLength) written.add(index);
|
|
11206
|
+
boundary = owner.activate();
|
|
11191
11207
|
} catch (error) {
|
|
11192
|
-
|
|
11193
|
-
const closed = new PipelineClosed();
|
|
11194
|
-
controllers[index].abort(closed);
|
|
11195
|
-
throw closed;
|
|
11196
|
-
}
|
|
11208
|
+
await owner.abandon(Promise.resolve());
|
|
11197
11209
|
throw error;
|
|
11198
11210
|
}
|
|
11199
|
-
|
|
11200
|
-
|
|
11201
|
-
|
|
11202
|
-
|
|
11211
|
+
const signal = AbortSignal.any([boundary.deliverySignal, io[invocationScope].signal]);
|
|
11212
|
+
const frame = {};
|
|
11213
|
+
const runtime = new _Runtime(
|
|
11214
|
+
this.fs,
|
|
11215
|
+
this.commands,
|
|
11216
|
+
this.middleware,
|
|
11217
|
+
this.budget,
|
|
11218
|
+
signal,
|
|
11219
|
+
this.fileWrites,
|
|
11220
|
+
this.outputFiles,
|
|
11221
|
+
boundary.deliverySignal,
|
|
11222
|
+
boundary,
|
|
11223
|
+
this.cancellationState,
|
|
11224
|
+
owner,
|
|
11225
|
+
childDepth,
|
|
11226
|
+
this.cancellationMaxDepth,
|
|
11227
|
+
frame
|
|
11228
|
+
);
|
|
11229
|
+
const input2 = new ShellInput(incoming?.readable ?? io.stdin, this.budget, signal);
|
|
11230
|
+
const pipeOutput = outgoing && { ownedOutput: outgoing.writable.ownedOutput, write: async (chunk) => {
|
|
11203
11231
|
try {
|
|
11204
|
-
|
|
11205
|
-
|
|
11206
|
-
exitCode = await interruptible(runtime.runCommandIsolated(command, child, {
|
|
11207
|
-
...isolateIO(io),
|
|
11208
|
-
stdin: input2,
|
|
11209
|
-
...incoming ? { stdinIsDefault: false } : {},
|
|
11210
|
-
stdout: pipeOutput ? this.budget.sink(pipeOutput, signal) : signalSink(io.stdout, signal),
|
|
11211
|
-
stderr: signalSink(io.stderr, signal)
|
|
11212
|
-
}).finally(() => stateMonitor(child)?.closeValues()), signal);
|
|
11232
|
+
await outgoing.writable.write(chunk);
|
|
11233
|
+
if (chunk.byteLength) written.add(index);
|
|
11213
11234
|
} catch (error) {
|
|
11214
|
-
if (
|
|
11215
|
-
|
|
11235
|
+
if (errorCode(error) === "EPIPE") {
|
|
11236
|
+
const closed = new PipelineClosed();
|
|
11237
|
+
controllers[index].abort(closed);
|
|
11238
|
+
throw closed;
|
|
11239
|
+
}
|
|
11240
|
+
throw error;
|
|
11216
11241
|
}
|
|
11217
|
-
|
|
11218
|
-
|
|
11219
|
-
|
|
11220
|
-
|
|
11221
|
-
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
|
|
11242
|
+
} };
|
|
11243
|
+
const executeStage = async () => {
|
|
11244
|
+
try {
|
|
11245
|
+
let exitCode;
|
|
11246
|
+
try {
|
|
11247
|
+
const child = await cloneState(state, this.signal);
|
|
11248
|
+
child.isolated = true;
|
|
11249
|
+
const work = runtime.runCommandIsolated(command, child, {
|
|
11250
|
+
...isolateIO(io),
|
|
11251
|
+
stdin: input2,
|
|
11252
|
+
...incoming ? { stdinIsDefault: false } : {},
|
|
11253
|
+
stdout: pipeOutput ? this.budget.sink(pipeOutput, signal) : signalSink(io.stdout, signal),
|
|
11254
|
+
stderr: signalSink(io.stderr, signal)
|
|
11255
|
+
}).finally(() => stateMonitor(child)?.closeValues());
|
|
11256
|
+
retain(work);
|
|
11257
|
+
exitCode = await interruptible(work, signal);
|
|
11258
|
+
} catch (error) {
|
|
11259
|
+
if (!(error instanceof PipelineClosed)) throw error;
|
|
11260
|
+
exitCode = 141;
|
|
11261
|
+
}
|
|
11262
|
+
return { exitCode };
|
|
11263
|
+
} finally {
|
|
11264
|
+
completed.add(index);
|
|
11265
|
+
if (incoming) {
|
|
11266
|
+
const upstream = index - 1;
|
|
11267
|
+
const close = scheduleTurn(() => {
|
|
11268
|
+
closing.delete(close);
|
|
11269
|
+
if (written.has(upstream) && !completed.has(upstream)) controllers[upstream].abort(new PipelineClosed());
|
|
11270
|
+
});
|
|
11271
|
+
closing.add(close);
|
|
11272
|
+
await incoming.abort();
|
|
11273
|
+
}
|
|
11274
|
+
await input2.close().catch((error) => {
|
|
11275
|
+
if (!(error instanceof PipelineClosed)) throw error;
|
|
11225
11276
|
});
|
|
11226
|
-
|
|
11227
|
-
await incoming.abort();
|
|
11277
|
+
if (outgoing) await outgoing.close().catch(() => void 0);
|
|
11228
11278
|
}
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11279
|
+
};
|
|
11280
|
+
let captured;
|
|
11281
|
+
try {
|
|
11282
|
+
captured = { kind: "return", value: await executeStage() };
|
|
11283
|
+
} catch (reason) {
|
|
11284
|
+
captured = frame.report && Object.is(frame.report.origin.signal.reason, reason) ? { kind: "throw", reason, report: frame.report } : { kind: "throw", reason };
|
|
11233
11285
|
}
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
|
|
11237
|
-
|
|
11238
|
-
|
|
11239
|
-
captured = frame.report && Object.is(frame.report.origin.signal.reason, reason) ? { kind: "throw", reason, report: frame.report } : { kind: "throw", reason };
|
|
11240
|
-
}
|
|
11241
|
-
const selection = await owner.finish(Promise.resolve(), captured);
|
|
11242
|
-
if (selection.outcome.kind === "throw") throw selection.outcome.reason;
|
|
11243
|
-
return selection.outcome.value.exitCode;
|
|
11244
|
-
});
|
|
11245
|
-
let statuses;
|
|
11246
|
-
try {
|
|
11286
|
+
const selection = await owner.finish(Promise.resolve(), captured);
|
|
11287
|
+
if (selection.outcome.kind === "throw") throw selection.outcome.reason;
|
|
11288
|
+
return selection.outcome.value.exitCode;
|
|
11289
|
+
});
|
|
11290
|
+
for (const task of tasks) retain(task);
|
|
11247
11291
|
statuses = await interruptible(Promise.all(tasks), this.signal);
|
|
11248
11292
|
} finally {
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11293
|
+
try {
|
|
11294
|
+
for (const close of closing) cancelTurn(close);
|
|
11295
|
+
for (const [index, controller] of controllers.entries()) if (!completed.has(index) || written.has(index)) controller.abort(new PipelineClosed());
|
|
11296
|
+
const aborts = pipes.map((pipe) => pipe.abort());
|
|
11297
|
+
for (const abort of aborts) retain(abort);
|
|
11298
|
+
await Promise.all(aborts);
|
|
11299
|
+
} finally {
|
|
11300
|
+
setupClosed = true;
|
|
11301
|
+
if (!retained.size) release();
|
|
11302
|
+
}
|
|
11252
11303
|
}
|
|
11253
11304
|
await this.publishStatus(state, statuses, io);
|
|
11254
11305
|
status = state.pipefail ? statuses.findLast((status2) => status2 !== 0) ?? 0 : statuses.at(-1);
|
|
@@ -15154,6 +15205,7 @@ var cloudflareWorkerLimits = Object.freeze({
|
|
|
15154
15205
|
maxInputBytes: 4 * 1024 * 1024,
|
|
15155
15206
|
maxOutputBytes: 4 * 1024 * 1024,
|
|
15156
15207
|
maxCommands: 1e3,
|
|
15208
|
+
maxPipelineStages: 64,
|
|
15157
15209
|
maxLoopIterations: 1e3,
|
|
15158
15210
|
maxSubstitutionDepth: 16,
|
|
15159
15211
|
maxSourceBytes: 256 * 1024,
|