@poe-platform/safe-bash 0.1.801 → 0.1.803

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.
Files changed (198) hide show
  1. package/README.md +4 -2
  2. package/dist/image-ast/index.browser.js +16 -5
  3. package/dist/image-ast/index.js +16 -5
  4. package/dist/safe-bash/chunks/chunk-2LSAMQER.js +84 -0
  5. package/dist/safe-bash/chunks/chunk-3HQU4OJO.js +13 -0
  6. package/dist/safe-bash/chunks/chunk-4BSJLKNM.js +14 -0
  7. package/dist/safe-bash/chunks/chunk-4D4N7IU2.js +47 -0
  8. package/dist/safe-bash/chunks/chunk-55YJASTN.js +14 -0
  9. package/dist/safe-bash/chunks/{chunk-NZQXYWA3.js → chunk-5OHX7C2V.js} +0 -1
  10. package/dist/safe-bash/chunks/chunk-7ZBU7KYV.js +14 -0
  11. package/dist/safe-bash/chunks/{chunk-7VNF5BFF.js → chunk-B7PIL77G.js} +101 -415
  12. package/dist/safe-bash/chunks/chunk-DQP3VHSB.js +15 -0
  13. package/dist/safe-bash/chunks/{chunk-VQDD3G76.js → chunk-EEEWOYEG.js} +18 -18
  14. package/dist/safe-bash/chunks/chunk-FZE4HW6G.js +11 -0
  15. package/dist/safe-bash/chunks/{chunk-45PK3NWI.js → chunk-GDYNCWRV.js} +1 -1
  16. package/dist/safe-bash/chunks/chunk-GEG3BWGE.js +14 -0
  17. package/dist/safe-bash/chunks/chunk-HBCN24ZA.js +50 -0
  18. package/dist/safe-bash/chunks/chunk-HZ7BWKQ3.js +13 -0
  19. package/dist/safe-bash/chunks/{chunk-ICFDYV64.js → chunk-HZAMGT5I.js} +2 -2
  20. package/dist/safe-bash/chunks/{chunk-FNDNHAGE.js → chunk-JMMEIDPF.js} +2 -2
  21. package/dist/safe-bash/chunks/{chunk-IVRQ4BXL.js → chunk-PH63PLPZ.js} +7 -7
  22. package/dist/safe-bash/chunks/{chunk-SZH7EJLD.js → chunk-PNBBUWSM.js} +5529 -6547
  23. package/dist/safe-bash/chunks/chunk-QGUV42T5.js +44 -0
  24. package/dist/safe-bash/chunks/chunk-R3NAKOED.js +51 -0
  25. package/dist/safe-bash/chunks/chunk-RRR7AQ24.js +38 -0
  26. package/dist/safe-bash/chunks/{chunk-PQRAK7HU.js → chunk-RYFQ3LZG.js} +281 -476
  27. package/dist/safe-bash/chunks/chunk-VBTDHOWC.js +55 -0
  28. package/dist/safe-bash/chunks/{chunk-NR3EM4LS.js → chunk-VKNVHEX3.js} +1 -6
  29. package/dist/safe-bash/chunks/chunk-XAQMU6OY.js +14 -0
  30. package/dist/safe-bash/chunks/chunk-ZVD5IS4V.js +49 -0
  31. package/dist/safe-bash/command-chunks/{chunk-ORYGZYKW.js → chunk-4FEVBOL5.js} +1 -1
  32. package/dist/safe-bash/command-chunks/{chunk-VXSLJH7G.js → chunk-6JSIFWYT.js} +26 -6
  33. package/dist/safe-bash/command-chunks/chunk-A7MU7762.js +200 -0
  34. package/dist/safe-bash/command-chunks/{chunk-KJIMDLBB.js → chunk-BXCXRYVU.js} +1 -1
  35. package/dist/safe-bash/command-chunks/{chunk-F4TEEZTL.js → chunk-CQHP3I66.js} +1 -1
  36. package/dist/safe-bash/command-chunks/{chunk-PEF7K3UQ.js → chunk-EARHPPPJ.js} +1 -1
  37. package/dist/safe-bash/command-chunks/{chunk-QKFSRZGQ.js → chunk-GFC2NTDG.js} +2 -2
  38. package/dist/safe-bash/command-chunks/chunk-GIRNFXP3.js +466 -0
  39. package/dist/safe-bash/command-chunks/{chunk-EFANWIHL.js → chunk-GY3BWK7K.js} +1 -0
  40. package/dist/safe-bash/command-chunks/{chunk-FPVUD6TH.js → chunk-HDCNKOIX.js} +9 -7
  41. package/dist/safe-bash/command-chunks/{chunk-MQFIPHIQ.js → chunk-ILX2NOLF.js} +18 -15
  42. package/dist/safe-bash/command-chunks/{chunk-5E4WAO4O.js → chunk-JD5QNRNO.js} +3 -3
  43. package/dist/safe-bash/command-chunks/{chunk-I237SNW5.js → chunk-LFJJQQND.js} +1 -1
  44. package/dist/safe-bash/command-chunks/{chunk-W5DNF4JH.js → chunk-LOICUCHG.js} +1 -1
  45. package/dist/safe-bash/command-chunks/{chunk-7U7EXOXX.js → chunk-NASVPT6F.js} +2 -1
  46. package/dist/safe-bash/command-chunks/{chunk-WBNZ4PRE.js → chunk-NGG2XL56.js} +7 -4
  47. package/dist/safe-bash/command-chunks/{chunk-GLOZX57Y.js → chunk-NKIELG7Y.js} +45 -115
  48. package/dist/safe-bash/command-chunks/{chunk-WPYIOKE3.js → chunk-PICVQ6B5.js} +2 -2
  49. package/dist/safe-bash/command-chunks/{chunk-YOFC45RK.js → chunk-QVOS4YXL.js} +1 -1
  50. package/dist/safe-bash/command-chunks/{chunk-VGG2DL5Q.js → chunk-TRR4MYWF.js} +4 -0
  51. package/dist/safe-bash/command-chunks/{chunk-2JRBIDAD.js → chunk-V4K2JDYU.js} +2 -2
  52. package/dist/safe-bash/command-chunks/{chunk-CZ7EN3JG.js → chunk-VT6MJBEI.js} +1 -1
  53. package/dist/safe-bash/command-chunks/{chunk-PCEFOYA3.js → chunk-WWIBP2ET.js} +41 -114
  54. package/dist/safe-bash/command-chunks/{chunk-F6OYH562.js → chunk-X54L3DBL.js} +4 -9
  55. package/dist/safe-bash/command-chunks/{chunk-TNOA7FCQ.js → chunk-YVNGTIJO.js} +1 -1
  56. package/dist/safe-bash/command-chunks/chunk-ZDN7MJE6.js +168 -0
  57. package/dist/safe-bash/commands/apply-patch/index.browser.js +14 -0
  58. package/dist/safe-bash/commands/archive/index.browser.js +36 -0
  59. package/dist/safe-bash/commands/bytes/compression/index.js +54 -51
  60. package/dist/safe-bash/commands/chmod/index.browser.js +14 -0
  61. package/dist/safe-bash/commands/chmod/index.d.ts +2 -0
  62. package/dist/safe-bash/commands/chmod/index.js +2 -0
  63. package/dist/safe-bash/commands/column/index.browser.js +12 -0
  64. package/dist/safe-bash/commands/du/index.browser.js +14 -0
  65. package/dist/safe-bash/commands/expr/index.browser.js +12 -0
  66. package/dist/safe-bash/commands/file/index.browser.js +14 -0
  67. package/dist/safe-bash/commands/filesystem.js +9 -2
  68. package/dist/safe-bash/commands/grep-aliases/index.browser.js +14 -0
  69. package/dist/safe-bash/commands/html-to-markdown/index.browser.js +16 -0
  70. package/dist/safe-bash/commands/metadata/chmod.d.ts +1 -7
  71. package/dist/safe-bash/commands/metadata/chmod.js +1 -204
  72. package/dist/safe-bash/commands/metadata/index.browser.js +17 -0
  73. package/dist/safe-bash/commands/metadata/internal.d.ts +1 -30
  74. package/dist/safe-bash/commands/metadata/internal.js +1 -76
  75. package/dist/safe-bash/commands/metadata/mktemp.d.ts +1 -3
  76. package/dist/safe-bash/commands/metadata/mktemp.js +1 -202
  77. package/dist/safe-bash/commands/metadata/stat.d.ts +1 -7
  78. package/dist/safe-bash/commands/metadata/stat.js +1 -530
  79. package/dist/safe-bash/commands/mktemp/index.browser.js +13 -0
  80. package/dist/safe-bash/commands/mktemp/index.d.ts +2 -0
  81. package/dist/safe-bash/commands/mktemp/index.js +2 -0
  82. package/dist/safe-bash/commands/network/index.browser.js +1 -1
  83. package/dist/safe-bash/commands/node/index.browser.js +4 -4
  84. package/dist/safe-bash/commands/portable-random.d.ts +1 -1
  85. package/dist/safe-bash/commands/portable-random.js +1 -12
  86. package/dist/safe-bash/commands/python/index.browser.js +8 -8
  87. package/dist/safe-bash/commands/regex-execution/public.browser.js +5 -3
  88. package/dist/safe-bash/commands/split/index.browser.js +14 -0
  89. package/dist/safe-bash/commands/stat/index.browser.js +13 -0
  90. package/dist/safe-bash/commands/stat/index.d.ts +2 -0
  91. package/dist/safe-bash/commands/stat/index.js +2 -0
  92. package/dist/safe-bash/commands/stream-format/index.browser.js +11 -0
  93. package/dist/safe-bash/commands/stream-inspection/index.browser.js +11 -0
  94. package/dist/safe-bash/commands/streams.js +5 -5
  95. package/dist/safe-bash/commands/table-text/index.browser.js +11 -0
  96. package/dist/safe-bash/commands/text.js +48 -143
  97. package/dist/safe-bash/commands/time-env/index.browser.js +15 -0
  98. package/dist/safe-bash/commands/tree/index.browser.js +14 -0
  99. package/dist/safe-bash/full-core.browser.js +256 -247
  100. package/dist/safe-bash/opt-in/commands/yq/native-work.js +1 -0
  101. package/dist/safe-bash/optional-host.browser.js +12 -12
  102. package/dist/safe-bash/plugins/index.browser.js +25 -11
  103. package/dist/safe-bash/registry-entry.browser.js +28 -14
  104. package/dist/safe-bash/search.browser.js +48 -0
  105. package/dist/safe-bash/shell/runtime.d.ts +3 -9
  106. package/dist/safe-bash/shell/runtime.js +63 -311
  107. package/dist/safe-bash/shell/shell.js +0 -23
  108. package/dist/safe-bash/shell/types.d.ts +2 -0
  109. package/dist/safe-bash/shell/worker-limits.js +1 -0
  110. package/dist/safe-bash/shell-entry.browser.js +19 -10
  111. package/dist/safe-bash/worker/host.js +1 -1
  112. package/dist/safe-bash-command-bc/index.js +12 -5
  113. package/dist/safe-bash-command-bzip2/index.js +4 -3
  114. package/dist/safe-bash-command-chmod/LICENSE +21 -0
  115. package/dist/safe-bash-command-chmod/command.d.ts +7 -0
  116. package/dist/safe-bash-command-chmod/command.js +11 -0
  117. package/dist/safe-bash-command-chmod/index.d.ts +6 -0
  118. package/dist/safe-bash-command-chmod/index.js +27 -0
  119. package/dist/safe-bash-command-exiftool/index.js +5 -5
  120. package/dist/safe-bash-command-find/find.js +1 -1
  121. package/dist/safe-bash-command-find/index.js +1 -1
  122. package/dist/safe-bash-command-fmt/index.js +9 -2
  123. package/dist/safe-bash-command-gzip/index.js +45 -42
  124. package/dist/safe-bash-command-imagemagick/index.js +3 -1
  125. package/dist/safe-bash-command-jq/index.js +1 -1
  126. package/dist/safe-bash-command-jq/jq.js +1 -1
  127. package/dist/safe-bash-command-less/index.js +12 -3
  128. package/dist/safe-bash-command-mktemp/LICENSE +21 -0
  129. package/dist/safe-bash-command-mktemp/command.d.ts +3 -0
  130. package/dist/safe-bash-command-mktemp/command.js +9 -0
  131. package/dist/safe-bash-command-mktemp/index.d.ts +6 -0
  132. package/dist/safe-bash-command-mktemp/index.js +25 -0
  133. package/dist/safe-bash-command-nl/index.js +1 -1
  134. package/dist/safe-bash-command-nl/nl.js +1 -1
  135. package/dist/safe-bash-command-od/index.js +6 -2
  136. package/dist/safe-bash-command-op/index.js +25 -6
  137. package/dist/safe-bash-command-rg/index.js +1 -1
  138. package/dist/safe-bash-command-rg/rg-command.d.ts +0 -1
  139. package/dist/safe-bash-command-rg/rg-command.js +3 -5
  140. package/dist/safe-bash-command-sed/index.js +1 -1
  141. package/dist/safe-bash-command-sed/sed.js +1 -1
  142. package/dist/safe-bash-command-sips/index.js +13 -5
  143. package/dist/safe-bash-command-sponge/index.js +10 -3
  144. package/dist/safe-bash-command-stat/LICENSE +21 -0
  145. package/dist/safe-bash-command-stat/command.d.ts +7 -0
  146. package/dist/safe-bash-command-stat/command.js +9 -0
  147. package/dist/safe-bash-command-stat/index.d.ts +6 -0
  148. package/dist/safe-bash-command-stat/index.js +25 -0
  149. package/dist/safe-bash-command-unexpand/index.js +1 -1
  150. package/dist/safe-bash-command-unexpand/unexpand.js +1 -1
  151. package/dist/safe-bash-command-unrtf/index.js +11 -1
  152. package/dist/safe-bash-command-xxd/index.js +6 -2
  153. package/dist/safe-bash-command-xz/command.d.ts +1 -1
  154. package/dist/safe-bash-command-xz/index.js +3 -2
  155. package/dist/safe-bash-command-yq/index.js +1 -0
  156. package/dist/safe-bash-command-yq/native-work.js +1 -0
  157. package/dist/safe-bash-command-yq/query.js +3 -0
  158. package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
  159. package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
  160. package/dist/safe-bash-compression-engine/files.js +6 -6
  161. package/dist/safe-bash-compression-engine/index.js +5 -5
  162. package/dist/safe-bash-compression-engine/operand.js +6 -6
  163. package/dist/safe-bash-compression-engine/options.js +1 -1
  164. package/dist/safe-bash-compression-engine/stream.js +5 -5
  165. package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
  166. package/dist/safe-bash-contracts/escaping.js +2 -2
  167. package/dist/safe-bash-contracts/filesystem-output.js +2 -2
  168. package/dist/safe-bash-contracts/index.js +2 -2
  169. package/dist/safe-bash-contracts/io.d.ts +2 -0
  170. package/dist/safe-bash-contracts/io.js +1 -1
  171. package/dist/safe-bash-contracts/output.js +2 -2
  172. package/dist/safe-bash-io-engine/commands/search/requirements.js +1 -1
  173. package/dist/safe-bash-io-engine/commands/text-programs/shared.js +1 -1
  174. package/dist/safe-bash-mcp/index.browser.js +11 -1
  175. package/dist/safe-bash-mcp/index.js +38 -17
  176. package/dist/safe-bash-metadata-engine/LICENSE +21 -0
  177. package/dist/safe-bash-metadata-engine/index.d.ts +30 -0
  178. package/dist/safe-bash-metadata-engine/index.js +82 -0
  179. package/dist/safe-bash-metadata-engine/random.d.ts +1 -0
  180. package/dist/safe-bash-metadata-engine/random.js +21 -0
  181. package/dist/safe-bash-regex-engine/index.js +4 -4
  182. package/dist/safe-bash-regex-engine/text/budget.d.ts +0 -1
  183. package/dist/safe-bash-regex-engine/text/budget.js +1 -1
  184. package/dist/safe-bash-regex-engine/text/regex.js +4 -4
  185. package/dist/safe-bash-regex-engine/text/replacement-buffer.js +2 -2
  186. package/dist/safe-bash-regex-engine/text/rust-syntax.js +2 -2
  187. package/dist/safe-bash-search-engine/ergonomic-regex.js +2 -2
  188. package/dist/safe-bash-search-engine/glob.js +2 -2
  189. package/dist/safe-bash-search-engine/grep.js +2 -2
  190. package/dist/safe-bash-search-engine/matcher.js +2 -2
  191. package/dist/safe-bash-search-engine/options.d.ts +2 -0
  192. package/dist/safe-bash-search-engine/options.js +1 -1
  193. package/dist/safe-bash-search-engine/output.js +1 -1
  194. package/dist/safe-bash-search-engine/shared.js +2 -2
  195. package/dist/safe-bash-search-engine/walk.js +3 -3
  196. package/dist/safe-playwright-cloudflare/browser-snapshot-json.js +2 -2
  197. package/dist/safe-playwright-cloudflare/browser-snapshot-references.js +1 -1
  198. package/package.json +91 -10
@@ -163,6 +163,7 @@ export const defaultLimits = {
163
163
  maxPathnameComponents: Infinity,
164
164
  maxRedirects: Infinity,
165
165
  maxPipelineStages: Infinity,
166
+ maxPipelineBytes: Infinity,
166
167
  maxLoopIterations: Infinity,
167
168
  maxSubstitutionDepth: Infinity,
168
169
  maxFunctionDepth: Infinity,
@@ -453,6 +454,7 @@ function tickSharedWallClockBudgets() {
453
454
  }
454
455
  }
455
456
  export class Budget {
457
+ pipelineBytes = 0;
456
458
  get fileSystemOperations() {
457
459
  return this._fileSystemOperations;
458
460
  }
@@ -494,7 +496,7 @@ export class Budget {
494
496
  this.maxSourceBytesSmi = limits.maxSourceBytes | 0;
495
497
  if (limits.maxPipelineStages < 0x3fffffff)
496
498
  this.maxPipelineStagesSmi = limits.maxPipelineStages | 0;
497
- if (limits.pipeHighWaterMark < 65536)
499
+ if (limits.pipeHighWaterMark < 65536 || limits.maxPipelineBytes !== Infinity)
498
500
  this.canSyncPurePipe = false;
499
501
  this.signal = signal ? combineManagedSignals(signal, this.controller.signal) : this.controller.signal;
500
502
  if (signal)
@@ -643,6 +645,16 @@ export class Budget {
643
645
  set fsOperations(value) {
644
646
  this._fileSystemOperations = value;
645
647
  }
648
+ pipelineInput = (bytes) => {
649
+ if (this.limits.maxPipelineBytes === Infinity)
650
+ return;
651
+ this.assertPipelineInput(bytes);
652
+ this.pipelineBytes += bytes;
653
+ };
654
+ assertPipelineInput(bytes) {
655
+ if (bytes > this.limits.maxPipelineBytes - this.pipelineBytes)
656
+ this.fail("maxPipelineBytes");
657
+ }
646
658
  reservePipelineStages(count) {
647
659
  this.signal.throwIfAborted();
648
660
  if (count > this.limits.maxPipelineStages - this._pipelineStages)
@@ -1493,6 +1505,7 @@ class BudgetedPipeStageSink {
1493
1505
  return Boolean(w.open && pipe && !pipe.failed && !pipe.signal?.aborted && pipe.readerReferences && (!pipe.writes || pipe.writes.size === 0) && (pipe.availableBytes ?? 0) < (pipe.highWaterMark ?? 0));
1494
1506
  }
1495
1507
  writeSync(chunk) {
1508
+ this.budget.assertPipelineInput(chunk.byteLength);
1496
1509
  this.budget.bytes += chunk.byteLength;
1497
1510
  this.writable.write(chunk);
1498
1511
  if (chunk.byteLength && this.written)
@@ -7446,282 +7459,6 @@ export class Runtime {
7446
7459
  }
7447
7460
  }
7448
7461
  }
7449
- tryRunFastConstEchoBatch(entryCachedUnit, sourceLength, state, io) {
7450
- if (state.noexec)
7451
- return undefined;
7452
- let leadingMkdirUnit;
7453
- let leadingMkdirPaths;
7454
- let firstCachedUnit = entryCachedUnit;
7455
- let firstCc = firstCachedUnit.unit.script._fastConstEcho;
7456
- if (!firstCc) {
7457
- const nextU = entryCachedUnit.nextCached;
7458
- if (!nextU || entryCachedUnit.locale !== false || nextU.locale !== false || (entryCachedUnit.unit.script.warnings && entryCachedUnit.unit.script.warnings.length > 0))
7459
- return undefined;
7460
- firstCc = nextU.unit.script._fastConstEcho;
7461
- if (!firstCc)
7462
- return undefined;
7463
- const mScript = entryCachedUnit.unit.script;
7464
- let mPaths = mScript._cachedMkdirPPaths;
7465
- if (mPaths === undefined) {
7466
- mPaths = null;
7467
- if (mScript.lists.length === 1 && !mScript.lists[0].terminator && mScript.lists[0].pipelines.length === 1 && !mScript.lists[0].pipelines[0].negate && mScript.lists[0].pipelines[0].commands.length === 1) {
7468
- const mCmd = mScript.lists[0].pipelines[0].commands[0];
7469
- if (mCmd.kind === "simple" && mCmd.redirects.length === 0 && mCmd.words.length >= 3 && mCmd.words[0].plain === "mkdir" && mCmd.words[1].plain === "-p") {
7470
- const arr = [];
7471
- let ok = true;
7472
- for (let wi = 2; wi < mCmd.words.length; wi++) {
7473
- const wp = mCmd.words[wi].plain;
7474
- if (!wp || !isCleanAbsolutePath(wp) || wp === "/" || wp === "/dev" || wp.startsWith("/dev/")) {
7475
- ok = false;
7476
- break;
7477
- }
7478
- arr.push(wp);
7479
- }
7480
- if (ok)
7481
- mPaths = arr;
7482
- }
7483
- }
7484
- mScript._cachedMkdirPPaths = mPaths;
7485
- }
7486
- if (!mPaths)
7487
- return undefined;
7488
- leadingMkdirUnit = entryCachedUnit;
7489
- leadingMkdirPaths = mPaths;
7490
- firstCachedUnit = nextU;
7491
- }
7492
- if (this.middleware.length > 0 || io.terminal !== undefined || io.asyncDefaultInput !== undefined || io.admittedHandles !== undefined || (this._fileWrites !== undefined && this._fileWrites.size > 0) || !this._isMemoryBackingFs || !this.backingFs || !this.budget.canRedirect1 || !this.budget.hasInfiniteFsOps || (io.descriptors && (io.descriptors.size > 3 || io.descriptors.get(0)?.closed || io.descriptors.get(1)?.closed || io.descriptors.get(2)?.closed))) {
7493
- return undefined;
7494
- }
7495
- const monitor = ensureStateMonitor(state, this.budget, io[invocationScope]);
7496
- const rawState = monitor.raw;
7497
- if (!this.tryStartExtensionsSync(state) || hasActiveExtensions(rawState) || rawState.externalInvocation || hasActiveVariableAttributes(rawState) || guestArrays(state) || rawState.noclobber || rawState.readonlyVariables?.has("PIPESTATUS") || hasShellFunction(rawState, "echo") || rawState.extensions?.builtins.has("echo")) {
7498
- return undefined;
7499
- }
7500
- const def = this.commands.get("echo");
7501
- if (!def || !defaultEchoExecutors.has(def.execute))
7502
- return undefined;
7503
- const store = monitor.store;
7504
- const existing = store?.get("PIPESTATUS");
7505
- const psTarget = existing ? "indexed" : pipelineStatusTarget(rawState);
7506
- if ((psTarget !== "indexed" && psTarget !== "absent") || store?.watches.has("PIPESTATUS") || monitor.hasOverlay("PIPESTATUS"))
7507
- return undefined;
7508
- if (existing && (existing.associative || existing.values.size !== 1 || existing.maximum !== 0))
7509
- return undefined;
7510
- const elem0 = existing?.values.get(0);
7511
- if (existing && (!elem0 || elem0.text.bytes !== 1 || existing.references !== 1 || elem0.text.references !== 1))
7512
- return undefined;
7513
- const byteLength0 = firstCc.encoded.byteLength;
7514
- if ((this.budget.bytes + byteLength0 > this.budget.maxOutputBytesSmi && byteLength0 > this.budget.limits.maxOutputBytes - this.budget.bytes) || !this.budget.canFileSystemOperation() || (this.budget.commands + 1 > this.budget.maxCommandsSmi && this.budget.commands + 1 > this.budget.limits.maxCommands)) {
7515
- return undefined;
7516
- }
7517
- const umask = rawState.umask ?? 0o022;
7518
- if (leadingMkdirUnit !== undefined && leadingMkdirPaths !== undefined) {
7519
- if ((umask & 0o300) !== 0 || (this._outputFiles !== undefined && this._outputFiles.size > 0) || hasShellFunction(rawState, "mkdir") || rawState.extensions?.builtins.has("mkdir"))
7520
- return undefined;
7521
- const mkdirDef = this.commands.get("mkdir");
7522
- if (!mkdirDef || !defaultMkdirExecutors.has(mkdirDef.execute))
7523
- return undefined;
7524
- const dirMode = 0o777 & ~umask;
7525
- try {
7526
- for (let mi = 0; mi < leadingMkdirPaths.length; mi++) {
7527
- const mp = leadingMkdirPaths[mi];
7528
- if (!tryMkdirMemorySync(this.backingFs, mp, true, dirMode, this.commandSignal, firstCc.dirPrefix.startsWith(mp) && firstCc.dirPrefix.length === mp.length + 1 ? firstCc.dirPrefix : undefined))
7529
- return undefined;
7530
- this.budget.fileSystemOperation();
7531
- }
7532
- }
7533
- catch {
7534
- this.signal.throwIfAborted();
7535
- return undefined;
7536
- }
7537
- this.budget.commands++;
7538
- this.budget.parsing.admit(firstCachedUnit.unitsCharged);
7539
- }
7540
- const mode = 0o666 & ~umask;
7541
- try {
7542
- if (!tryWriteMemoryFileInDirSync(this.backingFs, firstCc.dirPrefix, firstCc.fileName, firstCc.encoded, firstCc.append, mode, this.commandSignal))
7543
- return undefined;
7544
- }
7545
- catch {
7546
- this.signal.throwIfAborted();
7547
- return undefined;
7548
- }
7549
- this.budget.tick();
7550
- this.budget.fileSystemOperation();
7551
- this.budget.bytes += byteLength0;
7552
- let lastArg = firstCc.arg0;
7553
- let cur = firstCachedUnit;
7554
- const vars = rawState.variables;
7555
- const curLocale = (vars.LC_ALL || vars.LC_CTYPE || vars.LANG) ? byteLocale(vars) : false;
7556
- const mem = this.backingFs;
7557
- let deadRmTarget;
7558
- let deadRmTargetLen = 0;
7559
- const rmDef = this.commands.get("rm");
7560
- if (mem.symlinkCount === 0 && curLocale === false && rmDef && defaultRmExecutors.has(rmDef.execute) && !hasShellFunction(rawState, "rm") && !rawState.extensions?.builtins.has("rm")) {
7561
- const cachedCc = firstCc;
7562
- let target = cachedCc._cachedRmTarget;
7563
- let scanCount = cachedCc._cachedScanCount ?? 0;
7564
- if (target === undefined) {
7565
- let scan = firstCachedUnit;
7566
- scanCount = 1;
7567
- while (scan.nextCached !== undefined && scan.nextCached.locale === false && (!scan.nextCached.unit.script.warnings || scan.nextCached.unit.script.warnings.length === 0) && scan.nextCached.unit.script._fastConstEcho !== undefined) {
7568
- scan = scan.nextCached;
7569
- scanCount++;
7570
- }
7571
- target = null;
7572
- const after = scan.nextCached;
7573
- if (after !== undefined && after.locale === false && (!after.unit.script.warnings || after.unit.script.warnings.length === 0) && after.unit.script.lists.length === 1) {
7574
- const list0 = after.unit.script.lists[0];
7575
- if (!list0.terminator && list0.pipelines.length === 1 && !list0.pipelines[0].negate && list0.pipelines[0].commands.length === 1) {
7576
- const cmd0 = list0.pipelines[0].commands[0];
7577
- if (cmd0.kind === "simple" && cmd0.redirects.length === 0 && cmd0.words.length === 3 && cmd0.words[0].plain === "rm" && (cmd0.words[1].plain === "-rf" || cmd0.words[1].plain === "-fr")) {
7578
- const t = cmd0.words[2].plain;
7579
- if (t && t.length > 1 && t.charCodeAt(0) === 47 && t.charCodeAt(t.length - 1) !== 47 && !t.includes("/."))
7580
- target = t;
7581
- }
7582
- }
7583
- }
7584
- cachedCc._cachedRmTarget = target;
7585
- cachedCc._cachedScanCount = scanCount;
7586
- }
7587
- if (target !== null && this.budget.commands + scanCount + 1 <= this.budget.maxCommandsSmi && tryGetMemoryDirectoryEntryNamesSync(this.backingFs, target)?.size === 0) {
7588
- deadRmTarget = target;
7589
- deadRmTargetLen = target.length;
7590
- }
7591
- }
7592
- const cachedBatchPlan = deadRmTarget !== undefined ? firstCc._cachedEchoBatch : undefined;
7593
- if (cachedBatchPlan !== undefined && cachedBatchPlan !== null && mem.symlinkCount === 0 && !this.signal.aborted && this.budget.bytes + cachedBatchPlan.totalBytes <= this.budget.maxOutputBytesSmi && this.budget._fileSystemOperations + cachedBatchPlan.totalCount <= this.budget.maxFileSystemOperationsSmi && this.budget.commands + cachedBatchPlan.totalCount <= this.budget.maxCommandsSmi) {
7594
- this.budget.parsing.admit(cachedBatchPlan.totalUnitsCharged);
7595
- try {
7596
- mem.writeMemoryFilesInDirBatchFast(firstCc.fileName, firstCc.dirPrefix, cachedBatchPlan.fileNames, cachedBatchPlan.nameHashes, cachedBatchPlan.payloads, cachedBatchPlan.totalNameBytes, cachedBatchPlan.payloadBytesSum, mode);
7597
- this.budget.commands += cachedBatchPlan.totalCount;
7598
- this.budget._fileSystemOperations += cachedBatchPlan.totalCount;
7599
- this.budget.bytes += cachedBatchPlan.totalBytes;
7600
- lastArg = cachedBatchPlan.lastArg;
7601
- cur = cachedBatchPlan.endUnit;
7602
- }
7603
- catch {
7604
- this.signal.throwIfAborted();
7605
- }
7606
- }
7607
- if (cur !== cachedBatchPlan?.endUnit && cur.unit.next < sourceLength && mem.symlinkCount === 0 && !this.signal.aborted) {
7608
- const buildBatchStart = cur === firstCachedUnit && deadRmTarget !== undefined && cachedBatchPlan === undefined;
7609
- let bTotalCount = 0;
7610
- let bTotalBytes = 0;
7611
- let bTotalUnits = 0;
7612
- let bTotalNameBytes = 0;
7613
- let bPayloadBytesSum = 0;
7614
- let bCanCache = buildBatchStart && !firstCc.append;
7615
- const bFileNames = bCanCache ? [] : undefined;
7616
- const bHashes = bCanCache ? [] : undefined;
7617
- const bPayloads = bCanCache ? [] : undefined;
7618
- const bSeenNames = bCanCache ? new Set([firstCc.fileName]) : undefined;
7619
- while (cur.unit.next < sourceLength && mem.symlinkCount === 0 && !this.signal.aborted) {
7620
- const next = cur.nextCached;
7621
- if (!next || next.locale !== curLocale || (next.unit.script.warnings && next.unit.script.warnings.length > 0))
7622
- break;
7623
- const nextCc = next.unit.script._fastConstEcho;
7624
- if (!nextCc)
7625
- break;
7626
- const bLen = nextCc.encoded.byteLength;
7627
- if (this.budget.bytes + bLen > this.budget.maxOutputBytesSmi || this.budget._fileSystemOperations + 1 > this.budget.maxFileSystemOperationsSmi || this.budget.commands + 1 > this.budget.maxCommandsSmi) {
7628
- break;
7629
- }
7630
- this.budget.parsing.admit(next.unitsCharged);
7631
- if (!(deadRmTarget !== undefined && nextCc.dirPrefix.length === deadRmTargetLen + 1 && nextCc.dirPrefix.charCodeAt(deadRmTargetLen) === 47 && nextCc.dirPrefix.startsWith(deadRmTarget))) {
7632
- let nameHash = nextCc._nameHash;
7633
- if (nameHash === undefined) {
7634
- const fn = nextCc.fileName;
7635
- let h = 5381;
7636
- for (let ci = 0; ci < fn.length; ci++)
7637
- h = (((h & 0x1fffff) * 33) ^ fn.charCodeAt(ci)) & 0x3fffffff;
7638
- nextCc._nameHash = nameHash = h;
7639
- }
7640
- try {
7641
- mem.writeMemoryFileInDirFast(nextCc.dirPrefix, nextCc.fileName, nextCc.encoded, nextCc.append, mode, nameHash);
7642
- }
7643
- catch {
7644
- this.signal.throwIfAborted();
7645
- break;
7646
- }
7647
- }
7648
- if (bCanCache) {
7649
- const isDeadRm = deadRmTarget !== undefined && nextCc.dirPrefix.length === deadRmTargetLen + 1 && nextCc.dirPrefix.charCodeAt(deadRmTargetLen) === 47 && nextCc.dirPrefix.startsWith(deadRmTarget);
7650
- if (isDeadRm) {
7651
- bTotalCount++;
7652
- bTotalBytes += bLen;
7653
- bTotalUnits += next.unitsCharged;
7654
- }
7655
- else if (!nextCc.append && nextCc.dirPrefix === firstCc.dirPrefix && nextCc.fileName.length <= 85 && !bSeenNames.has(nextCc.fileName)) {
7656
- bSeenNames.add(nextCc.fileName);
7657
- bFileNames.push(nextCc.fileName);
7658
- bHashes.push(nextCc._nameHash);
7659
- bPayloads.push(nextCc.encoded);
7660
- bTotalNameBytes += nextCc.fileName.length * 2;
7661
- bPayloadBytesSum += bLen;
7662
- bTotalCount++;
7663
- bTotalBytes += bLen;
7664
- bTotalUnits += next.unitsCharged;
7665
- }
7666
- else
7667
- bCanCache = false;
7668
- }
7669
- this.budget.commands++;
7670
- this.budget._fileSystemOperations++;
7671
- this.budget.bytes += bLen;
7672
- lastArg = nextCc.arg0;
7673
- cur = next;
7674
- }
7675
- if (buildBatchStart) {
7676
- firstCc._cachedEchoBatch = bCanCache && bTotalCount > 0
7677
- ? {
7678
- endUnit: cur, totalCount: bTotalCount, totalBytes: bTotalBytes, totalUnitsCharged: bTotalUnits, lastArg, fileNames: bFileNames, nameHashes: new Int32Array(bHashes), payloads: bPayloads, totalNameBytes: bTotalNameBytes, payloadBytesSum: bPayloadBytesSum,
7679
- }
7680
- : null;
7681
- }
7682
- }
7683
- if (deadRmTarget !== undefined && cur.nextCached !== undefined && !this.signal.aborted && mem.symlinkCount === 0 && (this._outputFiles === undefined || this._outputFiles.size === 0) && !hasShellFunction(rawState, "rm") && !rawState.extensions?.builtins.has("rm")) {
7684
- const rmDef = this.commands.get("rm");
7685
- const rmUnit = cur.nextCached;
7686
- const rmCmd0 = rmUnit.unit.script.lists[0]?.pipelines[0]?.commands[0];
7687
- if (rmDef && defaultRmExecutors.has(rmDef.execute) && rmCmd0 && rmCmd0.kind === "simple" && rmCmd0.words[0]?.plain === "rm" && rmCmd0.words[2]?.plain === deadRmTarget) {
7688
- let rmOk = false;
7689
- try {
7690
- rmOk = tryRmRfMemorySync(this.backingFs, deadRmTarget, this.commandSignal);
7691
- }
7692
- catch {
7693
- this.signal.throwIfAborted();
7694
- }
7695
- if (rmOk) {
7696
- this.budget.parsing.admit(rmUnit.unitsCharged);
7697
- this.budget.commands++;
7698
- this.budget._fileSystemOperations++;
7699
- lastArg = deadRmTarget;
7700
- cur = rmUnit;
7701
- }
7702
- }
7703
- }
7704
- const restEpoch = monitor.chargeInternal(syncRestorationCharge, syncRestorationTickets).epoch;
7705
- rawState.substitutionStatus = 0;
7706
- if (rawState.variables._ !== undefined)
7707
- delete rawState.variables._;
7708
- rawState.lastArgument = lastArg;
7709
- if (io.assignmentDiagnosticContext)
7710
- io.assignmentDiagnosticContext.name = undefined;
7711
- if (!existing) {
7712
- monitor.lazyPipeStatus = singleStatusZero;
7713
- monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets);
7714
- }
7715
- else {
7716
- elem0.text.shellValue = "0";
7717
- store.changed(monitor.chargeInternal(syncPipeStatusCharge, syncPipeStatusTickets), "PIPESTATUS");
7718
- }
7719
- rawState.status = 0;
7720
- monitor.epoch = restEpoch;
7721
- if (store)
7722
- store.epoch = restEpoch;
7723
- return cur;
7724
- }
7725
7462
  tryRunCachedSyncForScript(script, monitor, io) {
7726
7463
  const rawScript = script;
7727
7464
  let plan = rawScript._cachedSyncForScriptPlan;
@@ -7808,6 +7545,9 @@ export class Runtime {
7808
7545
  rawScript._cachedSyncForScriptPlan = plan;
7809
7546
  }
7810
7547
  const forPlan = plan.forCmd._cachedForPlan;
7548
+ // Only integer registers can skip unquoted field splitting and globbing.
7549
+ if (plan.echoVar !== undefined && (!forPlan.touchedIntNamesList.includes(plan.echoVar) || forPlan.touchedIntNamesList.includes("IFS") || (rawState.variables.IFS !== undefined && rawState.variables.IFS !== " \t\n") || plan.initAssigns.some(assignment => assignment.name === "IFS")))
7550
+ return undefined;
7811
7551
  const fastSyncSink = plan.echoVar !== undefined
7812
7552
  ? ((io.stdout instanceof BudgetedSyncSink && io.stdout.write === BudgetedSyncSink.prototype.write) || (io.stdout instanceof Capture && io.stdout.write === Capture.prototype.write) ? io.stdout : undefined)
7813
7553
  : undefined;
@@ -7815,6 +7555,10 @@ export class Runtime {
7815
7555
  const def = this.commands.get("echo");
7816
7556
  if (!fastSyncSink || !def || !defaultEchoExecutors.has(def.execute) || hasShellFunction(rawState, "echo") || rawState.extensions?.builtins.has("echo") || (io.descriptors && io.descriptors.get(1)?.output !== io.stdout))
7817
7557
  return undefined;
7558
+ // Every signed SMI plus a newline fits in 12 bytes. Admit the bound before
7559
+ // speculative arithmetic; smaller allowances use ordinary execution.
7560
+ if (this.budget.maxOutputBytesSmi - this.budget.bytes < 12)
7561
+ return undefined;
7818
7562
  }
7819
7563
  const store = monitor.store;
7820
7564
  const existing = store?.get("PIPESTATUS");
@@ -7841,36 +7585,40 @@ export class Runtime {
7841
7585
  for (const assignment of plan.initAssigns)
7842
7586
  finalValues.set(assignment.name, assignment.strVal);
7843
7587
  const regNames = forPlan.regNames;
7844
- for (let r = 1; r < regNames.length; r++) {
7845
- const refName = regNames[r];
7846
- const parsed = fastSafeInt(finalValues.get(refName) ?? rawState.variables[refName], this.budget.parsing);
7847
- if (parsed === undefined)
7848
- return undefined;
7849
- sharedLoopIntRegs[r] = parsed | 0;
7850
- }
7851
- const { ok } = runIntForLoop(forPlan.fastLoopWords, forPlan.bodyStepCount, forPlan.intSteps, this.budget.parsing);
7852
- if (!ok)
7853
- return undefined;
7854
- for (let r = 0; r < regNames.length; r++)
7855
- finalValues.set(regNames[r], intToStr(sharedLoopIntRegs[r]));
7588
+ const savedParseBudget = this.budget.parsing.snapshot();
7589
+ let admitted = false;
7856
7590
  let lastArg = "";
7857
- if (plan.echoVar !== undefined) {
7858
- const echoVal = finalValues.get(plan.echoVar) ?? rawState.variables[plan.echoVar] ?? "";
7859
- const ifs = finalValues.get("IFS") ?? rawState.variables.IFS;
7860
- if (ifs !== undefined && ifs !== " \t\n")
7861
- return undefined;
7862
- if (echoVal.startsWith("-") || echoVal.includes("\0"))
7863
- return undefined;
7864
- const encoded = encodeRedirectTextWithNewlineToScratch(echoVal);
7865
- if (!encoded)
7866
- return undefined;
7867
- const bLen = encoded.byteLength;
7868
- if (this.budget.bytes + bLen > this.budget.maxOutputBytesSmi)
7869
- return undefined;
7870
- if (!fastSyncSink.writeSync(encoded))
7591
+ try {
7592
+ for (let r = 1; r < regNames.length; r++) {
7593
+ const refName = regNames[r];
7594
+ const parsed = fastSafeInt(finalValues.get(refName) ?? rawState.variables[refName], this.budget.parsing);
7595
+ if (parsed === undefined)
7596
+ return undefined;
7597
+ sharedLoopIntRegs[r] = parsed | 0;
7598
+ }
7599
+ const { ok } = runIntForLoop(forPlan.fastLoopWords, forPlan.bodyStepCount, forPlan.intSteps, this.budget.parsing);
7600
+ if (!ok)
7871
7601
  return undefined;
7872
- this.budget.bytes += bLen;
7873
- lastArg = echoVal;
7602
+ for (const name of forPlan.touchedIntNamesList)
7603
+ finalValues.set(name, intToStr(sharedLoopIntRegs[regNames.indexOf(name)]));
7604
+ if (plan.echoVar !== undefined) {
7605
+ const echoVal = finalValues.get(plan.echoVar);
7606
+ const encoded = encodeRedirectTextWithNewlineToScratch(echoVal);
7607
+ if (!encoded)
7608
+ return undefined;
7609
+ const bLen = encoded.byteLength;
7610
+ if (this.budget.bytes + bLen > this.budget.maxOutputBytesSmi)
7611
+ return undefined;
7612
+ if (!fastSyncSink.writeSync(encoded))
7613
+ return undefined;
7614
+ this.budget.bytes += bLen;
7615
+ lastArg = echoVal;
7616
+ }
7617
+ admitted = true;
7618
+ }
7619
+ finally {
7620
+ if (!admitted)
7621
+ this.budget.parsing.restore(savedParseBudget);
7874
7622
  }
7875
7623
  for (const [name, value] of finalValues)
7876
7624
  rawState.variables[name] = value;
@@ -8529,7 +8277,7 @@ export class Runtime {
8529
8277
  const n = pipeline.commands.length;
8530
8278
  this.budget.enterPipelineStages(n);
8531
8279
  this.budget.commands += n;
8532
- const pipeOptions = { highWaterMark: this.budget.limits.pipeHighWaterMark, signal: this.signal };
8280
+ const pipeOptions = { highWaterMark: this.budget.limits.pipeHighWaterMark, signal: this.signal, admitWrite: this.budget.pipelineInput };
8533
8281
  const pipes = new Array(n - 1);
8534
8282
  for (let i = 0; i < n - 1; i++) {
8535
8283
  pipes[i] = createBytePipe(pipeOptions);
@@ -15697,8 +15445,8 @@ export class Runtime {
15697
15445
  this.budget.tick();
15698
15446
  this.budget.iterations += wordCount;
15699
15447
  this.budget.commands += wordCount * forPlan.bodyStepCount;
15700
- for (let r = 0; r < regNames.length; r++) {
15701
- rawState.variables[regNames[r]] = intToStr(sharedLoopIntRegs[r]);
15448
+ for (const name of forPlan.touchedIntNamesList) {
15449
+ rawState.variables[name] = intToStr(sharedLoopIntRegs[regNames.indexOf(name)]);
15702
15450
  }
15703
15451
  const touchedList = forPlan.touchedIntNamesList;
15704
15452
  for (let t = 0; t < touchedList.length; t++) {
@@ -17082,8 +16830,8 @@ export class Runtime {
17082
16830
  rawState.status = 0;
17083
16831
  }
17084
16832
  runYieldCheckpoint(this.signal);
17085
- for (let r = 0; r < regNames.length; r++) {
17086
- rawState.variables[regNames[r]] = intToStr(sharedLoopIntRegs[r]);
16833
+ for (const name of forPlan.touchedIntNamesList) {
16834
+ rawState.variables[name] = intToStr(sharedLoopIntRegs[regNames.indexOf(name)]);
17087
16835
  }
17088
16836
  regNames.length = 0;
17089
16837
  }
@@ -18591,7 +18339,7 @@ export class Runtime {
18591
18339
  }
18592
18340
  for (let index = 1; index < pipeline.commands.length; index++)
18593
18341
  pipes.push(createBytePipe({
18594
- highWaterMark: this.budget.limits.pipeHighWaterMark, signal: this.signal,
18342
+ highWaterMark: this.budget.limits.pipeHighWaterMark, signal: this.signal, admitWrite: this.budget.pipelineInput,
18595
18343
  }));
18596
18344
  for (let index = 0; index < pipeline.commands.length; index++) {
18597
18345
  controllers.push(createManagedControlController());
@@ -35741,6 +35489,10 @@ export class Runtime {
35741
35489
  return true;
35742
35490
  }
35743
35491
  tryFastPureSubstitution(part, state, rawState, io) {
35492
+ if (!cCollation(rawState.variables.LC_ALL || rawState.variables.LC_COLLATE || rawState.variables.LANG || "C"))
35493
+ return undefined;
35494
+ if (this.budget.limits.maxPipelineBytes !== Infinity)
35495
+ return undefined;
35744
35496
  // Synchronous evaluators do not expose cumulative source-read accounting.
35745
35497
  // Use the command context whenever the caller has set an input ceiling.
35746
35498
  if (this.budget.limits.maxInputBytes !== Infinity)
@@ -1,5 +1,4 @@
1
1
  var _a;
2
- import { preverifyMemoryRgTree } from "../commands/search/rg-command.js";
3
2
  import { MemoryFileSystem } from "../fs/memory/index.js";
4
3
  function utf8ByteLength(str) {
5
4
  if (typeof globalThis.Buffer === "function")
@@ -598,27 +597,6 @@ export class Shell {
598
597
  let unit = firstCached.unit;
599
598
  let exitCode = 0;
600
599
  while (true) {
601
- if (currentCachedUnit !== undefined && (unit.script._fastConstEcho !== undefined || (currentCachedUnit.nextCached !== undefined && currentCachedUnit.nextCached.unit.script._fastConstEcho !== undefined))) {
602
- const batchEnd = runtime.tryRunFastConstEchoBatch(currentCachedUnit, source.length, currentState, io);
603
- if (batchEnd !== undefined) {
604
- currentCachedUnit = batchEnd;
605
- unit = batchEnd.unit;
606
- exitCode = 0;
607
- if (unit.next >= source.length)
608
- break;
609
- budget.signal.throwIfAborted();
610
- const vars = currentState.variables;
611
- const nextLocale = (vars.LC_ALL || vars.LC_CTYPE || vars.LANG) ? byteLocale(vars) : false;
612
- const nextCached = currentCachedUnit.locale === nextLocale ? currentCachedUnit.nextCached : undefined;
613
- if (nextCached !== undefined && (!nextCached.unit.script.warnings || nextCached.unit.script.warnings.length === 0)) {
614
- currentCachedUnit = nextCached;
615
- budget.parsing.admit(nextCached.unitsCharged);
616
- unit = nextCached.unit;
617
- continue;
618
- }
619
- return this.#continueWarmAsync(source, options, warm, sourceCache, undefined, unit, currentCachedUnit, exitCode);
620
- }
621
- }
622
600
  if (unit.script.lists.length) {
623
601
  const unitResult = runtime.runUnit(unit.script, currentState, io);
624
602
  if (unitResult instanceof Promise) {
@@ -1181,7 +1159,6 @@ export class Shell {
1181
1159
  stdout.enableScratchBuffer();
1182
1160
  stderr.enableScratchBuffer();
1183
1161
  void runtime.canFastMemoryRedirect;
1184
- preverifyMemoryRgTree(runtime.backingFs);
1185
1162
  this.#warmedInvocation = {
1186
1163
  budget,
1187
1164
  scope,
@@ -55,6 +55,8 @@ export interface ShellLimits {
55
55
  * Zero permits only redirect-free commands. Not a global byte or filesystem-call budget. */
56
56
  readonly maxRedirects?: number;
57
57
  readonly maxPipelineStages?: number;
58
+ /** Cumulative bytes written between pipeline stages per invocation, including nested pipelines. */
59
+ readonly maxPipelineBytes?: number;
58
60
  readonly maxLoopIterations?: number;
59
61
  readonly maxSubstitutionDepth?: number;
60
62
  /** Maximum simultaneously active shell functions; zero rejects function calls. Unlimited when omitted. */
@@ -45,6 +45,7 @@ export const cloudflareWorkerLimits = Object.freeze({
45
45
  maxPathnameComponents: 64,
46
46
  maxRedirects: 64,
47
47
  maxPipelineStages: 64,
48
+ maxPipelineBytes: 4 * 1024 * 1024,
48
49
  maxLoopIterations: 1_000,
49
50
  maxSubstitutionDepth: 16,
50
51
  maxFunctionDepth: 16,
@@ -1,29 +1,31 @@
1
+ import {
2
+ cloudflareWorkerLimits
3
+ } from "./chunks/chunk-2LSAMQER.js";
1
4
  import {
2
5
  Shell,
3
6
  ShellLimitError,
4
7
  ShellSyntaxError,
5
- cloudflareWorkerLimits,
6
8
  parseShell
7
- } from "./chunks/chunk-7VNF5BFF.js";
9
+ } from "./chunks/chunk-B7PIL77G.js";
10
+ import "./chunks/chunk-A7XEHALN.js";
8
11
  import "./chunks/chunk-TFIBK2GI.js";
9
12
  import "./chunks/chunk-3NDIFSNM.js";
10
- import "./chunks/chunk-SZH7EJLD.js";
13
+ import "./chunks/chunk-6O77NL2S.js";
14
+ import "./chunks/chunk-PNBBUWSM.js";
11
15
  import "./chunks/chunk-MHMMRCYC.js";
16
+ import "./chunks/chunk-OV6IHKO6.js";
17
+ import "./chunks/chunk-CHYGPFVM.js";
12
18
  import "./chunks/chunk-AUSNDQTJ.js";
13
19
  import "./chunks/chunk-CTVWDACF.js";
14
20
  import "./chunks/chunk-3R3AANOR.js";
15
- import "./chunks/chunk-OV6IHKO6.js";
16
21
  import "./chunks/chunk-XVOSKJE2.js";
17
22
  import "./chunks/chunk-C5OWC2TL.js";
18
- import "./chunks/chunk-IVRQ4BXL.js";
23
+ import "./chunks/chunk-PH63PLPZ.js";
19
24
  import "./chunks/chunk-D3ANYGMC.js";
20
- import "./chunks/chunk-CHYGPFVM.js";
21
- import "./chunks/chunk-6O77NL2S.js";
22
- import "./chunks/chunk-A7XEHALN.js";
23
25
  import "./chunks/chunk-J42RIHHJ.js";
24
26
  import "./chunks/chunk-I5HZ4FGE.js";
25
27
  import "./chunks/chunk-VTH3MLDU.js";
26
- import "./chunks/chunk-NZQXYWA3.js";
28
+ import "./chunks/chunk-5OHX7C2V.js";
27
29
  import "./chunks/chunk-74GHTNJA.js";
28
30
  import {
29
31
  CommandRegistry,
@@ -31,8 +33,15 @@ import {
31
33
  createCommandArguments,
32
34
  getCommandArguments
33
35
  } from "./chunks/chunk-7R5BDCG7.js";
34
- import "./chunks/chunk-IWDICZVK.js";
36
+ import "./chunks/chunk-55YJASTN.js";
37
+ import "./chunks/chunk-4BSJLKNM.js";
38
+ import "./chunks/chunk-DQP3VHSB.js";
39
+ import "./chunks/chunk-GEG3BWGE.js";
40
+ import "./chunks/chunk-VBTDHOWC.js";
41
+ import "./chunks/chunk-QGUV42T5.js";
42
+ import "./chunks/chunk-ZVD5IS4V.js";
35
43
  import "./chunks/chunk-E7OYNDGL.js";
44
+ import "./chunks/chunk-IWDICZVK.js";
36
45
  import {
37
46
  init_platform
38
47
  } from "./chunks/chunk-B7TAL7S5.js";
@@ -14,7 +14,7 @@ export function createWorkerKillAfterPolicy(registry, configuration, requiresMod
14
14
  // These counters/leases belong to the interpreter, not to a separate Shell.
15
15
  // Until a shared ledger is available, refuse rather than reset their quota.
16
16
  const limits = runtimeContext?.budget.limits ?? configuration.limits;
17
- const shared = ["maxCommands", "maxLoopIterations", "maxSourceBytes", "maxParseUnits", "maxExpansionBytes", "maxExpansionFields", "maxPipelineStages", "maxSubstitutionDepth", "maxFunctionDepth", "maxCpuMs"];
17
+ const shared = ["maxCommands", "maxLoopIterations", "maxSourceBytes", "maxParseUnits", "maxExpansionBytes", "maxExpansionFields", "maxPipelineStages", "maxPipelineBytes", "maxSubstitutionDepth", "maxFunctionDepth", "maxCpuMs"];
18
18
  if (shared.some(key => limits?.[key] !== undefined && limits[key] !== Infinity)) {
19
19
  await writeBytes(context.stderr, new TextEncoder().encode("timeout: worker escalation cannot preserve finite shared interpreter quotas\n"), context.signal);
20
20
  return { exitCode: 125 };
@@ -35,11 +35,12 @@ var UsageError = class extends Error {
35
35
  super(message);
36
36
  }
37
37
  };
38
- async function collectSourceBytes(source, signal, maxBytes) {
38
+ async function collectSourceBytes(source, signal, maxBytes, admit) {
39
39
  const chunks = [];
40
40
  let total = 0;
41
41
  for await (const chunk of readBytes(source, signal)) {
42
42
  total += chunk.byteLength;
43
+ admit(chunk.byteLength);
43
44
  if (total > maxBytes) throw new Error(`input exceeds maximum size (${maxBytes} bytes)`);
44
45
  chunks.push(chunk);
45
46
  }
@@ -673,6 +674,11 @@ function createBcCommand(options = {}) {
673
674
  description: "Arbitrary-precision calculator language",
674
675
  runtimeIdentity: commandRuntimeIdentity,
675
676
  async execute(context) {
677
+ let inputBytes = 0;
678
+ const admit = (bytes) => {
679
+ context.signal.throwIfAborted();
680
+ context.inputBudget?.check(inputBytes += bytes);
681
+ };
676
682
  context.signal.throwIfAborted();
677
683
  try {
678
684
  let mathlib = false;
@@ -721,14 +727,15 @@ function createBcCommand(options = {}) {
721
727
  }
722
728
  const sources = [...expressions];
723
729
  if (files.length === 0 && expressions.length === 0) {
724
- sources.push(decoder.decode(await collectSourceBytes(context.stdin, context.signal, maxInputBytes)));
730
+ sources.push(decoder.decode(await collectSourceBytes(context.stdin, context.signal, maxInputBytes, admit)));
725
731
  } else if (files.length > 0) {
726
732
  for (const file of files) {
727
733
  if (file === "-") {
728
- sources.push(decoder.decode(await collectSourceBytes(context.stdin, context.signal, maxInputBytes)));
734
+ sources.push(decoder.decode(await collectSourceBytes(context.stdin, context.signal, maxInputBytes, admit)));
729
735
  } else {
730
- const raw = await context.fs.readFile(pathPosix.resolve(context.cwd, file));
736
+ const raw = await context.fs.readFile(pathPosix.resolve(context.cwd, file), { signal: context.signal });
731
737
  context.signal.throwIfAborted();
738
+ admit(raw.byteLength);
732
739
  if (raw.byteLength > maxInputBytes) throw new Error(`bc program exceeds maximum input size (${maxInputBytes} bytes)`);
733
740
  sources.push(decoder.decode(raw));
734
741
  }
@@ -1064,7 +1071,7 @@ function createBcCommand(options = {}) {
1064
1071
  return { exitCode: 0 };
1065
1072
  } catch (err) {
1066
1073
  context.signal.throwIfAborted();
1067
- if (err instanceof Error && err.name === "AbortError") throw err;
1074
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "BudgetExceededError")) throw err;
1068
1075
  const msg = err instanceof Error ? err.message : String(err);
1069
1076
  const code = err instanceof UsageError ? 2 : 1;
1070
1077
  await writeText(context.stderr, `bc: ${msg}