@poe-platform/safe-bash 0.1.51 → 0.1.53

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.
@@ -9528,6 +9528,7 @@ var defaultLimits = {
9528
9528
  maxInputBytes: 32 * 1024 * 1024,
9529
9529
  maxOutputBytes: 16 * 1024 * 1024,
9530
9530
  maxCommands: 1e4,
9531
+ maxPipelineStages: 64,
9531
9532
  maxLoopIterations: 1e4,
9532
9533
  maxSubstitutionDepth: 64,
9533
9534
  maxSourceBytes: 1024 * 1024,
@@ -9627,6 +9628,7 @@ var Budget = class {
9627
9628
  signal;
9628
9629
  #wallClockTimer;
9629
9630
  #wallClockDeadline = 0;
9631
+ #pipelineStages = 0;
9630
9632
  #cpuStarted = monotonicNow();
9631
9633
  #armWallClock() {
9632
9634
  const remaining = this.#wallClockDeadline - Date.now();
@@ -9656,6 +9658,17 @@ var Budget = class {
9656
9658
  this.signal.throwIfAborted();
9657
9659
  if (++this.commands > this.limits.maxCommands) this.fail("maxCommands");
9658
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
+ }
9659
9672
  loop() {
9660
9673
  this.signal.throwIfAborted();
9661
9674
  if (++this.iterations > this.limits.maxLoopIterations) this.fail("maxLoopIterations");
@@ -11151,119 +11164,142 @@ var Runtime = class _Runtime {
11151
11164
  let status;
11152
11165
  if (pipeline.commands.length === 1) status = await this.command(pipeline.commands[0], state, io, false, pipeline.negate);
11153
11166
  else {
11154
- const pipes = pipeline.commands.slice(1).map(() => createBytePipe({
11155
- highWaterMark: this.budget.limits.pipeHighWaterMark,
11156
- signal: this.signal
11157
- }));
11158
- const controllers = pipeline.commands.map(() => new AbortController());
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 = [];
11159
11180
  const written = /* @__PURE__ */ new Set();
11160
11181
  const completed = /* @__PURE__ */ new Set();
11161
11182
  const closing = /* @__PURE__ */ new Set();
11162
- const tasks = pipeline.commands.map(async (command, index) => {
11163
- const incoming = pipes[index - 1];
11164
- const outgoing = pipes[index];
11165
- const childDepth = this.cancellationDepth + 1;
11166
- const controls = [
11167
- { role: "pipeline-control", signal: controllers[index].signal }
11168
- ];
11169
- const prepared = prepareChildCancellation(
11170
- this.cancellation,
11171
- void 0,
11172
- this.cancellationAdmission(childDepth, controls.length),
11173
- controls
11174
- );
11175
- const owner = new InvocationCancellationOwner(io[invocationScope], prepared, this.cancellationState);
11176
- let boundary;
11177
- try {
11178
- boundary = owner.activate();
11179
- } catch (error) {
11180
- await owner.abandon(Promise.resolve());
11181
- throw error;
11182
- }
11183
- const signal = AbortSignal.any([boundary.deliverySignal, io[invocationScope].signal]);
11184
- const frame = {};
11185
- const runtime = new _Runtime(
11186
- this.fs,
11187
- this.commands,
11188
- this.middleware,
11189
- this.budget,
11190
- signal,
11191
- this.fileWrites,
11192
- this.outputFiles,
11193
- boundary.deliverySignal,
11194
- boundary,
11195
- this.cancellationState,
11196
- owner,
11197
- childDepth,
11198
- this.cancellationMaxDepth,
11199
- frame
11200
- );
11201
- const input2 = new ShellInput(incoming?.readable ?? io.stdin, this.budget, signal);
11202
- 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;
11203
11205
  try {
11204
- await outgoing.writable.write(chunk);
11205
- if (chunk.byteLength) written.add(index);
11206
+ boundary = owner.activate();
11206
11207
  } catch (error) {
11207
- if (errorCode(error) === "EPIPE") {
11208
- const closed = new PipelineClosed();
11209
- controllers[index].abort(closed);
11210
- throw closed;
11211
- }
11208
+ await owner.abandon(Promise.resolve());
11212
11209
  throw error;
11213
11210
  }
11214
- } };
11215
- const executeStage = async () => {
11216
- try {
11217
- let exitCode;
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) => {
11218
11231
  try {
11219
- const child = await cloneState(state, this.signal);
11220
- child.isolated = true;
11221
- exitCode = await interruptible(runtime.runCommandIsolated(command, child, {
11222
- ...isolateIO(io),
11223
- stdin: input2,
11224
- ...incoming ? { stdinIsDefault: false } : {},
11225
- stdout: pipeOutput ? this.budget.sink(pipeOutput, signal) : signalSink(io.stdout, signal),
11226
- stderr: signalSink(io.stderr, signal)
11227
- }).finally(() => stateMonitor(child)?.closeValues()), signal);
11232
+ await outgoing.writable.write(chunk);
11233
+ if (chunk.byteLength) written.add(index);
11228
11234
  } catch (error) {
11229
- if (!(error instanceof PipelineClosed)) throw error;
11230
- exitCode = 141;
11235
+ if (errorCode(error) === "EPIPE") {
11236
+ const closed = new PipelineClosed();
11237
+ controllers[index].abort(closed);
11238
+ throw closed;
11239
+ }
11240
+ throw error;
11231
11241
  }
11232
- return { exitCode };
11233
- } finally {
11234
- completed.add(index);
11235
- if (incoming) {
11236
- const upstream = index - 1;
11237
- const close = scheduleTurn(() => {
11238
- closing.delete(close);
11239
- if (written.has(upstream) && !completed.has(upstream)) controllers[upstream].abort(new PipelineClosed());
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;
11240
11276
  });
11241
- closing.add(close);
11242
- await incoming.abort();
11277
+ if (outgoing) await outgoing.close().catch(() => void 0);
11243
11278
  }
11244
- await input2.close().catch((error) => {
11245
- if (!(error instanceof PipelineClosed)) throw error;
11246
- });
11247
- if (outgoing) await outgoing.close().catch(() => void 0);
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 };
11248
11285
  }
11249
- };
11250
- let captured;
11251
- try {
11252
- captured = { kind: "return", value: await executeStage() };
11253
- } catch (reason) {
11254
- captured = frame.report && Object.is(frame.report.origin.signal.reason, reason) ? { kind: "throw", reason, report: frame.report } : { kind: "throw", reason };
11255
- }
11256
- const selection = await owner.finish(Promise.resolve(), captured);
11257
- if (selection.outcome.kind === "throw") throw selection.outcome.reason;
11258
- return selection.outcome.value.exitCode;
11259
- });
11260
- let statuses;
11261
- 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);
11262
11291
  statuses = await interruptible(Promise.all(tasks), this.signal);
11263
11292
  } finally {
11264
- for (const close of closing) cancelTurn(close);
11265
- for (const [index, controller] of controllers.entries()) if (!completed.has(index) || written.has(index)) controller.abort(new PipelineClosed());
11266
- await Promise.all(pipes.map((pipe) => pipe.abort()));
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
+ }
11267
11303
  }
11268
11304
  await this.publishStatus(state, statuses, io);
11269
11305
  status = state.pipefail ? statuses.findLast((status2) => status2 !== 0) ?? 0 : statuses.at(-1);
@@ -15169,6 +15205,7 @@ var cloudflareWorkerLimits = Object.freeze({
15169
15205
  maxInputBytes: 4 * 1024 * 1024,
15170
15206
  maxOutputBytes: 4 * 1024 * 1024,
15171
15207
  maxCommands: 1e3,
15208
+ maxPipelineStages: 64,
15172
15209
  maxLoopIterations: 1e3,
15173
15210
  maxSubstitutionDepth: 16,
15174
15211
  maxSourceBytes: 256 * 1024,